-
Notifications
You must be signed in to change notification settings - Fork 0
/
day23.hs
88 lines (74 loc) · 3.43 KB
/
day23.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
import Data.List
import Data.Maybe (fromJust)
import qualified Data.Array as A
import qualified Data.Graph as G
main :: IO ()
main = do
a1
a2
type XY = (Int,Int)
type Map = A.Array XY Char
type Links = G.Graph
getInput :: IO Map
getInput = do
content <- transpose . lines <$> readFile "y2023/inputs/d23"
let size = length content - 1
return (A.listArray ((0,0),(size,size)) (concat content))
createLinks :: Map -> (XY, XY, (Links, Int -> ([(XY,Int)], XY, [XY]), XY -> Maybe Int))
createLinks m = (start, end, G.graphFromEdges (travel <$> nodes))
where
(_,(w,h)) = A.bounds m
start = (1,0)
end = (w-1,h)
nodes = start : [(x,y) | ((x,y),c) <- A.assocs m, c == '.', 0 < x && x < w, 0 < y && y < h, length (filter (\nb -> m A.! nb `elem` "<>v") [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]) > 1] ++ [end]
travel :: XY -> ([(XY,Int)], XY, [XY])
travel xy@(x,y) = (paths, xy, map fst paths)
where
paths
| xy == start = [path xy (1,1) 1]
| xy == end = []
| otherwise = [path xy nb 1 | nb <- [(x+1,y),(x,y+1)], m A.! nb `elem` ">v"]
path :: XY -> XY -> Int -> (XY,Int)
path prev xy@(x,y) d | xy `elem` nodes = (xy,d)
| otherwise = path xy (head [nb | nb <- [(x-1,y),(x+1,y),(x,y-1),(x,y+1)], nb /= prev, m A.! nb /= '#']) (d+1)
dfs :: Int -> Int -> Links -> (Int -> Int -> Int) -> Int
dfs s e g dist = f [] s 0
where
f :: [Int] -> Int -> Int -> Int
f set i d | i == e = d
| otherwise = maximum $ [f (j:set) j (d + dist i j) | j <- g A.! i, j `notElem` set] ++ [0]
a1 :: IO ()
a1 = do
(start, end, (links, fromIdx, toIdx)) <- createLinks <$> getInput
let s = fromJust (toIdx start)
let e = fromJust (toIdx end)
let getDists (a,_,_) = a
let getXY (_,b,_) = b
let getEdgeDist a b = fromJust $ getXY (fromIdx b) `lookup` getDists (fromIdx a)
print $ dfs s e links getEdgeDist
a2 :: IO ()
a2 = do
(start, end, (links, fromIdx, toIdx)) <- createLinks' <$> getInput
let s = fromJust (toIdx start)
let e = fromJust (toIdx end)
let getDists (a,_,_) = a
let getXY (_,b,_) = b
let getEdgeDist a b = fromJust $ getXY (fromIdx b) `lookup` getDists (fromIdx a)
print $ dfs s e links getEdgeDist
createLinks' :: Map -> (XY, XY, (Links, Int -> ([(XY,Int)], XY, [XY]), XY -> Maybe Int))
createLinks' m = (start, end, G.graphFromEdges (travel <$> nodes))
where
(_,(w,h)) = A.bounds m
start = (1,0)
end = (w-1,h)
nodes = start : [(x,y) | ((x,y),c) <- A.assocs m, c == '.', 0 < x && x < w, 0 < y && y < h, length (filter (\nb -> m A.! nb `elem` "<>v") [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]) > 1] ++ [end]
travel :: XY -> ([(XY,Int)], XY, [XY])
travel xy@(x,y) = (paths, xy, map fst paths)
where
paths
| xy == start = [path xy (1,1) 1]
| xy == end = []
| otherwise = [path xy nb 1 | nb <- [(x+1,y),(x-1,y),(x,y-1),(x,y+1)], m A.! nb /= '#'] -- changed generator and condition
path :: XY -> XY -> Int -> (XY,Int)
path prev xy@(x,y) d | xy `elem` nodes = (xy,d)
| otherwise = path xy (head [nb | nb <- [(x-1,y),(x+1,y),(x,y-1),(x,y+1)], nb /= prev, m A.! nb /= '#']) (d+1)