Completed day 12
This commit is contained in:
parent
79645abe5a
commit
b189630416
143
day12/Cargo.lock
generated
Normal file
143
day12/Cargo.lock
generated
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "day12"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-bigint 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"thread_local 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||||
|
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
|
||||||
|
"checksum num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
|
||||||
|
"checksum num-bigint 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f115de20ad793e857f76da2563ff4a09fbcfd6fe93cca0c5d996ab5f3ee38d"
|
||||||
|
"checksum num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
|
||||||
|
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||||
|
"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
|
||||||
|
"checksum num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3"
|
||||||
|
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||||
|
"checksum regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87"
|
||||||
|
"checksum regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90"
|
||||||
|
"checksum thread_local 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88ddf1ad580c7e3d1efff877d972bcc93f995556b9087a5a259630985c88ceab"
|
12
day12/Cargo.toml
Normal file
12
day12/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "day12"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Tyler Hallada <tyler@hallada.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
num = "0.2.1"
|
||||||
|
regex = "1.3.3"
|
4
day12/input/input.txt
Normal file
4
day12/input/input.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x=3, y=2, z=-6>
|
||||||
|
<x=-13, y=18, z=10>
|
||||||
|
<x=-8, y=-1, z=13>
|
||||||
|
<x=5, y=10, z=4>
|
4
day12/input/test1.txt
Normal file
4
day12/input/test1.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x=-1, y=0, z=2>
|
||||||
|
<x=2, y=-10, z=-7>
|
||||||
|
<x=4, y=-8, z=8>
|
||||||
|
<x=3, y=5, z=-1>
|
4
day12/input/test2.txt
Normal file
4
day12/input/test2.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x=-8, y=-10, z=0>
|
||||||
|
<x=5, y=5, z=10>
|
||||||
|
<x=2, y=-7, z=3>
|
||||||
|
<x=9, y=-8, z=-3>
|
418
day12/src/main.rs
Normal file
418
day12/src/main.rs
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{prelude::*, BufReader};
|
||||||
|
use std::ops::AddAssign;
|
||||||
|
use std::ops::Index;
|
||||||
|
use std::result;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use num::integer::lcm;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
type Result<T> = result::Result<T, Box<dyn Error>>;
|
||||||
|
|
||||||
|
const INPUT: &str = "input/input.txt";
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
|
struct Vector {
|
||||||
|
x: i64,
|
||||||
|
y: i64,
|
||||||
|
z: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
|
struct Body {
|
||||||
|
position: Vector,
|
||||||
|
velocity: Vector,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
|
struct NBody {
|
||||||
|
bodies: Vec<Body>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Body {
|
||||||
|
type Err = Box<dyn Error>;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Body> {
|
||||||
|
lazy_static! {
|
||||||
|
static ref RE: Regex =
|
||||||
|
Regex::new(r"<x=(?P<x>-?\d+), y=(?P<y>-?\d+), z=(?P<z>-?\d+)>").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let captures = match RE.captures(s) {
|
||||||
|
None => {
|
||||||
|
return Err(From::from("Malformed scan, no positions could be found"));
|
||||||
|
}
|
||||||
|
Some(captures) => captures,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Body {
|
||||||
|
position: Vector {
|
||||||
|
x: captures["x"].parse()?,
|
||||||
|
y: captures["y"].parse()?,
|
||||||
|
z: captures["z"].parse()?,
|
||||||
|
},
|
||||||
|
velocity: Vector::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vector {
|
||||||
|
fn new() -> Vector {
|
||||||
|
Vector { x: 0, y: 0, z: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign for Vector {
|
||||||
|
fn add_assign(&mut self, other: Self) {
|
||||||
|
*self = Self {
|
||||||
|
x: self.x + other.x,
|
||||||
|
y: self.y + other.y,
|
||||||
|
z: self.z + other.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<&str> for Vector {
|
||||||
|
type Output = i64;
|
||||||
|
|
||||||
|
fn index(&self, index: &str) -> &i64 {
|
||||||
|
match index {
|
||||||
|
"x" => &self.x,
|
||||||
|
"y" => &self.y,
|
||||||
|
"z" => &self.z,
|
||||||
|
_ => panic!("unknown field: {}", index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Body {
|
||||||
|
fn add_gravity(&self, gravity: &mut Vector, other: &Self) {
|
||||||
|
if self.position.x > other.position.x {
|
||||||
|
gravity.x -= 1;
|
||||||
|
} else if self.position.x < other.position.x {
|
||||||
|
gravity.x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.position.y > other.position.y {
|
||||||
|
gravity.y -= 1;
|
||||||
|
} else if self.position.y < other.position.y {
|
||||||
|
gravity.y += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.position.z > other.position.z {
|
||||||
|
gravity.z -= 1;
|
||||||
|
} else if self.position.z < other.position.z {
|
||||||
|
gravity.z += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NBody {
|
||||||
|
fn run_step(&mut self) {
|
||||||
|
let mut gravities = Vec::new();
|
||||||
|
for body in self.bodies.iter() {
|
||||||
|
let mut gravity = Vector::new();
|
||||||
|
for other_body in self.bodies.iter() {
|
||||||
|
body.add_gravity(&mut gravity, other_body);
|
||||||
|
}
|
||||||
|
gravities.push(gravity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, gravity) in gravities.into_iter().enumerate() {
|
||||||
|
self.bodies[index].velocity += gravity;
|
||||||
|
let velocity = self.bodies[index].velocity;
|
||||||
|
self.bodies[index].position += velocity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn total_energy(&self) -> i64 {
|
||||||
|
let mut total_energy = 0;
|
||||||
|
for body in self.bodies.iter() {
|
||||||
|
let potential_energy =
|
||||||
|
body.position.x.abs() + body.position.y.abs() + body.position.z.abs();
|
||||||
|
let kinetic_energy =
|
||||||
|
body.velocity.x.abs() + body.velocity.y.abs() + body.velocity.z.abs();
|
||||||
|
total_energy += potential_energy * kinetic_energy;
|
||||||
|
}
|
||||||
|
total_energy
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state(&self, component: &str) -> [(i64, i64); 4] {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
self.bodies[0].position[component],
|
||||||
|
self.bodies[0].velocity[component],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
self.bodies[1].position[component],
|
||||||
|
self.bodies[1].velocity[component],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
self.bodies[2].position[component],
|
||||||
|
self.bodies[2].velocity[component],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
self.bodies[3].position[component],
|
||||||
|
self.bodies[3].velocity[component],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_moon_scan(filename: &str) -> Result<NBody> {
|
||||||
|
let file = File::open(filename)?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
let mut moons = vec![];
|
||||||
|
|
||||||
|
for line in reader.lines() {
|
||||||
|
moons.push(line?.parse()?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(NBody { bodies: moons })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_part1(filename: &str) -> Result<i64> {
|
||||||
|
let mut nbody = read_moon_scan(filename)?;
|
||||||
|
for _ in 0..1000 {
|
||||||
|
nbody.run_step();
|
||||||
|
}
|
||||||
|
Ok(nbody.total_energy())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_part2(filename: &str) -> Result<u64> {
|
||||||
|
let mut step_count = 0;
|
||||||
|
let mut x_states: HashSet<[(i64, i64); 4]> = HashSet::new();
|
||||||
|
let mut y_states: HashSet<[(i64, i64); 4]> = HashSet::new();
|
||||||
|
let mut z_states: HashSet<[(i64, i64); 4]> = HashSet::new();
|
||||||
|
let mut x_repeated_step_count = None;
|
||||||
|
let mut y_repeated_step_count = None;
|
||||||
|
let mut z_repeated_step_count = None;
|
||||||
|
let mut nbody = read_moon_scan(filename)?;
|
||||||
|
while x_repeated_step_count == None
|
||||||
|
|| y_repeated_step_count == None
|
||||||
|
|| z_repeated_step_count == None
|
||||||
|
{
|
||||||
|
if x_repeated_step_count == None {
|
||||||
|
let x_state = nbody.state("x");
|
||||||
|
if x_states.contains(&x_state) {
|
||||||
|
x_repeated_step_count = Some(step_count);
|
||||||
|
} else {
|
||||||
|
x_states.insert(x_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if y_repeated_step_count == None {
|
||||||
|
let y_state = nbody.state("y");
|
||||||
|
if y_states.contains(&y_state) {
|
||||||
|
y_repeated_step_count = Some(step_count);
|
||||||
|
} else {
|
||||||
|
y_states.insert(y_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if z_repeated_step_count == None {
|
||||||
|
let z_state = nbody.state("z");
|
||||||
|
if z_states.contains(&z_state) {
|
||||||
|
z_repeated_step_count = Some(step_count);
|
||||||
|
} else {
|
||||||
|
z_states.insert(z_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbody.run_step();
|
||||||
|
step_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(lcm(
|
||||||
|
x_repeated_step_count.unwrap(),
|
||||||
|
lcm(
|
||||||
|
y_repeated_step_count.unwrap(),
|
||||||
|
z_repeated_step_count.unwrap(),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
println!("Part 1: {}", solve_part1(INPUT)?);
|
||||||
|
println!("Part 2: {}", solve_part2(INPUT)?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const TEST_INPUT1: &str = "input/test1.txt";
|
||||||
|
const TEST_INPUT2: &str = "input/test2.txt";
|
||||||
|
fn nbody_1() -> NBody {
|
||||||
|
NBody {
|
||||||
|
bodies: vec![
|
||||||
|
Body {
|
||||||
|
position: Vector { x: -1, y: 0, z: 2 },
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector {
|
||||||
|
x: 2,
|
||||||
|
y: -10,
|
||||||
|
z: -7,
|
||||||
|
},
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 4, y: -8, z: 8 },
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 3, y: 5, z: -1 },
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn nbody_1_after_10_steps() -> NBody {
|
||||||
|
NBody {
|
||||||
|
bodies: vec![
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 2, y: 1, z: -3 },
|
||||||
|
velocity: Vector { x: -3, y: -2, z: 1 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 1, y: -8, z: 0 },
|
||||||
|
velocity: Vector { x: -1, y: 1, z: 3 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 3, y: -6, z: 1 },
|
||||||
|
velocity: Vector { x: 3, y: 2, z: -3 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 2, y: 0, z: 4 },
|
||||||
|
velocity: Vector { x: 1, y: -1, z: -1 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn nbody_2() -> NBody {
|
||||||
|
NBody {
|
||||||
|
bodies: vec![
|
||||||
|
Body {
|
||||||
|
position: Vector {
|
||||||
|
x: -8,
|
||||||
|
y: -10,
|
||||||
|
z: 0,
|
||||||
|
},
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 5, y: 5, z: 10 },
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 2, y: -7, z: 3 },
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector { x: 9, y: -8, z: -3 },
|
||||||
|
velocity: Vector { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn nbody_2_after_100_steps() -> NBody {
|
||||||
|
NBody {
|
||||||
|
bodies: vec![
|
||||||
|
Body {
|
||||||
|
position: Vector {
|
||||||
|
x: 8,
|
||||||
|
y: -12,
|
||||||
|
z: -9,
|
||||||
|
},
|
||||||
|
velocity: Vector { x: -7, y: 3, z: 0 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector {
|
||||||
|
x: 13,
|
||||||
|
y: 16,
|
||||||
|
z: -3,
|
||||||
|
},
|
||||||
|
velocity: Vector {
|
||||||
|
x: 3,
|
||||||
|
y: -11,
|
||||||
|
z: -5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector {
|
||||||
|
x: -29,
|
||||||
|
y: -11,
|
||||||
|
z: -1,
|
||||||
|
},
|
||||||
|
velocity: Vector { x: -3, y: 7, z: 4 },
|
||||||
|
},
|
||||||
|
Body {
|
||||||
|
position: Vector {
|
||||||
|
x: 16,
|
||||||
|
y: -13,
|
||||||
|
z: 23,
|
||||||
|
},
|
||||||
|
velocity: Vector { x: 7, y: 1, z: 1 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reads_moon_scan_file() {
|
||||||
|
assert_eq!(read_moon_scan(TEST_INPUT1).unwrap(), nbody_1());
|
||||||
|
assert_eq!(read_moon_scan(TEST_INPUT2).unwrap(), nbody_2());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_10_steps() {
|
||||||
|
let mut nbody = read_moon_scan(TEST_INPUT1).unwrap();
|
||||||
|
for _ in 0..10 {
|
||||||
|
nbody.run_step();
|
||||||
|
}
|
||||||
|
assert_eq!(nbody, nbody_1_after_10_steps());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runs_100_steps() {
|
||||||
|
let mut nbody = read_moon_scan(TEST_INPUT2).unwrap();
|
||||||
|
for _ in 0..100 {
|
||||||
|
nbody.run_step();
|
||||||
|
}
|
||||||
|
assert_eq!(nbody, nbody_2_after_100_steps());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn calculates_total_energy_after_10_steps() {
|
||||||
|
let mut nbody = read_moon_scan(TEST_INPUT1).unwrap();
|
||||||
|
for _ in 0..10 {
|
||||||
|
nbody.run_step();
|
||||||
|
}
|
||||||
|
assert_eq!(nbody.total_energy(), 179);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn calculates_total_energy_after_100_steps() {
|
||||||
|
let mut nbody = read_moon_scan(TEST_INPUT2).unwrap();
|
||||||
|
for _ in 0..100 {
|
||||||
|
nbody.run_step();
|
||||||
|
}
|
||||||
|
assert_eq!(nbody.total_energy(), 1940);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn finds_repeated_states() {
|
||||||
|
assert_eq!(solve_part2(TEST_INPUT1).unwrap(), 2772);
|
||||||
|
assert_eq!(solve_part2(TEST_INPUT2).unwrap(), 4686774924);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user