Day 10
[advent-of-code-17.git] / src / advent10 / advent10.hs
1 import Data.List.Split (splitOn, chunksOf)
2 import Data.Char (ord)
3 import Data.Bits (xor)
4 import Text.Printf (printf)
5
6 main :: IO ()
7 main = do
8 text <- readFile "data/advent10.txt"
9 let ls = map read $ splitOn "," text
10 print $ part1 ls
11 putStrLn $ part2 text
12
13
14 part1 :: [Int] -> Int
15 part1 lengths = (tied!!0) * (tied!!1)
16 where (tied, _, _) = foldl step ([0..255], 0, 0) lengths
17
18
19 part2 :: String -> String
20 part2 text = densify tied
21 where lengths = p2lengths text
22 (tied, _, _) = foldl step ([0..255], 0, 0) lengths
23
24 step :: ([Int], Int, Int) -> Int -> ([Int], Int, Int)
25 step (original, start, skip) len = (replaced, start', skip + 1)
26 where replaced = tie original start len
27 start' = (start + len + skip) `mod` (length original)
28
29 tie :: [a] -> Int -> Int -> [a]
30 tie original start len = replace original replacement start
31 where replacement = reverse $ extract original start len
32
33 extract :: [a] -> Int -> Int -> [a]
34 extract items from len = take len $ drop from $ items ++ items
35
36 replace :: [a] -> [a] -> Int -> [a]
37 replace original replacement from = take (length original) (start ++ replacement ++ remainder)
38 where excess = drop (length original - from) replacement
39 stub = drop (length excess) original
40 start = take from (excess ++ stub)
41 remainder = drop (length $ start ++ replacement) original
42
43
44 p2lengths :: String -> [Int]
45 p2lengths text = take (length chunk * 64) $ cycle chunk
46 where chunk = map ord text ++ [17, 31, 73, 47, 23]
47
48 densify :: [Int] -> String
49 densify ns = concatMap (printf "%02x") codes
50 where chunks = chunksOf 16 ns
51 compress = foldl1 xor
52 codes = map compress chunks