From: Neil Smith Date: Fri, 9 Dec 2016 15:32:05 +0000 (+0000) Subject: Day 8 X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=d2d274d6990859e8d32f7f7416fcd7d6c062b6ea;p=advent-of-code-16.git Day 8 --- diff --git a/advent08.hs b/advent08.hs new file mode 100644 index 0000000..0c5987c --- /dev/null +++ b/advent08.hs @@ -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 index 0000000..e6aa6a1 --- /dev/null +++ b/advent08.txt @@ -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 index 0000000..b871666 --- /dev/null +++ b/day08.html @@ -0,0 +1,158 @@ + + + + +Day 8 - Advent of Code 2016 + + + + + + +

Advent of Code

Neil Smith (AoC++) 16*

      /^2016$/

+ + + +
+

--- Day 8: Two-Factor Authentication ---

You come across a door implementing what you can only assume is an implementation of two-factor authentication after a long game of requirements telephone.

+

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 little screen, and you type that code on a keypad. Then, presumably, the door unlocks.

+

Unfortunately, the screen has been smashed. 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 would have displayed.

+

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 50 pixels wide and 6 pixels tall, all of which start off, and is capable of three somewhat peculiar operations:

+
    +
  • rect AxB turns on all of the pixels in a rectangle at the top-left of the screen which is A wide and B tall.
  • +
  • rotate row y=A by B shifts all of the pixels in row A (0 is the top row) right by B pixels. Pixels that would fall off the right end appear at the left end of the row.
  • +
  • rotate column x=A by B shifts all of the pixels in column A (0 is the left column) down by B pixels. Pixels that would fall off the bottom appear at the top of the column.
  • +
+

For example, here is a simple sequence on a smaller screen:

+
    +
  • rect 3x2 creates a small rectangle in the top-left corner:

    ###....
    +###....
    +.......
  • +
  • rotate column x=1 by 1 rotates the second column down by one pixel:

    #.#....
    +###....
    +.#.....
  • +
  • rotate row y=0 by 4 rotates the top row right by four pixels:

    ....#.#
    +###....
    +.#.....
  • +
  • rotate column x=1 by 1 again rotates the second column down by one pixel, causing the bottom pixel to wrap back to the top:

    .#..#.#
    +#.#....
    +.#.....
  • +
+

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.

+

There seems to be an intermediate check of the voltage used by the display: after you swipe your card, if the screen did work, how many pixels should be lit?

+
+

Your puzzle answer was 119.

--- Part Two ---

You notice that the screen is only capable of displaying capital letters; in the font it uses, each letter is 5 pixels wide and 6 tall.

+

After you swipe your card, what code is the screen trying to display?

+
+

Your puzzle answer was ZFHFSFOGPO.

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