-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day17.fs
103 lines (81 loc) · 2.62 KB
/
Day17.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
namespace Adventofcode2021
module Day17 =
[<Literal>]
let InputFile = "Day17Input.txt"
type TargetArea =
{ xStart: int
xEnd: int
yStart: int
yEnd: int }
let parse (s: string) =
let regex = System.Text.RegularExpressions.Regex(@"([-]?\d)+")
let matches = regex.Matches(s)
{ xStart = int matches.[0].Value
xEnd = int matches.[1].Value
yStart = int matches.[2].Value
yEnd = int matches.[3].Value }
let step (xPos, yPos) (xVel, yVel) =
let xPos' = xPos + xVel
let yPos' = yPos + yVel
let xVel' =
if xVel > 0 then xVel - 1
else if xVel < 0 then xVel + 1
else xVel
let yVel' = yVel - 1
(xPos', yPos'), (xVel', yVel')
type PositionJudgement =
| InTargetArea
| InFlight
| Overshoot
let judgePosition targetArea (xPos, yPos) =
if targetArea.xStart <= xPos
&& xPos <= targetArea.xEnd
&& targetArea.yStart <= yPos
&& yPos <= targetArea.yEnd then
InTargetArea
else if yPos < targetArea.yStart then
Overshoot
else
InFlight
let shoot pos velocity targetArea =
let rec helper pos velocity targetArea yPath =
let pos', velocity' = step pos velocity
let yPath' = List.append yPath [ snd pos' ]
match judgePosition targetArea pos' with
| InTargetArea -> yPath' |> List.max |> Some
| InFlight -> helper pos' velocity' targetArea yPath'
| Overshoot -> None
helper pos velocity targetArea List.empty
let findVelocity targetArea =
let startPos = (0, 0)
seq {
for x in 0..300 do
for y in 0..300 do
let r = shoot startPos (x, y) targetArea
match r with
| Some y -> yield y
| None -> ()
}
|> Seq.max
let day17 () =
InputFile
|> System.IO.File.ReadAllText
|> parse
|> findVelocity
let findDistinctVelocities targetArea =
let startPos = (0, 0)
seq {
for x in 0..400 do
for y in -200..400 do
let r = shoot startPos (x, y) targetArea
match r with
| Some _ -> yield (x, y)
| None -> ()
}
|> Seq.distinct
|> Seq.length
let day17Part2 () =
InputFile
|> System.IO.File.ReadAllText
|> parse
|> findDistinctVelocities