never executed always true always false
1 {-|
2 Module: Y2015.D11
3 Description: Advent of Code Day 11 Solutions.
4 License: MIT
5 Maintainer: @tylerjl
6
7 Solutions to the day 11 set of problems for <adventofcode.com>.
8 -}
9 module Y2015.D11
10 ( rotate
11 ) where
12
13 import Data.List (group, isInfixOf, tails)
14
15 import Y2015.Util ((<&&>))
16
17 alphabet :: String
18 alphabet = ['a' .. 'z']
19
20 meetsReqs :: String -> Bool
21 meetsReqs = hasPairs <&&> (not . forbidden) <&&> hasStraightFast
22
23 hasPairs :: String -> Bool
24 hasPairs = (1 <) . length . filter ((<) 1 . length) . group
25
26 forbidden :: String -> Bool
27 forbidden = any (`elem` ("iol" :: String))
28
29 hasStraightFast :: String -> Bool
30 hasStraightFast = not . null . filterAsc . subSeqs
31 where
32 filterAsc = filter (`isInfixOf` alphabet)
33 subSeqs = takeWhile ((== 3) . length) . map (take 3) . tails
34
35 increment :: String -> String
36 increment = reverse . step . reverse
37 where
38 step [] = []
39 step [x]
40 | x == 'z' = "aa"
41 | otherwise = [succ x]
42 step (x:xs)
43 | x /= 'z' = succ x : xs
44 | otherwise = 'a' : step xs
45
46 -- |Rotate a password within specific rules
47 rotate
48 :: String -- ^ Starting password
49 -> String -- ^ Next valid password
50 rotate = nextValid . increment
51 where
52 nextValid = head . filter meetsReqs . iterate increment