Skip to content

Commit 2ae1afe

Browse files
committed
feat: completed day 12
1 parent d4fb717 commit 2ae1afe

File tree

4 files changed

+234
-0
lines changed

4 files changed

+234
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
- [Day 9](https://github.com/ankjevel/adventofcode/tree/2019/day_09) 🌟 🌟
1515
- [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 🌟
1616
- [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟
17+
- [Day 12](https://github.com/ankjevel/adventofcode/tree/2019/day_12) 🌟 🌟

day_12/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "day_12"
3+
version = "0.1.0"
4+
authors = ["Dennis Pettersson <mail@dennispettersson.se>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
num-integer = "0.1.41"

day_12/src/lib.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
extern crate num_integer;
2+
3+
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
4+
pub struct Moon {
5+
pub position: (i64, i64, i64),
6+
pub velocity: (i64, i64, i64),
7+
}
8+
9+
impl Moon {
10+
pub fn new(input: Vec<i64>) -> Moon {
11+
let mut iter = input.into_iter();
12+
13+
let x = iter.next().unwrap();
14+
let y = iter.next().unwrap();
15+
let z = iter.next().unwrap();
16+
17+
Moon {
18+
position: (x, y, z),
19+
velocity: (0, 0, 0),
20+
}
21+
}
22+
23+
pub fn total_energy(&self) -> i64 {
24+
let (x, y, z) = self.position;
25+
let (dx, dy, dz) = self.velocity;
26+
27+
let pot = x.abs() + y.abs() + z.abs();
28+
let kin = dx.abs() + dy.abs() + dz.abs();
29+
30+
pot * kin
31+
}
32+
33+
pub fn gravity(&self, compared: &Moon) -> (i64, i64, i64) {
34+
let (ax, ay, az) = self.position;
35+
let (bx, by, bz) = compared.position;
36+
37+
(gravity(ax, bx), gravity(ay, by), gravity(az, bz))
38+
}
39+
}
40+
41+
pub fn gravity(a: i64, b: i64) -> i64 {
42+
if a > b {
43+
-1
44+
} else if b > a {
45+
1
46+
} else {
47+
0
48+
}
49+
}
50+
51+
pub fn new_moon(moon: &Moon, energy: &(i64, i64, i64)) -> Moon {
52+
let (ddx, ddy, ddz) = energy;
53+
54+
let (dx, dy, dz) = moon.velocity;
55+
let (dx, dy, dz) = (dx + ddx, dy + ddy, dz + ddz);
56+
57+
let (x, y, z) = moon.position;
58+
let (x, y, z) = (x + dx, y + dy, z + dz);
59+
60+
Moon {
61+
position: (x, y, z),
62+
velocity: (dx, dy, dz),
63+
}
64+
}
65+
66+
pub fn parse_input(input: &str) -> Vec<Moon> {
67+
input
68+
.lines()
69+
.map(str::trim)
70+
.filter(|string| !string.is_empty())
71+
.map(|part| {
72+
part.split(',')
73+
.map(str::trim)
74+
.map(str::to_owned)
75+
.map(|s| {
76+
s.replace('>', "")
77+
.replace('<', "")
78+
.split('=')
79+
.last()
80+
.unwrap()
81+
.parse::<i64>()
82+
.unwrap()
83+
})
84+
.collect()
85+
})
86+
.map(Moon::new)
87+
.collect()
88+
}

day_12/src/main.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use ::day_12::{gravity, new_moon, parse_input, Moon};
2+
use num_integer::lcm;
3+
use std::mem::replace;
4+
5+
fn part_01(input: &Vec<Moon>, steps: usize) -> i64 {
6+
let mut moons = input.clone();
7+
let mut new_moons = vec![];
8+
for _ in 0..steps {
9+
for (i, moon) in moons.iter().enumerate() {
10+
let mut ddx = 0;
11+
let mut ddy = 0;
12+
let mut ddz = 0;
13+
for (j, other) in moons.iter().enumerate() {
14+
if i == j {
15+
continue;
16+
}
17+
let (x, y, z) = moon.gravity(&other);
18+
ddx += x;
19+
ddy += y;
20+
ddz += z;
21+
}
22+
new_moons.push(new_moon(&moon, &(ddx, ddy, ddz)))
23+
}
24+
moons = replace(&mut new_moons, vec![]);
25+
}
26+
moons.iter().map(Moon::total_energy).sum()
27+
}
28+
29+
type SimplifiedMoon = (i64, i64);
30+
31+
fn part_02(input: &Vec<Moon>) -> u128 {
32+
let to_id = |input: &SimplifiedMoon| -> String {
33+
"pos=".to_string() + &input.0.to_string() + &",vel=" + &input.1.to_string()
34+
};
35+
36+
let to_hash = |input: Vec<SimplifiedMoon>| -> String {
37+
input.iter().map(to_id).collect::<Vec<String>>().join("|")
38+
};
39+
40+
let run_simulation = |input: Vec<SimplifiedMoon>| -> u128 {
41+
let mut moons = input.clone();
42+
let mut new_moons = vec![];
43+
let mut steps = 0;
44+
45+
let initial_state = to_hash(input.clone());
46+
47+
'outer: loop {
48+
steps += 1;
49+
50+
for (i, moon) in moons.iter().enumerate() {
51+
let mut energy = 0;
52+
for (j, other) in moons.iter().enumerate() {
53+
if i == j {
54+
continue;
55+
}
56+
energy += gravity(moon.0, other.0);
57+
}
58+
let (position, velocity) = moon;
59+
let velocity = velocity + energy;
60+
let position = position + velocity;
61+
new_moons.push((position.to_owned(), velocity.to_owned()))
62+
}
63+
64+
if to_hash(new_moons.clone()) == initial_state {
65+
break 'outer;
66+
};
67+
68+
moons = replace(&mut new_moons, vec![]);
69+
}
70+
71+
steps
72+
};
73+
74+
let x = run_simulation(
75+
input
76+
.clone()
77+
.iter()
78+
.map(|moon| (moon.position.0, 0))
79+
.collect(),
80+
);
81+
let y = run_simulation(
82+
input
83+
.clone()
84+
.iter()
85+
.map(|moon| (moon.position.1, 0))
86+
.collect(),
87+
);
88+
let z = run_simulation(
89+
input
90+
.clone()
91+
.iter()
92+
.map(|moon| (moon.position.2, 0))
93+
.collect(),
94+
);
95+
96+
lcm(lcm(x, y), z)
97+
}
98+
99+
fn main() {
100+
let input = parse_input(&include_str!("../../input/day_12"));
101+
println!("part_01: {}", part_01(&input, 1_000));
102+
println!("part_02: {}", part_02(&input));
103+
}
104+
105+
#[cfg(test)]
106+
#[allow(dead_code)]
107+
mod tests {
108+
use super::*;
109+
110+
const EXAMPLE_DATA_01: &'static str = "
111+
<x=-1, y=0, z=2>
112+
<x=2, y=-10, z=-7>
113+
<x=4, y=-8, z=8>
114+
<x=3, y=5, z=-1>
115+
";
116+
117+
const EXAMPLE_DATA_02: &'static str = "
118+
<x=-8, y=-10, z=0>
119+
<x=5, y=5, z=10>
120+
<x=2, y=-7, z=3>
121+
<x=9, y=-8, z=-3>
122+
";
123+
124+
#[test]
125+
fn it_gets_the_examples_on_part_01_right() {
126+
assert_eq!(part_01(&parse_input(&EXAMPLE_DATA_01), 10), 179);
127+
assert_eq!(part_01(&parse_input(&EXAMPLE_DATA_02), 100), 1940);
128+
}
129+
130+
#[test]
131+
fn it_gets_the_examples_on_part_02_right() {
132+
assert_eq!(part_02(&parse_input(&EXAMPLE_DATA_01)), 2772);
133+
assert_eq!(part_02(&parse_input(&EXAMPLE_DATA_02)), 4686774924);
134+
}
135+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy