day12 task 2

This commit is contained in:
Johannes
2019-12-15 11:46:40 +01:00
parent 71d068ab2c
commit e8b911fac0
4 changed files with 95 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
mod tasks;
fn main() {
tasks::day14::run();
tasks::day12::run();
}

View File

@@ -1,3 +1,4 @@
use num_integer::Integer;
use regex::Regex;
#[allow(dead_code)]
@@ -14,10 +15,6 @@ pub fn run() {
Point { x, y, z }
})
.collect();
task1(input.clone());
}
fn task1(input: Vec<Point>) {
let moons: Vec<_> = input
.into_iter()
.map(|pos| Moon {
@@ -25,42 +22,84 @@ fn task1(input: Vec<Point>) {
vel: Point::new(0, 0, 0),
})
.collect();
let finals = (0..1000).fold(moons, |moons, _run| {
let gravities: Vec<Point> = moons
.iter()
.map(|base| {
moons.iter().fold(Point::new(0, 0, 0), |grav, other_moon| {
grav.add(base.pos.gravity(other_moon.pos))
})
})
.collect();
let moons = moons
.into_iter()
.zip(gravities.into_iter())
.map(|(mut moon, grav)| {
moon.vel = moon.vel.add(grav);
moon.pos = moon.pos.add(moon.vel);
moon
})
.collect();
//println!("{}: {:?}", run, moons);
moons
});
task1(moons.clone());
task2(moons.clone());
}
fn task1(moons: Vec<Moon>) {
let finals = (0..1000).fold(moons, |moons, _run| step(moons));
let energy: i32 = finals
.iter()
.map(|moon| moon.pos.energy() * moon.vel.energy())
.sum();
println!("Task 1: sum of energy is {}", energy);
//392 too low
}
#[derive(Debug)]
fn task2(moons: Vec<Moon>) {
let xstart: Vec<_> = moons.iter().map(|it| [it.pos.x, it.vel.x]).collect();
let ystart: Vec<_> = moons.iter().map(|it| [it.pos.y, it.vel.y]).collect();
let zstart: Vec<_> = moons.iter().map(|it| [it.pos.z, it.vel.z]).collect();
let result = (1 as usize..)
.scan((None, None, None, moons), |(dx, dy, dz, moons), run| {
let mut new_moons = step(moons.clone());
moons.clear();
moons.append(&mut new_moons);
let xv: Vec<_> = moons.iter().map(|it| [it.pos.x, it.vel.x]).collect();
let yv: Vec<_> = moons.iter().map(|it| [it.pos.y, it.vel.y]).collect();
let zv: Vec<_> = moons.iter().map(|it| [it.pos.z, it.vel.z]).collect();
if *dx == None && xv == xstart {
*dx = Some(run);
}
if *dy == None && yv == ystart {
*dy = Some(run);
}
if *dz == None && zv == zstart {
*dz = Some(run);
}
if dx.is_some() && dy.is_some() && dz.is_some() {
Some(Some((dx.unwrap(), dy.unwrap(), dz.unwrap())))
} else {
Some(None)
}
})
.find(|bla| bla.is_some());
if let Some(Some((x, y, z))) = result {
println!(
"Task 2: {:?} until a visited state is reached again",
x.lcm(&y.lcm(&z))
);
}
}
fn step(moons: Vec<Moon>) -> Vec<Moon> {
let gravities: Vec<Point> = moons
.iter()
.map(|base| {
moons.iter().fold(Point::new(0, 0, 0), |grav, other_moon| {
grav.add(base.pos.gravity(other_moon.pos))
})
})
.collect();
let moons = moons
.into_iter()
.zip(gravities.into_iter())
.map(|(mut moon, grav)| {
moon.vel = moon.vel.add(grav);
moon.pos = moon.pos.add(moon.vel);
moon
})
.collect();
moons
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
struct Moon {
pos: Point,
vel: Point,
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
struct Point {
x: i32,
y: i32,