Skip to content

Commit 96f5ac1

Browse files
committed
day20
1 parent c697c31 commit 96f5ac1

File tree

3 files changed

+171
-10
lines changed

3 files changed

+171
-10
lines changed

day20/Program.fs

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,171 @@
1-
module Program = let [<EntryPoint>] main _ = 0
1+
open System.Diagnostics
2+
3+
open Xunit
4+
open FsUnit.Xunit
5+
6+
let findIndex2D (a: 'T[][]) (v: 'T) =
7+
List.allPairs [ 0 .. (a.Length - 1) ] [ 0 .. (a[0].Length - 1) ]
8+
|> List.find (fun (i, j) -> a[i][j] = v)
9+
10+
let bfs (si, sj) (maze: char[][]) =
11+
let transition (i, j) dist =
12+
let newNodes, newDist =
13+
(dist, [ (-1, 0); (0, -1); (1, 0); (0, 1) ])
14+
||> List.mapFold (fun dist (di, dj) ->
15+
let ni, nj = i + di, j + dj
16+
17+
if
18+
0 <= ni
19+
&& ni < maze.Length
20+
&& 0 <= nj
21+
&& nj < maze[ni].Length
22+
&& maze[ni][nj] <> '#'
23+
&& not (Map.containsKey (ni, nj) dist)
24+
then
25+
(Some(ni, nj), dist |> Map.add (ni, nj) (dist[(i, j)] + 1))
26+
else
27+
(None, dist))
28+
29+
(List.choose id newNodes, newDist)
30+
31+
let rec bfs' nodes dist =
32+
if List.isEmpty nodes then
33+
dist
34+
else
35+
let newNodes, newDist =
36+
(dist, nodes) ||> List.mapFold (fun dist node -> transition node dist)
37+
38+
bfs' (List.concat newNodes) newDist
39+
40+
bfs' [ (si, sj) ] (Map [ (si, sj), 0 ])
41+
42+
let part1 (maze: char[][]) =
43+
let si, sj = findIndex2D maze 'S'
44+
let gi, gj = findIndex2D maze 'E'
45+
46+
let dist = bfs (si, sj) maze
47+
48+
List.allPairs [ 0 .. (maze.Length - 1) ] [ 0 .. (maze[0].Length - 1) ]
49+
|> List.choose (fun (i, j) ->
50+
let tate =
51+
i >= 1 && i + 1 < maze.Length && maze[i - 1][j] <> '#' && maze[i + 1][j] <> '#'
52+
53+
let yoko =
54+
j >= 1
55+
&& j + 1 < maze[i].Length
56+
&& maze[i][j - 1] <> '#'
57+
&& maze[i][j + 1] <> '#'
58+
59+
if maze[i][j] = '#' && (tate || yoko) then
60+
maze[i][j] <- '.'
61+
let d = bfs (si, sj) maze
62+
maze[i][j] <- '#'
63+
64+
Some(dist[(gi, gj)] - d[(gi, gj)])
65+
else
66+
None)
67+
|> List.countBy id
68+
|> List.sort
69+
70+
let part2 (maze: char[][]) =
71+
let si, sj = findIndex2D maze 'S'
72+
73+
let dist = bfs (si, sj) maze
74+
75+
List.allPairs (Map.toList dist) (Map.toList dist)
76+
|> List.choose (fun (((i, j), d), ((i', j'), d')) ->
77+
let e = abs (i - i') + abs (j - j')
78+
if d' - d >= 0 && e <= 20 then Some(d' - d - e) else None)
79+
|> List.countBy id
80+
|> List.sort
81+
82+
let parse (input: string) =
83+
input.Split("\n") |> Array.map (fun line -> line.ToCharArray())
84+
85+
module Example =
86+
let input =
87+
"###############
88+
#...#...#.....#
89+
#.#.#.#.#.###.#
90+
#S#...#.#.#...#
91+
#######.#.#.###
92+
#######.#.#...#
93+
#######.#.###.#
94+
###..E#...#...#
95+
###.#######.###
96+
#...###...#...#
97+
#.#####.#.###.#
98+
#.#...#.#.#...#
99+
#.#.#.#.#.#.###
100+
#...#...#...###
101+
###############"
102+
103+
[<Fact>]
104+
let testPart1 () =
105+
parse input
106+
|> part1
107+
|> should
108+
be
109+
(supersetOf
110+
[ (2, 14)
111+
(4, 14)
112+
(6, 2)
113+
(8, 4)
114+
(10, 2)
115+
(12, 3)
116+
(20, 1)
117+
(36, 1)
118+
(38, 1)
119+
(40, 1)
120+
(64, 1) ])
121+
122+
[<Fact>]
123+
let testPart2 () =
124+
parse input
125+
|> part2
126+
|> should
127+
be
128+
(supersetOf
129+
[ (50, 32)
130+
(52, 31)
131+
(54, 29)
132+
(56, 39)
133+
(58, 25)
134+
(60, 23)
135+
(62, 20)
136+
(64, 19)
137+
(66, 12)
138+
(68, 14)
139+
(70, 12)
140+
(72, 22)
141+
(74, 4)
142+
(76, 3) ])
143+
144+
[<EntryPoint>]
145+
let main _ =
146+
let input = stdin.ReadToEnd().TrimEnd()
147+
let maze = parse input
148+
149+
let timer = Stopwatch()
150+
timer.Start()
151+
152+
maze
153+
|> part1
154+
|> Seq.sumBy (fun (save, ps) -> if save >= 100 then ps else 0)
155+
|> printfn "Part 1: %d"
156+
157+
timer.Stop()
158+
printfn "elapsed = %A" timer.Elapsed // 00:04:17.2126316
159+
160+
161+
timer.Restart()
162+
163+
maze
164+
|> part2
165+
|> Seq.sumBy (fun (save, ps) -> if save >= 100 then ps else 0)
166+
|> printfn "Part 2: %d"
167+
168+
timer.Stop()
169+
printfn "elapsed = %A" timer.Elapsed // 00:01:08.6627788
170+
171+
0

day20/Tests.fs

Lines changed: 0 additions & 8 deletions
This file was deleted.

day20/day20.fsproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<Compile Include="Tests.fs" />
1312
<Compile Include="Program.fs" />
1413
</ItemGroup>
1514

0 commit comments

Comments
 (0)