-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day11.fs
123 lines (99 loc) · 3.67 KB
/
Day11.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
namespace Adventofcode2021
module Day11 =
[<Literal>]
let InputFile = "Day11Input.txt"
let incAll (octopuses: int [] []) =
octopuses
|> Array.map (fun line -> line |> Array.map (fun x -> x + 1))
let getNeighbours (octopuses: int [] []) (x, y) =
let maxX = octopuses.[0].Length - 1
let maxY = octopuses.Length - 1
[ (x - 1, y - 1)
(x, y - 1)
(x + 1, y - 1)
(x + 1, y)
(x + 1, y + 1)
(x, y + 1)
(x - 1, y + 1)
(x - 1, y) ]
|> List.filter (fun (x, y) -> 0 <= x && x <= maxX && 0 <= y && y <= maxY)
let incNeighbours octopuses (x, y) =
let neighbours = getNeighbours octopuses (x, y)
for (x, y) in neighbours do
octopuses.[y].[x] <- octopuses.[y].[x] + 1
octopuses
let rec incFlashNeighbours octopuses flashers =
match flashers with
| p :: rest ->
let octopuses' = incNeighbours octopuses p
incFlashNeighbours octopuses' rest
| [] -> octopuses
let rec flash (octopuses: int [] []) alreadyFlashed =
let maxX = octopuses.[0].Length - 1
let maxY = octopuses.Length - 1
let flashers =
seq {
for y in 0..maxY do
for x in 0..maxX do
if
octopuses.[y].[x] >= 10
&& not (List.contains (x, y) alreadyFlashed)
then
(x, y)
}
|> Seq.toList
if Seq.isEmpty flashers then
octopuses
else
let octopuses' = incFlashNeighbours octopuses flashers
let alreadyFlashed' = List.append flashers alreadyFlashed
flash octopuses' alreadyFlashed'
let countFlashers (octopuses: int [] []) =
let maxX = octopuses.[0].Length - 1
let maxY = octopuses.Length - 1
seq {
for y in 0..maxY do
for x in 0..maxX do
if octopuses.[y].[x] >= 10 then 1
}
|> Seq.sum
let resetFlashers (octopuses: int [] []) =
let maxX = octopuses.[0].Length - 1
let maxY = octopuses.Length - 1
for y in 0..maxY do
for x in 0..maxX do
if octopuses.[y].[x] >= 10 then
octopuses.[y].[x] <- 0
octopuses
let rec step n flashes octopuses =
if n = 0 then
flashes
else
let octopuses' = incAll octopuses
let octopuses'' = flash octopuses' List.empty
let flashesOfStep = countFlashers octopuses''
let flashes' = flashes + flashesOfStep
let octopuses''' = resetFlashers octopuses''
step (n - 1) flashes' octopuses'''
let day11 () =
InputFile
|> System.IO.File.ReadAllLines
|> Array.map (fun line -> line.ToCharArray() |> Array.map (string >> int))
|> step 100 0
let runTillSync (octopuses: int [] []) =
let octopusesCount = octopuses.Length * octopuses.[0].Length
let rec step n octopuses =
let octopuses' = incAll octopuses
let octopuses'' = flash octopuses' List.empty
let flashesOfStep = countFlashers octopuses''
let octopuses''' = resetFlashers octopuses''
if flashesOfStep = octopusesCount then
n
else
step (n + 1) octopuses'''
step 1 octopuses
let day11Part2 () =
InputFile
|> System.IO.File.ReadAllLines
|> Array.map (fun line -> line.ToCharArray() |> Array.map (string >> int))
|> runTillSync