Tweaked task 1
[summerofcode2018soln.git] / src / task1 / task1.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 20,
6 "metadata": {},
7 "outputs": [],
8 "source": [
9 "instructions = [l.strip() for l in open('../../data/01-mowmaster.txt')]"
10 ]
11 },
12 {
13 "cell_type": "markdown",
14 "metadata": {},
15 "source": [
16 "# Part 1\n",
17 "`startswith()` isn't useful that often, but it makes for easily readable code when it is."
18 ]
19 },
20 {
21 "cell_type": "code",
22 "execution_count": 31,
23 "metadata": {},
24 "outputs": [
25 {
26 "data": {
27 "text/plain": [
28 "1136"
29 ]
30 },
31 "execution_count": 31,
32 "metadata": {},
33 "output_type": "execute_result"
34 }
35 ],
36 "source": [
37 "non_comments = 0\n",
38 "for i in instructions:\n",
39 " if not i.startswith('#'):\n",
40 " non_comments += 1\n",
41 "non_comments"
42 ]
43 },
44 {
45 "cell_type": "markdown",
46 "metadata": {},
47 "source": [
48 "This sort if simple walking along a list is sometimes easier with a list comprehension. \n",
49 "\n",
50 "In this case, I transform each element into the number 1, but only if it's not a comment. Then I sum all the 1s, which is the number of non-comment lines."
51 ]
52 },
53 {
54 "cell_type": "code",
55 "execution_count": 21,
56 "metadata": {},
57 "outputs": [
58 {
59 "data": {
60 "text/plain": [
61 "1136"
62 ]
63 },
64 "execution_count": 21,
65 "metadata": {},
66 "output_type": "execute_result"
67 }
68 ],
69 "source": [
70 "sum(1 for i in instructions if not i.startswith('#'))"
71 ]
72 },
73 {
74 "cell_type": "markdown",
75 "metadata": {},
76 "source": [
77 "Or, as a one-liner:"
78 ]
79 },
80 {
81 "cell_type": "code",
82 "execution_count": 22,
83 "metadata": {},
84 "outputs": [
85 {
86 "data": {
87 "text/plain": [
88 "1136"
89 ]
90 },
91 "execution_count": 22,
92 "metadata": {},
93 "output_type": "execute_result"
94 }
95 ],
96 "source": [
97 "sum(1 for i in open('../../data/01-mowmaster.txt') if not i.startswith('#'))"
98 ]
99 },
100 {
101 "cell_type": "markdown",
102 "metadata": {},
103 "source": [
104 "How many comments and total lines?"
105 ]
106 },
107 {
108 "cell_type": "code",
109 "execution_count": 23,
110 "metadata": {},
111 "outputs": [
112 {
113 "data": {
114 "text/plain": [
115 "395"
116 ]
117 },
118 "execution_count": 23,
119 "metadata": {},
120 "output_type": "execute_result"
121 }
122 ],
123 "source": [
124 "sum(1 for i in instructions if i.startswith('#'))"
125 ]
126 },
127 {
128 "cell_type": "code",
129 "execution_count": 24,
130 "metadata": {},
131 "outputs": [
132 {
133 "data": {
134 "text/plain": [
135 "1531"
136 ]
137 },
138 "execution_count": 24,
139 "metadata": {},
140 "output_type": "execute_result"
141 }
142 ],
143 "source": [
144 "len(instructions)"
145 ]
146 },
147 {
148 "cell_type": "markdown",
149 "metadata": {},
150 "source": [
151 "# Part 2\n",
152 "\n",
153 "I have the `mower` as an \"object\" storing its state. (In this case, the mower is a `dict` and the state is just its location and direction.) As each instruction is executed, the mower is updated."
154 ]
155 },
156 {
157 "cell_type": "markdown",
158 "metadata": {},
159 "source": [
160 "An initial mower. I adopt the Scratch convention that a heading of 0 degrees is up, increasing clockwise; so right is 90 degrees."
161 ]
162 },
163 {
164 "cell_type": "code",
165 "execution_count": 25,
166 "metadata": {},
167 "outputs": [],
168 "source": [
169 "def init_mowmaster():\n",
170 " return {'x': 0, 'y': 0, 'd': 90}"
171 ]
172 },
173 {
174 "cell_type": "markdown",
175 "metadata": {},
176 "source": [
177 "Execute the instructions. Do them one at a time, updating the mowmaster for each one.\n",
178 "\n",
179 "(Can you see an accumulator pattern again?)"
180 ]
181 },
182 {
183 "cell_type": "code",
184 "execution_count": 26,
185 "metadata": {},
186 "outputs": [],
187 "source": [
188 "def execute(mowmaster, instructions, debug=False):\n",
189 " for instruction in instructions:\n",
190 " mowmaster = execute_one(mowmaster, instruction, debug=debug)\n",
191 " return mowmaster"
192 ]
193 },
194 {
195 "cell_type": "markdown",
196 "metadata": {},
197 "source": [
198 "Execute one instruction. If it starts `C` or `A`, turn; if it starts `F`, move forward. Ignore all other instructions."
199 ]
200 },
201 {
202 "cell_type": "code",
203 "execution_count": 27,
204 "metadata": {},
205 "outputs": [],
206 "source": [
207 "def execute_one(mowmaster, instruction, debug=False):\n",
208 " if instruction == 'C':\n",
209 " mowmaster['d'] = (mowmaster['d'] + 90) % 360 # Use the modulus operator to keep the angle in the range 0--360\n",
210 " elif instruction == 'A':\n",
211 " mowmaster['d'] = (mowmaster['d'] - 90) % 360\n",
212 " elif instruction.startswith('F'):\n",
213 " mowmaster = move(mowmaster, int(instruction[1:]))\n",
214 " if debug: \n",
215 " print(instruction, mowmaster)\n",
216 " return mowmaster"
217 ]
218 },
219 {
220 "cell_type": "markdown",
221 "metadata": {},
222 "source": [
223 "The movement. Update `x` or `y` depending on the direction."
224 ]
225 },
226 {
227 "cell_type": "code",
228 "execution_count": 28,
229 "metadata": {},
230 "outputs": [],
231 "source": [
232 "def move(mower, distance):\n",
233 " if mower['d'] == 0:\n",
234 " mower['y'] += distance\n",
235 " elif mower['d'] == 90:\n",
236 " mower['x'] += distance\n",
237 " elif mower['d'] == 180:\n",
238 " mower['y'] -= distance\n",
239 " elif mower['d'] == 270:\n",
240 " mower['x'] -= distance\n",
241 " else:\n",
242 " raise ValueError\n",
243 " return mower"
244 ]
245 },
246 {
247 "cell_type": "markdown",
248 "metadata": {},
249 "source": [
250 "Finally, how far the Mowmaster has moved."
251 ]
252 },
253 {
254 "cell_type": "code",
255 "execution_count": 29,
256 "metadata": {},
257 "outputs": [],
258 "source": [
259 "def mowmaster_distance(mw):\n",
260 " return abs(mw['x']) + abs(mw['y'])"
261 ]
262 },
263 {
264 "cell_type": "markdown",
265 "metadata": {},
266 "source": [
267 "Now we have all the parts, put them together into the solution."
268 ]
269 },
270 {
271 "cell_type": "code",
272 "execution_count": 30,
273 "metadata": {},
274 "outputs": [
275 {
276 "data": {
277 "text/plain": [
278 "337"
279 ]
280 },
281 "execution_count": 30,
282 "metadata": {},
283 "output_type": "execute_result"
284 }
285 ],
286 "source": [
287 "mw = init_mowmaster()\n",
288 "execute(mw, instructions)\n",
289 "mowmaster_distance(mw)"
290 ]
291 },
292 {
293 "cell_type": "code",
294 "execution_count": null,
295 "metadata": {},
296 "outputs": [],
297 "source": []
298 }
299 ],
300 "metadata": {
301 "kernelspec": {
302 "display_name": "Python 3",
303 "language": "python",
304 "name": "python3"
305 },
306 "language_info": {
307 "codemirror_mode": {
308 "name": "ipython",
309 "version": 3
310 },
311 "file_extension": ".py",
312 "mimetype": "text/x-python",
313 "name": "python",
314 "nbconvert_exporter": "python",
315 "pygments_lexer": "ipython3",
316 "version": "3.6.5"
317 }
318 },
319 "nbformat": 4,
320 "nbformat_minor": 2
321 }