-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday23_part01.fs
70 lines (58 loc) · 2.3 KB
/
day23_part01.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
module day23_part01
open System.Collections.Generic
open AdventOfCode_2023.Modules
type Coord = {
Row: int
Col: int
Dir: int
}
let numOfDirs = 4
let rowDirs = [| -1; 0; 1; 0 |]
let colDirs = [| 0; 1; 0; -1 |]
let directions = [| '^'; '>'; 'v'; '<' |]
let parseInput (lines: string list) =
let map = Array2D.create (lines.Length) (lines.Head.Length) '.'
for row in 0..lines.Length - 1 do
for col in 0..lines.Head.Length - 1 do
map.[row, col] <- lines.[row].[col]
map
let execute =
//let path = "day23/test_input_01.txt"
let path = "day23/day23_input.txt"
let map = LocalHelper.GetLinesFromFile path |> List.ofSeq |> parseInput
let queue = new Queue<Coord>()
let distances = new Dictionary<(int*int*int), int>()
let addDistance (row: int) (col: int) (dir: int) (distance: int) =
let key = (row, col, dir)
if not (distances.ContainsKey(key)) then
distances.Add(key, distance) |> ignore
else
distances[key] <- distance
queue.Enqueue({ Row = row; Col = col; Dir = dir }) |> ignore
let isValidPosition (row: int) (col: int) =
0 <= row && row < map.GetLength(0) && 0 <= col && col < map.GetLength(1) && map.[row, col] <> '#'
let isOpposite (dir1: int) (dir2: int) =
(dir1 ^^^ dir2) = 2
addDistance 0 1 2 0
while queue.Count > 0 do
let coord = queue.Dequeue()
let currentDistance = distances[(coord.Row, coord.Col, coord.Dir)]
let el = map.[coord.Row, coord.Col]
let dirIdx =
match Array.tryFindIndex (fun c -> c = el) directions with
| Some i -> i
| None -> -1
for d in 0..numOfDirs - 1 do
if not ((isOpposite d coord.Dir) || (dirIdx >= 0 && d <> dirIdx)) then
let newRow = coord.Row + rowDirs.[d]
let newCol = coord.Col + colDirs.[d]
if isValidPosition newRow newCol then
addDistance newRow newCol d (currentDistance + 1)
let longestDistance =
distances
|> Seq.filter (fun keyvalue ->
let (row, col, _) = keyvalue.Key
row = map.GetLength(0) - 1 && col = map.GetLength(1) - 2)
|> Seq.map (fun keyvalue -> keyvalue.Value)
|> Seq.max
longestDistance