1 module Main(main) where
3 import Data.ByteString.Char8 (pack)
4 import qualified Crypto.Hash as C
6 type Position = (Int, Int)
7 data Agendum = Agendum {position :: Position, path :: String, hash :: String} deriving (Show, Eq)
8 type Agenda = [Agendum]
13 input = "qljzarfv" -- my input
21 part1 = putStrLn $ path $ extractJust $ bfs initialAgenda
24 part2 = print $ bfs2 initialAgenda 0
26 initialAgenda :: Agenda
27 initialAgenda = [Agendum {position=(1, 1), path="", hash=(getHash "")}]
29 getHash :: String -> String
30 getHash path = show (C.hash $ pack (input ++ path) :: C.Digest C.MD5)
32 extractJust :: Maybe Agendum -> Agendum
33 extractJust Nothing = head initialAgenda
34 extractJust (Just x) = x
36 bfs :: Agenda -> Maybe Agendum
38 bfs (current:agenda) =
39 if isGoal current then Just current
40 else bfs (agenda ++ (successors current))
42 bfs2 :: Agenda -> Int -> Int
44 bfs2 (current:agenda) l =
45 if isGoal current then bfs2 agenda (length $ path $ current)
46 else bfs2 (agenda ++ (successors current)) l
48 isGoal :: Agendum -> Bool
49 isGoal agendum = (position agendum) == (4, 4)
51 isLegalPos :: Position -> Bool
52 isLegalPos p = fst p >= 1 && fst p <= 4 && snd p >= 1 && snd p <= 4
54 successors :: Agendum -> Agenda
55 successors state = [Agendum {position = step p0 ld,
57 hash = getHash (path0 ++ [ld])} | ld <- legalDoors ]
63 legalDoors = filter (isLegalPos . (step p0)) doors
65 openDoors :: String -> String
66 openDoors h = up ++ down ++ left ++ right
68 up = if h!!0 `elem` "bcdef" then "U" else ""
69 down = if h!!1 `elem` "bcdef" then "D" else ""
70 left = if h!!2 `elem` "bcdef" then "L" else ""
71 right = if h!!3 `elem` "bcdef" then "R" else ""
73 step :: Position -> Char -> Position
74 step (r, c) 'U' = (r-1, c)
75 step (r, c) 'D' = (r+1, c)
76 step (r, c) 'L' = (r, c-1)
77 step (r, c) 'R' = (r, c+1)