summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-12-10 12:26:50 +0100
committertomsmeding <tom.smeding@gmail.com>2017-12-10 12:26:50 +0100
commit58e320e3cc4380974109c2ad5b27a7cb10c32a46 (patch)
tree67d7f785b93cd1b6acfe707aa5f96fa8b68f627f
parentc02550850331a9b3b8f70a722aabdd74c446ce84 (diff)
Day 10
That was a really long description. Fun hash though.
-rw-r--r--2017/10.hs59
-rw-r--r--2017/10.in1
2 files changed, 60 insertions, 0 deletions
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