X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=src%2Ftask3%2Ftask3.ipynb;fp=src%2Ftask3%2Ftask3.ipynb;h=4f640f8ff929c9f361e913c72d0afbab44954e9f;hb=7f605871c37afd7d659fa70cfea0eaef18ef6695;hp=0000000000000000000000000000000000000000;hpb=62ffc4273743b4e3727982f17a1abfb130edd0f1;p=summerofcode2018soln.git diff --git a/src/task3/task3.ipynb b/src/task3/task3.ipynb new file mode 100644 index 0000000..4f640f8 --- /dev/null +++ b/src/task3/task3.ipynb @@ -0,0 +1,274 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "instructions = [l.strip() for l in open('../../data/03-graffiti.txt') if not l.startswith('#')]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Part 1\n", + "Similar to task 1, but rather than just tracking the state of the mower, now we track the state of the grass as well.\n", + "\n", + "The grass is a `dict` of mown patches. The key in the `grass` is a pair (2-tuple) of `x` and `y` position. The value is `True` if the patch is mown. Unmown patches aren't recorded in the `grass`.\n", + "\n", + "`pen` records whether the Mowmaster is mowing or not." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "def initial_world():\n", + " return {'x': 0, 'y': 0, 'd': 0, 'pen': False, 'grass': {}}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One function for each command. The function is passed the world, and it updates the world." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "def f(world, distance):\n", + " for d in range(distance):\n", + " if world['d'] == 0:\n", + " world['y'] += 1\n", + " elif world['d'] == 90:\n", + " world['x'] += 1\n", + " elif world['d'] == 180:\n", + " world['y'] -= 1\n", + " elif world['d'] == 270:\n", + " world['x'] -= 1\n", + " else:\n", + " raise ValueError\n", + " if world['pen']:\n", + " world['grass'][world['x'], world['y']] = True\n", + " return world" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def c(world):\n", + " world['d'] = (world['d'] + 90) % 360\n", + " return world" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def a(world):\n", + " world['d'] = (world['d'] - 90) % 360\n", + " return world" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def u(world):\n", + " world['pen'] = False\n", + " return world" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def d(world):\n", + " world['pen'] = True\n", + " world['grass'][world['x'], world['y']] = True\n", + " return world" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A dispatch table of commands. The keys are the command names, the values is the function to call and whether that function takes an argument or not." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "table = {\n", + " 'F': {'func': f, 'arg': True},\n", + " 'C': {'func': c, 'arg': False},\n", + " 'A': {'func': a, 'arg': False},\n", + " 'U': {'func': u, 'arg': False},\n", + " 'D': {'func': d, 'arg': False},\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def execute(world, instructions, debug=False):\n", + " for instruction in instructions:\n", + " world = execute_one(world, instruction, debug=debug)\n", + " return world" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To execute a command, look it up in the dispatch table. If it's there, call the function." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "def execute_one(world, instruction, debug=False):\n", + " instruction_name = instruction[0]\n", + " if instruction_name in table:\n", + " if table[instruction_name]['arg']:\n", + " arg = int(instruction[1:])\n", + " world = table[instruction_name]['func'](world, arg)\n", + " else:\n", + " world = table[instruction_name]['func'](world)\n", + " return world" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "246" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w = initial_world()\n", + "execute(w, instructions)\n", + "len(w['grass'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Part 2\n", + "\n", + "The `show_world` returns a string with a square for each mown patch. The string contains the embedded newlines, so I call `print` on the result." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "def show_world(world):\n", + " width_max = max(p[0] for p in world['grass'])\n", + " width_min = min(p[0] for p in world['grass'])\n", + " height_max = max(p[1] for p in world['grass'])\n", + " height_min = min(p[1] for p in world['grass'])\n", + " display = {}\n", + " for r in range(height_max, height_min-1, -1):\n", + " display[r] = ''\n", + " for c in range(width_min, width_max+1):\n", + " if (c, r) in world['grass']:\n", + " display[r] += '⌷'\n", + " else:\n", + " display[r] += ' '\n", + " return '\\n'.join(display[r] for r in reversed(sorted(display)))" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "⌷⌷⌷⌷⌷⌷ \n", + "⌷ \n", + "⌷ \n", + "⌷⌷⌷⌷⌷⌷ \n", + "⌷ \n", + "⌷ \n", + "⌷ \n", + "⌷ \n", + "⌷⌷⌷⌷⌷⌷ ⌷\n" + ] + } + ], + "source": [ + "print(show_world(w))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}