Day 8
authorNeil Smith <neil.git@njae.me.uk>
Fri, 9 Dec 2016 15:32:05 +0000 (15:32 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Fri, 9 Dec 2016 15:32:05 +0000 (15:32 +0000)
advent08.hs [new file with mode: 0644]
advent08.txt [new file with mode: 0644]
day08.html [new file with mode: 0644]

diff --git a/advent08.hs b/advent08.hs
new file mode 100644 (file)
index 0000000..0c5987c
--- /dev/null
@@ -0,0 +1,152 @@
+module Main(main) where
+
+import Data.Array.IArray
+import Text.Parsec
+-- import Control.Applicative
+import Control.Applicative ((<$), (<*), (*>), (<*>), pure, liftA)
+import Control.Monad (liftM, ap)
+
+-- Row 1 is top, column 1 is left
+type Position = (Int, Int)
+type Screen = Array Position Bool
+
+data Direction = Row | Column deriving (Show)
+data Command = Rect Int Int | Rotate Direction Int Int deriving (Show)
+
+data ScState a = ScState (Screen -> (Screen, a))
+
+mkScreen :: Int -> Int -> Screen
+mkScreen w h = array ((0, 0), (h - 1, w - 1))
+    [((i, j), False) | i <- [0..(h-1)], j <- [0..(w-1)]]
+
+
+showScreen :: Screen -> String
+showScreen screen = unlines [showRow r | r <- [minRow..maxRow]]
+    where ((minRow, minCol), (maxRow, maxCol)) = bounds screen
+          showCell True  = '#'
+          showCell False = '.'
+          showRow r = [showCell (screen!(r, c)) | c <- [minCol..maxCol]]
+
+countLights :: Screen -> Int
+countLights screen = length $ filter (id) $ elems screen
+
+screen0 = mkScreen 50 6
+
+instrs = [ Rect 3 2
+         , Rotate Column 1 1
+         , Rotate Row 0 4
+         , Rotate Column 1 1
+         , Rotate Row 1 6
+         , Rotate Row 2 8
+         , Rect 1 3
+         ]
+
+main :: IO ()
+main = do
+    text <- readFile "advent08.txt"
+    let instrs = successfulParse $ parseCommands text
+    -- print instrs
+    part1 instrs
+    part2 instrs
+
+part1 :: [Command] -> IO ()
+part1 instructions = 
+    putStrLn $ showScreen $ (extractScreen . doInstructions) instructions
+
+part2 :: [Command] -> IO ()
+part2 instructions =
+    print $ countLights $ (extractScreen . doInstructions) instructions
+
+instance Functor ScState where
+  fmap = liftM
+
+instance Applicative ScState where
+  pure  = return
+  (<*>) = ap
+
+instance Monad (ScState) where
+    return x = ScState (\screen -> (screen, x))
+
+    (ScState st) >>= f
+        = ScState (\screen -> let
+                            (newScreen, y) = st screen
+                            (ScState transformer) = f y
+                            in
+                            transformer newScreen)
+
+doInstructions [] = return 0
+doInstructions (i:is) = 
+    do doInstruction i
+       doInstructions is
+       return 0
+
+doInstruction i = ScState (execute i)
+
+execute (Rect w h) screen = (rect screen w h, 0)
+execute (Rotate Column c n) screen = (rotateColumn screen c n, 0)
+execute (Rotate Row r n) screen = (rotateRow screen r n, 0)
+
+extractScreen (ScState st) = fst (st screen0)
+
+parseCommands :: String -> Either ParseError [Command]
+parseCommands input = parse commandFile "(unknown)" input
+
+commandFile = commandLine `endBy` newline
+commandLine = (try rectCommand) <|> rotateCommand
+
+rectCommand = 
+    do  string "rect"
+        spaces
+        w <- (many1 digit)
+        char 'x'
+        h <- (many1 digit)
+        return (Rect (read w) (read h))
+
+rotateCommand = 
+    do  string "rotate"
+        spaces
+        direction <- (string "row" <|> string "column")
+        spaces
+        string "x=" <|> string "y="
+        index <- (many1 digit)
+        spaces
+        string "by"
+        spaces
+        distance <- (many1 digit)
+        return (buildCommand direction index distance)
+
+buildCommand "row" i d = Rotate Row (read i) (read d)
+buildCommand "column" i d = Rotate Column (read i) (read d)
+
+successfulParse :: Either ParseError [a] -> [a]
+successfulParse (Left _) = []
+successfulParse (Right a) = a
+
+
+
+
+rect :: Screen -> Int -> Int -> Screen
+rect screen w h = screen // newBits
+    where newBits = [((i, j), True) | i <- [0..(h-1)], j <- [0..(w-1)]]
+
+rotateColumn :: Screen -> Int -> Int -> Screen
+rotateColumn screen column givenShift = screen // newCells
+    where 
+        ((minRow, minCol), (maxRow, maxCol)) = bounds screen
+        colLength = 1 + maxRow - minRow
+        shift = givenShift `mod` colLength
+        offset = colLength - shift
+        column0 = [screen!(r, column) | r <- [minRow..maxRow]]
+        newColumn = (drop offset column0) ++ (take offset column0)
+        newCells = [((r, column), cell) | (r, cell) <- zip [minRow..maxRow] newColumn]
+
+rotateRow :: Screen -> Int -> Int -> Screen
+rotateRow screen row givenShift = screen // newCells
+    where 
+        ((minRow, minCol), (maxRow, maxCol)) = bounds screen
+        rowLength = 1 + maxCol - minCol
+        shift = givenShift `mod` rowLength
+        offset = rowLength - shift
+        row0 = [screen!(row, c) | c <- [minCol..maxCol]]
+        newRow = (drop offset row0) ++ (take offset row0)
+        newCells = [((row, c), cell) | (c, cell) <- zip [minCol..maxCol] newRow]
diff --git a/advent08.txt b/advent08.txt
new file mode 100644 (file)
index 0000000..e6aa6a1
--- /dev/null
@@ -0,0 +1,193 @@
+rect 1x1
+rotate row y=0 by 5
+rect 1x1
+rotate row y=0 by 5
+rect 1x1
+rotate row y=0 by 5
+rect 1x1
+rotate row y=0 by 5
+rect 1x1
+rotate row y=0 by 2
+rect 1x1
+rotate row y=0 by 2
+rect 1x1
+rotate row y=0 by 3
+rect 1x1
+rotate row y=0 by 3
+rect 2x1
+rotate row y=0 by 2
+rect 1x1
+rotate row y=0 by 3
+rect 2x1
+rotate row y=0 by 2
+rect 1x1
+rotate row y=0 by 3
+rect 2x1
+rotate row y=0 by 5
+rect 4x1
+rotate row y=0 by 5
+rotate column x=0 by 1
+rect 4x1
+rotate row y=0 by 10
+rotate column x=5 by 2
+rotate column x=0 by 1
+rect 9x1
+rotate row y=2 by 5
+rotate row y=0 by 5
+rotate column x=0 by 1
+rect 4x1
+rotate row y=2 by 5
+rotate row y=0 by 5
+rotate column x=0 by 1
+rect 4x1
+rotate column x=40 by 1
+rotate column x=27 by 1
+rotate column x=22 by 1
+rotate column x=17 by 1
+rotate column x=12 by 1
+rotate column x=7 by 1
+rotate column x=2 by 1
+rotate row y=2 by 5
+rotate row y=1 by 3
+rotate row y=0 by 5
+rect 1x3
+rotate row y=2 by 10
+rotate row y=1 by 7
+rotate row y=0 by 2
+rotate column x=3 by 2
+rotate column x=2 by 1
+rotate column x=0 by 1
+rect 4x1
+rotate row y=2 by 5
+rotate row y=1 by 3
+rotate row y=0 by 3
+rect 1x3
+rotate column x=45 by 1
+rotate row y=2 by 7
+rotate row y=1 by 10
+rotate row y=0 by 2
+rotate column x=3 by 1
+rotate column x=2 by 2
+rotate column x=0 by 1
+rect 4x1
+rotate row y=2 by 13
+rotate row y=0 by 5
+rotate column x=3 by 1
+rotate column x=0 by 1
+rect 4x1
+rotate row y=3 by 10
+rotate row y=2 by 10
+rotate row y=0 by 5
+rotate column x=3 by 1
+rotate column x=2 by 1
+rotate column x=0 by 1
+rect 4x1
+rotate row y=3 by 8
+rotate row y=0 by 5
+rotate column x=3 by 1
+rotate column x=2 by 1
+rotate column x=0 by 1
+rect 4x1
+rotate row y=3 by 17
+rotate row y=2 by 20
+rotate row y=0 by 15
+rotate column x=13 by 1
+rotate column x=12 by 3
+rotate column x=10 by 1
+rotate column x=8 by 1
+rotate column x=7 by 2
+rotate column x=6 by 1
+rotate column x=5 by 1
+rotate column x=3 by 1
+rotate column x=2 by 2
+rotate column x=0 by 1
+rect 14x1
+rotate row y=1 by 47
+rotate column x=9 by 1
+rotate column x=4 by 1
+rotate row y=3 by 3
+rotate row y=2 by 10
+rotate row y=1 by 8
+rotate row y=0 by 5
+rotate column x=2 by 2
+rotate column x=0 by 2
+rect 3x2
+rotate row y=3 by 12
+rotate row y=2 by 10
+rotate row y=0 by 10
+rotate column x=8 by 1
+rotate column x=7 by 3
+rotate column x=5 by 1
+rotate column x=3 by 1
+rotate column x=2 by 1
+rotate column x=1 by 1
+rotate column x=0 by 1
+rect 9x1
+rotate row y=0 by 20
+rotate column x=46 by 1
+rotate row y=4 by 17
+rotate row y=3 by 10
+rotate row y=2 by 10
+rotate row y=1 by 5
+rotate column x=8 by 1
+rotate column x=7 by 1
+rotate column x=6 by 1
+rotate column x=5 by 1
+rotate column x=3 by 1
+rotate column x=2 by 2
+rotate column x=1 by 1
+rotate column x=0 by 1
+rect 9x1
+rotate column x=32 by 4
+rotate row y=4 by 33
+rotate row y=3 by 5
+rotate row y=2 by 15
+rotate row y=0 by 15
+rotate column x=13 by 1
+rotate column x=12 by 3
+rotate column x=10 by 1
+rotate column x=8 by 1
+rotate column x=7 by 2
+rotate column x=6 by 1
+rotate column x=5 by 1
+rotate column x=3 by 1
+rotate column x=2 by 1
+rotate column x=1 by 1
+rotate column x=0 by 1
+rect 14x1
+rotate column x=39 by 3
+rotate column x=35 by 4
+rotate column x=20 by 4
+rotate column x=19 by 3
+rotate column x=10 by 4
+rotate column x=9 by 3
+rotate column x=8 by 3
+rotate column x=5 by 4
+rotate column x=4 by 3
+rotate row y=5 by 5
+rotate row y=4 by 5
+rotate row y=3 by 33
+rotate row y=1 by 30
+rotate column x=48 by 1
+rotate column x=47 by 5
+rotate column x=46 by 5
+rotate column x=45 by 1
+rotate column x=43 by 1
+rotate column x=38 by 3
+rotate column x=37 by 3
+rotate column x=36 by 5
+rotate column x=35 by 1
+rotate column x=33 by 1
+rotate column x=32 by 5
+rotate column x=31 by 5
+rotate column x=30 by 1
+rotate column x=23 by 4
+rotate column x=22 by 3
+rotate column x=21 by 3
+rotate column x=20 by 1
+rotate column x=12 by 2
+rotate column x=11 by 2
+rotate column x=3 by 5
+rotate column x=2 by 5
+rotate column x=1 by 3
+rotate column x=0 by 4
diff --git a/day08.html b/day08.html
new file mode 100644 (file)
index 0000000..b871666
--- /dev/null
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 8 - Advent of Code 2016</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" type="text/css" href="/static/style.css?8"/>
+<link rel="shortcut icon" href="/favicon.ico?2"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  The best surprises don't
+even appear in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not Google, and I can only take
+so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, ads, social media),
+I built the whole thing myself, including the design, animations, prose, and
+all of the puzzles.
+
+The puzzles probably took the longest; the easiest ones were around 45 minutes
+each, but the harder ones took 2-3 hours, and a few even longer than that. A
+lot of effort went into building this thing - I hope you're enjoying playing it
+as much as I enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2016/about">[About]</a></li><li><a href="/2016/support">[AoC++]</a></li><li><a href="/2016/events">[Events]</a></li><li><a href="/2016/settings">[Settings]</a></li><li><a href="/2016/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <span class="supporter">(AoC++)</span> <span class="star-count">16*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">/^</span><a href="/2016">2016</a><span class="title-event-wrap">$/</span></h1><nav><ul><li><a href="/2016">[Calendar]</a></li><li><a href="/2016/leaderboard">[Leaderboard]</a></li><li><a href="/2016/stats">[Stats]</a></li><li><a href="/2016/sponsors">[Sponsors]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2016/sponsors">sponsors</a> help make AoC possible:</div><p><a href="https://www.detroitlabs.com/careers" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);">Detroit Labs</a> - Build beautiful mobile apps.</p></div>
+<div id="ad">
+<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- Advent of Code Wide Skyscraper -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:160px;height:600px"
+     data-ad-client="ca-pub-9420604735624631"
+     data-ad-slot="8014013294"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script>
+</div><!--/ad-->
+</div><!--/sidebar-->
+
+<main>
+<article class="day-desc"><h2>--- Day 8: Two-Factor Authentication ---</h2><p>You come across a door implementing what you can only assume is an implementation of <a href="https://en.wikipedia.org/wiki/Multi-factor_authentication">two-factor authentication</a> after a long game of <a href="https://en.wikipedia.org/wiki/Requirement">requirements</a> <a href="https://en.wikipedia.org/wiki/Chinese_whispers">telephone</a>.</p>
+<p>To get past the door, you first swipe a keycard (no problem; there was one on a nearby desk). Then, it displays a code on a <a href="https://www.google.com/search?q=tiny+lcd&tbm=isch">little screen</a>, and you type that code on a keypad. Then, presumably, the door unlocks.</p>
+<p>Unfortunately, the screen has been <span title="BUT BY WHOM?!">smashed</span>. After a few minutes, you've taken everything apart and figured out how it works. Now you just have to work out what the screen <em>would</em> have displayed.</p>
+<p>The magnetic strip on the card you swiped encodes a series of instructions for the screen; these instructions are your puzzle input. The screen is <em><code>50</code> pixels wide and <code>6</code> pixels tall</em>, all of which start <em>off</em>, and is capable of three somewhat peculiar operations:</p>
+<ul>
+<li><code>rect AxB</code> turns <em>on</em> all of the pixels in a rectangle at the top-left of the screen which is <code>A</code> wide and <code>B</code> tall.</li>
+<li><code>rotate row y=A by B</code> shifts all of the pixels in row <code>A</code> (0 is the top row) <em>right</em> by <code>B</code> pixels. Pixels that would fall off the right end appear at the left end of the row.</li>
+<li><code>rotate column x=A by B</code> shifts all of the pixels in column <code>A</code> (0 is the left column) <em>down</em> by <code>B</code> pixels. Pixels that would fall off the bottom appear at the top of the column.</li>
+</ul>
+<p>For example, here is a simple sequence on a smaller screen:</p>
+<ul>
+<li><p><code>rect 3x2</code> creates a small rectangle in the top-left corner:</p><pre><code>###....
+###....
+.......</code></pre></li>
+<li><p><code>rotate column x=1 by 1</code> rotates the second column down by one pixel:</p><pre><code>#.#....
+###....
+.#.....</code></pre></li>
+<li><p><code>rotate row y=0 by 4</code> rotates the top row right by four pixels:</p><pre><code>....#.#
+###....
+.#.....</code></pre></li>
+<li><p><code>rotate column x=1 by 1</code> again rotates the second column down by one pixel, causing the bottom pixel to wrap back to the top:</p><pre><code>.#..#.#
+#.#....
+.#.....</code></pre></li>
+</ul>
+<p>As you can see, this display technology is extremely powerful, and will soon dominate the tiny-code-displaying-screen market.  That's what the advertisement on the back of the display tries to convince you, anyway.</p>
+<p>There seems to be an intermediate check of the voltage used by the display: after you swipe your card, if the screen did work, <em>how many pixels should be lit?</em></p>
+</article>
+<p>Your puzzle answer was <code>119</code>.</p><article class="day-desc"><h2>--- Part Two ---</h2><p>You notice that the screen is only capable of displaying capital letters; in the font it uses, each letter is <code>5</code> pixels wide and <code>6</code> tall.</p>
+<p>After you swipe your card, <em>what code is the screen trying to display?</em></p>
+</article>
+<p>Your puzzle answer was <code>ZFHFSFOGPO</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p>
+<p>At this point, you should <a href="/2016">return to your advent calendar</a> and try another puzzle.</p>
+<p>If you still want to see it, you can <a href="8/input" target="_blank">get your puzzle input</a>.</p>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Two%2DFactor+Authentication%22+%2D+Day+8+%2D+Advent+of+Code+2016&amp;url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F8&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="https://plus.google.com/share?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F8" target="_blank">Google+</a>
+  <a href="http://www.reddit.com/submit?url=http%3A%2F%2Fadventofcode%2Ecom%2F2016%2Fday%2F8&amp;title=I%27ve+completed+%22Two%2DFactor+Authentication%22+%2D+Day+8+%2D+Advent+of+Code+2016" target="_blank">Reddit</a
+></span>]</span> this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file