{ "cells": [ { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "instructions = [l.strip() for l in open('../../data/01-mowmaster.txt')]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Part 1\n", "`startswith()` isn't useful that often, but it makes for easily readable code when it is." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1136" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "non_comments = 0\n", "for i in instructions:\n", " if not i.startswith('#'):\n", " non_comments += 1\n", "non_comments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This sort if simple walking along a list is sometimes easier with a list comprehension. \n", "\n", "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." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1136" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(1 for i in instructions if not i.startswith('#'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or, as a one-liner:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1136" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(1 for i in open('../../data/01-mowmaster.txt') if not i.startswith('#'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How many comments and total lines?" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "395" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(1 for i in instructions if i.startswith('#'))" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1531" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(instructions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Part 2\n", "\n", "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." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An initial mower. I adopt the Scratch convention that a heading of 0 degrees is up, increasing clockwise; so right is 90 degrees." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "def init_mowmaster():\n", " return {'x': 0, 'y': 0, 'd': 90}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Execute the instructions. Do them one at a time, updating the mowmaster for each one.\n", "\n", "(Can you see an accumulator pattern again?)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "def execute(mowmaster, instructions, debug=False):\n", " for instruction in instructions:\n", " mowmaster = execute_one(mowmaster, instruction, debug=debug)\n", " return mowmaster" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Execute one instruction. If it starts `C` or `A`, turn; if it starts `F`, move forward. Ignore all other instructions." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "def execute_one(mowmaster, instruction, debug=False):\n", " if instruction == 'C':\n", " mowmaster['d'] = (mowmaster['d'] + 90) % 360 # Use the modulus operator to keep the angle in the range 0--360\n", " elif instruction == 'A':\n", " mowmaster['d'] = (mowmaster['d'] - 90) % 360\n", " elif instruction.startswith('F'):\n", " mowmaster = move(mowmaster, int(instruction[1:]))\n", " if debug: \n", " print(instruction, mowmaster)\n", " return mowmaster" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The movement. Update `x` or `y` depending on the direction." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "def move(mower, distance):\n", " if mower['d'] == 0:\n", " mower['y'] += distance\n", " elif mower['d'] == 90:\n", " mower['x'] += distance\n", " elif mower['d'] == 180:\n", " mower['y'] -= distance\n", " elif mower['d'] == 270:\n", " mower['x'] -= distance\n", " else:\n", " raise ValueError\n", " return mower" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, how far the Mowmaster has moved." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "def mowmaster_distance(mw):\n", " return abs(mw['x']) + abs(mw['y'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we have all the parts, put them together into the solution." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "337" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mw = init_mowmaster()\n", "execute(mw, instructions)\n", "mowmaster_distance(mw)" ] }, { "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 }