-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDay24.hs
88 lines (72 loc) · 2.03 KB
/
Day24.hs
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module Main where
import Utilities
import Geometry
import Graph
import Data.List
import Data.Maybe
import Data.Map (Map, (!))
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
type Input = Maze
type NodeName = Char
data Maze = Maze { openPos :: Set Position, nodeLoc :: Map NodeName Position }
deriving Show
parse :: String -> Input
parse s = Maze {
openPos = Set.fromList [p | (p, c) <- pcs, c /= '#'],
nodeLoc = Map.fromList [(c, p) | (p, c) <- pcs, c /= '#' && c /= '.']
}
where
pcs = readGrid s
-- Part One --
neighbours :: Maze -> Position -> [Position]
neighbours m p =
[p' |
dp <- unitVectors,
let p' = p .+. dp,
Set.member p' (openPos m)]
nodes :: Maze -> [NodeName]
nodes m = Map.keys (nodeLoc m)
-- distances between nodes within the maze
type Graph = Map (NodeName, NodeName) Int
mkGraph :: Maze -> Graph
mkGraph m =
Map.fromList [((src, dest), dist) |
src <- nodes m,
(dist, ns) <- zip [0..] (bfs (neighbours m) [nodeLoc m!src]),
n <- ns,
dest <- maybeToList (Map.lookup n nodeOf)]
where
nodeOf = Map.fromList [(p, n) | (n, p) <- Map.assocs (nodeLoc m)]
startNode :: NodeName
startNode = '0'
solve1 :: Input -> Int
solve1 m = minimum (map cost (permutations other_ns))
where
cost path = sum [g!e | e <- zip (startNode:path) path]
other_ns = filter (/= startNode) (nodes m)
g = mkGraph m
testInput :: String
testInput =
"###########\n\
\#0.1.....2#\n\
\#.#######.#\n\
\#4.......3#\n\
\###########\n"
tests1 :: [(String, Int)]
tests1 = [(testInput, 14)]
-- Part Two --
solve2 :: Input -> Int
solve2 m = minimum (map cost (permutations other_ns))
where
cost path = sum [g!e | e <- zip (startNode:path) (path ++ [startNode])]
other_ns = filter (/= startNode) (nodes m)
g = mkGraph m
main :: IO ()
main = do
s <- readFile "input/24.txt"
let input = parse s
putStr (unlines (failures "solve1" (solve1 . parse) tests1))
print (solve1 input)
print (solve2 input)