94669fd3b7ea54ac6e81f031cc2d2c853163f77b
[advent-of-code-16.git] / advent13.hs
1 import Data.List ((\\), nub, sortOn)
2 import Data.Bits (popCount)
3
4 type Pos = (Int, Int)
5
6 seed = 1362
7
8 goal1 = (31, 39)
9
10 main :: IO ()
11 main = do
12 part1
13 part2
14
15
16 part1 :: IO ()
17 part1 = print $ length $ tail $ extractJust $ aStar [[(1, 1)]] []
18
19 part2 :: IO ()
20 part2 = do print $ length $ tail $ edl 50 [[(1, 1)]] []
21 putStrLn $ showRoomR 30 25 $ edl 50 [[(1, 1)]] []
22
23
24 extractJust :: Maybe [a] -> [a]
25 extractJust Nothing = []
26 extractJust (Just x) = x
27
28 isWall :: Int -> Int -> Bool
29 isWall x y = (popCount n) `mod` 2 == 1
30 where
31 n = x*x + 3*x + 2*x*y + y + y*y + seed
32
33
34 showRoom w h = showRoomR w h []
35
36 showRoomR w h reached = unlines rows
37 where
38 rows = [row x | x <- [0..h]]
39 row x = [showCell x y | y <- [0..w]]
40 showCell x y = if (isWall x y)
41 then '#'
42 else if (x, y) `elem` reached
43 then 'O'
44 else '.'
45
46
47 aStar :: [[Pos]] -> [Pos] -> Maybe [Pos]
48 aStar [] _ = Nothing
49 aStar (currentTrail:trails) closed =
50 if isGoal (head currentTrail) then Just currentTrail
51 else if (head currentTrail) `elem` closed then aStar trails closed
52 else aStar newAgenda ((head currentTrail): closed)
53 where newAgenda =
54 sortOn (\a -> trailCost a) $
55 trails ++ (candidates currentTrail closed)
56 trailCost t = estimateCost (head t) + length t - 1
57
58
59 -- exhaustive depth-limited
60 edl :: Int -> [[Pos]] -> [Pos] -> [Pos]
61 edl _ [] closed = nub closed
62 edl limit (currentTrail:trails) closed =
63 if (length currentTrail) > (limit+1) then edl limit trails ((head currentTrail):closed)
64 else if (head currentTrail) `elem` closed then edl limit trails closed
65 else edl limit newAgenda ((head currentTrail):closed)
66 where newAgenda = trails ++ (candidates currentTrail closed)
67
68 candidates :: [Pos] -> [Pos] -> [[Pos]]
69 candidates currentTrail closed = newCandidates
70 where
71 (candidate:trail) = currentTrail
72 succs = legalSuccessors $ successors candidate
73 nonloops = (succs \\ trail) \\ closed
74 newCandidates = map (\n -> n:candidate:trail) nonloops
75
76 isGoal :: Pos -> Bool
77 isGoal p = p == goal1
78
79 isLegal :: Pos -> Bool
80 isLegal (x, y) =
81 x >= 0 && y >= 0 && (not $ isWall x y)
82
83 successors :: Pos -> [Pos]
84 successors (x, y) = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
85
86 legalSuccessors :: [Pos] -> [Pos]
87 legalSuccessors = filter (isLegal)
88
89 estimateCost :: Pos -> Int
90 estimateCost (x, y) = abs (x - gx) + abs (y - gy)
91 where (gx, gy) = goal1
92