From 56de4596adb43e9505c41fdd734954099d2f8a99 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Wed, 19 Sep 2018 11:23:14 +0100 Subject: [PATCH] Tweaked task 1 --- src/task1/task1-mpc.hs | 8 +-- src/task1/task1.hs | 4 +- src/task1/task1.ipynb | 129 ++++++++++++++++++++++++++++++++--------- 3 files changed, 107 insertions(+), 34 deletions(-) diff --git a/src/task1/task1-mpc.hs b/src/task1/task1-mpc.hs index e2127b6..27b279a 100644 --- a/src/task1/task1-mpc.hs +++ b/src/task1/task1-mpc.hs @@ -33,7 +33,6 @@ data Mowmaster = Mowmaster { direction :: Direction data Instruction = Forward Distance | Clockwise | Anticlockwise - | Comment String deriving (Show, Eq) @@ -48,10 +47,10 @@ part1 :: [Instruction] -> Int part1 = length part2 :: [Instruction] -> Int -part2 instructions = finalDistance $ executeAll instructions +part2 = finalDistance . executeAll where executeAll = foldl' execute initialMowmaster -initialMowmaster = Mowmaster North (0, 0) +initialMowmaster = Mowmaster East (0, 0) -- Calculate manhattan distance from start to this state @@ -65,10 +64,9 @@ execute :: Mowmaster -> Instruction -> Mowmaster execute m (Forward s) = m {position = forward s (direction m) (position m)} execute m Clockwise = m {direction = turnCW (direction m)} execute m Anticlockwise = m {direction = turnACW (direction m)} -execute m _ = m -- Move in the current direction -forward :: Int -> Direction -> Position -> Position +forward :: Distance -> Direction -> Position -> Position forward s North (e, n) = (e, n+s) forward s South (e, n) = (e, n-s) forward s West (e, n) = (e-s, n) diff --git a/src/task1/task1.hs b/src/task1/task1.hs index e7a4f4b..b0e2630 100644 --- a/src/task1/task1.hs +++ b/src/task1/task1.hs @@ -57,7 +57,7 @@ readInstruction i = readInstruction' (head i) (tail i) readInstruction' _ t = Comment t -initialMowmaster = Mowmaster North (0, 0) +initialMowmaster = Mowmaster East (0, 0) -- Calculate manhattan distance from start to this state @@ -75,7 +75,7 @@ execute m (Comment _) = m -- Move in the current direction -forward :: Int -> Direction -> Position -> Position +forward :: Distance -> Direction -> Position -> Position forward s North (e, n) = (e, n+s) forward s South (e, n) = (e, n-s) forward s West (e, n) = (e-s, n) diff --git a/src/task1/task1.ipynb b/src/task1/task1.ipynb index a5632bb..a9c4dcf 100644 --- a/src/task1/task1.ipynb +++ b/src/task1/task1.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -13,12 +13,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Part 1" + "# Part 1\n", + "`startswith()` isn't useful that often, but it makes for easily readable code when it is." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -27,7 +28,40 @@ "1136" ] }, - "execution_count": 3, + "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" } @@ -45,7 +79,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -54,7 +88,7 @@ "1136" ] }, - "execution_count": 4, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -63,9 +97,16 @@ "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": 5, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -74,7 +115,7 @@ "395" ] }, - "execution_count": 5, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -85,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -94,7 +135,7 @@ "1531" ] }, - "execution_count": 6, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -116,12 +157,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "An initial mower. The initial location and direction don't matter in this case, so I choose a location that's easy and an arbitrary location." + "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": 12, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ @@ -133,25 +174,45 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Execute the instructions. If it starts `C` or `A`, turn; if it starts `F`, move forward. Ignore all other instructions." + "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": 13, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "def execute(mowmaster, instructions, debug=False):\n", " for instruction in instructions:\n", - " if instruction == 'C':\n", - " mowmaster['d'] = (mowmaster['d'] + 90) % 360 # Use the modul\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", + " 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" ] }, @@ -159,12 +220,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The " + "The movement. Update `x` or `y` depending on the direction." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -182,9 +243,16 @@ " return mower" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, how far the Mowmaster has moved." + ] + }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ @@ -192,9 +260,16 @@ " 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": 18, + "execution_count": 30, "metadata": {}, "outputs": [ { @@ -203,7 +278,7 @@ "337" ] }, - "execution_count": 18, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } -- 2.34.1