From 58e320e3cc4380974109c2ad5b27a7cb10c32a46 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Sun, 10 Dec 2017 12:26:50 +0100 Subject: Day 10 That was a really long description. Fun hash though. --- 2017/10.hs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2017/10.in | 1 + 2 files changed, 60 insertions(+) create mode 100644 2017/10.hs create mode 100644 2017/10.in (limited to '2017') diff --git a/2017/10.hs b/2017/10.hs new file mode 100644 index 0000000..0c962ab --- /dev/null +++ b/2017/10.hs @@ -0,0 +1,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 diff --git a/2017/10.in b/2017/10.in new file mode 100644 index 0000000..70508ac --- /dev/null +++ b/2017/10.in @@ -0,0 +1 @@ +230,1,2,221,97,252,168,169,57,99,0,254,181,255,235,167 -- cgit v1.2.3-70-g09d2