+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, "")
+}