From: Greg Burri Date: Tue, 10 Dec 2024 21:16:09 +0000 (+0100) Subject: Format the code to standards X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=fcb2a69f4f90dce890c7f891dcae0f9bd1843c75;p=advent_of_code_2019.git Format the code to standards --- diff --git a/.gitignore b/.gitignore index 94bb2fb..4d34c50 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk -data/day08.png + +data/day* \ No newline at end of file diff --git a/data/put_your_data_files_here.txt b/data/put_your_data_files_here.txt new file mode 100644 index 0000000..52a6950 --- /dev/null +++ b/data/put_your_data_files_here.txt @@ -0,0 +1 @@ +Filename: "dayXX.input" \ No newline at end of file diff --git a/src/day01.rs b/src/day01.rs index ca1d470..922a685 100644 --- a/src/day01.rs +++ b/src/day01.rs @@ -3,7 +3,9 @@ pub fn sum_mass_to_fuel(masses: &[i32]) -> i32 { } pub fn sum_mass_to_fuel_2(masses: &[i32]) -> i32 { - masses.iter().fold(0, |sum, mass| sum + mass_to_fuel_2(*mass)) + masses + .iter() + .fold(0, |sum, mass| sum + mass_to_fuel_2(*mass)) } fn mass_to_fuel(mass: i32) -> i32 { @@ -15,7 +17,9 @@ fn mass_to_fuel_2(mass: i32) -> i32 { let mut current_mass = mass; loop { let fuel = mass_to_fuel(current_mass); - if fuel <= 0 { break } + if fuel <= 0 { + break; + } current_mass = fuel; sum += fuel; } @@ -40,4 +44,4 @@ mod tests { assert_eq!(mass_to_fuel_2(1969), 966); assert_eq!(mass_to_fuel_2(100_756), 50346); } -} \ No newline at end of file +} diff --git a/src/day02.rs b/src/day02.rs index fd26331..cd361e2 100644 --- a/src/day02.rs +++ b/src/day02.rs @@ -8,10 +8,16 @@ fn execute_op_code(code: &mut [i32]) -> i32 { let mut cursor = 0; loop { match code[cursor] { - 1 => code[code[cursor + 3] as usize] = code[code[cursor + 1] as usize] + code[code[cursor + 2] as usize], - 2 => code[code[cursor + 3] as usize] = code[code[cursor + 1] as usize] * code[code[cursor + 2] as usize], + 1 => { + code[code[cursor + 3] as usize] = + code[code[cursor + 1] as usize] + code[code[cursor + 2] as usize] + } + 2 => { + code[code[cursor + 3] as usize] = + code[code[cursor + 1] as usize] * code[code[cursor + 2] as usize] + } 99 => return code[0], - _ => panic!("Unknown code: {}", code[cursor]) + _ => panic!("Unknown code: {}", code[cursor]), } cursor += 4; } @@ -25,7 +31,7 @@ pub fn find_noun_and_verb(code: &[i32]) -> i32 { code_copy[1] = noun; code_copy[2] = verb; if execute_op_code(&mut code_copy) == 19_690_720 { - return 100 * noun + verb + return 100 * noun + verb; } } } @@ -54,4 +60,4 @@ mod tests { execute_op_code(&mut c4); assert_eq!(c4[0], 30); } -} \ No newline at end of file +} diff --git a/src/day03.rs b/src/day03.rs index cb50f8a..f6f16b8 100644 --- a/src/day03.rs +++ b/src/day03.rs @@ -1,4 +1,7 @@ -use std::{collections::{HashMap, HashSet}, iter::{Iterator, FromIterator}}; +use std::{ + collections::{HashMap, HashSet}, + iter::{FromIterator, Iterator}, +}; pub fn split_movements(movements: &str) -> Vec<&str> { movements.split(',').collect() @@ -10,10 +13,30 @@ fn positions(wire: &[&str]) -> Vec<(i32, i32)> { for mov in wire { let distance = mov[1..].parse::().unwrap(); match mov.chars().nth(0).unwrap() { - 'U' => { for y2 in y+1 ..= y + distance { pos.push((x, y2)); } y += distance }, - 'D' => { for y2 in (y - distance .. y).rev() { pos.push((x, y2)); } y -= distance }, - 'R' => { for x2 in x+1 ..= x + distance { pos.push((x2, y)); } x += distance }, - 'L' | _ => { for x2 in (x - distance .. x).rev() { pos.push((x2, y)); } x -= distance }, + 'U' => { + for y2 in y + 1..=y + distance { + pos.push((x, y2)); + } + y += distance + } + 'D' => { + for y2 in (y - distance..y).rev() { + pos.push((x, y2)); + } + y -= distance + } + 'R' => { + for x2 in x + 1..=x + distance { + pos.push((x2, y)); + } + x += distance + } + 'L' | _ => { + for x2 in (x - distance..x).rev() { + pos.push((x2, y)); + } + x -= distance + } } } pos @@ -28,18 +51,26 @@ pub fn manhattan_distance_from_cross_to_port(wire1: &[&str], wire2: &[&str]) -> pub fn first_cross_sum_of_lengths(wire1: &[&str], wire2: &[&str]) -> usize { let positions_wire1 = positions(wire1); - let positions_wire1_indexed: HashMap<&(i32, i32), usize> = HashMap::from_iter(positions_wire1.iter().enumerate().map(|(i, pos)| (pos, i)).rev()); + let positions_wire1_indexed: HashMap<&(i32, i32), usize> = HashMap::from_iter( + positions_wire1 + .iter() + .enumerate() + .map(|(i, pos)| (pos, i)) + .rev(), + ); positions(wire2) - .iter().enumerate().filter_map( - |(j, pos2)| { - if let Some (i) = positions_wire1_indexed.get(pos2) { - Some (j + i + 2) - } else { - None - } + .iter() + .enumerate() + .filter_map(|(j, pos2)| { + if let Some(i) = positions_wire1_indexed.get(pos2) { + Some(j + i + 2) + } else { + None } - ).min().unwrap() + }) + .min() + .unwrap() } #[cfg(test)] @@ -99,4 +130,4 @@ mod tests { 410 ); } -} \ No newline at end of file +} diff --git a/src/day04.rs b/src/day04.rs index 5f66df4..c575472 100644 --- a/src/day04.rs +++ b/src/day04.rs @@ -1,7 +1,11 @@ use std::cmp::Ordering; pub fn parse_range(raw: &str) -> (i32, i32) { - let nums: Vec = raw.trim().split('-').map(|n| n.parse::().unwrap()).collect(); + let nums: Vec = raw + .trim() + .split('-') + .map(|n| n.parse::().unwrap()) + .collect(); (nums[0], nums[1]) } @@ -18,37 +22,33 @@ fn get_digits(value: i32) -> Digits { } pub fn nb_passwords_part1(min: i32, max: i32) -> i32 { - nb_passwords( - min, - max, - &|digits: &Digits| { - for i in 1 .. digits.len() { - if digits[i - 1] == digits[i] { return true; } + nb_passwords(min, max, &|digits: &Digits| { + for i in 1..digits.len() { + if digits[i - 1] == digits[i] { + return true; } - false } - ) + false + }) } pub fn nb_passwords_part2(min: i32, max: i32) -> i32 { - nb_passwords( - min, - max, - &|digits: &Digits| { - let mut last = digits[0]; - let mut n = 1; - for d in &digits[1..] { - if *d == last { - n += 1; - } else { - if n == 2 { return true; } - n = 1; + nb_passwords(min, max, &|digits: &Digits| { + let mut last = digits[0]; + let mut n = 1; + for d in &digits[1..] { + if *d == last { + n += 1; + } else { + if n == 2 { + return true; } - last = *d; + n = 1; } - n == 2 + last = *d; } - ) + n == 2 + }) } fn nb_passwords(min: i32, max: i32, valid_password: &dyn Fn(&Digits) -> bool) -> i32 { @@ -57,10 +57,12 @@ fn nb_passwords(min: i32, max: i32, valid_password: &dyn Fn(&Digits) -> bool) -> let l = digits.len(); fn set_range(from: usize, to: usize, value: u8, digits: &mut Digits) { - for d in &mut digits[from .. to] { *d = value; } + for d in &mut digits[from..to] { + *d = value; + } } - for i in (1 .. l).rev() { + for i in (1..l).rev() { if digits[i - 1] < digits[i] { set_range(0, i, digits[i], &mut digits); break; @@ -70,21 +72,23 @@ fn nb_passwords(min: i32, max: i32, valid_password: &dyn Fn(&Digits) -> bool) -> let mut n = 0; loop { - if valid_password(&digits) { n += 1; } + if valid_password(&digits) { + n += 1; + } - for i in 0 .. l { + for i in 0..l { if i == l - 1 || digits[i + 1] <= digits[i] && digits[i] != 9 { set_range(0, i + 1, digits[i] + 1, &mut digits); break; } } - for i in (0 .. l).rev() { + for i in (0..l).rev() { match digits[i].cmp(&digits_max[i]) { Ordering::Greater => return n, Ordering::Less => break, - Ordering::Equal => () + Ordering::Equal => (), } } } -} \ No newline at end of file +} diff --git a/src/day06.rs b/src/day06.rs index 1ff649d..77ae402 100644 --- a/src/day06.rs +++ b/src/day06.rs @@ -16,7 +16,7 @@ fn parents<'a>(orbits: &'a Orbits, planet: &str) -> Vec<&'a str> { let mut parents = Vec::<&str>::new(); let mut current_planet = planet; - while let Some (parent) = orbits.get(current_planet) { + while let Some(parent) = orbits.get(current_planet) { parents.insert(0, parent); current_planet = parent; } @@ -25,7 +25,9 @@ fn parents<'a>(orbits: &'a Orbits, planet: &str) -> Vec<&'a str> { } pub fn total_direct_and_indirect_orbits(orbits: &Orbits) -> usize { - orbits.keys().fold(0, |sum, planet| { sum + parents(orbits, &planet).len() }) + orbits + .keys() + .fold(0, |sum, planet| sum + parents(orbits, &planet).len()) } pub fn nb_orbital_transfers(orbits: &Orbits, loc1: &str, loc2: &str) -> usize { @@ -33,7 +35,7 @@ pub fn nb_orbital_transfers(orbits: &Orbits, loc1: &str, loc2: &str) -> usize { let parents_loc2 = parents(orbits, loc2); for i in 0..cmp::min(parents_loc1.len(), parents_loc2.len()) { if parents_loc1[i] != parents_loc2[i] { - return parents_loc1.len() + parents_loc2.len() - 2 * i + return parents_loc1.len() + parents_loc2.len() - 2 * i; } } 0 @@ -45,8 +47,7 @@ mod tests { #[test] fn part1() { - let lines: Vec<&str> = - "COM)B + let lines: Vec<&str> = "COM)B B)C C)D D)E @@ -56,7 +57,9 @@ mod tests { D)I E)J J)K - K)L".lines().collect(); + K)L" + .lines() + .collect(); let n = total_direct_and_indirect_orbits(&build_orbits(&lines)); assert_eq!(n, 42); @@ -64,8 +67,7 @@ mod tests { #[test] fn part2() { - let lines: Vec<&str> = - "COM)B + let lines: Vec<&str> = "COM)B B)C C)D D)E @@ -77,9 +79,11 @@ mod tests { J)K K)L K)YOU - I)SAN".lines().collect(); + I)SAN" + .lines() + .collect(); let n = nb_orbital_transfers(&build_orbits(&lines), "SAN", "YOU"); assert_eq!(n, 4); } -} \ No newline at end of file +} diff --git a/src/day07.rs b/src/day07.rs index 1ab98f7..6d4ecdc 100644 --- a/src/day07.rs +++ b/src/day07.rs @@ -1,4 +1,8 @@ -use std::sync::{Arc, Barrier, mpsc::{self, Sender, Receiver}, atomic::{AtomicI64, Ordering}}; +use std::sync::{ + atomic::{AtomicI64, Ordering}, + mpsc::{self, Receiver, Sender}, + Arc, Barrier, +}; use itertools::Itertools; use threadpool::ThreadPool; @@ -6,17 +10,23 @@ use threadpool::ThreadPool; use super::intcode; fn last_thruster_signal(code: &[i64], phase_setting: &[i64]) -> i64 { - phase_setting.iter().fold(0, |last_output, input| intcode::execute_op_code(&code, &[*input, last_output])[0]) + phase_setting.iter().fold(0, |last_output, input| { + intcode::execute_op_code(&code, &[*input, last_output])[0] + }) } pub fn find_largest_last_thruster_signal(code: &[i64]) -> i64 { - (0i64 ..= 4i64).permutations(5).map(|phase_setting| last_thruster_signal(&code, &phase_setting)).max().unwrap() + (0i64..=4i64) + .permutations(5) + .map(|phase_setting| last_thruster_signal(&code, &phase_setting)) + .max() + .unwrap() } struct Stage { input_channel: mpsc::Receiver, output_channel: mpsc::Sender, - last_produced_value: i64 + last_produced_value: i64, } impl intcode::IO for Stage { @@ -24,7 +34,7 @@ impl intcode::IO for Stage { fn read(&mut self) -> i64 { match self.input_channel.recv() { Ok(value) => value, - Err(_) => 0 + Err(_) => 0, } } @@ -35,23 +45,30 @@ impl intcode::IO for Stage { } } -fn last_thruster_signal_with_feedback_loop(code: &[i64], phase_setting: &[i64], pool: &ThreadPool) -> i64 { +fn last_thruster_signal_with_feedback_loop( + code: &[i64], + phase_setting: &[i64], + pool: &ThreadPool, +) -> i64 { let n = phase_setting.len(); let mut senders = Vec::>::new(); let mut receivers = Vec::>::new(); - for (i, (s, r)) in (0 .. n).map(|i| (i, mpsc::channel::())) { + for (i, (s, r)) in (0..n).map(|i| (i, mpsc::channel::())) { // Initial values. s.send(phase_setting[i]).unwrap_or_default(); - if i == 0 { s.send(0).unwrap_or_default(); } + if i == 0 { + s.send(0).unwrap_or_default(); + } senders.insert(if i == 0 { 0 } else { i - 1 }, s); receivers.push(r); } // Prepare each pair of received and sender for the each stages. - let mut channels: Vec<(Receiver, Sender)> = receivers.drain(..).zip(senders.drain(..)).collect(); + let mut channels: Vec<(Receiver, Sender)> = + receivers.drain(..).zip(senders.drain(..)).collect(); let result = Arc::new(AtomicI64::new(0)); let barrier = Arc::new(Barrier::new(2)); @@ -61,16 +78,18 @@ fn last_thruster_signal_with_feedback_loop(code: &[i64], phase_setting: &[i64], let barrier = barrier.clone(); let result = result.clone(); - pool.execute( - move || { - let mut stage = Stage { input_channel: receiver, output_channel: sender, last_produced_value: 0 }; - intcode::execute_op_code_with_custom_io(&code_copy, &mut stage); - if i == 4 { - result.store(stage.last_produced_value, Ordering::Relaxed); - barrier.wait(); - } + pool.execute(move || { + let mut stage = Stage { + input_channel: receiver, + output_channel: sender, + last_produced_value: 0, + }; + intcode::execute_op_code_with_custom_io(&code_copy, &mut stage); + if i == 4 { + result.store(stage.last_produced_value, Ordering::Relaxed); + barrier.wait(); } - ) + }) } barrier.wait(); @@ -79,7 +98,11 @@ fn last_thruster_signal_with_feedback_loop(code: &[i64], phase_setting: &[i64], pub fn find_largest_last_thruster_signal_with_feedback_loop(code: &[i64]) -> i64 { let pool = ThreadPool::new(5); - (5i64 ..= 9i64).permutations(5).map(|phase_setting| last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool)).max().unwrap() + (5i64..=9i64) + .permutations(5) + .map(|phase_setting| last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool)) + .max() + .unwrap() } #[cfg(test)] @@ -88,38 +111,59 @@ mod tests { #[test] fn part1_sample_1() { - let code = vec![3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]; - let phase_setting = [4,3,2,1,0]; + let code = vec![ + 3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0, + ]; + let phase_setting = [4, 3, 2, 1, 0]; assert_eq!(last_thruster_signal(&code, &phase_setting), 43210); } #[test] fn part1_sample_2() { - let code = vec![3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0]; - let phase_setting = [0,1,2,3,4]; + let code = vec![ + 3, 23, 3, 24, 1002, 24, 10, 24, 1002, 23, -1, 23, 101, 5, 23, 23, 1, 24, 23, 23, 4, 23, + 99, 0, 0, + ]; + let phase_setting = [0, 1, 2, 3, 4]; assert_eq!(last_thruster_signal(&code, &phase_setting), 54321); } #[test] fn part1_sample_3() { - let code = vec![3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0]; - let phase_setting = [1,0,4,3,2]; + let code = vec![ + 3, 31, 3, 32, 1002, 32, 10, 32, 1001, 31, -2, 31, 1007, 31, 0, 33, 1002, 33, 7, 33, 1, + 33, 31, 31, 1, 32, 31, 31, 4, 31, 99, 0, 0, 0, + ]; + let phase_setting = [1, 0, 4, 3, 2]; assert_eq!(last_thruster_signal(&code, &phase_setting), 65210); } #[test] fn part2_sample_1() { - let code = vec![3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5]; - let phase_setting = [9,8,7,6,5]; + let code = vec![ + 3, 26, 1001, 26, -4, 26, 3, 27, 1002, 27, 2, 27, 1, 27, 26, 27, 4, 27, 1001, 28, -1, + 28, 1005, 28, 6, 99, 0, 0, 5, + ]; + let phase_setting = [9, 8, 7, 6, 5]; let pool = ThreadPool::new(5); - assert_eq!(last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool), 139_629_729); + assert_eq!( + last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool), + 139_629_729 + ); } #[test] fn part2_sample_2() { - let code = vec![3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10]; - let phase_setting = [9,7,8,5,6]; + let code = vec![ + 3, 52, 1001, 52, -5, 52, 3, 53, 1, 52, 56, 54, 1007, 54, 5, 55, 1005, 55, 26, 1001, 54, + -5, 54, 1105, 1, 12, 1, 53, 54, 53, 1008, 54, 0, 55, 1001, 55, 1, 55, 2, 53, 55, 53, 4, + 53, 1001, 56, -1, 56, 1005, 56, 6, 99, 0, 0, 0, 0, 10, + ]; + let phase_setting = [9, 7, 8, 5, 6]; let pool = ThreadPool::new(5); - assert_eq!(last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool), 18_216); + assert_eq!( + last_thruster_signal_with_feedback_loop(&code, &phase_setting, &pool), + 18_216 + ); } -} \ No newline at end of file +} diff --git a/src/day08.rs b/src/day08.rs index 50fb119..36f98b8 100644 --- a/src/day08.rs +++ b/src/day08.rs @@ -1,20 +1,24 @@ pub fn read_from_string(raw: &str) -> Vec { - raw.chars().map(|c| c.to_digit(10).unwrap() as u8).collect::>() + raw.chars() + .map(|c| c.to_digit(10).unwrap() as u8) + .collect::>() } pub fn decode_image(digits: &[u8], width: usize, height: usize) -> Vec> { let nb_pixel = width * height; let nb_layers = digits.len() / nb_pixel; let mut layers: Vec> = Vec::new(); - for i in 0 .. nb_layers { - let layer: Vec = Vec::from(&digits[i * nb_pixel .. (i+1) * nb_pixel]); + for i in 0..nb_layers { + let layer: Vec = Vec::from(&digits[i * nb_pixel..(i + 1) * nb_pixel]); layers.push(layer); } layers } fn count(layer: &[u8], value: u8) -> u32 { - layer.iter().fold(0, |sum, pix| if *pix == value { sum + 1 } else { sum }) + layer + .iter() + .fold(0, |sum, pix| if *pix == value { sum + 1 } else { sum }) } pub fn layer_with_fewer_0(layers: &[Vec]) -> &Vec { @@ -35,7 +39,7 @@ pub fn merge_layers(layers: &[Vec]) -> Vec { let mut result: Vec = Vec::new(); result.resize(size, 0); - for i in 0 .. size { + for i in 0..size { for layer in layers { if layer[i] != 2 { result[i] = layer[i]; @@ -70,4 +74,4 @@ mod tests { let layer = merge_layers(&layers[..]); assert_eq!(layer, vec![0, 1, 1, 0]); } -} \ No newline at end of file +} diff --git a/src/day10.rs b/src/day10.rs index 62b989b..799b0a8 100644 --- a/src/day10.rs +++ b/src/day10.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; pub fn read_map(raw: &str) -> Vec<(i32, i32)> { let lines: Vec<&str> = raw.lines().map(|l| l.trim()).collect(); let mut map = Vec::<(i32, i32)>::new(); - for x in 0 .. lines[0].len() { + for x in 0..lines[0].len() { for (y, line) in lines.iter().enumerate() { if line.chars().nth(x) == Some('#') { map.push((x as i32, y as i32)); @@ -15,7 +15,8 @@ pub fn read_map(raw: &str) -> Vec<(i32, i32)> { fn angle(x1: i32, y1: i32, x2: i32, y2: i32) -> i64 { // Axis are reverted to match the clockwise laser rotation beginning up. - let angle_f64 = (2.0 * std::f64::consts::PI - ((x1 - x2) as f64).atan2((y1 - y2) as f64)) % (2.0 * std::f64::consts::PI); + let angle_f64 = (2.0 * std::f64::consts::PI - ((x1 - x2) as f64).atan2((y1 - y2) as f64)) + % (2.0 * std::f64::consts::PI); (angle_f64 * 1_000_000.0) as i64 } @@ -43,22 +44,29 @@ pub fn find_best_location(map: &[(i32, i32)]) -> (usize, (i32, i32)) { type PositionsAndDistances = Vec<((i32, i32), i64)>; -pub fn location_nth_vaporized_asteroid(pos: (i32, i32), map: &[(i32, i32)], n: usize) -> (i32, i32) { +pub fn location_nth_vaporized_asteroid( + pos: (i32, i32), + map: &[(i32, i32)], + n: usize, +) -> (i32, i32) { // Angle -> [(position, distance)]. let mut asteroids = HashMap::::new(); let (x1, y1) = pos; for (x2, y2) in map { - let angle = angle(x1, y1, *x2 , *y2); - let dist = squared_distance(x1, y1, *x2 , *y2); + let angle = angle(x1, y1, *x2, *y2); + let dist = squared_distance(x1, y1, *x2, *y2); match asteroids.get_mut(&angle) { - Some (lineup_asteroids) => lineup_asteroids.push(((*x2, *y2), dist)), - None => { asteroids.insert(angle, vec![((*x2, *y2), dist)]); } + Some(lineup_asteroids) => lineup_asteroids.push(((*x2, *y2), dist)), + None => { + asteroids.insert(angle, vec![((*x2, *y2), dist)]); + } } } // Sort everything by angle and by distance. - let mut sorted_asteroids: Vec<(&i64, &mut PositionsAndDistances)> = asteroids.iter_mut().collect(); + let mut sorted_asteroids: Vec<(&i64, &mut PositionsAndDistances)> = + asteroids.iter_mut().collect(); sorted_asteroids.sort_by(|(a1, _), (a2, _)| a1.cmp(a2)); for (_, lineup_asteroids) in sorted_asteroids.iter_mut() { lineup_asteroids.sort_by(|(_, l1), (_, l2)| l1.cmp(l2)) @@ -68,7 +76,9 @@ pub fn location_nth_vaporized_asteroid(pos: (i32, i32), map: &[(i32, i32)], n: u loop { for (_, lineup_asteroids) in sorted_asteroids.iter_mut() { let ((x, y), _) = lineup_asteroids.remove(0); - if i == n { return (x, y) } + if i == n { + return (x, y); + } i += 1; } } @@ -80,8 +90,7 @@ mod tests { #[test] fn part1_sample_1() { - let raw_map = - ".#..# + let raw_map = ".#..# ..... ##### ....# @@ -92,8 +101,7 @@ mod tests { #[test] fn part1_sample_2() { - let raw_map = - "......#.#. + let raw_map = "......#.#. #..#.#.... ..#######. .#.#.###.. @@ -109,8 +117,7 @@ mod tests { #[test] fn part1_sampl3() { - let raw_map = - "#.#...#.#. + let raw_map = "#.#...#.#. .###....#. .#....#... ##.#.#.#.# @@ -126,8 +133,7 @@ mod tests { #[test] fn part1_sample_4() { - let raw_map = - ".#..#..### + let raw_map = ".#..#..### ####.###.# ....###.#. ..###.##.# @@ -143,8 +149,7 @@ mod tests { #[test] fn part1_sample_5() { - let raw_map = - ".#..##.###...####### + let raw_map = ".#..##.###...####### ##.############..##. .#.######.########.# .###.#######.####.#. @@ -168,11 +173,9 @@ mod tests { assert_eq!(find_best_location(&map).0, 210); } - #[test] fn part2_sample_1() { - let raw_map = - ".#....#####...#.. + let raw_map = ".#....#####...#.. ##...##.#####..## ##...#...#.#####. ..#.....X...###.. @@ -188,8 +191,7 @@ mod tests { #[test] fn part2_sample_2() { - let raw_map = - ".#..##.###...####### + let raw_map = ".#..##.###...####### ##.############..##. .#.######.########.# .###.#######.####.#. @@ -214,4 +216,4 @@ mod tests { let pos_200th = location_nth_vaporized_asteroid(pos, &map, 200); assert_eq!(pos_200th, (8, 2)); } -} \ No newline at end of file +} diff --git a/src/day11.rs b/src/day11.rs index 8847bb1..822e218 100644 --- a/src/day11.rs +++ b/src/day11.rs @@ -4,14 +4,14 @@ use super::intcode; enum NextCommand { Paint, - Turn + Turn, } struct Robot { next_command: NextCommand, current_pos: (i32, i32), current_dir: i32, // 0: up, 1: right, 2: down, 3: left. - panels: HashMap<(i32, i32), i64> + panels: HashMap<(i32, i32), i64>, } impl Robot { @@ -20,7 +20,7 @@ impl Robot { next_command: NextCommand::Paint, current_pos: (0, 0), current_dir: 0, - panels: HashMap::new() + panels: HashMap::new(), } } } @@ -31,22 +31,25 @@ impl intcode::IO for Robot { } fn write(&mut self, value: i64) { - self.next_command = - match self.next_command { - NextCommand::Paint => { self.panels.insert(self.current_pos, value); NextCommand::Turn }, - NextCommand::Turn => { - self.current_dir = (self.current_dir + if value == 0 /* Turn left. */ { 3 } else /* Turn right. */ { 1 }) % 4; - let (x, y) = self.current_pos; - self.current_pos = - match self.current_dir { - 0 => (x , y + 1), - 1 => (x + 1, y ), - 2 => (x , y - 1), - 3 | _ => (x - 1, y ) - }; - NextCommand::Paint - } + self.next_command = match self.next_command { + NextCommand::Paint => { + self.panels.insert(self.current_pos, value); + NextCommand::Turn } + NextCommand::Turn => { + self.current_dir = (self.current_dir + + if value == 0 /* Turn left. */ { 3 } else /* Turn right. */ { 1 }) + % 4; + let (x, y) = self.current_pos; + self.current_pos = match self.current_dir { + 0 => (x, y + 1), + 1 => (x + 1, y), + 2 => (x, y - 1), + 3 | _ => (x - 1, y), + }; + NextCommand::Paint + } + } } } @@ -73,8 +76,8 @@ pub fn panels_to_layer(panels: &HashMap<(i32, i32), i64>) -> (Vec, usize) { let mut layer = Vec::new(); layer.resize(width * height, 0); - for x in min_x ..= max_x { - for y in min_y ..= max_y { + for x in min_x..=max_x { + for y in min_y..=max_y { let pos = (x - min_x) + ((height as i32 - y + min_y - 1) * width as i32); // Y axis is down. layer[pos as usize] = *panels.get(&(x, y)).unwrap_or(&0) as u8; } @@ -85,8 +88,8 @@ pub fn panels_to_layer(panels: &HashMap<(i32, i32), i64>) -> (Vec, usize) { #[cfg(test)] mod tests { - use super::*; use super::intcode::IO; + use super::*; #[test] fn part1() { @@ -114,4 +117,4 @@ mod tests { assert_eq!(robot.panels.len(), 6); } -} \ No newline at end of file +} diff --git a/src/day12.rs b/src/day12.rs index db95447..34aefac 100644 --- a/src/day12.rs +++ b/src/day12.rs @@ -4,7 +4,7 @@ use std::{cmp::Ordering, ops::AddAssign}; pub struct Vector3D { x: i32, y: i32, - z: i32 + z: i32, } impl AddAssign for Vector3D { @@ -12,7 +12,7 @@ impl AddAssign for Vector3D { *self = Self { x: self.x + other.x, y: self.y + other.y, - z: self.z + other.z + z: self.z + other.z, }; } } @@ -20,13 +20,13 @@ impl AddAssign for Vector3D { #[derive(Debug, Copy, Clone)] pub struct Moon { position: Vector3D, - velocity: Vector3D + velocity: Vector3D, } impl Moon { fn total_energy(&self) -> i32 { - (self.position.x.abs() + self.position.y.abs() + self.position.z.abs()) * - (self.velocity.x.abs() + self.velocity.y.abs() + self.velocity.z.abs()) + (self.position.x.abs() + self.position.y.abs() + self.position.z.abs()) + * (self.velocity.x.abs() + self.velocity.y.abs() + self.velocity.z.abs()) } } @@ -35,9 +35,21 @@ fn next_step(moons: &mut Vec) { let moons_copy = moons.clone(); for m1 in moons.iter_mut() { for m2 in &moons_copy { - m1.velocity.x += match m2.position.x.cmp(&m1.position.x) { Ordering::Greater => 1, Ordering::Less => -1, Ordering::Equal => 0 }; - m1.velocity.y += match m2.position.y.cmp(&m1.position.y) { Ordering::Greater => 1, Ordering::Less => -1, Ordering::Equal => 0 }; - m1.velocity.z += match m2.position.z.cmp(&m1.position.z) { Ordering::Greater => 1, Ordering::Less => -1, Ordering::Equal => 0 }; + m1.velocity.x += match m2.position.x.cmp(&m1.position.x) { + Ordering::Greater => 1, + Ordering::Less => -1, + Ordering::Equal => 0, + }; + m1.velocity.y += match m2.position.y.cmp(&m1.position.y) { + Ordering::Greater => 1, + Ordering::Less => -1, + Ordering::Equal => 0, + }; + m1.velocity.z += match m2.position.z.cmp(&m1.position.z) { + Ordering::Greater => 1, + Ordering::Less => -1, + Ordering::Equal => 0, + }; } } @@ -48,17 +60,25 @@ fn next_step(moons: &mut Vec) { } fn create_moons(moon_positions: &[Vector3D]) -> Vec { - moon_positions.iter().map(|position| Moon { position: *position, velocity: Vector3D { x: 0, y: 0, z: 0 } }).collect() + moon_positions + .iter() + .map(|position| Moon { + position: *position, + velocity: Vector3D { x: 0, y: 0, z: 0 }, + }) + .collect() } pub fn final_energy(moon_positions: &[Vector3D], steps: u32) -> i32 { let mut moons: Vec = create_moons(moon_positions); - for _ in 0 .. steps { + for _ in 0..steps { next_step(&mut moons); } - moons.iter().fold(0, |energy, moon| energy + moon.total_energy()) + moons + .iter() + .fold(0, |energy, moon| energy + moon.total_energy()) } pub fn find_same_state(moon_positions: &[Vector3D]) -> i64 { @@ -73,39 +93,56 @@ pub fn find_same_state(moon_positions: &[Vector3D]) -> i64 { next_step(&mut moons); i += 1; - if nb_cycles.x == 0 && initial_state.iter().zip(&moons).all( - |(m1, m2)| m1.position.x == m2.position.x && m1.velocity.x == m2.velocity.x - ) { nb_cycles.x = i; } + if nb_cycles.x == 0 + && initial_state + .iter() + .zip(&moons) + .all(|(m1, m2)| m1.position.x == m2.position.x && m1.velocity.x == m2.velocity.x) + { + nb_cycles.x = i; + } - if nb_cycles.y == 0 && initial_state.iter().zip(&moons).all( - |(m1, m2)| m1.position.y == m2.position.y && m1.velocity.y == m2.velocity.y - ) { nb_cycles.y = i; } + if nb_cycles.y == 0 + && initial_state + .iter() + .zip(&moons) + .all(|(m1, m2)| m1.position.y == m2.position.y && m1.velocity.y == m2.velocity.y) + { + nb_cycles.y = i; + } - if nb_cycles.z == 0 && initial_state.iter().zip(&moons).all( - |(m1, m2)| m1.position.z == m2.position.z && m1.velocity.z == m2.velocity.z - ) { nb_cycles.z = i; } + if nb_cycles.z == 0 + && initial_state + .iter() + .zip(&moons) + .all(|(m1, m2)| m1.position.z == m2.position.z && m1.velocity.z == m2.velocity.z) + { + nb_cycles.z = i; + } if nb_cycles.x != 0 && nb_cycles.y != 0 && nb_cycles.z != 0 { - return (nb_cycles.x as i64).lcm(&(nb_cycles.y as i64)).lcm(&(nb_cycles.z as i64)) + return (nb_cycles.x as i64) + .lcm(&(nb_cycles.y as i64)) + .lcm(&(nb_cycles.z as i64)); } } } pub fn parse_positions(input: &str) -> Vec { use regex::Regex; - fn build_pattern(var: &str) -> Regex { Regex::new(&format!(r".*{}\W*?=\W*?(-?.*?\d+).*", var)).unwrap() } + fn build_pattern(var: &str) -> Regex { + Regex::new(&format!(r".*{}\W*?=\W*?(-?.*?\d+).*", var)).unwrap() + } let rex = build_pattern("x"); let rey = build_pattern("y"); let rez = build_pattern("z"); input .lines() - .map(|l| - Vector3D { - x: rex.captures(l).unwrap()[1].parse().unwrap(), - y: rey.captures(l).unwrap()[1].parse().unwrap(), - z: rez.captures(l).unwrap()[1].parse().unwrap() - } - ) + .map(|l| Vector3D { + x: rex.captures(l).unwrap()[1].parse().unwrap(), + y: rey.captures(l).unwrap()[1].parse().unwrap(), + z: rez.captures(l).unwrap()[1].parse().unwrap(), + }) .collect() } @@ -115,8 +152,7 @@ mod tests { #[test] fn part1() { - let input = - " + let input = " "; @@ -126,12 +162,11 @@ mod tests { #[test] fn part2() { - let input = - " + let input = " "; let coordinates = parse_positions(input); assert_eq!(find_same_state(&coordinates), 4_686_774_924); } -} \ No newline at end of file +} diff --git a/src/day13.rs b/src/day13.rs index 286791b..4823211 100644 --- a/src/day13.rs +++ b/src/day13.rs @@ -19,13 +19,20 @@ enum Tile { pub fn count_nb_block(code: &[i64]) -> i32 { let output = intcode::execute_op_code(code, &[]); - output.iter().chunks(3).into_iter().map( - |tile_with_pos| { + output + .iter() + .chunks(3) + .into_iter() + .map(|tile_with_pos| { let tile_with_pos: Vec<&i64> = tile_with_pos.collect(); let tile = Tile::try_from(*tile_with_pos[2] as u8).unwrap(); - if tile == Tile::Block { 1 } else { 0 } - } - ).sum() + if tile == Tile::Block { + 1 + } else { + 0 + } + }) + .sum() } struct State { @@ -53,12 +60,11 @@ impl intcode::IO for State { } else if tile == Tile::Paddle { self.paddle_position_x = self.buffer[0]; } - self.joystick = - match self.paddle_position_x.cmp(&self.ball_position_x) { - Ordering::Greater => -1, - Ordering::Less => 1, - Ordering::Equal => 0 - }; + self.joystick = match self.paddle_position_x.cmp(&self.ball_position_x) { + Ordering::Greater => -1, + Ordering::Less => 1, + Ordering::Equal => 0, + }; } self.buffer.clear(); } @@ -66,7 +72,13 @@ impl intcode::IO for State { } pub fn final_score(code: &[i64]) -> i64 { - let mut state = State { score: 0, joystick: 0, paddle_position_x: 0, ball_position_x: 0, buffer: Vec::new() }; + let mut state = State { + score: 0, + joystick: 0, + paddle_position_x: 0, + ball_position_x: 0, + buffer: Vec::new(), + }; intcode::execute_op_code_with_custom_io(&code, &mut state); state.score } diff --git a/src/day14.rs b/src/day14.rs index 7dfb6e6..e921cbd 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -22,7 +22,10 @@ pub fn parse(input: &str) -> Reactions { let reaction: Vec<&str> = line.split("=>").collect(); let input_chemicals: Vec = reaction[0].split(',').map(parse_chemical).collect(); let output_chemical = parse_chemical(reaction[1]); - result.insert(output_chemical.name, (output_chemical.quantity, input_chemicals)); + result.insert( + output_chemical.name, + (output_chemical.quantity, input_chemicals), + ); } result } @@ -32,46 +35,77 @@ pub fn ore_needed_per_fuel(reactions: &Reactions) -> i64 { ore_needed(reactions, 1, &mut remainders) } -fn ore_needed(reactions: &Reactions, fuel_quantity: i64, remainders: &mut HashMap) -> i64 { - - fn needed(reactions: &Reactions, chemicals: &[Chemical], remainders: &mut HashMap) -> i64 { +fn ore_needed( + reactions: &Reactions, + fuel_quantity: i64, + remainders: &mut HashMap, +) -> i64 { + fn needed( + reactions: &Reactions, + chemicals: &[Chemical], + remainders: &mut HashMap, + ) -> i64 { chemicals.iter().fold(0, |sum, chemical| { - let quantity_needed = - match remainders.get(&chemical.name) { - Some(quantity) => { - let remainder = quantity - chemical.quantity; - if remainder < 0 { - remainders.remove(&chemical.name); - remainder.abs() - } else { - remainders.insert(chemical.name.clone(), remainder); - 0 - } - }, - None => chemical.quantity - }; - - sum + - if chemical.name == "ORE" { - quantity_needed - } else { - match reactions.get(&chemical.name) { - Some((quantity_produced, chemicals_needed)) => { - let n = (quantity_needed / quantity_produced) + (if quantity_needed % quantity_produced == 0 { 0 } else { 1 }); - let rem = n * quantity_produced - quantity_needed; - match remainders.get(&chemical.name) { - Some(&q) => { remainders.insert(chemical.name.clone(), q + rem); }, - None => { remainders.insert(chemical.name.clone(), rem); } + let quantity_needed = match remainders.get(&chemical.name) { + Some(quantity) => { + let remainder = quantity - chemical.quantity; + if remainder < 0 { + remainders.remove(&chemical.name); + remainder.abs() + } else { + remainders.insert(chemical.name.clone(), remainder); + 0 + } + } + None => chemical.quantity, + }; + + sum + if chemical.name == "ORE" { + quantity_needed + } else { + match reactions.get(&chemical.name) { + Some((quantity_produced, chemicals_needed)) => { + let n = (quantity_needed / quantity_produced) + + (if quantity_needed % quantity_produced == 0 { + 0 + } else { + 1 + }); + let rem = n * quantity_produced - quantity_needed; + match remainders.get(&chemical.name) { + Some(&q) => { + remainders.insert(chemical.name.clone(), q + rem); + } + None => { + remainders.insert(chemical.name.clone(), rem); } - needed(reactions, &chemicals_needed.iter().map(|c| Chemical { quantity: n * c.quantity, name: c.name.clone() }).collect::>(), remainders) - }, - None => panic!("Unable to find reaction to create {}", chemical.name) + } + needed( + reactions, + &chemicals_needed + .iter() + .map(|c| Chemical { + quantity: n * c.quantity, + name: c.name.clone(), + }) + .collect::>(), + remainders, + ) } + None => panic!("Unable to find reaction to create {}", chemical.name), } + } }) } - needed(reactions, &[Chemical { quantity: fuel_quantity, name: String::from("FUEL") }], remainders) + needed( + reactions, + &[Chemical { + quantity: fuel_quantity, + name: String::from("FUEL"), + }], + remainders, + ) } pub fn fuel_produced(reactions: &Reactions, ore: i64, ore_per_fuel: i64) -> i64 { @@ -84,7 +118,7 @@ pub fn fuel_produced(reactions: &Reactions, ore: i64, ore_per_fuel: i64) -> i64 ore_available -= ore_needed(reactions, fuel, &mut remainders); if ore_available <= 0 { - return fuel_produced + return fuel_produced; } fuel_produced += fuel; @@ -97,8 +131,7 @@ mod tests { #[test] fn part1_sample_1() { - let input = - "10 ORE => 10 A + let input = "10 ORE => 10 A 1 ORE => 1 B 7 A, 1 B => 1 C 7 A, 1 C => 1 D @@ -110,8 +143,7 @@ mod tests { #[test] fn part1_sample_2() { - let input = - "9 ORE => 2 A + let input = "9 ORE => 2 A 8 ORE => 3 B 7 ORE => 5 C 3 A, 4 B => 1 AB @@ -124,8 +156,7 @@ mod tests { #[test] fn part1_sample_3() { - let input = - "157 ORE => 5 NZVS + let input = "157 ORE => 5 NZVS 165 ORE => 6 DCFZ 44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL 12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ @@ -140,8 +171,7 @@ mod tests { #[test] fn part1_sample_4() { - let input = - "2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG + let input = "2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG 17 NVRVD, 3 JNWZP => 8 VPVL 53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL 22 VJHF, 37 MNCFX => 5 FWMGM @@ -159,8 +189,7 @@ mod tests { #[test] fn part1_sample_5() { - let input = - "171 ORE => 8 CNZTR + let input = "171 ORE => 8 CNZTR 7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL 114 ORE => 4 BHXH 14 VRPVC => 6 BMBT @@ -183,8 +212,7 @@ mod tests { #[test] fn part2_sample_1() { - let input = - "157 ORE => 5 NZVS + let input = "157 ORE => 5 NZVS 165 ORE => 6 DCFZ 44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL 12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ @@ -195,13 +223,15 @@ mod tests { 3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT"; let reactions = parse(input); let ore_per_fuel = ore_needed_per_fuel(&reactions); - assert_eq!(fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel), 82_892_753); + assert_eq!( + fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel), + 82_892_753 + ); } #[test] fn part2_sample_2() { - let input = - "2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG + let input = "2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG 17 NVRVD, 3 JNWZP => 8 VPVL 53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL 22 VJHF, 37 MNCFX => 5 FWMGM @@ -215,13 +245,15 @@ mod tests { 176 ORE => 6 VJHF"; let reactions = parse(input); let ore_per_fuel = ore_needed_per_fuel(&reactions); - assert_eq!(fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel), 5_586_022); + assert_eq!( + fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel), + 5_586_022 + ); } #[test] fn part2_sample_3() { - let input = - "171 ORE => 8 CNZTR + let input = "171 ORE => 8 CNZTR 7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL 114 ORE => 4 BHXH 14 VRPVC => 6 BMBT @@ -240,6 +272,9 @@ mod tests { 5 BHXH, 4 VRPVC => 5 LTCX"; let reactions = parse(input); let ore_per_fuel = ore_needed_per_fuel(&reactions); - assert_eq!(fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel), 460_664); + assert_eq!( + fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel), + 460_664 + ); } -} \ No newline at end of file +} diff --git a/src/day15.rs b/src/day15.rs index 2af8e3c..b2791e6 100644 --- a/src/day15.rs +++ b/src/day15.rs @@ -1,4 +1,7 @@ -use std::{collections::{HashMap, HashSet}, iter::FromIterator}; +use std::{ + collections::{HashMap, HashSet}, + iter::FromIterator, +}; use super::intcode; @@ -26,21 +29,28 @@ impl DroidTrackingSystem { current_path: vec![(0, 0)], oxygen_location: (0, 0), steps_to_oxygen: 0, - all_locations_explored: false + all_locations_explored: false, } } - fn current_position(&self) -> (i32, i32) { *self.current_path.last().unwrap() } + fn current_position(&self) -> (i32, i32) { + *self.current_path.last().unwrap() + } fn positions_around(&self) -> Vec<(i64, (i32, i32))> { let (x, y) = self.current_position(); - vec![(1, (x, y + 1)), (2, (x, y - 1)), (3, (x - 1, y)), (4, (x + 1, y))] + vec![ + (1, (x, y + 1)), + (2, (x, y - 1)), + (3, (x - 1, y)), + (4, (x + 1, y)), + ] } fn get_state(&self, position: (i32, i32)) -> LocationState { match self.board.get(&position) { Some(state) => *state, - None => LocationState::Unknown + None => LocationState::Unknown, } } @@ -53,7 +63,7 @@ impl DroidTrackingSystem { for (mov, pos) in self.positions_around() { if self.get_state(pos) == LocationState::Unknown { self.current_path.push(pos); - return mov + return mov; } } @@ -61,7 +71,7 @@ impl DroidTrackingSystem { if self.get_state(pos) == LocationState::Visited { self.set_state(self.current_position(), LocationState::DeadEnd); self.current_path.pop(); - return mov + return mov; } } @@ -69,7 +79,9 @@ impl DroidTrackingSystem { 1 } - // 0: droid hit a wall, 1: droid moved one step, 2: droid moved one step and has found the oxygen system. + // 0: droid hit a wall + // 1: droid moved one step + // 2: droid moved one step and has found the oxygen system. fn reply_from_droid(&mut self, status: i64) { if status == 0 { self.set_state(self.current_position(), LocationState::Wall); @@ -77,7 +89,8 @@ impl DroidTrackingSystem { } else if status == 1 || status == 2 { self.set_state(self.current_position(), LocationState::Visited); - // We need to explore all positions even if we find the oxygen to compute the time (see 'time_to_flood_the_area') in part 2. + // We need to explore all positions even if we find the oxygen to compute the time + // (see 'time_to_flood_the_area') in part 2. if status == 2 { self.steps_to_oxygen = self.current_path.len() as i32 - 1; self.oxygen_location = self.current_position(); @@ -130,4 +143,4 @@ pub fn time_to_flood_the_area(dts: &DroidTrackingSystem) -> i32 { } max_length - 1 -} \ No newline at end of file +} diff --git a/src/day16.rs b/src/day16.rs index 931ff5b..b6b7f6a 100644 --- a/src/day16.rs +++ b/src/day16.rs @@ -1,34 +1,46 @@ use std::iter::FromIterator; pub fn parse(input: &str) -> Vec { - input.chars().map(|c| c.to_digit(10).unwrap() as i32).collect() + input + .chars() + .map(|c| c.to_digit(10).unwrap() as i32) + .collect() } -pub fn fft(signal: &[i32], pattern: &[i32], nb_phases: i32, offset: usize, length: usize, nb_signal_repeated: usize) -> Vec { - +pub fn fft( + signal: &[i32], + pattern: &[i32], + nb_phases: i32, + offset: usize, + length: usize, + nb_signal_repeated: usize, +) -> Vec { let l = signal.len(); let pattern_l = pattern.len(); let mut output = Vec::from_iter(signal.iter().cycle().take(l * nb_signal_repeated).copied()); - for _ in 0 .. nb_phases { + for _ in 0..nb_phases { let cloned_output = output.clone(); - for i in 0 .. output.len() { - output[i] = - cloned_output.iter().enumerate().fold( - 0, - |sum, (j, value)| { - sum + value * pattern[(j + 1) / (i + 1) % pattern_l] - } - ).abs() % 10; + for i in 0..output.len() { + output[i] = cloned_output + .iter() + .enumerate() + .fold(0, |sum, (j, value)| { + sum + value * pattern[(j + 1) / (i + 1) % pattern_l] + }) + .abs() + % 10; } } - Vec::from(&output[offset .. offset + length]) + Vec::from(&output[offset..offset + length]) } pub fn digits_as_string(signal: &[i32]) -> String { - signal.iter().fold(String::new(), |result, digit| result + &digit.to_string()) + signal + .iter() + .fold(String::new(), |result, digit| result + &digit.to_string()) } // Part 2 is from 'https://github.com/mkeeter/advent-of-code/blob/master/2019/16/src/main.rs'. @@ -102,4 +114,4 @@ mod tests { let output = fft(&signal, &[0, 1, 0, -1], 100, 0, 8, 1); assert_eq!(digits_as_string(&output), "52432133"); } -} \ No newline at end of file +} diff --git a/src/day17.rs b/src/day17.rs index c3c3917..bdad2bb 100644 --- a/src/day17.rs +++ b/src/day17.rs @@ -5,7 +5,12 @@ use itertools::Itertools; use super::intcode; #[derive(PartialEq, Eq, Copy, Clone, Debug)] -enum Direction { Up, Left, Down, Right } +enum Direction { + Up, + Left, + Down, + Right, +} impl TryFrom for Direction { type Error = (); @@ -16,16 +21,22 @@ impl TryFrom for Direction { '<' => Ok(Direction::Left), 'v' => Ok(Direction::Down), '>' => Ok(Direction::Right), - _ => Err(()) + _ => Err(()), } } } #[derive(PartialEq, Eq, Copy, Clone, Debug)] -enum Movement { Left, Right } +enum Movement { + Left, + Right, +} #[derive(PartialEq, Eq, Copy, Clone, Debug)] -struct MovementCommand { mov: Movement, steps: u32 } +struct MovementCommand { + mov: Movement, + steps: u32, +} struct RobotTrackingSystem { board: Vec>, @@ -57,7 +68,7 @@ impl RobotTrackingSystem { current_x = 0; } else { let c = (*c as u8) as char; - if let Ok(dir) = Direction::try_from(c) { + if let Ok(dir) = Direction::try_from(c) { rts.start_position = (current_x, rts.board.len() as i32); rts.start_dir = dir } @@ -89,7 +100,12 @@ impl RobotTrackingSystem { let mut steps = 0; 'main: loop { - let positions = [(Direction::Up, (x, y - 1)), (Direction::Left, (x - 1, y)), (Direction::Right, (x + 1, y)), (Direction::Down, (x, y + 1))]; + let positions = [ + (Direction::Up, (x, y - 1)), + (Direction::Left, (x - 1, y)), + (Direction::Right, (x + 1, y)), + (Direction::Down, (x, y + 1)), + ]; let next_position = positions.iter().find(|(d, _)| *d == dir).unwrap().1; @@ -105,19 +121,26 @@ impl RobotTrackingSystem { } if steps != 0 { - self.dir_commands.push(MovementCommand { mov: last_mov, steps }); + self.dir_commands.push(MovementCommand { + mov: last_mov, + steps, + }); steps = 0; } for (d, p) in &positions { if self.get(p.0, p.1) == Some('#') && !visited_locations.contains(p) { - - last_mov = - match (dir, *d) { - (Direction::Up, Direction::Right) | (Direction::Right, Direction::Down) | (Direction::Down, Direction::Left) | (Direction::Left, Direction::Up) => Movement::Right, - (Direction::Up, Direction::Left) | (Direction::Left, Direction::Down) | (Direction::Down, Direction::Right) | (Direction::Right, Direction::Up) => Movement::Left, - _ => panic!("Unable to find a movement from {:?} to {:?}", dir, *d) - }; + last_mov = match (dir, *d) { + (Direction::Up, Direction::Right) + | (Direction::Right, Direction::Down) + | (Direction::Down, Direction::Left) + | (Direction::Left, Direction::Up) => Movement::Right, + (Direction::Up, Direction::Left) + | (Direction::Left, Direction::Down) + | (Direction::Down, Direction::Right) + | (Direction::Right, Direction::Up) => Movement::Left, + _ => panic!("Unable to find a movement from {:?} to {:?}", dir, *d), + }; visited_locations.insert(*p); steps += 1; @@ -134,17 +157,18 @@ impl RobotTrackingSystem { } struct CommandSequences { - commands: Vec<(usize, Range)> // Each range is associated with a sequence number (first tuple value). + // Each range is associated with a sequence number (first tuple value). + commands: Vec<(usize, Range)>, } -fn is_overlapping(r1: &Range, r2: &Range) -> bool { +fn is_overlapping(r1: &Range, r2: &Range) -> bool { r1.start < r2.start && r1.end > r2.start || r2.start < r1.start && r2.end > r1.start } impl CommandSequences { fn new() -> Self { CommandSequences { - commands: Vec::new() + commands: Vec::new(), } } @@ -153,20 +177,29 @@ impl CommandSequences { let len_min = 3; let len_max = 6; - for l1 in len_min ..= len_max { - for l2 in len_min ..= len_max { - for l3 in len_min ..= len_max { + for l1 in len_min..=len_max { + for l2 in len_min..=len_max { + for l3 in len_min..=len_max { self.commands.clear(); let mut position: usize = 0; - for seq_num in 0 .. 3 { - let l = match seq_num { 0 => l1, 1 => l2, _ => l3 }; - let range = position .. position + l; + for seq_num in 0..3 { + let l = match seq_num { + 0 => l1, + 1 => l2, + _ => l3, + }; + let range = position..position + l; self.commands.push((seq_num, range.clone())); // Try to find the sequence elsewhere in 'movements'. let mut position2 = position + l; while position2 <= movements.len() - l { - let range2 = position2 .. position2 + l; - if !self.commands.iter().any(|(_, r)| is_overlapping(&r, &range2)) && movements.get(range.clone()) == movements.get(range2.clone()) { + let range2 = position2..position2 + l; + if !self + .commands + .iter() + .any(|(_, r)| is_overlapping(&r, &range2)) + && movements.get(range.clone()) == movements.get(range2.clone()) + { self.commands.push((seq_num, range2)); position2 += l; } else { @@ -181,19 +214,31 @@ impl CommandSequences { } // Check if all movements are included into a sequence. - if self.commands.iter().fold(0, |sum, (_, range)| sum + range.len()) == movements.len() { + if self + .commands + .iter() + .fold(0, |sum, (_, range)| sum + range.len()) + == movements.len() + { return; } } - } } } } -struct Part1 { output: Vec, } +struct Part1 { + output: Vec, +} -impl Part1 { fn new() -> Self { Part1 { output: Vec::::new() } }} +impl Part1 { + fn new() -> Self { + Part1 { + output: Vec::::new(), + } + } +} struct Part2 { output: Vec, @@ -204,11 +249,24 @@ struct Part2 { dust_collected: i64, } -impl Part2 { fn new() -> Self { Part2 { output: Vec::::new(), rts: None, commands_sequences: CommandSequences::new(), input: Vec::new(), input_position: 0, dust_collected: 0 } } } +impl Part2 { + fn new() -> Self { + Part2 { + output: Vec::::new(), + rts: None, + commands_sequences: CommandSequences::new(), + input: Vec::new(), + input_position: 0, + dust_collected: 0, + } + } +} impl intcode::IO for Part1 { // Read instructions - fn read(&mut self) -> i64 { 0 } + fn read(&mut self) -> i64 { + 0 + } // Send to the output channel. fn write(&mut self, value: i64) { @@ -221,22 +279,50 @@ impl intcode::IO for Part2 { fn read(&mut self) -> i64 { if self.rts.is_none() { self.rts = Some(RobotTrackingSystem::from(&self.output)); - self.commands_sequences.find_sequences(&self.rts.as_ref().unwrap().dir_commands); + self.commands_sequences + .find_sequences(&self.rts.as_ref().unwrap().dir_commands); // 1: add the movements sequences: "A,B,C,A\n" // Max: 10 sequence calls. - for (i, (seq_num, _)) in self.commands_sequences.commands.iter().sorted_by(|(_, r1), (_, r2)| r1.start.cmp(&r2.start)).enumerate() { - if i > 0 { self.input.push(44); } + for (i, (seq_num, _)) in self + .commands_sequences + .commands + .iter() + .sorted_by(|(_, r1), (_, r2)| r1.start.cmp(&r2.start)) + .enumerate() + { + if i > 0 { + self.input.push(44); + } self.input.push(*seq_num as i64 + 65); } self.input.push(10); // 2: Add the sequence A, B and C: "R,8,L,2,R,1\n", Max: ~6 movements. - for seq_num in 0 .. 3 { - let (_, sequence) = self.commands_sequences.commands.iter().find(|(s, _)| *s == seq_num).unwrap(); - for (i, movement_command) in self.rts.as_ref().unwrap().dir_commands.get(sequence.clone()).unwrap().iter().enumerate() { - - if i > 0 { self.input.push(44); } - if movement_command.mov == Movement::Left { self.input.push(76); } else { self.input.push(82); } + for seq_num in 0..3 { + let (_, sequence) = self + .commands_sequences + .commands + .iter() + .find(|(s, _)| *s == seq_num) + .unwrap(); + for (i, movement_command) in self + .rts + .as_ref() + .unwrap() + .dir_commands + .get(sequence.clone()) + .unwrap() + .iter() + .enumerate() + { + if i > 0 { + self.input.push(44); + } + if movement_command.mov == Movement::Left { + self.input.push(76); + } else { + self.input.push(82); + } self.input.push(44); for c in movement_command.steps.to_string().as_bytes() { self.input.push(*c as i64); @@ -268,11 +354,13 @@ pub fn scaffold_intersections(code: &[i64]) -> i32 { let mut part1 = Part1::new(); intcode::execute_op_code_with_custom_io(code, &mut part1); let rts = RobotTrackingSystem::from(&part1.output); - rts.crossings.iter().fold(0, |sum, crossing| sum + crossing.0 * crossing.1) + rts.crossings + .iter() + .fold(0, |sum, crossing| sum + crossing.0 * crossing.1) } pub fn collected_dust(code: &[i64]) -> i64 { let mut part2 = Part2::new(); intcode::execute_op_code_with_custom_io(code, &mut part2); part2.dust_collected -} \ No newline at end of file +} diff --git a/src/day18.rs b/src/day18.rs index 027f403..3bd7819 100644 --- a/src/day18.rs +++ b/src/day18.rs @@ -18,7 +18,12 @@ impl Vault { let mut entrance = (0, 0); for (row, line) in input.lines().enumerate() { tunnels.push(line.trim().chars().collect::>()); - if let Some((col, _)) = tunnels.last().unwrap().iter().find_position(|c| c == &&START_SYMBOL) { + if let Some((col, _)) = tunnels + .last() + .unwrap() + .iter() + .find_position(|c| c == &&START_SYMBOL) + { entrance = (row as i32, col as i32); } } @@ -38,40 +43,50 @@ mod v1 { } struct NodeIterator { - current: Option> + current: Option>, } impl NodeIterator { - fn from(node: Rc) -> NodeIterator { NodeIterator { current: Some(node) } } + fn from(node: Rc) -> NodeIterator { + NodeIterator { + current: Some(node), + } + } } impl Iterator for NodeIterator { type Item = Rc; fn next(&mut self) -> Option> { let next = self.current.as_ref().map(|n| Rc::clone(n)); - self.current = - match self.current.as_ref() { - Some(n) => n.parent.as_ref().map(|n| Rc::clone(n)), - None => None - }; + self.current = match self.current.as_ref() { + Some(n) => n.parent.as_ref().map(|n| Rc::clone(n)), + None => None, + }; next } } impl Node { fn new(parent: Option>, length_to_parent: u32, key: char) -> Self { - Node { parent, length_to_parent, key } + Node { + parent, + length_to_parent, + key, + } } } - fn iter(node: Rc) -> NodeIterator { NodeIterator::from(node) } - fn nb_of_keys(node: Rc) -> u32 { iter(node).count() as u32 - 1 } + fn nb_of_keys(node: Rc) -> u32 { + iter(node).count() as u32 - 1 + } - fn length(node: Rc) -> u32 { iter(node).fold(0, |sum, node| sum + node.length_to_parent) } + fn length(node: Rc) -> u32 { + iter(node).fold(0, |sum, node| sum + node.length_to_parent) + } fn can_open(node: Rc, door: char) -> bool { let key_needed = door.to_ascii_lowercase(); @@ -84,7 +99,7 @@ mod v1 { #[allow(dead_code)] pub fn nb_steps_to_collect_all_key(vault: &Vault) -> u32 { - fn find_keys(from : (i32, i32), parent: Rc, vault: &Vault) -> Vec> { + fn find_keys(from: (i32, i32), parent: Rc, vault: &Vault) -> Vec> { let mut to_visit = vec![(from, 1)]; let mut visited_positions: HashSet<(i32, i32)> = HashSet::new(); let mut reachable_keys = Vec::>::new(); @@ -95,30 +110,46 @@ mod v1 { } while let Some((pos, steps)) = to_visit.pop() { - - if cfg!(debug_assertions) { println!("Pos to visit: {:?}", pos); } + if cfg!(debug_assertions) { + println!("Pos to visit: {:?}", pos); + } visited_positions.insert(pos); for pos_d in &[(-1, 0), (0, 1), (1, 0), (0, -1)] { let adjacent = (pos.0 + pos_d.0, pos.1 + pos_d.1); - if cfg!(debug_assertions) { println!("Adjacent: {:?}", adjacent); } + if cfg!(debug_assertions) { + println!("Adjacent: {:?}", adjacent); + } if !visited_positions.contains(&adjacent) { match vault.tunnels[adjacent.0 as usize][adjacent.1 as usize] { // Simple floor or a door or a owned key. - c if c == FLOOR_SYMBOL || c == START_SYMBOL || c.is_ascii_uppercase() && can_open(Rc::clone(&parent), c) || c.is_ascii_lowercase() && has_key(Rc::clone(&parent), c) => { - if cfg!(debug_assertions) { println!("-> To visit"); } + c if c == FLOOR_SYMBOL + || c == START_SYMBOL + || c.is_ascii_uppercase() && can_open(Rc::clone(&parent), c) + || c.is_ascii_lowercase() && has_key(Rc::clone(&parent), c) => + { + if cfg!(debug_assertions) { + println!("-> To visit"); + } to_visit.push((adjacent, steps + 1)); - }, - c if c.is_ascii_lowercase() => { // A non-owned key. - if cfg!(debug_assertions) { println!("-> A new key! {:?}", c); } + } + c if c.is_ascii_lowercase() => { + // A non-owned key. + if cfg!(debug_assertions) { + println!("-> A new key! {:?}", c); + } visited_positions.insert(adjacent); let node = Rc::new(Node::new(Some(Rc::clone(&parent)), steps, c)); reachable_keys.append(&mut find_keys(adjacent, node, vault)); - }, - _ => if cfg!(debug_assertions) { println!("-> WALL") }, + } + _ => { + if cfg!(debug_assertions) { + println!("-> WALL") + } + } } } } @@ -134,7 +165,13 @@ mod v1 { let root = Rc::new(Node::new(None, 0, START_SYMBOL)); let nodes = find_keys(vault.entrance, root, vault); - nodes.iter().map(|n| (length(Rc::clone(n)), nb_of_keys(Rc::clone(n)))).sorted_by(|(l1, n1), (l2, n2)| n1.cmp(&n2).then(l1.cmp(&l2))).next().unwrap().0 + nodes + .iter() + .map(|n| (length(Rc::clone(n)), nb_of_keys(Rc::clone(n)))) + .sorted_by(|(l1, n1), (l2, n2)| n1.cmp(&n2).then(l1.cmp(&l2))) + .next() + .unwrap() + .0 } } @@ -145,19 +182,34 @@ mod v2 { struct Path { to_visit: Vec<(i32, i32)>, visited: HashSet<(i32, i32)>, - keys: Vec + keys: Vec, } impl Path { pub fn new(initial_position: (i32, i32)) -> Self { - Path { to_visit: vec![initial_position], visited: HashSet::new(), keys: Vec::new() } + Path { + to_visit: vec![initial_position], + visited: HashSet::new(), + keys: Vec::new(), + } } } pub fn nb_steps_to_collect_all_key(vault: &Vault) -> u32 { - let nb_of_keys: usize = vault.tunnels.iter().map(|line| line.iter().fold(0, |acc, c| if c.is_ascii_lowercase() { acc + 1 } else { acc })).sum(); - - if cfg!(debug_assertions) { println!("nb_of_keys = {}", nb_of_keys); } + let nb_of_keys: usize = vault + .tunnels + .iter() + .map(|line| { + line.iter().fold( + 0, + |acc, c| if c.is_ascii_lowercase() { acc + 1 } else { acc }, + ) + }) + .sum(); + + if cfg!(debug_assertions) { + println!("nb_of_keys = {}", nb_of_keys); + } let mut paths = vec![Path::new(vault.entrance)]; @@ -166,9 +218,11 @@ mod v2 { step += 1; let mut new_paths: Vec = Vec::new(); - if cfg!(debug_assertions) { println!("----------------------------\n{:?}", paths); } + if cfg!(debug_assertions) { + println!("----------------------------\n{:?}", paths); + } - for i in (0 .. paths.len()).rev() { + for i in (0..paths.len()).rev() { let path = &mut paths[i]; let to_visit = path.to_visit.clone(); @@ -185,18 +239,26 @@ mod v2 { let c = vault.tunnels[adjacent.0 as usize][adjacent.1 as usize]; if c == WALL_SYMBOL { - } - else if c.is_ascii_lowercase() && !path.keys.contains(&c) { + } else if c.is_ascii_lowercase() && !path.keys.contains(&c) { if path.keys.len() + 1 == nb_of_keys { return step; } - let mut new_path = Path { to_visit: vec![adjacent], visited: HashSet::new(), keys: path.keys.clone() }; + let mut new_path = Path { + to_visit: vec![adjacent], + visited: HashSet::new(), + keys: path.keys.clone(), + }; new_path.keys.push(c); new_paths.push(new_path); } // Simple floor or a door or a owned key. - else if c == FLOOR_SYMBOL || c == START_SYMBOL || c.is_ascii_lowercase() || c.is_ascii_uppercase() && path.keys.contains(&c.to_ascii_lowercase()) { + else if c == FLOOR_SYMBOL + || c == START_SYMBOL + || c.is_ascii_lowercase() + || c.is_ascii_uppercase() + && path.keys.contains(&c.to_ascii_lowercase()) + { path.to_visit.push(adjacent); } } @@ -223,18 +285,21 @@ mod tests { #[test] fn part1_sample1() { - let input = - "######### - #b.A.@.a# - #########"; + let input = "######### +#b.A.@.a# +#########"; let vault = Vault::parse(input); dbg!(&vault); - if cfg!(debug_assertions) { println!("===== Version 1 =====") } + if cfg!(debug_assertions) { + println!("===== Version 1 =====") + } let steps_v1 = v1::nb_steps_to_collect_all_key(&vault); - if cfg!(debug_assertions) { println!("===== Version 2 =====") } + if cfg!(debug_assertions) { + println!("===== Version 2 =====") + } let steps_v2 = v2::nb_steps_to_collect_all_key(&vault); assert_eq!(steps_v1, steps_v2); @@ -244,12 +309,11 @@ mod tests { #[test] fn part1_sample2() { - let input = - "######################## - #f.D.E.e.C.b.A.@.a.B.c.# - ######################.# - #d.....................# - ########################"; + let input = "######################## +#f.D.E.e.C.b.A.@.a.B.c.# +######################.# +#d.....................# +########################"; let vault = Vault::parse(input); @@ -263,12 +327,11 @@ mod tests { #[test] fn part1_sample3() { - let input = - "######################## - #...............b.C.D.f# - #.###################### - #.....@.a.B.c.d.A.e.F.g# - ########################"; + let input = "######################## +#...............b.C.D.f# +#.###################### +#.....@.a.B.c.d.A.e.F.g# +########################"; let vault = Vault::parse(input); @@ -282,16 +345,15 @@ mod tests { #[test] fn part1_sample4() { - let input = - "################# - #i.G..c...e..H.p# - ########.######## - #j.A..b...f..D.o# - ########@######## - #k.E..a...g..B.n# - ########.######## - #l.F..d...h..C.m# - #################"; + let input = "################# +#i.G..c...e..H.p# +########.######## +#j.A..b...f..D.o# +########@######## +#k.E..a...g..B.n# +########.######## +#l.F..d...h..C.m# +#################"; let vault = Vault::parse(input); @@ -305,12 +367,11 @@ mod tests { #[test] fn part1_sample4b() { - let input = - "################# - #j.A..b...a..D.o# - ########@######## - #k.E..e...d..B.n# - #################"; + let input = "################# +#j.A..b...a..D.o# +########@######## +#k.E..e...d..B.n# +#################"; let vault = Vault::parse(input); @@ -324,13 +385,12 @@ mod tests { #[test] fn part1_sample5() { - let input = - "######################## - #@..............ac.GI.b# - ###d#e#f################ - ###A#B#C################ - ###g#h#i################ - ########################"; + let input = "######################## +#@..............ac.GI.b# +###d#e#f################ +###A#B#C################ +###g#h#i################ +########################"; let vault = Vault::parse(input); @@ -341,4 +401,4 @@ mod tests { println!("Steps: {}", steps_v1); } -} \ No newline at end of file +} diff --git a/src/intcode.rs b/src/intcode.rs index fee58ca..e446932 100644 --- a/src/intcode.rs +++ b/src/intcode.rs @@ -2,26 +2,28 @@ enum Mode { Position, Immediate, - Relative + Relative, } pub trait IO { fn read(&mut self) -> i64; fn write(&mut self, value: i64); - fn halt(&self) -> bool { false } - fn finished(&mut self) { } + fn halt(&self) -> bool { + false + } + fn finished(&mut self) {} } struct Buffer { output: Vec, - input: Vec + input: Vec, } impl Buffer { fn from(input: &[i64]) -> Self { Buffer { output: Vec::new(), - input: Vec::from(input) + input: Vec::from(input), } } } @@ -38,7 +40,7 @@ impl IO for Buffer { // 'true' -> immediate mode, 'false' -> position mode. fn read_op_and_modes(mut code: i64) -> (i64, [Mode; 3]) { - let mut modes: [Mode; 3] = [ Mode::Position, Mode::Position, Mode::Position ]; + let mut modes: [Mode; 3] = [Mode::Position, Mode::Position, Mode::Position]; for i in (2..=4).rev() { let power = 10i64.pow(i); @@ -66,22 +68,35 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) { let mut relative_base = 0; fn read(position: usize, code: &[i64], mode: Mode, relative_base: i64) -> i64 { - if position >= code.len() { return 0 } + if position >= code.len() { + return 0; + } match mode { - Mode::Position => if code[position] as usize >= code.len() { 0 } else { code[code[position] as usize] }, + Mode::Position => { + if code[position] as usize >= code.len() { + 0 + } else { + code[code[position] as usize] + } + } Mode::Immediate => code[position], - Mode::Relative => if (code[position] + relative_base) as usize >= code.len() { 0 } else { code[(code[position] + relative_base) as usize] } + Mode::Relative => { + if (code[position] + relative_base) as usize >= code.len() { + 0 + } else { + code[(code[position] + relative_base) as usize] + } + } } } fn write(position: usize, value: i64, code: &mut Vec, mode: Mode, relative_base: i64) { - let ref_position = - match mode { - Mode::Position => code[position] as usize, - Mode::Immediate => panic!("Can't write un immediate mode"), - Mode::Relative => (code[position] + relative_base) as usize - }; + let ref_position = match mode { + Mode::Position => code[position] as usize, + Mode::Immediate => panic!("Can't write un immediate mode"), + Mode::Relative => (code[position] + relative_base) as usize, + }; if ref_position >= code.len() { code.resize(ref_position + 1, 0); @@ -90,7 +105,13 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) { code[ref_position] = value; } - fn jump_if(cond: bool, cursor: usize, code: &[i64], modes: [Mode; 3], relative_base: i64) -> usize { + fn jump_if( + cond: bool, + cursor: usize, + code: &[i64], + modes: [Mode; 3], + relative_base: i64, + ) -> usize { let value = read(cursor + 1, &code, modes[0], relative_base); if cond == (value != 0) { read(cursor + 2, &code, modes[1], relative_base) as usize @@ -100,22 +121,38 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) { } loop { - if io.halt() { break; } + if io.halt() { + break; + } let (op, modes) = read_op_and_modes(code[cursor]); match op { // Sum. 1 => { - write(cursor + 3, read(cursor + 1, &code, modes[0], relative_base) + read(cursor + 2, &code, modes[1], relative_base), &mut code, modes[2], relative_base); + write( + cursor + 3, + read(cursor + 1, &code, modes[0], relative_base) + + read(cursor + 2, &code, modes[1], relative_base), + &mut code, + modes[2], + relative_base, + ); cursor += 4; - }, + } // Multiply. 2 => { - write(cursor + 3, read(cursor + 1, &code, modes[0], relative_base) * read(cursor + 2, &code, modes[1], relative_base), &mut code, modes[2], relative_base); + write( + cursor + 3, + read(cursor + 1, &code, modes[0], relative_base) + * read(cursor + 2, &code, modes[1], relative_base), + &mut code, + modes[2], + relative_base, + ); cursor += 4; - }, + } // Input. 3 => { @@ -137,15 +174,39 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) { // Less than. 7 => { - write(cursor + 3, if read(cursor + 1, &code, modes[0], relative_base) < read(cursor + 2, &code, modes[1], relative_base) { 1 } else { 0 }, &mut code, modes[2], relative_base); + write( + cursor + 3, + if read(cursor + 1, &code, modes[0], relative_base) + < read(cursor + 2, &code, modes[1], relative_base) + { + 1 + } else { + 0 + }, + &mut code, + modes[2], + relative_base, + ); cursor += 4; - }, + } // Equals. 8 => { - write(cursor + 3, if read(cursor + 1, &code, modes[0], relative_base) == read(cursor + 2, &code, modes[1], relative_base) { 1 } else { 0 }, &mut code, modes[2], relative_base); + write( + cursor + 3, + if read(cursor + 1, &code, modes[0], relative_base) + == read(cursor + 2, &code, modes[1], relative_base) + { + 1 + } else { + 0 + }, + &mut code, + modes[2], + relative_base, + ); cursor += 4; - }, + } // Change relative base. 9 => { @@ -155,7 +216,7 @@ pub fn execute_op_code_with_custom_io(code: &[i64], io: &mut dyn IO) { 99 => break, - _ => panic!("Unknown code: {}", code[cursor]) + _ => panic!("Unknown code: {}", code[cursor]), } } @@ -168,7 +229,11 @@ mod tests_day05 { #[test] fn part2() { - let c = [3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99]; + let c = [ + 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0, + 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, + 20, 1105, 1, 46, 98, 99, + ]; let r1 = execute_op_code(&c, &[7]); assert_eq!(r1[0], 999); @@ -187,22 +252,24 @@ mod tests_day09 { #[test] fn copy_of_itself() { - let c = [109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99]; + let c = [ + 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, + ]; let r = execute_op_code(&c, &Vec::new()); assert_eq!(r, c); } #[test] fn output_big_number() { - let c = [1102,34_915_192,34_915_192,7,4,7,99,0]; + let c = [1102, 34_915_192, 34_915_192, 7, 4, 7, 99, 0]; let r = execute_op_code(&c, &Vec::new()); assert_eq!(r[0], 1_219_070_632_396_864); } #[test] fn input_big_number() { - let c = [104,1_125_899_906_842_624,99]; + let c = [104, 1_125_899_906_842_624, 99]; let r = execute_op_code(&c, &Vec::new()); assert_eq!(r[0], 1_125_899_906_842_624); } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index ef4a7a7..e23f773 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ use std::fs; use std::time::Instant; mod common; -mod intcode; mod day01; mod day02; mod day03; @@ -20,15 +19,24 @@ mod day15; mod day16; mod day17; mod day18; +mod intcode; fn day01() -> String { let masses = common::read_list_of_numbers("data/day01.input", "\n"); - format!("part1: {}, part2: {}", day01::sum_mass_to_fuel(&masses), day01::sum_mass_to_fuel_2(&masses)) + format!( + "part1: {}, part2: {}", + day01::sum_mass_to_fuel(&masses), + day01::sum_mass_to_fuel_2(&masses) + ) } fn day02() -> String { let code = common::read_list_of_numbers("data/day02.input", ","); - format!("part1: {}, part2: {}", day02::execute_op_code_with_state_fixed(&mut Vec::from(&code[..])), day02::find_noun_and_verb(&code)) + format!( + "part1: {}, part2: {}", + day02::execute_op_code_with_state_fixed(&mut Vec::from(&code[..])), + day02::find_noun_and_verb(&code) + ) } fn day03() -> String { @@ -36,33 +44,55 @@ fn day03() -> String { let movements: Vec<&str> = file_content.lines().collect(); format!( "part1: {}, part2: {}", - day03::manhattan_distance_from_cross_to_port(&day03::split_movements(&movements[0]), &day03::split_movements(&movements[1])), - day03::first_cross_sum_of_lengths(&day03::split_movements(&movements[0]), &day03::split_movements(&movements[1])) + day03::manhattan_distance_from_cross_to_port( + &day03::split_movements(&movements[0]), + &day03::split_movements(&movements[1]) + ), + day03::first_cross_sum_of_lengths( + &day03::split_movements(&movements[0]), + &day03::split_movements(&movements[1]) + ) ) } fn day04() -> String { let raw = fs::read_to_string("data/day04.input").unwrap(); let (min, max) = day04::parse_range(&raw); - format!("part1: {:?}, part2: {}", day04::nb_passwords_part1(min, max), day04::nb_passwords_part2(min, max)) + format!( + "part1: {:?}, part2: {}", + day04::nb_passwords_part1(min, max), + day04::nb_passwords_part2(min, max) + ) } fn day05() -> String { let code = common::read_list_of_numbers("data/day05.input", ","); - format!("part1: {:?}, part2: {:?}", intcode::execute_op_code(&code, &[1]), intcode::execute_op_code(&code, &[5])) + format!( + "part1: {:?}, part2: {:?}", + intcode::execute_op_code(&code, &[1]), + intcode::execute_op_code(&code, &[5]) + ) } fn day06() -> String { let file_content = fs::read_to_string("data/day06.input").unwrap(); let lines: Vec<&str> = file_content.lines().collect(); let orbits = day06::build_orbits(&lines); - format!("part1: {}, part2: {}", day06::total_direct_and_indirect_orbits(&orbits), day06::nb_orbital_transfers(&orbits, "SAN", "YOU")) + format!( + "part1: {}, part2: {}", + day06::total_direct_and_indirect_orbits(&orbits), + day06::nb_orbital_transfers(&orbits, "SAN", "YOU") + ) } fn day07() -> String { let code = common::read_list_of_numbers("data/day07.input", ","); - format!("part1: {}, part2: {}", day07::find_largest_last_thruster_signal(&code), day07::find_largest_last_thruster_signal_with_feedback_loop(&code)) + format!( + "part1: {}, part2: {}", + day07::find_largest_last_thruster_signal(&code), + day07::find_largest_last_thruster_signal_with_feedback_loop(&code) + ) } fn day08() -> String { @@ -74,13 +104,21 @@ fn day08() -> String { let layer = day08::layer_with_fewer_0(&layers[..]); let merged = day08::merge_layers(&layers[..]); - format!("part1: {}, part2:\n{}", day08::one_digits_times_two_digits(layer), common::layer_to_printable_string(&merged, 25)) + format!( + "part1: {}, part2:\n{}", + day08::one_digits_times_two_digits(layer), + common::layer_to_printable_string(&merged, 25) + ) } fn day09() -> String { let code = common::read_list_of_numbers::<&str, i64>("data/day09.input", ","); - format!("part1: {:?}, part2: {:?}", intcode::execute_op_code(&code, &[1]), intcode::execute_op_code(&code, &[2])) + format!( + "part1: {:?}, part2: {:?}", + intcode::execute_op_code(&code, &[1]), + intcode::execute_op_code(&code, &[2]) + ) } fn day10() -> String { @@ -95,32 +133,52 @@ fn day11() -> String { let panels = day11::run_robot(&code, 1); let (layer, width) = day11::panels_to_layer(&panels); - format!("part1: {:?}, part2:\n{}", day11::run_robot(&code, 0).len(), common::layer_to_printable_string(&layer, width)) + format!( + "part1: {:?}, part2:\n{}", + day11::run_robot(&code, 0).len(), + common::layer_to_printable_string(&layer, width) + ) } fn day12() -> String { let coordinates = day12::parse_positions(&fs::read_to_string("data/day12.input").unwrap()); - format!("part1: {}, part2: {}", day12::final_energy(&coordinates, 1000), day12::find_same_state(&coordinates)) + format!( + "part1: {}, part2: {}", + day12::final_energy(&coordinates, 1000), + day12::find_same_state(&coordinates) + ) } fn day13() -> String { let code = common::read_list_of_numbers::<&str, i64>("data/day13.input", ","); let mut modified_code = Vec::from(&code[..]); modified_code[0] = 2; - format!("part1: {}, part2: {}", day13::count_nb_block(&code), day13::final_score(&modified_code)) + format!( + "part1: {}, part2: {}", + day13::count_nb_block(&code), + day13::final_score(&modified_code) + ) } fn day14() -> String { let reactions = day14::parse(&fs::read_to_string("data/day14.input").unwrap()); let ore_per_fuel = day14::ore_needed_per_fuel(&reactions); - format!("part1: {}, part2: {}", ore_per_fuel, day14::fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel)) + format!( + "part1: {}, part2: {}", + ore_per_fuel, + day14::fuel_produced(&reactions, 1_000_000_000_000, ore_per_fuel) + ) } fn day15() -> String { let code = common::read_list_of_numbers("data/day15.input", ","); let (n, dts) = day15::nb_of_movement_to_reach_oxygen(&code); - format!("part1: {}, part2: {}", n, day15::time_to_flood_the_area(&dts)) + format!( + "part1: {}, part2: {}", + n, + day15::time_to_flood_the_area(&dts) + ) } fn day16() -> String { @@ -128,7 +186,11 @@ fn day16() -> String { let signal = day16::parse(&signal_raw); let output_part_1 = day16::fft(&signal, &[0, 1, 0, -1], 100, 0, 8, 1); // let output_part_2 = day16::part2(&signal); - format!("part1: {}, part2: {}", day16::digits_as_string(&output_part_1), /*day16::digits_as_string(&output_part_2)*/ "") + format!( + "part1: {}, part2: {}", + day16::digits_as_string(&output_part_1), + /*day16::digits_as_string(&output_part_2)*/ "" + ) } fn day17() -> String { @@ -159,51 +221,40 @@ fn format_micros(t: u128) -> String { fn do_day(days: &[fn() -> String], day: usize) { let now = Instant::now(); - println!("Result of day {:02}: {} (time: {})", day, days[day - 1](), format_micros(now.elapsed().as_micros())); + println!( + "Result of day {:02}: {} (time: {})", + day, + days[day - 1](), + format_micros(now.elapsed().as_micros()) + ); } fn main() { println!("https://adventofcode.com/2019"); - let days: Vec String> = vec!( - day01, - day02, - day03, - day04, - day05, - day06, - day07, - day08, - day09, - day10, - day11, - day12, - day13, - day14, - day15, - day16, - day17, - day18, - ); + let days: Vec String> = vec![ + day01, day02, day03, day04, day05, day06, day07, day08, day09, day10, day11, day12, day13, + day14, day15, day16, day17, day18, + ]; let args: Vec = env::args().skip(1).collect(); // No argument -> execute all day problems. if args.is_empty() { let now = Instant::now(); - for i in 1 ..= days.len() { + for i in 1..=days.len() { do_day(&days, i) } - println!("Time to execute all days: {}", format_micros(now.elapsed().as_micros())); + println!( + "Time to execute all days: {}", + format_micros(now.elapsed().as_micros()) + ); } else { for arg in args { match arg.parse::() { - Ok(day) if day >= 1 && day <= days.len() => - do_day(&days, day), - Ok(day) => - println!("Unknown day: {}", day), - Err(error) => - println!("Unable to parse day number: \"{}\", error: {}", arg, error) + Ok(day) if day >= 1 && day <= days.len() => do_day(&days, day), + Ok(day) => println!("Unknown day: {}", day), + Err(error) => println!("Unable to parse day number: \"{}\", error: {}", arg, error), } } }