Working version
[advent-of-code-16.git] / advent14.hs
1 import Data.List (nub, tails, null)
2 import Data.Hash.MD5 (md5s, Str(..))
3
4 salt = "yjdafjpo"
5 -- salt = "abc"
6
7 main :: IO ()
8 main = do
9 part1
10 part2
11
12 part1 :: IO ()
13 part1 = print $ head $ drop 63 $ filter (\i -> possibleKey sq i && confirmKey sq i) [0..]
14 where sq = md5sequence
15
16 part2 :: IO ()
17 part2 = print $ head $ drop 63 $ filter (\i -> possibleKey sq i && confirmKey sq i) [0..]
18 where sq = md5sequenceS
19
20 md5sequence :: [String]
21 md5sequence = [makeMd5 i | i <- [0..]]
22 where makeMd5 i = md5s (Str (salt ++ show i))
23
24 md5sequenceS :: [String]
25 md5sequenceS = [makeMd5 i | i <- [0..]]
26 where makeMd5 i = stretch $ md5s (Str (salt ++ show i))
27 stretch h0 = foldr (\_ h -> md5s (Str h)) h0 [1..2016]
28
29 possibleKey :: [String] -> Int-> Bool
30 possibleKey s = not . null . repeats 3 . ((!!) s)
31
32 confirmKey :: [String] -> Int -> Bool
33 confirmKey s i = any (confirmation) $ take 1000 $ drop (i+1) s
34 where c = head $ repeats 3 $ s!!i
35 confirmation m = c `elem` (repeats 5 m)
36
37 repeats :: Int -> String -> [String]
38 repeats n = filter (null . tail) . map (nub) . substrings n
39
40 substrings :: Int -> [a] -> [[a]]
41 substrings l = filter (\s -> (length s) == l) . map (take l) . tails