From 98fb1acf36bb318266a95284760866faff505765 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Thu, 1 Dec 2016 14:22:39 +0000 Subject: [PATCH] Day 1 done --- .gitignore | 38 +++++++++ README.html | 12 +++ README.md | 31 ++++++++ advent01.hs | 96 ++++++++++++++++++++++ advent01.txt | 1 + day01.html | 145 ++++++++++++++++++++++++++++++++++ modest.css | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 542 insertions(+) create mode 100644 .gitignore create mode 100644 README.html create mode 100644 README.md create mode 100644 advent01.hs create mode 100644 advent01.txt create mode 100644 day01.html create mode 100644 modest.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3200a6e --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Extensionless files +* +!/**/ +!*.* + +# Haskell bits +dist +dist-* +cabal-dev +*.o +*.hi +*.chi +*.chs.h +*.dyn_o +*.dyn_hi +.hpc +.hsenv +.cabal-sandbox/ +cabal.sandbox.config +*.prof +*.aux +*.hp +*.eventlog +.stack-work/ +cabal.project.local +.HTF/ + +# A semelance of purity! +# IPython +.ipynb* +*.ipynb + +# Sublime text +*.sublime-workspace + +# Logs +*.log + diff --git a/README.html b/README.html new file mode 100644 index 0000000..0877da1 --- /dev/null +++ b/README.html @@ -0,0 +1,12 @@ +

+

Advent of Code 2016

+

Code to solve the Advent of Code puzzles. This year, I'm trying to use the puzzles as a prompt to learn Haskell.

+

Learn you a Haskell, Introduction to Haskell 98, and Hackage are good resources.

+

I'm using the basic Haskell Platform installation (install with

+
$ sudo aptitude install haskell-platform
+

).

+

Compile the code with

+
ghc -o advent01 advent01.hs
+

then run it as

+
advent01
+

(Using the Modest styles.)

diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe9e6b5 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +--- +title: "Advent of Code 2016" +output: + html_document: + css: modest.css +--- + + +# Advent of Code 2016 + +Code to solve the [Advent of Code](http://adventofcode.com/2016/) puzzles. This year, I'm trying to use the puzzles as a prompt to learn [Haskell](https://wiki.haskell.org/Haskell). + +[Learn you a Haskell](http://learnyouahaskell.com/chapters), [Introduction to Haskell 98](https://www.haskell.org/tutorial/index.html), and [Hackage](https://hackage.haskell.org/) are good resources. + +I'm using the basic Haskell Platform installation (install with +``` +$ sudo aptitude install haskell-platform +``` +). + +Compile the code with +``` +ghc -o advent01 advent01.hs +``` + +then run it as +``` +advent01 +``` + +(Using the [Modest styles](https://github.com/markdowncss/modest).) \ No newline at end of file diff --git a/advent01.hs b/advent01.hs new file mode 100644 index 0000000..27a6f21 --- /dev/null +++ b/advent01.hs @@ -0,0 +1,96 @@ +import Data.List (sort) +import Data.List.Split (splitOn) + +-- turn direction, number of steps +data Step = Step Char Int deriving (Show) + +data Direction = North | East | South | West + deriving (Enum, Show, Bounded, Eq) + +-- direction, easting, northing +data Position = Position Direction Int Int deriving (Show) +-- Two positions are the same if they're in the same place, +-- regardless of facing +instance Eq Position where + Position _ e n == Position _ e' n' = e == e' && n == n' + +main :: IO () +main = do + instructions <- readFile "advent01.txt" + part1 instructions + part2 instructions + +part1 :: String -> IO () +part1 instructions = do + let answer = finalDistance $ last $ stepsFromStart $ steps instructions + print answer + +part2 :: String -> IO () +part2 instructions = do + let visited = finalDistance $ firstRepeat $ stepsFromStart $ expandSteps $ steps instructions + print visited + + +-- Extract the steps from the input string. +steps :: String -> [Step] +steps s = map readStep $ splitOn ", " s + where readStep (d:l) = Step d (read l) + +-- Take steps from the starting position +stepsFromStart :: [Step] -> [Position] +stepsFromStart = takeSteps (Position North 0 0) + +-- Calculate manhattan distance from start to this state +finalDistance :: Position -> Int +finalDistance (Position _ e n) = (abs e) + (abs n) + +-- For part 2: convert one step of many spaces to many steps of one space each +expandSteps :: [Step] -> [Step] +expandSteps = + concatMap expandStep + where expandStep (Step dir d) = (Step dir 1) : replicate (d - 1) (Step 'S' 1) + +-- Execute a series of steps, keeping track of the positions after each step +takeSteps :: Position -> [Step] -> [Position] +takeSteps pos steps = scanl move pos steps + +-- Make one move, by updating direction then position +move :: Position -> Step -> Position +move (Position facing easting northing) + (Step turnInstr distance) = + Position facing' easting' northing' + where facing' = turn turnInstr facing + (easting', northing') = takeStep facing' distance easting northing + +-- Turn right, left, or straight +turn :: Char -> Direction -> Direction +turn 'R' direction = turnCW direction +turn 'L' direction = turnACW direction +turn 'S' direction = direction + +-- Move in the current direction +takeStep :: Direction -> Int -> Int -> Int -> (Int, Int) +takeStep North d e n = (e, n+d) +takeStep South d e n = (e, n-d) +takeStep West d e n = (e-d, n) +takeStep East d e n = (e+d, n) + + +-- | a `succ` that wraps +turnCW :: (Bounded a, Enum a, Eq a) => a -> a +turnCW dir | dir == maxBound = minBound + | otherwise = succ dir + +-- | a `pred` that wraps +turnACW :: (Bounded a, Enum a, Eq a) => a -> a +turnACW dir | dir == minBound = maxBound + | otherwise = pred dir + +-- All the prefixes of a list of items +prefixes = scanl addTerm [] + where addTerm ps t = ps ++ [t] + +-- The first item that exists in a prefix of the list to that point +firstRepeat positions = + last $ head $ dropWhile (\p -> (last p) `notElem` (tail $ reverse p)) + (tail $ prefixes positions) diff --git a/advent01.txt b/advent01.txt new file mode 100644 index 0000000..62fb6e8 --- /dev/null +++ b/advent01.txt @@ -0,0 +1 @@ +R2, L3, R2, R4, L2, L1, R2, R4, R1, L4, L5, R5, R5, R2, R2, R1, L2, L3, L2, L1, R3, L5, R187, R1, R4, L1, R5, L3, L4, R50, L4, R2, R70, L3, L2, R4, R3, R194, L3, L4, L4, L3, L4, R4, R5, L1, L5, L4, R1, L2, R4, L5, L3, R4, L5, L5, R5, R3, R5, L2, L4, R4, L1, R3, R1, L1, L2, R2, R2, L3, R3, R2, R5, R2, R5, L3, R2, L5, R1, R2, R2, L4, L5, L1, L4, R4, R3, R1, R2, L1, L2, R4, R5, L2, R3, L4, L5, L5, L4, R4, L2, R1, R1, L2, L3, L2, R2, L4, R3, R2, L1, L3, L2, L4, L4, R2, L3, L3, R2, L4, L3, R4, R3, L2, L1, L4, R4, R2, L4, L4, L5, L1, R2, L5, L2, L3, R2, L2 \ No newline at end of file diff --git a/day01.html b/day01.html new file mode 100644 index 0000000..72667d5 --- /dev/null +++ b/day01.html @@ -0,0 +1,145 @@ + + + + +Day 1 - Advent of Code 2016 + + + + + + +

Advent of Code

Neil Smith 2*

       y(2016)

+ + + +
+

--- Day 1: No Time for a Taxicab ---

Santa's sleigh uses a very high-precision clock to guide its movements, and the clock's oscillator is regulated by stars. Unfortunately, the stars have been stolen... by the Easter Bunny. To save Christmas, Santa needs you to retrieve all fifty stars by December 25th.

+

Collect stars by solving puzzles. Two puzzles will be made available on each day in the advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!

+

You're airdropped near Easter Bunny Headquarters in a city somewhere. "Near", unfortunately, is as close as you can get - the instructions on the Easter Bunny Recruiting Document the Elves intercepted start here, and nobody had time to work them out further.

+

The Document indicates that you should start at the given coordinates (where you just landed) and face North. Then, follow the provided sequence: either turn left (L) or right (R) 90 degrees, then walk forward the given number of blocks, ending at a new intersection.

+

There's no time to follow such ridiculous instructions on foot, though, so you take a moment and work out the destination. Given that you can only walk on the street grid of the city, how far is the shortest path to the destination?

+

For example:

+
    +
  • Following R2, L3 leaves you 2 blocks East and 3 blocks North, or 5 blocks away.
  • +
  • R2, R2, R2 leaves you 2 blocks due South of your starting position, which is 2 blocks away.
  • +
  • R5, L5, R5, R3 leaves you 12 blocks away.
  • +
+

How many blocks away is Easter Bunny HQ?

+
+

Your puzzle answer was 246.

--- Part Two ---

Then, you notice the instructions continue on the back of the Recruiting Document. Easter Bunny HQ is actually at the first location you visit twice.

+

For example, if your instructions are R8, R4, R4, R8, the first location you visit twice is 4 blocks away, due East.

+

How many blocks away is the first location you visit twice?

+
+

Your puzzle answer was 124.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your advent calendar and try another puzzle.

+

If you still want to see it, you can get your puzzle input.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file diff --git a/modest.css b/modest.css new file mode 100644 index 0000000..947a9ea --- /dev/null +++ b/modest.css @@ -0,0 +1,219 @@ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } +} + +pre, +code { + font-family: Menlo, Monaco, "Courier New", monospace; +} + +pre { + padding: .5rem; + line-height: 1.25; + overflow-x: scroll; +} + +a, +a:visited { + color: #3498db; +} + +a:hover, +a:focus, +a:active { + color: #2980b9; +} + +.modest-no-decoration { + text-decoration: none; +} + +html { + font-size: 12px; +} + +@media screen and (min-width: 32rem) and (max-width: 48rem) { + html { + font-size: 15px; + } +} + +@media screen and (min-width: 48rem) { + html { + font-size: 16px; + } +} + +body { + line-height: 1.85; +} + +p, +.modest-p { + font-size: 1rem; + margin-bottom: 1.3rem; +} + +h1, +.modest-h1, +h2, +.modest-h2, +h3, +.modest-h3, +h4, +.modest-h4 { + margin: 1.414rem 0 .5rem; + font-weight: inherit; + line-height: 1.42; +} + +h1, +.modest-h1 { + margin-top: 0; + font-size: 3.998rem; +} + +h2, +.modest-h2 { + font-size: 2.827rem; +} + +h3, +.modest-h3 { + font-size: 1.999rem; +} + +h4, +.modest-h4 { + font-size: 1.414rem; +} + +h5, +.modest-h5 { + font-size: 1.121rem; +} + +h6, +.modest-h6 { + font-size: .88rem; +} + +small, +.modest-small { + font-size: .707em; +} + +/* https://github.com/mrmrs/fluidity */ + +img, +canvas, +iframe, +video, +svg, +select, +textarea { + max-width: 100%; +} + +@import url(http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,300italic,700); + +@import url(http://fonts.googleapis.com/css?family=Arimo:700,700italic); + +html { + font-size: 18px; + max-width: 100%; +} + +body { + color: #444; + font-family: 'Open Sans Condensed', sans-serif; + font-weight: 300; + margin: 0 auto; + max-width: 48rem; + line-height: 1.45; + padding: .25rem; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: Arimo, Helvetica, sans-serif; +} + +h1, +h2, +h3 { + border-bottom: 2px solid #fafafa; + margin-bottom: 1.15rem; + padding-bottom: .5rem; + text-align: center; +} + +blockquote { + border-left: 8px solid #fafafa; + padding: 1rem; +} + +pre, +code { + background-color: #fafafa; +} \ No newline at end of file -- 2.34.1