diff options
author | Kjetil Orbekk <kjetil.orbekk@gmail.com> | 2019-12-15 08:53:28 -0500 |
---|---|---|
committer | Kjetil Orbekk <kjetil.orbekk@gmail.com> | 2019-12-15 08:53:28 -0500 |
commit | b27ede6524ea8794dd8a95213d1861cd9ff2d745 (patch) | |
tree | 5557bc28ebce3468814107c27631036cdd84cfba /advent | |
parent | caa8efb96982f7db378ba1e8ee467040fa25e896 (diff) |
Moons
Diffstat (limited to 'advent')
-rw-r--r-- | advent/Cargo.toml | 11 | ||||
-rw-r--r-- | advent/src/12.rs | 113 |
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 |