summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kjetil.orbekk@gmail.com>2019-12-15 08:53:28 -0500
committerKjetil Orbekk <kjetil.orbekk@gmail.com>2019-12-15 08:53:28 -0500
commitb27ede6524ea8794dd8a95213d1861cd9ff2d745 (patch)
tree5557bc28ebce3468814107c27631036cdd84cfba
parentcaa8efb96982f7db378ba1e8ee467040fa25e896 (diff)
Moons
-rw-r--r--advent/Cargo.toml11
-rw-r--r--advent/src/12.rs113
2 files changed, 124 insertions, 0 deletions
diff --git a/advent/Cargo.toml b/advent/Cargo.toml
new file mode 100644
index 0000000..46c4fb0
--- /dev/null
+++ b/advent/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "advent"
+version = "0.1.0"
+authors = ["Kjetil Orbekk <kjetil.orbekk@gmail.com>"]
+edition = "2018"
+
+[[bin]]
+name = "12"
+path = "src/12.rs"
+
+[dependencies]
diff --git a/advent/src/12.rs b/advent/src/12.rs
new file mode 100644
index 0000000..4eefad0
--- /dev/null
+++ b/advent/src/12.rs
@@ -0,0 +1,113 @@
+use std::fmt;
+
+#[derive(Debug)]
+struct Moon {
+ position: (i64, i64, i64),
+ velocity: (i64, i64, i64),
+}
+
+fn sign(x: i64) -> i64 {
+ if x < 0 {
+ -1
+ } else if x > 0 {
+ 1
+ } else {
+ 0
+ }
+}
+
+impl Moon {
+ fn step(&self, moons: &Vec<Moon>) -> Moon {
+ let (x, y, z) = self.position;
+ let (mut gx, mut gy, mut gz) = self.velocity;
+ for moon in moons {
+ let (ox, oy, oz) = moon.position;
+ gx += sign(ox - x);
+ gy += sign(oy - y);
+ gz += sign(oz - z);
+ }
+ let position = (x + gx, y + gy, z + gz);
+ Moon { position: position, velocity: (gx, gy, gz) }
+ }
+
+ fn energy(&self) -> i64 {
+ let (x, y, z) = self.position;
+ let (p, q, r) = self.velocity;
+ (x.abs() + y.abs() + z.abs()) * (p.abs() + q.abs() + r.abs())
+ }
+}
+
+fn make_moon(x: i64, y: i64, z: i64) -> Moon {
+ Moon { position: (x, y, z), velocity: (0, 0, 0) }
+}
+
+impl fmt::Display for Moon {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let (x, y, z) = self.position;
+ let (p, q, r) = self.velocity;
+ write!(f, "pos=<x={:3}, y={:3}, z={:3}>, vel=<x={:3}, y={:3}, z={:3}>",
+ x, y, z, p, q, r)
+ }
+}
+
+#[derive(Debug)]
+struct Moons(Vec<Moon>);
+
+impl Moons {
+ fn step(&self) -> Moons {
+ Moons(self.0.iter().map(|m| m.step(&self.0)).collect())
+ }
+
+ fn energy(&self) -> i64 {
+ self.0.iter().map(|m| m.energy()).sum()
+ }
+}
+
+impl fmt::Display for Moons {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ for moon in &self.0 {
+ moon.fmt(f)?;
+ write!(f, "\n")?;
+ }
+ Ok(())
+ }
+}
+
+fn run_steps(mut m: Moons, steps: i64, debug: bool) {
+ for i in 0..steps {
+ if debug {
+ println!("After {} steps:", i);
+ println!("{}", m);
+ }
+ m = m.step()
+ }
+ println!("After {} steps:", steps);
+ println!("{}", m);
+ println!("energy={:3}", m.energy())
+}
+
+fn main() {
+ let _ex1 = Moons(vec!(
+ make_moon(-1, 0, 2),
+ make_moon(2, -10, -7),
+ make_moon(4, -8, 8),
+ make_moon(3, 5, -1),
+ ));
+ let _ex2 = Moons(vec!(
+ make_moon(-8, -10, 0),
+ make_moon(5, 5, 10),
+ make_moon(2, -7, 3),
+ make_moon(9, -8, -3),
+ ));
+ run_steps(_ex1, 10, true);
+ println!();
+ run_steps(_ex2, 1000, false);
+}
+
+// After 1000 steps:
+// pos=<x=-26, y= 45, z=-31>, vel=<x= 2, y= 17, z= 6>
+// pos=<x= 87, y= 23, z=-12>, vel=<x=-14, y=-13, z= 9>
+// pos=<x=-33, y= -2, z=-24>, vel=<x= -2, y=-15, z= -5>
+// pos=<x=-20, y=-86, z= 77>, vel=<x= 14, y= 11, z=-10>
+//
+// energy=14645