--- /dev/null
+[submodule "advent_of_code_common"]
+ path = advent_of_code_common
+ url = ssh://gitolite3@gburri.org:9851/advent_of_code_common.git
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-itertools = "0.10"
+advent_of_code_common = { path = "advent_of_code_common" }
+
+itertools = "0.13"
threadpool = "1.8"
regex = "1"
num = "0.4"
-num_enum = "0.5"
\ No newline at end of file
+num_enum = "0.7"
+rustc-hash = "2.1"
+
+[profile.release]
+opt-level = 3
+lto = true
+codegen-units = 1
+debug = true # Needed by 'cargo flamegraph' when profiling.
--- /dev/null
+Subproject commit b9fa0908044042af2ca3dd66281b58afd289b4e4
-use std::{fs, path::Path, str::FromStr};\r
+use std::{\r
+ io::{read_to_string, BufRead},\r
+ str::FromStr,\r
+};\r
\r
-pub fn read_list_of_numbers<P, T>(file: P, sep: &str) -> Vec<T>\r
+pub fn read_list_of_numbers<T>(reader: &mut dyn BufRead, sep: &str) -> Vec<T>\r
where\r
- P: AsRef<Path>,\r
T: FromStr,\r
- T::Err: std::fmt::Debug\r
-\r
+ T::Err: std::fmt::Debug,\r
{\r
- fs::read_to_string(file).unwrap().split(sep).map(|line| line.trim().parse::<T>().unwrap()).collect()\r
+ read_to_string(reader)\r
+ .unwrap()\r
+ .split(sep)\r
+ .map(|line| line.trim().parse::<T>().unwrap())\r
+ .collect()\r
}\r
\r
pub fn layer_to_printable_string(layer: &[u8], width: usize) -> String {\r
let mut i = 0;\r
\r
loop {\r
- for _ in 0 .. width {\r
+ for _ in 0..width {\r
if layer[i] == 0 {\r
result += " ";\r
} else {\r
result += "█";\r
}\r
i += 1;\r
- if i >= layer.len() { return result }\r
+ if i >= layer.len() {\r
+ return result;\r
+ }\r
}\r
result += "\n";\r
}\r
-}
\ No newline at end of file
+}\r
-use std::{\r
- collections::{HashMap, HashSet},\r
- iter::{FromIterator, Iterator},\r
-};\r
+use std::iter::{FromIterator, Iterator};\r
+\r
+use rustc_hash::{FxHashMap, FxHashSet};\r
\r
pub fn split_movements(movements: &str) -> Vec<&str> {\r
movements.split(',').collect()\r
}\r
\r
pub fn manhattan_distance_from_cross_to_port(wire1: &[&str], wire2: &[&str]) -> i32 {\r
- let positions_wire1: HashSet<(i32, i32)> = HashSet::from_iter(positions(wire1));\r
- let positions_wire2: HashSet<(i32, i32)> = HashSet::from_iter(positions(wire2));\r
- let cross: HashSet<_> = positions_wire1.intersection(&positions_wire2).collect();\r
+ let positions_wire1: FxHashSet<(i32, i32)> = FxHashSet::from_iter(positions(wire1));\r
+ let positions_wire2: FxHashSet<(i32, i32)> = FxHashSet::from_iter(positions(wire2));\r
+ let cross: FxHashSet<_> = positions_wire1.intersection(&positions_wire2).collect();\r
cross.iter().map(|(x, y)| x.abs() + y.abs()).min().unwrap()\r
}\r
\r
pub fn first_cross_sum_of_lengths(wire1: &[&str], wire2: &[&str]) -> usize {\r
let positions_wire1 = positions(wire1);\r
- let positions_wire1_indexed: HashMap<&(i32, i32), usize> = HashMap::from_iter(\r
+ let positions_wire1_indexed: FxHashMap<&(i32, i32), usize> = FxHashMap::from_iter(\r
positions_wire1\r
.iter()\r
.enumerate()\r
-use std::{cmp, collections::HashMap};
+use std::cmp;
+
+use rustc_hash::FxHashMap;
// All planets indexing their parent (planet -> parent).
-type Orbits = HashMap<String, String>;
+type Orbits = FxHashMap<String, String>;
pub fn build_orbits(orbits_str: &[&str]) -> Orbits {
- let mut orbits = Orbits::new();
+ let mut orbits = Orbits::default();
for orbit in orbits_str {
let planets: Vec<&str> = orbit.trim().split(')').collect();
orbits.insert(String::from(planets[1]), String::from(planets[0]));
-use std::collections::{HashMap, HashSet};
+use rustc_hash::{FxHashMap, FxHashSet};
pub fn read_map(raw: &str) -> Vec<(i32, i32)> {
let lines: Vec<&str> = raw.lines().map(|l| l.trim()).collect();
let mut best_nb_observable_asteroid = 0;
let (mut best_x, mut best_y) = (0, 0);
for (x1, y1) in map {
- let mut angles = HashSet::<i64>::new();
+ let mut angles = FxHashSet::<i64>::default();
for (x2, y2) in map {
angles.insert(angle(*x1, *y1, *x2, *y2));
}
n: usize,
) -> (i32, i32) {
// Angle -> [(position, distance)].
- let mut asteroids = HashMap::<i64, PositionsAndDistances>::new();
+ let mut asteroids = FxHashMap::<i64, PositionsAndDistances>::default();
let (x1, y1) = pos;
for (x2, y2) in map {
-use std::collections::HashMap;\r
+use rustc_hash::FxHashMap;\r
\r
use super::intcode;\r
\r
next_command: NextCommand,\r
current_pos: (i32, i32),\r
current_dir: i32, // 0: up, 1: right, 2: down, 3: left.\r
- panels: HashMap<(i32, i32), i64>,\r
+ panels: FxHashMap<(i32, i32), i64>,\r
}\r
\r
impl Robot {\r
next_command: NextCommand::Paint,\r
current_pos: (0, 0),\r
current_dir: 0,\r
- panels: HashMap::new(),\r
+ panels: FxHashMap::default(),\r
}\r
}\r
}\r
}\r
}\r
\r
-pub fn run_robot(code: &[i64], initial_value: i64) -> HashMap<(i32, i32), i64> {\r
+pub fn run_robot(code: &[i64], initial_value: i64) -> FxHashMap<(i32, i32), i64> {\r
let mut robot = Robot::new();\r
if initial_value != 0 {\r
robot.panels.insert((0, 0), initial_value);\r
robot.panels\r
}\r
\r
-pub fn panels_to_layer(panels: &HashMap<(i32, i32), i64>) -> (Vec<u8>, usize) {\r
+pub fn panels_to_layer(panels: &FxHashMap<(i32, i32), i64>) -> (Vec<u8>, usize) {\r
let coordinates: Vec<&(i32, i32)> = panels.keys().collect();\r
let min_x = coordinates.iter().min_by_key(|(x, _)| x).unwrap().0;\r
let max_x = coordinates.iter().max_by_key(|(x, _)| x).unwrap().0;\r
impl AddAssign for Vector3D {
fn add_assign(&mut self, other: Self) {
- *self = Self {
- x: self.x + other.x,
- y: self.y + other.y,
- z: self.z + other.z,
- };
+ self.x += other.x;
+ self.y += other.y;
+ self.z += other.z;
}
}
-use std::collections::HashMap;
+use rustc_hash::FxHashMap;
#[derive(Debug)]
pub struct Chemical {
name: String,
}
-type Reactions = HashMap<String, (i64, Vec<Chemical>)>;
+type Reactions = FxHashMap<String, (i64, Vec<Chemical>)>;
fn parse_chemical(input: &str) -> Chemical {
let quantity_and_name: Vec<&str> = input.trim().split(' ').collect();
}
pub fn parse(input: &str) -> Reactions {
- let mut result = Reactions::new();
+ let mut result = Reactions::default();
for line in input.lines() {
let reaction: Vec<&str> = line.split("=>").collect();
let input_chemicals: Vec<Chemical> = reaction[0].split(',').map(parse_chemical).collect();
}
pub fn ore_needed_per_fuel(reactions: &Reactions) -> i64 {
- let mut remainders = HashMap::new();
+ let mut remainders = FxHashMap::default();
ore_needed(reactions, 1, &mut remainders)
}
fn ore_needed(
reactions: &Reactions,
fuel_quantity: i64,
- remainders: &mut HashMap<String, i64>,
+ remainders: &mut FxHashMap<String, i64>,
) -> i64 {
fn needed(
reactions: &Reactions,
chemicals: &[Chemical],
- remainders: &mut HashMap<String, i64>,
+ remainders: &mut FxHashMap<String, i64>,
) -> i64 {
chemicals.iter().fold(0, |sum, chemical| {
let quantity_needed = match remainders.get(&chemical.name) {
pub fn fuel_produced(reactions: &Reactions, ore: i64, ore_per_fuel: i64) -> i64 {
let mut ore_available = ore;
let mut fuel_produced = 0;
- let mut remainders = HashMap::new();
+ let mut remainders = FxHashMap::default();
loop {
let fuel = 1.max(ore_available / ore_per_fuel); // Approximate the fuel we can produce.
-use std::{\r
- collections::{HashMap, HashSet},\r
- iter::FromIterator,\r
-};\r
+use std::iter::FromIterator;\r
+\r
+use rustc_hash::{FxHashMap, FxHashSet};\r
\r
use super::intcode;\r
\r
\r
#[derive(Clone)]\r
pub struct DroidTrackingSystem {\r
- board: HashMap<(i32, i32), LocationState>,\r
+ board: FxHashMap<(i32, i32), LocationState>,\r
current_path: Vec<(i32, i32)>,\r
oxygen_location: (i32, i32),\r
steps_to_oxygen: i32,\r
impl DroidTrackingSystem {\r
fn new() -> Self {\r
DroidTrackingSystem {\r
- board: HashMap::from_iter(vec![((0, 0), LocationState::Visited)].into_iter()),\r
+ board: FxHashMap::from_iter(vec![((0, 0), LocationState::Visited)].into_iter()),\r
current_path: vec![(0, 0)],\r
oxygen_location: (0, 0),\r
steps_to_oxygen: 0,\r
pub fn time_to_flood_the_area(dts: &DroidTrackingSystem) -> i32 {\r
let mut dts = dts.clone(); // To be mutable.\r
dts.current_path = vec![dts.oxygen_location];\r
- let mut visited: HashSet<(i32, i32)> = HashSet::from_iter(dts.current_path.iter().copied());\r
+ let mut visited: FxHashSet<(i32, i32)> = FxHashSet::from_iter(dts.current_path.iter().copied());\r
let mut max_length = 0;\r
\r
'main: while !dts.current_path.is_empty() {\r
-use std::{collections::HashSet, convert::TryFrom, ops::Range};\r
+use std::{convert::TryFrom, ops::Range};\r
+\r
+use rustc_hash::FxHashSet;\r
\r
use itertools::Itertools;\r
\r
fn run_through(&mut self) {\r
let (mut x, mut y) = self.start_position;\r
let mut dir = self.start_dir;\r
- let mut visited_locations = HashSet::<(i32, i32)>::new();\r
+ let mut visited_locations = FxHashSet::<(i32, i32)>::default();\r
visited_locations.insert((x, y));\r
\r
let mut last_mov = Movement::Left;\r
-use itertools::Itertools;
-use std::collections::HashSet;
use std::rc::Rc;
+use itertools::Itertools;
+use rustc_hash::FxHashSet;
+
#[derive(Debug)]
pub struct Vault {
tunnels: Vec<Vec<char>>,
pub fn nb_steps_to_collect_all_key(vault: &Vault) -> u32 {
fn find_keys(from: (i32, i32), parent: Rc<Node>, vault: &Vault) -> Vec<Rc<Node>> {
let mut to_visit = vec![(from, 1)];
- let mut visited_positions: HashSet<(i32, i32)> = HashSet::new();
+ let mut visited_positions: FxHashSet<(i32, i32)> = FxHashSet::default();
let mut reachable_keys = Vec::<Rc<Node>>::new();
if cfg!(debug_assertions) {
#[derive(Debug)]
struct Path {
to_visit: Vec<(i32, i32)>,
- visited: HashSet<(i32, i32)>,
+ visited: FxHashSet<(i32, i32)>,
keys: Vec<char>,
}
pub fn new(initial_position: (i32, i32)) -> Self {
Path {
to_visit: vec![initial_position],
- visited: HashSet::new(),
+ visited: FxHashSet::default(),
keys: Vec::new(),
}
}
let mut new_path = Path {
to_visit: vec![adjacent],
- visited: HashSet::new(),
+ visited: FxHashSet::default(),
keys: path.keys.clone(),
};
new_path.keys.push(c);
--- /dev/null
+use std::io::{read_to_string, BufRead};
+
+use crate::*;
+
+pub fn day01(reader: &mut dyn BufRead) -> String {
+ let masses = common::read_list_of_numbers(reader, "\n");
+ format!(
+ "part1: {}, part2: {}",
+ day01::sum_mass_to_fuel(&masses),
+ day01::sum_mass_to_fuel_2(&masses)
+ )
+}
+
+pub fn day02(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers(reader, ",");
+ format!(
+ "part1: {}, part2: {}",
+ day02::execute_op_code_with_state_fixed(&mut Vec::from(&code[..])),
+ day02::find_noun_and_verb(&code)
+ )
+}
+
+pub fn day03(reader: &mut dyn BufRead) -> String {
+ let file_content = read_to_string(reader).unwrap();
+ 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])
+ )
+ )
+}
+
+pub fn day04(reader: &mut dyn BufRead) -> String {
+ let raw = read_to_string(reader).unwrap();
+ let (min, max) = day04::parse_range(&raw);
+ format!(
+ "part1: {:?}, part2: {}",
+ day04::nb_passwords_part1(min, max),
+ day04::nb_passwords_part2(min, max)
+ )
+}
+
+pub fn day05(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers(reader, ",");
+ format!(
+ "part1: {:?}, part2: {:?}",
+ intcode::execute_op_code(&code, &[1]),
+ intcode::execute_op_code(&code, &[5])
+ )
+}
+
+pub fn day06(reader: &mut dyn BufRead) -> String {
+ let file_content = read_to_string(reader).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")
+ )
+}
+
+pub fn day07(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers(reader, ",");
+
+ format!(
+ "part1: {}, part2: {}",
+ day07::find_largest_last_thruster_signal(&code),
+ day07::find_largest_last_thruster_signal_with_feedback_loop(&code)
+ )
+}
+
+pub fn day08(reader: &mut dyn BufRead) -> String {
+ let img = read_to_string(reader).unwrap();
+
+ let raw = day08::read_from_string(&img);
+ let layers = day08::decode_image(&raw, 25, 6);
+
+ 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)
+ )
+}
+
+pub fn day09(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers::<i64>(reader, ",");
+
+ format!(
+ "part1: {:?}, part2: {:?}",
+ intcode::execute_op_code(&code, &[1]),
+ intcode::execute_op_code(&code, &[2])
+ )
+}
+
+pub fn day10(reader: &mut dyn BufRead) -> String {
+ let map = day10::read_map(&read_to_string(reader).unwrap());
+ let (n, location) = day10::find_best_location(&map);
+ let (x, y) = day10::location_nth_vaporized_asteroid(location, &map, 200);
+ format!("part1: {}, part2: {}", n, x * 100 + y)
+}
+
+pub fn day11(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers::<i64>(reader, ",");
+ 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)
+ )
+}
+
+pub fn day12(reader: &mut dyn BufRead) -> String {
+ let coordinates = day12::parse_positions(&read_to_string(reader).unwrap());
+ format!(
+ "part1: {}, part2: {}",
+ day12::final_energy(&coordinates, 1000),
+ day12::find_same_state(&coordinates)
+ )
+}
+
+pub fn day13(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers::<i64>(reader, ",");
+ let mut modified_code = Vec::from(&code[..]);
+ modified_code[0] = 2;
+ format!(
+ "part1: {}, part2: {}",
+ day13::count_nb_block(&code),
+ day13::final_score(&modified_code)
+ )
+}
+
+pub fn day14(reader: &mut dyn BufRead) -> String {
+ let reactions = day14::parse(&read_to_string(reader).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)
+ )
+}
+
+pub fn day15(reader: &mut dyn BufRead) -> String {
+ let code = common::read_list_of_numbers(reader, ",");
+ let (n, dts) = day15::nb_of_movement_to_reach_oxygen(&code);
+ format!(
+ "part1: {}, part2: {}",
+ n,
+ day15::time_to_flood_the_area(&dts)
+ )
+}
+
+pub fn day16(reader: &mut dyn BufRead) -> String {
+ let signal_raw = read_to_string(reader).unwrap();
+ 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),
+ "<skipped: take too long ~ 20 s>" // day16::digits_as_string(&output_part_2)
+ )
+}
+
+pub fn day17(reader: &mut dyn BufRead) -> String {
+ let mut code = common::read_list_of_numbers(reader, ",");
+ let intersections = day17::scaffold_intersections(&code);
+ code[0] = 2;
+ let dust = day17::collected_dust(&code);
+ format!("part1: {}, part2: {}", intersections, dust)
+}
+
+pub fn day18(reader: &mut dyn BufRead) -> String {
+ let vault_raw = read_to_string(reader).unwrap();
+ let vault = day18::Vault::parse(&vault_raw);
+ let nb_steps = day18::nb_steps_to_collect_all_key(&vault);
+
+ format!("part1: {}, part2: {}", nb_steps, "")
+}
-use std::env;
-use std::fs;
-use std::time::Instant;
+use std::io::BufRead;
+
+use advent_of_code_common;
mod common;
mod day01;
mod day16;
mod day17;
mod day18;
+mod days;
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)
- )
-}
-
-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)
- )
-}
-
-fn day03() -> String {
- let file_content = fs::read_to_string("data/day03.input").unwrap();
- 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])
- )
- )
-}
-
-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)
- )
-}
-
-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])
- )
-}
-
-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")
- )
-}
-
-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)
- )
-}
-
-fn day08() -> String {
- let img = fs::read_to_string("data/day08.input").unwrap();
-
- let raw = day08::read_from_string(&img);
- let layers = day08::decode_image(&raw, 25, 6);
-
- 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)
- )
-}
-
-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])
- )
-}
-
-fn day10() -> String {
- let map = day10::read_map(&fs::read_to_string("data/day10.input").unwrap());
- let (n, location) = day10::find_best_location(&map);
- let (x, y) = day10::location_nth_vaporized_asteroid(location, &map, 200);
- format!("part1: {}, part2: {}", n, x * 100 + y)
-}
-
-fn day11() -> String {
- let code = common::read_list_of_numbers::<&str, i64>("data/day11.input", ",");
- 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)
- )
-}
-
-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)
- )
-}
-
-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)
- )
-}
-
-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)
- )
-}
-
-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)
- )
-}
-
-fn day16() -> String {
- let signal_raw = fs::read_to_string("data/day16.input").unwrap();
- 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)*/ "<skipped: take too long ~ 1 min>"
- )
-}
-
-fn day17() -> String {
- let mut code = common::read_list_of_numbers("data/day17.input", ",");
- let intersections = day17::scaffold_intersections(&code);
- code[0] = 2;
- let dust = day17::collected_dust(&code);
- format!("part1: {}, part2: {}", intersections, dust)
-}
-
-fn day18() -> String {
- let vault_raw = fs::read_to_string("data/day18.input").unwrap();
- let vault = day18::Vault::parse(&vault_raw);
- let nb_steps = day18::nb_steps_to_collect_all_key(&vault);
-
- format!("part1: {}, part2: {}", nb_steps, "")
-}
-
-fn format_micros(t: u128) -> String {
- if t < 10_000 {
- format!("{} μs", t)
- } else if t < 10_000_000u128 {
- format!("{} ms", t / 1_000u128)
- } else {
- format!("{} s", t / 1_000_000u128)
- }
-}
-
-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())
- );
-}
-
fn main() {
println!("https://adventofcode.com/2019");
- let days: Vec<fn() -> String> = vec![
- day01, day02, day03, day04, day05, day06, day07, day08, day09, day10, day11, day12, day13,
- day14, day15, day16, day17, day18,
+ let days: Vec<fn(&mut dyn BufRead) -> String> = vec![
+ days::day01,
+ days::day02,
+ days::day03,
+ days::day04,
+ days::day05,
+ days::day06,
+ days::day07,
+ days::day08,
+ days::day09,
+ days::day10,
+ days::day11,
+ days::day12,
+ days::day13,
+ days::day14,
+ days::day15,
+ days::day16,
+ days::day17,
+ days::day18,
+ // days::day19,
+ // days::day20,
+ // days::day21,
+ // days::day22,
+ // days::day23,
+ // days::day24,
];
- let args: Vec<String> = 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() {
- do_day(&days, i)
- }
- println!(
- "Time to execute all days: {}",
- format_micros(now.elapsed().as_micros())
- );
- } else {
- for arg in args {
- match arg.parse::<usize>() {
- 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),
- }
- }
- }
+ advent_of_code_common::run(days);
}