summary refs log tree commit diff stats
path: root/day20.fsx
diff options
context:
space:
mode:
Diffstat (limited to 'day20.fsx')
-rw-r--r--day20.fsx71
1 files changed, 71 insertions, 0 deletions
diff --git a/day20.fsx b/day20.fsx
new file mode 100644
index 0000000..e357986
--- /dev/null
+++ b/day20.fsx
@@ -0,0 +1,71 @@
+open System.IO
+open System.Text.RegularExpressions
+
+type Vector =
+    struct
+        val mutable x: int
+        val mutable y: int
+        val mutable z: int
+        new(X, Y, Z) = {x=X; y=Y; z=Z}
+
+        member this.add(other: Vector) =
+            this.x <- this.x + other.x
+            this.y <- this.y + other.y
+            this.z <- this.z + other.z
+        
+        member this.manhattan() =
+            abs this.x + abs this.y + abs this.z
+        
+        override this.ToString() =
+            sprintf "(%d, %d, %d)" this.x this.y this.z
+    end
+
+type Projectile =
+    struct
+        val id: int
+        val mutable position: Vector
+        val mutable velocity: Vector
+        val acceleration:     Vector
+        new(ID, pos, vel, acc) = {id=ID; position=pos; velocity=vel; acceleration=acc}
+
+        member this.update() =
+            this.velocity.add(this.acceleration)
+            this.position.add(this.velocity)
+            this
+
+        member this.distance() =
+            this.velocity.manhattan()
+
+        override this.ToString() =
+            sprintf "p=%A v=%A a=%A" this.position this.velocity this.acceleration
+    end
+
+let parseInput i str =
+    let m = Regex("(-?\d+)").Matches(str)
+    let values = [for g in m -> int g.Value]
+    if List.length values <> 9 then printfn "%A" values; failwith "invalid input"
+    Projectile(i, Vector(values[0], values[1], values[2]), 
+                  Vector(values[3], values[4], values[5]), 
+                  Vector(values[6], values[7], values[8]))
+
+let part1() =
+    let mutable projectiles = File.ReadAllLines "day20.txt" |> Array.mapi parseInput
+    // assume that 1000 simulations is good enough
+    for i = 1 to 1000 do
+        projectiles <- Array.map (fun (x: Projectile) -> x.update()) projectiles
+    Array.minBy (fun (x: Projectile) -> x.distance()) projectiles |> (fun x -> x.id) |> printfn "%d"
+
+let part2() =
+    let mutable projectiles = File.ReadAllLines "day20.txt" |> Array.mapi parseInput
+    for i = 1 to 1000 do
+        projectiles <- Array.map (fun (x: Projectile) -> x.update()) projectiles
+        let uncollided = Array.groupBy (fun (x: Projectile) -> x.position) projectiles
+                         |> Array.filter (fun (pos, xs) -> Array.length xs = 1)
+                         |> Array.map snd
+                         |> Array.fold Array.append Array.empty
+        projectiles <- uncollided
+    Array.length projectiles |> printfn "%d"
+
+let () =
+    part1()
+    part2()
\ No newline at end of file