commit 701edf2e478876c8d6ce1a777ebdc1ffe2b63383
parent 4db9605cc6ae0f13baded3dfef2a59f8c8986b6d
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date: Fri, 13 Dec 2019 01:18:39 -0500
Add Rust solution for day 12
Diffstat:
A | day-12/day-12.rs | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 92 insertions(+), 0 deletions(-)
diff --git a/day-12/day-12.rs b/day-12/day-12.rs
@@ -0,0 +1,92 @@
+fn main() {
+ let input = vec![
+ vec![14, 15, -2],
+ vec![17, -3, 4],
+ vec![6, 12, -13],
+ vec![-2, 10, -8],
+ ];
+
+ println!("Rust:");
+ println!("Part 1: {}", part_1(&input));
+ println!("Part 2: {}", part_2(&input));
+}
+
+fn evolve(coord: &mut Vec<isize>, velocity: &mut Vec<isize>) {
+ let num_stars = coord.len();
+ for i in 0..num_stars {
+ for j in (i + 1)..num_stars {
+ let dv = (coord[j] - coord[i]).signum();
+ velocity[i] += dv;
+ velocity[j] -= dv;
+ }
+ }
+ coord
+ .iter_mut()
+ .zip(velocity.iter())
+ .for_each(|(c, v)| *c += v);
+}
+
+fn calc_energy(coord: &Vec<Vec<isize>>, velocity: &Vec<Vec<isize>>) -> isize {
+ // Calculate energy.
+ let pot = (0..coord[0].len())
+ .map(|i| (0..coord.len()).fold(0, |acc, dim| acc + coord[dim][i].abs()))
+ .collect::<Vec<_>>();
+ let kin = (0..velocity[0].len())
+ .map(|i| (0..coord.len()).fold(0, |acc, dim| acc + velocity[dim][i].abs()))
+ .collect::<Vec<_>>();
+ pot.iter()
+ .zip(kin.iter())
+ .fold(0, |acc, (p, k)| acc + p * k)
+}
+
+fn calc_period(mut coord: Vec<isize>) -> u128 {
+ let mut velocity = vec![0; coord.len()];
+ let mut i = 0;
+ let mut abs_speed_sum = 1;
+ while abs_speed_sum != 0 {
+ evolve(&mut coord, &mut velocity);
+ // Cycle reaches half point when all speed reaches 0.
+ abs_speed_sum = velocity.iter().fold(0, |acc, v| acc + v.abs());
+ i += 1;
+ }
+ i * 2
+}
+
+fn gcd(mut x: u128, mut y: u128) -> u128 {
+ while x > 0 && y > 0 {
+ x %= y;
+ if x != 0 {
+ y %= x;
+ }
+ }
+ x + y
+}
+
+fn lcm(x: u128, y: u128) -> u128 {
+ let factor = gcd(x, y);
+ x * y / factor
+}
+
+fn part_1(input: &Vec<Vec<isize>>) -> isize {
+ // Treat each direction independently.
+ let num_dim = input[0].len();
+ let num_star = input.len();
+ let mut coord = (0..num_dim)
+ .map(|dim| input.iter().map(|c| c[dim]).collect())
+ .collect::<Vec<Vec<isize>>>();
+ let mut velocity = vec![vec![0; num_star]; num_dim];
+ for _ in 0..1000 {
+ (0..num_dim)
+ .for_each(|dim| evolve(coord.get_mut(dim).unwrap(), velocity.get_mut(dim).unwrap()));
+ }
+ calc_energy(&coord, &velocity)
+}
+
+fn part_2(input: &Vec<Vec<isize>>) -> u128 {
+ // Each direction should be independent and have their own cycles.
+ // So get the period in each direction and find least common multiplier.
+ let num_dim = input[0].len();
+ (0..num_dim)
+ .map(|dim| calc_period(input.iter().map(|c| c[dim]).collect()))
+ .fold(1, |acc, cycle| lcm(acc, cycle))
+}