aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2019-12-12 23:17:30 +0100
committerReiner Herrmann <reiner@reiner-h.de>2019-12-14 20:42:54 +0100
commit37c19114cda1f6987658874b36c430bf13846d24 (patch)
treee44f3aa96a25fbe636ee5c824ae48857b26a2fce /src/main.rs
parent9876a09b9069da056fabe75d81486601cb1ede4c (diff)
day12
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs126
1 files changed, 125 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs
index e482946..c0fa47d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -933,8 +933,132 @@ fn day11() {
}
}
+#[derive(PartialEq, Eq, Clone, Copy)]
+struct Position {
+ x: isize,
+ y: isize,
+ z: isize,
+}
+
+#[derive(PartialEq, Eq, Clone, Copy)]
+struct Moon {
+ pos: Position,
+ velocity: Position,
+}
+
+impl Moon {
+ fn new(x: isize, y: isize, z: isize) -> Moon {
+ Moon {
+ pos: Position { x, y, z },
+ velocity: Position { x: 0, y: 0, z: 0 },
+ }
+ }
+
+ fn apply_gravity(&mut self, other: &Moon) {
+ self.velocity.x += (other.pos.x - self.pos.x).signum();
+ self.velocity.y += (other.pos.y - self.pos.y).signum();
+ self.velocity.z += (other.pos.z - self.pos.z).signum();
+ }
+
+ fn update_position(&mut self) {
+ self.pos.x += self.velocity.x;
+ self.pos.y += self.velocity.y;
+ self.pos.z += self.velocity.z;
+ }
+
+ fn potential_energy(&self) -> isize {
+ self.pos.x.abs() + self.pos.y.abs() + self.pos.z.abs()
+ }
+
+ fn kinetic_energy(&self) -> isize {
+ self.velocity.x.abs() + self.velocity.y.abs() + self.velocity.z.abs()
+ }
+
+ fn total_energy(&self) -> isize {
+ self.potential_energy() * self.kinetic_energy()
+ }
+}
+
+fn simulate_moons(moons: &mut Vec<Moon>) {
+ for i in 0..moons.len() {
+ for j in 0..moons.len() {
+ let other = moons[j].clone();
+ moons[i].apply_gravity(&other);
+ }
+ }
+ for moon in moons {
+ moon.update_position();
+ }
+}
+
+fn gcd(a: isize, b: isize) -> isize {
+ if b == 0 {
+ a
+ } else {
+ gcd(b, a % b)
+ }
+}
+
+fn lcm(a: isize, b: isize) -> isize {
+ (a*b).abs() / gcd(a, b)
+}
+
+fn day12() {
+ let initial_state = vec![
+ Moon::new(17, -9, 4),
+ Moon::new( 2, 2, -13),
+ Moon::new(-1, 5, -1),
+ Moon::new( 4, 7, -7),
+ ];
+ let mut moons = initial_state.clone();
+
+ for _ in 0..1000 {
+ simulate_moons(&mut moons);
+ }
+
+ let total_energy: isize = moons.iter()
+ .map(|moon| moon.total_energy())
+ .sum();
+ println!("12a: {}", total_energy);
+
+ let mut period_x = 0;
+ let initial_x_values: Vec<(isize, isize)> = moons.iter().map(|moon| (moon.pos.x, moon.velocity.x)).collect();
+ loop {
+ period_x += 1;
+ simulate_moons(&mut moons);
+ let x_values: Vec<(isize, isize)> = moons.iter().map(|moon| (moon.pos.x, moon.velocity.x)).collect();
+ if x_values == initial_x_values {
+ break;
+ }
+ }
+
+ let mut period_y = 0;
+ let initial_y_values: Vec<(isize, isize)> = moons.iter().map(|moon| (moon.pos.y, moon.velocity.y)).collect();
+ loop {
+ period_y += 1;
+ simulate_moons(&mut moons);
+ let y_values: Vec<(isize, isize)> = moons.iter().map(|moon| (moon.pos.y, moon.velocity.y)).collect();
+ if y_values == initial_y_values {
+ break;
+ }
+ }
+
+ let mut period_z = 0;
+ let initial_z_values: Vec<(isize, isize)> = moons.iter().map(|moon| (moon.pos.z, moon.velocity.z)).collect();
+ loop {
+ period_z += 1;
+ simulate_moons(&mut moons);
+ let z_values: Vec<(isize, isize)> = moons.iter().map(|moon| (moon.pos.z, moon.velocity.z)).collect();
+ if z_values == initial_z_values {
+ break;
+ }
+ }
+
+ println!("12b: {}", lcm(lcm(period_x, period_y), period_z));
+}
+
fn main() {
- day11();
+ day12();
}
#[cfg(test)]