-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday17_part01.fs
159 lines (133 loc) · 4.46 KB
/
day17_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
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
module day17_part01
open AdventOfCode_2022.Modules
type JetsState = { Pattern: char array; Index: int }
with member this.Next () =
{ this with Index = (this.Index + 1) % this.Pattern.Length }
member this.Current = this.Pattern[this.Index]
type Figure = uint8 list
let inline (>>) figure shift = List.map (fun y -> y >>> shift) figure
let inline (<<) figure shift = List.map (fun y -> y <<< shift) figure
let figures = [|
[
0b0011110uy
]
[
0b0001000uy
0b0011100uy
0b0001000uy
]
[
0b0000100uy
0b0000100uy
0b0011100uy
]
[
0b0010000uy
0b0010000uy
0b0010000uy
0b0010000uy
]
[
0b0011000uy
0b0011000uy
]
|]
type FiguresState = { Figures: Figure array; Index : int }
with member this.Next() =
{ this with Index = (this.Index + 1) % this.Figures.Length }
member this.Current = this.Figures[this.Index]
type FallingState = { Figure : Figure; Position: int }
type State = {
RestedFiguresCount: int64
TowerHeight: int64
Rested: Figure;
Figures: FiguresState
Jets: JetsState;
Falling: FallingState
}
let jet (state : State) =
let { Falling = falling } = state
let newFalling =
match state.Jets.Current with
| '>' ->
if (List.exists (fun x -> x &&& 0b0000001uy <> 0uy) falling.Figure)
then falling
else {falling with Figure = falling.Figure >> 1}
| '<' ->
if (List.exists (fun x -> x &&& 0b1000000uy <> 0uy) falling.Figure)
then falling
else {falling with Figure = falling.Figure << 1}
{ state with Falling = newFalling }
let gravity (state : State) =
{ state with Falling = { state.Falling with Position = state.Falling.Position + 1} }
let private revertIfCollision (state : State) (requestedState : State) =
let { Falling = { Figure = figure; Position = pos } } = requestedState
let figureHeight = List.length figure
if (List.length state.Rested - pos < figureHeight)
then state
else
let collision =
state.Rested |> List.skip pos |> List.take figureHeight
|> List.zip figure
|> List.map (fun (x,y) -> x &&& y)
|> List.exists ((<>)0uy)
if collision then state
else requestedState
let checkCollision (f : State -> State) =
fun state ->
let newState = f state
revertIfCollision state newState
let fix state =
let { Falling = { Figure = figure; Position = pos } } = state
let figureHeight = List.length figure
let (before, rest1) = List.splitAt pos state.Rested
let (atFalling, rest) = List.splitAt figureHeight rest1
let newRested =
atFalling
|> List.zip figure
|> List.map (fun (x,y) -> x ||| y)
let heightIncrease =
atFalling |> List.filter ((=)0uy) |> List.length
{
state with Rested = before @ newRested @ rest;
TowerHeight = state.TowerHeight + int64 heightIncrease;
RestedFiguresCount = state.RestedFiguresCount + 1L;
}
let newFigure s =
let figures = s.Figures.Next();
let newRested =
s.Rested
|> List.skipWhile ((=)0uy)
|> List.append (List.replicate (figures.Current.Length + 3) 0uy)
{ s with Rested = newRested; Figures = figures; Falling = { Figure = figures.Current; Position = 0 }}
let nextState state =
let afterJet = state |> checkCollision jet
let afterGravity = afterJet |> checkCollision gravity
if (afterJet.Falling = afterGravity.Falling)
then
{ (afterJet |> fix |> newFigure) with Jets = state.Jets.Next(); }
else
{ afterGravity with Jets = state.Jets.Next()}
let infiniteStates initial =
Seq.unfold (fun s -> let newS = nextState s in Some(newS, newS)) initial
let stateDefaultActual jets =
{
Rested = [
0uy
0uy
0uy
0uy
]
RestedFiguresCount = 0
TowerHeight = 0
Figures = { Figures = figures; Index = 0}
Jets = { Pattern = jets; Index = 0}
Falling = { Figure = figures[0]; Position = 0 }
}
let totalHeight jets =
let state = stateDefaultActual jets
(infiniteStates state |> Seq.find (fun s -> s.RestedFiguresCount = 2022L)).TowerHeight
let execute =
let path = "day17/day17_input.txt"
let jets = (LocalHelper.GetContentFromFile path).ToCharArray()
totalHeight jets