From b27ede6524ea8794dd8a95213d1861cd9ff2d745 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Sun, 15 Dec 2019 08:53:28 -0500 Subject: Moons --- advent/Cargo.toml | 11 ++++++ advent/src/12.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 advent/Cargo.toml create mode 100644 advent/src/12.rs 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 "] +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 { + 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=, vel=", + x, y, z, p, q, r) + } +} + +#[derive(Debug)] +struct Moons(Vec); + +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=, vel= +// pos=, vel= +// pos=, vel= +// pos=, vel= +// +// energy=14645 -- cgit v1.2.3