blob: 0c962ab693d71046d0f1fa20f1d72f7d6f3bd228 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
import Control.Monad
import Data.Bits (xor)
import Data.Char
import Data.List
import Numeric
strip :: String -> String
strip = dropWhile isSpace . reverse . dropWhile isSpace . reverse
splitOn :: Eq a => a -> [a] -> [[a]]
splitOn _ [] = []
splitOn ch str = case break (== ch) str of
(pre, ch' : post) | ch' == ch -> pre : splitOn ch post
(pre, _) -> [pre]
rotate :: Int -> [a] -> [a]
rotate num l = take (length l) (drop num (cycle l))
blocks :: Int -> [a] -> [[a]]
blocks _ [] = []
blocks n l = let (pre, post) = splitAt n l in pre : blocks n post
pad :: Int -> a -> [a] -> [a]
pad len x list = replicate (len - length list) x ++ list
tie' :: [a] -> [Int] -> Int -> [a]
tie' chain [] _ = chain
tie' chain (len : lens) skip =
let (sub, rest) = splitAt len chain
in tie' (rotate skip (rest ++ reverse sub)) lens (skip + 1)
tie :: [a] -> [Int] -> [a]
tie chain lens =
let chainlen = length chain
numlens = length lens
backnum = chainlen - (sum lens + numlens * (numlens - 1) `div` 2) `mod` chainlen
in rotate backnum (tie' chain lens 0)
part1 :: IO ()
part1 = do
let chainlen = 256
lenlist <- liftM (map read . splitOn ',') (readFile "10.in")
let result = tie [0..chainlen-1] lenlist
print (let (a:b:_) = result in a * b)
part2 :: IO ()
part2 = do
let chainlen = 256
lenlist <- liftM ((++ [17, 31, 73, 47, 23]) . map ord . strip) (readFile "10.in")
let sparse = tie [0..chainlen-1] (take (64 * length lenlist) (cycle lenlist))
let dense = map (foldl1 xor) (blocks 16 sparse) :: [Int]
putStrLn $ concat $ map (pad 2 '0' . flip showHex "") dense
main :: IO ()
main = part1 >> part2
|