X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=app%2Fadvent08.hs;fp=app%2Fadvent08.hs;h=0000000000000000000000000000000000000000;hb=fd498a2713d69a5d55179ff07e58ce296d6fba94;hp=ccf2de0f735e28b21e7115ab22f8186447ef9e7d;hpb=3a26b187d5dc23b05fb73daabe52a92976a7a3c7;p=advent-of-code-16.git diff --git a/app/advent08.hs b/app/advent08.hs deleted file mode 100644 index ccf2de0..0000000 --- a/app/advent08.hs +++ /dev/null @@ -1,148 +0,0 @@ -module Main(main) where - -import Data.Array.IArray -import Text.Parsec -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 :: Screen -screen0 = mkScreen 50 6 - - -main :: IO () -main = do - text <- readFile "data/advent08.txt" - let instrs = successfulParse $ parseCommands text - part1 instrs - part2 instrs - -part1 :: [Command] -> IO () -part1 commands = - print $ countLights $ (extractScreen . doCommands) commands - -part2 :: [Command] -> IO () -part2 commands = - putStrLn $ showScreen $ (extractScreen . doCommands) commands - - -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) - -doCommands :: [Command] -> ScState (Int) -doCommands [] = return 0 -doCommands (i:is) = - do doCommand i - doCommands is - return 0 - -doCommand :: Command -> ScState Int -doCommand i = ScState (execute i) - -execute :: Command -> (Screen -> (Screen, Int)) -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 Int -> Screen -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]