-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday24_part02.fs
104 lines (85 loc) · 3.05 KB
/
day24_part02.fs
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
module day24_part02
open AdventOfCode_2016.Modules
open AdventOfCode_Utilities.Utilities
open System.Collections.Generic
type CellKind =
| Empty
| Wall
type Cell = {
Row: int
Col: int
Kind: CellKind
}
type CheckPoint = {
Name: int
Pos: Cell
}
let parseContent(lines: string array) =
let (maxrows, maxcols) = (lines.Length, lines[0].Length)
let map = Array2D.init maxrows maxcols (fun r c -> { Row = r; Col = c; Kind = Empty })
let checkpoints =
[for row in 0..maxrows-1 do
for col in 0..maxcols-1 do
if lines[row][col] = '#' then
map[row, col] <- { map[row, col] with Kind = Wall }
elif lines[row][col] <> '.' then
let name = (lines[row][col]).ToString()
yield { Name = (int)name; Pos = map[row, col] }
]
(map, checkpoints)
let findShortestPath (graph: Cell[,]) (start: Cell) (goal: Cell) =
let maxRows = graph.GetLength(0)
let maxCols = graph.GetLength(1)
let isInBoundaries (row: int) (col: int) =
row >= 0 && col >= 0 && row < maxRows && col < maxCols
let directions = [ (-1, 0); (1, 0); (0, 1); (0, -1) ]
let queue = Queue<Cell * int>()
let visited = HashSet<Cell>()
queue.Enqueue((start, 0))
let rec bfs () =
if queue.Count = 0 then None
else
let (current, path) = queue.Dequeue()
if current = goal then
Some(path)
else
if not (visited.Contains(current)) && current.Kind.IsEmpty then
let _ = visited.Add(current)
for (dRow, dCol) in directions do
let nextRow = current.Row + dRow
let nextCol = current.Col + dCol
if isInBoundaries nextRow nextCol then
let neighbor = graph[nextRow, nextCol]
if not (visited.Contains(neighbor)) then
queue.Enqueue((neighbor, path+1))
bfs ()
bfs ()
let findAllWays(map: Cell[,]) (checkpoints: CheckPoint list) =
let memoLengths = Dictionary<(CheckPoint*CheckPoint), int>()
combination 2 checkpoints
|> List.iter(fun c ->
let (start, goal) = (c.Item(0), c.Item(1))
let distance = findShortestPath map start.Pos goal.Pos
memoLengths.Add((start, goal), distance.Value)
memoLengths.Add((goal, start), distance.Value)
)
let startzero = checkpoints |> List.find(fun c -> c.Name = 0)
let possiblepaths =
permutations checkpoints
|> List.filter(fun p ->
p.Item(0).Name = 0
)
possiblepaths
|> List.map(fun p ->
List.pairwise (p @ [startzero])
|> List.map(fun (s, g) ->
memoLengths[(s, g)]
)
|> List.sum
)
|> List.min
let execute =
let path = "day24/day24_input.txt"
let content = LocalHelper.GetLinesFromFile path
let (map, checkpoints) = parseContent content
findAllWays map checkpoints