summaryrefslogtreecommitdiff
path: root/2015/day11.hs
blob: f3c05b338af1564f944371cf2cf90c40410f4de9 (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
module Main where

import Data.Char
import Numeric

pairs :: String -> [(Char,Char)]
pairs (a:b:cs) = (a,b) : pairs (b:cs)
pairs _ = []

allEqual :: (Eq a) => [a] -> Bool
allEqual (a:b:cs) = if a /= b then False else allEqual (b:cs)
allEqual _ = True


hasStraight :: String -> Bool
hasStraight (a:b:c:ds) = (y == x + 1 && z == x + 2) || hasStraight (b:c:ds)
    where (x,y,z) = (ord a,ord b,ord c)
hasStraight _ = False

hasForbidden :: String -> Bool
hasForbidden [] = False
hasForbidden (x:xs) = x /= 'i' && x /= 'o' && x /= 'l' && not (hasForbidden xs)

hasTwoPairs :: String -> Bool
hasTwoPairs s = (not.allEqual) $ filter (\(a,b) -> a == b) (pairs s)

isValid :: String -> Bool
isValid s = hasStraight s && not (hasForbidden s) && hasTwoPairs s


show26 :: Int -> String
show26 n = showIntAtBase 26 (\d -> chr (97 + d)) n ""

read26 :: String -> Int
read26 = fst . head . readInt 26 (\c -> let o = ord c in 97 <= o && o <= 122) (\c -> ord c - 97)

pad :: Int -> Char -> String -> String
pad n c s = if length s < n then pad n c (c:s) else s


nextpass :: String -> String
nextpass s = pad (length s) 'a' $ show26 $ succ $ read26 s

nextvalidpass :: String -> String
nextvalidpass = head . dropWhile (not . isValid) . iterate nextpass


day11 :: IO ()
day11 = do
  print $ nextvalidpass $ nextpass $ nextvalidpass "cqjxjnds"

main = day11