day-12.rs (2660B)
1 fn main() { 2 let input = vec![ 3 vec![14, 15, -2], 4 vec![17, -3, 4], 5 vec![6, 12, -13], 6 vec![-2, 10, -8], 7 ]; 8 9 println!("Rust:"); 10 println!("Part 1: {}", part_1(&input)); 11 println!("Part 2: {}", part_2(&input)); 12 } 13 14 fn evolve(coord: &mut Vec<isize>, velocity: &mut Vec<isize>) { 15 let num_stars = coord.len(); 16 for i in 0..num_stars { 17 for j in (i + 1)..num_stars { 18 let dv = (coord[j] - coord[i]).signum(); 19 velocity[i] += dv; 20 velocity[j] -= dv; 21 } 22 } 23 coord 24 .iter_mut() 25 .zip(velocity.iter()) 26 .for_each(|(c, v)| *c += v); 27 } 28 29 fn calc_energy(coord: &Vec<Vec<isize>>, velocity: &Vec<Vec<isize>>) -> isize { 30 // Calculate energy. 31 let pot = (0..coord[0].len()) 32 .map(|i| (0..coord.len()).fold(0, |acc, dim| acc + coord[dim][i].abs())) 33 .collect::<Vec<_>>(); 34 let kin = (0..velocity[0].len()) 35 .map(|i| (0..coord.len()).fold(0, |acc, dim| acc + velocity[dim][i].abs())) 36 .collect::<Vec<_>>(); 37 pot.iter() 38 .zip(kin.iter()) 39 .fold(0, |acc, (p, k)| acc + p * k) 40 } 41 42 fn calc_period(mut coord: Vec<isize>) -> u128 { 43 let mut velocity = vec![0; coord.len()]; 44 let mut i = 0; 45 let mut abs_speed_sum = 1; 46 while abs_speed_sum != 0 { 47 evolve(&mut coord, &mut velocity); 48 // Cycle reaches half point when all speed reaches 0. 49 abs_speed_sum = velocity.iter().fold(0, |acc, v| acc + v.abs()); 50 i += 1; 51 } 52 i * 2 53 } 54 55 fn gcd(mut x: u128, mut y: u128) -> u128 { 56 while x > 0 && y > 0 { 57 x %= y; 58 if x != 0 { 59 y %= x; 60 } 61 } 62 x + y 63 } 64 65 fn lcm(x: u128, y: u128) -> u128 { 66 let factor = gcd(x, y); 67 x * y / factor 68 } 69 70 fn part_1(input: &Vec<Vec<isize>>) -> isize { 71 // Treat each direction independently. 72 let num_dim = input[0].len(); 73 let num_star = input.len(); 74 let mut coord = (0..num_dim) 75 .map(|dim| input.iter().map(|c| c[dim]).collect()) 76 .collect::<Vec<Vec<isize>>>(); 77 let mut velocity = vec![vec![0; num_star]; num_dim]; 78 for _ in 0..1000 { 79 (0..num_dim) 80 .for_each(|dim| evolve(coord.get_mut(dim).unwrap(), velocity.get_mut(dim).unwrap())); 81 } 82 calc_energy(&coord, &velocity) 83 } 84 85 fn part_2(input: &Vec<Vec<isize>>) -> u128 { 86 // Each direction should be independent and have their own cycles. 87 // So get the period in each direction and find least common multiplier. 88 let num_dim = input[0].len(); 89 (0..num_dim) 90 .map(|dim| calc_period(input.iter().map(|c| c[dim]).collect())) 91 .fold(1, |acc, cycle| lcm(acc, cycle)) 92 }