4f640f8ff929c9f361e913c72d0afbab44954e9f
[summerofcode2018soln.git] / src / task3 / task3.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {},
7 "outputs": [],
8 "source": [
9 "instructions = [l.strip() for l in open('../../data/03-graffiti.txt') if not l.startswith('#')]"
10 ]
11 },
12 {
13 "cell_type": "markdown",
14 "metadata": {},
15 "source": [
16 "# Part 1\n",
17 "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",
18 "\n",
19 "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",
20 "\n",
21 "`pen` records whether the Mowmaster is mowing or not."
22 ]
23 },
24 {
25 "cell_type": "code",
26 "execution_count": 18,
27 "metadata": {},
28 "outputs": [],
29 "source": [
30 "def initial_world():\n",
31 " return {'x': 0, 'y': 0, 'd': 0, 'pen': False, 'grass': {}}"
32 ]
33 },
34 {
35 "cell_type": "markdown",
36 "metadata": {},
37 "source": [
38 "One function for each command. The function is passed the world, and it updates the world."
39 ]
40 },
41 {
42 "cell_type": "code",
43 "execution_count": 20,
44 "metadata": {},
45 "outputs": [],
46 "source": [
47 "def f(world, distance):\n",
48 " for d in range(distance):\n",
49 " if world['d'] == 0:\n",
50 " world['y'] += 1\n",
51 " elif world['d'] == 90:\n",
52 " world['x'] += 1\n",
53 " elif world['d'] == 180:\n",
54 " world['y'] -= 1\n",
55 " elif world['d'] == 270:\n",
56 " world['x'] -= 1\n",
57 " else:\n",
58 " raise ValueError\n",
59 " if world['pen']:\n",
60 " world['grass'][world['x'], world['y']] = True\n",
61 " return world"
62 ]
63 },
64 {
65 "cell_type": "code",
66 "execution_count": 4,
67 "metadata": {},
68 "outputs": [],
69 "source": [
70 "def c(world):\n",
71 " world['d'] = (world['d'] + 90) % 360\n",
72 " return world"
73 ]
74 },
75 {
76 "cell_type": "code",
77 "execution_count": 5,
78 "metadata": {},
79 "outputs": [],
80 "source": [
81 "def a(world):\n",
82 " world['d'] = (world['d'] - 90) % 360\n",
83 " return world"
84 ]
85 },
86 {
87 "cell_type": "code",
88 "execution_count": 6,
89 "metadata": {},
90 "outputs": [],
91 "source": [
92 "def u(world):\n",
93 " world['pen'] = False\n",
94 " return world"
95 ]
96 },
97 {
98 "cell_type": "code",
99 "execution_count": 7,
100 "metadata": {},
101 "outputs": [],
102 "source": [
103 "def d(world):\n",
104 " world['pen'] = True\n",
105 " world['grass'][world['x'], world['y']] = True\n",
106 " return world"
107 ]
108 },
109 {
110 "cell_type": "markdown",
111 "metadata": {},
112 "source": [
113 "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."
114 ]
115 },
116 {
117 "cell_type": "code",
118 "execution_count": 21,
119 "metadata": {},
120 "outputs": [],
121 "source": [
122 "table = {\n",
123 " 'F': {'func': f, 'arg': True},\n",
124 " 'C': {'func': c, 'arg': False},\n",
125 " 'A': {'func': a, 'arg': False},\n",
126 " 'U': {'func': u, 'arg': False},\n",
127 " 'D': {'func': d, 'arg': False},\n",
128 "}"
129 ]
130 },
131 {
132 "cell_type": "code",
133 "execution_count": 12,
134 "metadata": {},
135 "outputs": [],
136 "source": [
137 "def execute(world, instructions, debug=False):\n",
138 " for instruction in instructions:\n",
139 " world = execute_one(world, instruction, debug=debug)\n",
140 " return world"
141 ]
142 },
143 {
144 "cell_type": "markdown",
145 "metadata": {},
146 "source": [
147 "To execute a command, look it up in the dispatch table. If it's there, call the function."
148 ]
149 },
150 {
151 "cell_type": "code",
152 "execution_count": 14,
153 "metadata": {},
154 "outputs": [],
155 "source": [
156 "def execute_one(world, instruction, debug=False):\n",
157 " instruction_name = instruction[0]\n",
158 " if instruction_name in table:\n",
159 " if table[instruction_name]['arg']:\n",
160 " arg = int(instruction[1:])\n",
161 " world = table[instruction_name]['func'](world, arg)\n",
162 " else:\n",
163 " world = table[instruction_name]['func'](world)\n",
164 " return world"
165 ]
166 },
167 {
168 "cell_type": "code",
169 "execution_count": 35,
170 "metadata": {},
171 "outputs": [
172 {
173 "data": {
174 "text/plain": [
175 "246"
176 ]
177 },
178 "execution_count": 35,
179 "metadata": {},
180 "output_type": "execute_result"
181 }
182 ],
183 "source": [
184 "w = initial_world()\n",
185 "execute(w, instructions)\n",
186 "len(w['grass'])"
187 ]
188 },
189 {
190 "cell_type": "markdown",
191 "metadata": {},
192 "source": [
193 "# Part 2\n",
194 "\n",
195 "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."
196 ]
197 },
198 {
199 "cell_type": "code",
200 "execution_count": 31,
201 "metadata": {},
202 "outputs": [],
203 "source": [
204 "def show_world(world):\n",
205 " width_max = max(p[0] for p in world['grass'])\n",
206 " width_min = min(p[0] for p in world['grass'])\n",
207 " height_max = max(p[1] for p in world['grass'])\n",
208 " height_min = min(p[1] for p in world['grass'])\n",
209 " display = {}\n",
210 " for r in range(height_max, height_min-1, -1):\n",
211 " display[r] = ''\n",
212 " for c in range(width_min, width_max+1):\n",
213 " if (c, r) in world['grass']:\n",
214 " display[r] += '⌷'\n",
215 " else:\n",
216 " display[r] += ' '\n",
217 " return '\\n'.join(display[r] for r in reversed(sorted(display)))"
218 ]
219 },
220 {
221 "cell_type": "code",
222 "execution_count": 34,
223 "metadata": {},
224 "outputs": [
225 {
226 "name": "stdout",
227 "output_type": "stream",
228 "text": [
229 "⌷⌷⌷⌷⌷⌷ \n",
230 "⌷ \n",
231 "⌷ \n",
232 "⌷⌷⌷⌷⌷⌷ \n",
233 "⌷ \n",
234 "⌷ \n",
235 "⌷ \n",
236 "⌷ \n",
237 "⌷⌷⌷⌷⌷⌷ ⌷\n"
238 ]
239 }
240 ],
241 "source": [
242 "print(show_world(w))"
243 ]
244 },
245 {
246 "cell_type": "code",
247 "execution_count": null,
248 "metadata": {},
249 "outputs": [],
250 "source": []
251 }
252 ],
253 "metadata": {
254 "kernelspec": {
255 "display_name": "Python 3",
256 "language": "python",
257 "name": "python3"
258 },
259 "language_info": {
260 "codemirror_mode": {
261 "name": "ipython",
262 "version": 3
263 },
264 "file_extension": ".py",
265 "mimetype": "text/x-python",
266 "name": "python",
267 "nbconvert_exporter": "python",
268 "pygments_lexer": "ipython3",
269 "version": "3.6.5"
270 }
271 },
272 "nbformat": 4,
273 "nbformat_minor": 2
274 }