├── 2015 ├── Cargo.lock ├── Cargo.toml ├── run_clippy.bash ├── run_tests.bash ├── src │ └── bin │ │ ├── day01.rs │ │ ├── day02.rs │ │ ├── day03.rs │ │ ├── day04.rs │ │ ├── day05.rs │ │ ├── day06.rs │ │ ├── day07.rs │ │ ├── day08.rs │ │ ├── day09.rs │ │ ├── day10.rs │ │ ├── day11.rs │ │ ├── day12.rs │ │ ├── day13.rs │ │ ├── day14.rs │ │ ├── day15.rs │ │ ├── day16.rs │ │ ├── day17.rs │ │ ├── day18.rs │ │ ├── day19.rs │ │ ├── day20.rs │ │ ├── day21.rs │ │ ├── day22.rs │ │ ├── day23.rs │ │ ├── day24.rs │ │ └── day25.rs └── tests │ ├── day01.input │ ├── day01.output │ ├── day02.input │ ├── day02.output │ ├── day03.input │ ├── day03.output │ ├── day04.input │ ├── day04.output │ ├── day05.input │ ├── day05.output │ ├── day06.input │ ├── day06.output │ ├── day07.input │ ├── day07.output │ ├── day08.input │ ├── day08.output │ ├── day09.input │ ├── day09.output │ ├── day10.input │ ├── day10.output │ ├── day11.input │ ├── day11.output │ ├── day12.input │ ├── day12.output │ ├── day13.input │ ├── day13.output │ ├── day14.input │ ├── day14.output │ ├── day15.example.input │ ├── day15.example.output │ ├── day15.input │ ├── day15.output │ ├── day16.input │ ├── day16.output │ ├── day17.input │ ├── day17.output │ ├── day18.input │ ├── day18.output │ ├── day19.example1.input │ ├── day19.example1.output │ ├── day19.example2.input │ ├── day19.example2.output │ ├── day19.input │ ├── day19.output │ ├── day20.input │ ├── day20.output │ ├── day21.input │ ├── day21.output │ ├── day22.input │ ├── day22.output │ ├── day23.input │ ├── day23.output │ ├── day24.input │ ├── day24.output │ ├── day25.input │ └── day25.output ├── 2016 ├── Cargo.lock ├── Cargo.toml ├── dl.bash ├── run.bash ├── src │ └── bin │ │ ├── bonus.rs │ │ ├── day01.rs │ │ ├── day02.rs │ │ ├── day03.rs │ │ ├── day04.rs │ │ ├── day05.rs │ │ ├── day06.rs │ │ ├── day07.rs │ │ ├── day08.rs │ │ ├── day09.rs │ │ ├── day10.rs │ │ ├── day11.rs │ │ ├── day12.rs │ │ ├── day13.rs │ │ ├── day14.rs │ │ ├── day15.rs │ │ ├── day16.rs │ │ ├── day17.rs │ │ ├── day18.rs │ │ ├── day19.rs │ │ ├── day20.rs │ │ ├── day21.rs │ │ ├── day22.rs │ │ ├── day23.rs │ │ ├── day24.rs │ │ └── day25.rs └── tests │ ├── day01 │ ├── input │ └── output │ ├── day02 │ ├── input │ └── output │ ├── day03 │ ├── input │ └── output │ ├── day04 │ ├── input │ └── output │ ├── day05 │ ├── input │ └── output │ ├── day06 │ ├── input │ └── output │ ├── day07 │ ├── input │ └── output │ ├── day08 │ ├── input │ └── output │ ├── day09 │ ├── input │ └── output │ ├── day10 │ ├── input │ └── output │ ├── day11 │ ├── input │ └── output │ ├── day12 │ ├── input │ └── output │ ├── day13 │ ├── input │ └── output │ ├── day14 │ ├── input │ └── output │ ├── day15 │ ├── input │ └── output │ ├── day16 │ ├── input │ └── output │ ├── day17 │ ├── input │ └── output │ ├── day18 │ ├── input │ └── output │ ├── day19 │ ├── input │ └── output │ ├── day20 │ ├── input │ └── output │ ├── day21 │ ├── input │ └── output │ ├── day22 │ ├── input │ └── output │ ├── day23 │ ├── input │ └── output │ ├── day24 │ ├── input │ └── output │ └── day25 │ ├── input │ └── output ├── 2017 ├── Cargo.lock ├── Cargo.toml ├── dl.bash ├── run.bash ├── src │ ├── bin │ │ ├── day01.rs │ │ ├── day02.rs │ │ ├── day03.rs │ │ ├── day04.rs │ │ ├── day05.rs │ │ ├── day06.rs │ │ ├── day07.rs │ │ ├── day08.rs │ │ ├── day09.rs │ │ ├── day10.rs │ │ ├── day11.rs │ │ ├── day12.rs │ │ ├── day13.rs │ │ ├── day14.rs │ │ ├── day15.rs │ │ ├── day16.rs │ │ ├── day17.rs │ │ ├── day18.rs │ │ ├── day19.rs │ │ ├── day20.rs │ │ ├── day21-2.rs │ │ ├── day21.rs │ │ ├── day22.rs │ │ ├── day23.rs │ │ ├── day24.rs │ │ └── day25.rs │ ├── knot.rs │ └── lib.rs └── tests │ ├── day01 │ ├── input │ └── output │ ├── day02 │ ├── input │ └── output │ ├── day03 │ ├── input │ └── output │ ├── day04 │ ├── input │ └── output │ ├── day05 │ ├── input │ └── output │ ├── day06 │ ├── input │ └── output │ ├── day07 │ ├── input │ └── output │ ├── day08 │ ├── input │ └── output │ ├── day09 │ ├── input │ └── output │ ├── day10 │ ├── input │ └── output │ ├── day11 │ ├── input │ └── output │ ├── day12 │ ├── input │ └── output │ ├── day13 │ ├── input │ └── output │ ├── day14 │ ├── input │ └── output │ ├── day15 │ ├── input │ └── output │ ├── day16 │ ├── input │ └── output │ ├── day17 │ ├── input │ └── output │ ├── day18 │ ├── input │ └── output │ ├── day19 │ ├── input │ └── output │ ├── day20 │ ├── input │ └── output │ ├── day21 │ ├── input │ └── output │ ├── day22 │ ├── input │ └── output │ ├── day23 │ ├── input │ └── output │ ├── day24 │ ├── input │ └── output │ └── day25 │ ├── input │ └── output ├── 2018 ├── Cargo.lock ├── Cargo.toml ├── dl.bash ├── run.bash ├── src │ └── bin │ │ ├── day01.rs │ │ ├── day02.rs │ │ ├── day03.rs │ │ ├── day04.rs │ │ ├── day05.rs │ │ ├── day06.rs │ │ ├── day07.rs │ │ ├── day08.rs │ │ ├── day09-vec_deque.rs │ │ ├── day09.rs │ │ ├── day10.rs │ │ ├── day11.rs │ │ ├── day12.rs │ │ ├── day13.rs │ │ ├── day14.rs │ │ ├── day15.rs │ │ ├── day16.rs │ │ ├── day17.rs │ │ ├── day18.rs │ │ ├── day19.rs │ │ ├── day20.rs │ │ ├── day21.rs │ │ ├── day22.rs │ │ ├── day23.rs │ │ ├── day24.rs │ │ └── day25.rs └── tests │ ├── day01 │ ├── input │ └── output │ ├── day02 │ ├── input │ └── output │ ├── day03 │ ├── input │ └── output │ ├── day04 │ ├── input │ └── output │ ├── day05 │ ├── input │ └── output │ ├── day06 │ ├── input │ └── output │ ├── day07 │ ├── input │ └── output │ ├── day08 │ ├── input │ └── output │ ├── day09 │ ├── input │ └── output │ ├── day10 │ ├── input │ └── output │ ├── day11 │ ├── input │ └── output │ ├── day12 │ ├── input │ └── output │ ├── day13 │ ├── input │ └── output │ ├── day14 │ ├── input │ └── output │ ├── day15 │ ├── input │ └── output │ ├── day16 │ ├── input │ └── output │ ├── day17 │ ├── input │ └── output │ ├── day18 │ ├── input │ └── output │ ├── day19 │ ├── input │ └── output │ ├── day20 │ ├── input │ └── output │ ├── day21 │ ├── input │ └── output │ ├── day22 │ ├── input │ └── output │ ├── day23 │ ├── input │ └── output │ ├── day24 │ ├── input │ └── output │ └── day25 │ ├── input │ └── output ├── 2019 ├── Cargo.lock ├── Cargo.toml ├── cache │ ├── answer_01_1 │ ├── answer_01_2 │ ├── answer_02_1 │ ├── answer_02_2 │ ├── answer_03_1 │ ├── answer_03_2 │ ├── answer_04_1 │ ├── answer_04_2 │ ├── answer_05_1 │ ├── answer_05_2 │ ├── answer_06_1 │ ├── answer_06_2 │ ├── answer_07_1 │ ├── answer_07_2 │ ├── answer_08_1 │ ├── answer_08_2 │ ├── answer_09_1 │ ├── answer_09_2 │ ├── answer_10_1 │ ├── answer_10_2 │ ├── answer_11_1 │ ├── answer_11_2 │ ├── answer_12_1 │ ├── answer_12_2 │ ├── answer_13_1 │ ├── answer_13_2 │ ├── answer_14_1 │ ├── answer_14_2 │ ├── answer_15_1 │ ├── answer_15_2 │ ├── answer_16_1 │ ├── answer_16_2 │ ├── answer_17_1 │ ├── answer_17_2 │ ├── answer_18_1 │ ├── answer_18_2 │ ├── answer_19_1 │ ├── answer_19_2 │ ├── answer_20_1 │ ├── answer_20_2 │ ├── answer_21_1 │ ├── answer_21_2 │ ├── answer_22_1 │ ├── answer_23_1 │ ├── answer_23_2 │ ├── answer_24_1 │ ├── answer_24_2 │ ├── input_01 │ ├── input_02 │ ├── input_03 │ ├── input_04 │ ├── input_05 │ ├── input_06 │ ├── input_07 │ ├── input_08 │ ├── input_09 │ ├── input_10 │ ├── input_11 │ ├── input_12 │ ├── input_13 │ ├── input_14 │ ├── input_15 │ ├── input_16 │ ├── input_17 │ ├── input_18 │ ├── input_19 │ ├── input_20 │ ├── input_21 │ ├── input_22 │ ├── input_23 │ ├── input_24 │ └── input_25 └── src │ ├── day01.rs │ ├── day02.rs │ ├── day03.rs │ ├── day04.rs │ ├── day05.rs │ ├── day06.rs │ ├── day07.rs │ ├── day08.rs │ ├── day09.rs │ ├── day10.rs │ ├── day11.rs │ ├── day12.rs │ ├── day13.rs │ ├── day14.rs │ ├── day15.rs │ ├── day16.rs │ ├── day17.rs │ ├── day18.rs │ ├── day19.rs │ ├── day20.rs │ ├── day21.rs │ ├── day22.rs │ ├── day23.rs │ ├── day24.rs │ ├── day25.rs │ ├── intcode.rs │ ├── lib.rs │ ├── ocr.rs │ ├── point.rs │ └── util.rs ├── 2020 ├── Cargo.lock ├── Cargo.toml ├── cache │ ├── answer_01_1 │ ├── answer_01_2 │ ├── answer_02_1 │ ├── answer_02_2 │ ├── answer_03_1 │ ├── answer_03_2 │ ├── answer_04_1 │ ├── answer_04_2 │ ├── answer_05_1 │ ├── answer_05_2 │ ├── answer_06_1 │ ├── answer_06_2 │ ├── answer_07_1 │ ├── answer_07_2 │ ├── example_01_1 │ ├── example_02_1 │ ├── example_03_1 │ ├── example_04_1 │ ├── example_04_3 │ ├── example_04_4 │ ├── example_06_1 │ ├── example_06_2 │ ├── example_06_3 │ ├── example_07_1 │ ├── example_07_2 │ ├── input_01 │ ├── input_02 │ ├── input_03 │ ├── input_04 │ ├── input_05 │ ├── input_06 │ └── input_07 └── src │ ├── day01.rs │ ├── day02.rs │ ├── day03.rs │ ├── day04.rs │ ├── day05.rs │ ├── day06.rs │ ├── day07.rs │ ├── lib.rs │ ├── point.rs │ └── util.rs ├── .gitignore ├── .travis.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | cache: cargo 4 | 5 | before_script: 6 | - rustup component add clippy 7 | 8 | script: 9 | - cd 2019 10 | - cargo clippy --all-targets -- -D warnings -D clippy::pedantic 11 | - cargo test --release 12 | -------------------------------------------------------------------------------- /2015/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "AdventOfCode" 3 | version = "0.1.0" 4 | authors = ["Benoît Zugmeyer "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | rust-crypto = "^0.2" 9 | pcre = "0.2.1" 10 | permutohedron = "0.2.0" 11 | serde_json = "0.6.0" 12 | regex = "0.1" 13 | lazy_static = "0.1.15" 14 | -------------------------------------------------------------------------------- /2015/run_clippy.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | ROOT_DIR=$(dirname $0) 6 | 7 | for bin_file in "$ROOT_DIR"/src/bin/*.rs; do 8 | file_without_extension="${bin_file%.*}" 9 | name="$(basename "$file_without_extension")" 10 | cargo clippy --bin "$name" 11 | done 12 | 13 | -------------------------------------------------------------------------------- /2015/run_tests.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | ROOT_DIR=$(dirname $0) 6 | 7 | for input_file in "$ROOT_DIR"/tests/*.input; do 8 | file_without_extension="${input_file%.*}" 9 | output_file="$file_without_extension.output" 10 | name="$(basename "$file_without_extension")" 11 | dayname="${name%%.*}" 12 | 13 | echo -n "Running $name " 14 | if [[ -f "$ROOT_DIR/target/release/$dayname" ]]; then 15 | echo -n "using release target" 16 | bin="$ROOT_DIR/target/release/$dayname" 17 | elif [[ -f "$ROOT_DIR/target/debug/$dayname" ]]; then 18 | echo -n "using debug target" 19 | bin="$ROOT_DIR/target/debug/$dayname" 20 | else 21 | echo "no binary, skipping" 22 | continue 23 | fi 24 | 25 | echo -n "... " 26 | 27 | output=$("$bin" < "$input_file") 28 | diff_output=$(diff -u "$output_file" <(echo "$output") 2>&1 || true) 29 | if [[ -n $diff_output ]]; then 30 | echo "failed:" 31 | echo "$diff_output" 32 | echo 33 | else 34 | echo "succeed" 35 | fi 36 | done 37 | -------------------------------------------------------------------------------- /2015/src/bin/day01.rs: -------------------------------------------------------------------------------- 1 | use std::io::stdin; 2 | use std::io::Read; 3 | 4 | fn main() { 5 | let (negative_floor, final_floor) = stdin() 6 | .bytes() 7 | .scan(0, |acc, result| { 8 | match result { 9 | Ok(b'(') => *acc += 1, 10 | Ok(b')') => *acc -= 1, 11 | _ => {} 12 | }; 13 | Some(*acc) 14 | }) 15 | .enumerate() 16 | .fold((None, 0), |(negative_floor, _), (index, floor)| { 17 | ( 18 | if negative_floor.is_none() && floor == -1 { 19 | Some(index + 1) 20 | } else { 21 | negative_floor 22 | }, 23 | floor, 24 | ) 25 | }); 26 | 27 | println!("Final floor: {}", final_floor); 28 | 29 | if let Some(floor) = negative_floor { 30 | println!("Position of the floor -1: {}", floor); 31 | } else { 32 | println!("Santa doesn't go to the floor -1"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /2015/src/bin/day02.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::BufRead; 3 | 4 | fn compute_surface_and_length(line: &str) -> (i32, i32) { 5 | let mut numbers = line 6 | .split('x') 7 | .map(|n| n.parse::().unwrap_or(0)) 8 | .collect::>(); 9 | numbers.sort(); 10 | 11 | let surface = match numbers[..] { 12 | [l, w, h] => { 13 | let surfaces = vec![l * w, l * h, w * h]; 14 | surfaces.iter().sum::() * 2 + surfaces.iter().min().unwrap() 15 | } 16 | _ => 0, 17 | }; 18 | 19 | let length = numbers.iter().product::() + numbers.iter().take(2).sum::() * 2; 20 | 21 | (surface, length) 22 | } 23 | 24 | fn main() { 25 | let (surface, length) = io::stdin() 26 | .lock() 27 | .lines() 28 | .filter_map(|line| line.ok()) 29 | .fold((0, 0), |(total_surface, total_length), ref line| { 30 | let (surface, length) = compute_surface_and_length(line); 31 | (total_surface + surface, total_length + length) 32 | }); 33 | 34 | println!("Total surface: {}", surface); 35 | println!("Total length: {}", length); 36 | } 37 | -------------------------------------------------------------------------------- /2015/src/bin/day03.rs: -------------------------------------------------------------------------------- 1 | use std::collections::btree_set::BTreeSet; 2 | use std::io; 3 | use std::io::Read; 4 | 5 | struct Coordinates { 6 | x: i32, 7 | y: i32, 8 | } 9 | 10 | impl Coordinates { 11 | fn new() -> Self { 12 | Coordinates { x: 0, y: 0 } 13 | } 14 | 15 | fn apply(&mut self, direction: u8) { 16 | match direction { 17 | b'<' => self.x -= 1, 18 | b'>' => self.x += 1, 19 | b'v' => self.y -= 1, 20 | b'^' => self.y += 1, 21 | _ => {} 22 | }; 23 | } 24 | } 25 | 26 | impl Default for Coordinates { 27 | fn default() -> Self { 28 | Self::new() 29 | } 30 | } 31 | 32 | fn main() { 33 | let mut santa_first_year = Coordinates::new(); 34 | let mut santa = Coordinates::new(); 35 | let mut robot = Coordinates::new(); 36 | 37 | let mut houses_first_year: BTreeSet<(i32, i32)> = BTreeSet::new(); 38 | let mut houses_next_year: BTreeSet<(i32, i32)> = BTreeSet::new(); 39 | 40 | let directions = io::stdin().bytes().filter_map(|ch| ch.ok()); 41 | 42 | for (index, ch) in directions.enumerate() { 43 | santa_first_year.apply(ch); 44 | houses_first_year.insert((santa_first_year.x, santa_first_year.y)); 45 | 46 | let coords_next_year = if index % 2 == 0 { 47 | &mut santa 48 | } else { 49 | &mut robot 50 | }; 51 | coords_next_year.apply(ch); 52 | houses_next_year.insert((coords_next_year.x, coords_next_year.y)); 53 | } 54 | 55 | println!("Total first year: {}", houses_first_year.len()); 56 | println!("Total next year: {}", houses_next_year.len()); 57 | } 58 | -------------------------------------------------------------------------------- /2015/src/bin/day04.rs: -------------------------------------------------------------------------------- 1 | extern crate crypto; 2 | 3 | use crypto::digest::Digest; 4 | use crypto::md5::Md5; 5 | use std::io; 6 | use std::io::BufRead; 7 | 8 | fn find(secret: &[u8], number_of_zeroes: u8) -> u32 { 9 | let mut result: Vec = vec![0; 16]; 10 | let mut md5 = Md5::new(); 11 | let number_of_bytes = ((number_of_zeroes + 1) / 2) as usize; 12 | let mut zeroes = vec![0xffu8; number_of_bytes]; 13 | if number_of_zeroes % 2 == 1 { 14 | if let Some(last) = zeroes.last_mut() { 15 | *last = 0xf0; 16 | } 17 | } 18 | 19 | (1..) 20 | .find(|n| { 21 | md5.input(secret); 22 | md5.input(n.to_string().as_bytes()); 23 | md5.result(&mut result); 24 | md5.reset(); 25 | zeroes.iter().zip(&result).all(|(z, r)| z & r == 0) 26 | }) 27 | .unwrap() 28 | } 29 | 30 | fn main() { 31 | let line = io::stdin().lock().lines().next().unwrap().unwrap(); 32 | let secret = line.as_bytes(); 33 | println!("5 zeroes result: {}", find(&secret, 5)); 34 | println!("6 zeroes result: {}", find(&secret, 6)); 35 | } 36 | -------------------------------------------------------------------------------- /2015/src/bin/day05.rs: -------------------------------------------------------------------------------- 1 | extern crate pcre; 2 | 3 | use pcre::Pcre; 4 | use std::io; 5 | use std::io::BufRead; 6 | 7 | fn main() { 8 | let mut vowels: Pcre = Pcre::compile(r"[aeiou].*[aeiou].*[aeiou]").unwrap(); 9 | let mut double: Pcre = Pcre::compile(r"(.)\1").unwrap(); 10 | let mut bad: Pcre = Pcre::compile(r"ab|cd|pq|xy").unwrap(); 11 | 12 | let mut pairs = Pcre::compile(r"(..).*\1").unwrap(); 13 | let mut repeats = Pcre::compile(r"(.).\1").unwrap(); 14 | 15 | let is_nice = &mut |s: &str| { 16 | vowels.exec(s).is_some() && double.exec(s).is_some() && bad.exec(s).is_none() 17 | }; 18 | let better_is_nice = &mut |s: &str| pairs.exec(s).is_some() && repeats.exec(s).is_some(); 19 | 20 | let (count, better_count) = 21 | io::stdin() 22 | .lock() 23 | .lines() 24 | .filter_map(|l| l.ok()) 25 | .fold((0, 0), |(n, bn), ref line| { 26 | ( 27 | n + if is_nice(line) { 1 } else { 0 }, 28 | bn + if better_is_nice(line) { 1 } else { 0 }, 29 | ) 30 | }); 31 | 32 | println!("Nice strings: {}", count); 33 | println!("Better nice strings: {}", better_count); 34 | } 35 | -------------------------------------------------------------------------------- /2015/src/bin/day08.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | 3 | use regex::Regex; 4 | use std::io; 5 | use std::io::BufRead; 6 | 7 | fn main() { 8 | let re = Regex::new(r#""|\\\\|\\x|\\"#).unwrap(); 9 | 10 | let sum2 = &|(a1, a2), (b1, b2)| (a1 + b1, a2 + b2); 11 | 12 | let (count, encoded_count): (u32, u32) = io::stdin() 13 | .lock() 14 | .lines() 15 | .filter_map(|l| l.ok()) 16 | .map(|ref line| { 17 | re.captures_iter(line) 18 | .map(|m| match m.at(0).unwrap() { 19 | r#"""# => (1, 1), 20 | r"\\" => (1, 2), 21 | r"\" => (0, 1), 22 | r"\x" => (3, 1), 23 | _ => (0, 0), 24 | }) 25 | .fold((0, 2), sum2) 26 | }) 27 | .fold((0, 0), sum2); 28 | 29 | println!("Extra characters: {}", count); 30 | println!("Extra characters for encoded string: {}", encoded_count); 31 | } 32 | -------------------------------------------------------------------------------- /2015/src/bin/day09.rs: -------------------------------------------------------------------------------- 1 | extern crate permutohedron; 2 | extern crate regex; 3 | 4 | use permutohedron::Heap; 5 | use regex::Regex; 6 | use std::cmp::{max, min}; 7 | use std::collections::BTreeMap; 8 | use std::collections::BTreeSet; 9 | use std::io; 10 | use std::io::BufRead; 11 | 12 | fn new_path(from: &str, to: &str) -> BTreeSet { 13 | let mut path = BTreeSet::new(); 14 | path.insert(String::from(from)); 15 | path.insert(String::from(to)); 16 | path 17 | } 18 | 19 | fn main() { 20 | let mut all_cities = BTreeSet::new(); 21 | let mut distances = BTreeMap::new(); 22 | 23 | let re = Regex::new(r"(\w+) to (\w+) = (\d+)").unwrap(); 24 | 25 | for line in io::stdin().lock().lines().filter_map(|l| l.ok()) { 26 | if let Some(ref m) = re.captures(&line) { 27 | all_cities.insert(String::from(m.at(1).unwrap())); 28 | all_cities.insert(String::from(m.at(2).unwrap())); 29 | let path = new_path(m.at(1).unwrap(), m.at(2).unwrap()); 30 | let distance = m.at(3).unwrap().parse::().unwrap(); 31 | distances.insert(path, distance); 32 | } 33 | } 34 | 35 | let mut all_cities_vec = all_cities.iter().collect::>(); 36 | 37 | let (max, min) = Heap::new(&mut all_cities_vec) 38 | .map(|cities| { 39 | let mut cities_iter = cities.iter(); 40 | let starting_city = cities_iter.next().unwrap(); 41 | cities_iter 42 | .scan(starting_city, |previous_city, city| { 43 | let distance = distances.get(&new_path(previous_city, city)); 44 | *previous_city = city; 45 | distance 46 | }) 47 | .sum::() 48 | }) 49 | .fold((u32::min_value(), u32::max_value()), |(max_d, min_d), d| { 50 | (max(max_d, d), min(min_d, d)) 51 | }); 52 | 53 | println!("Shortest route: {}", min); 54 | println!("Longest route: {}", max); 55 | } 56 | -------------------------------------------------------------------------------- /2015/src/bin/day10.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | #[allow(dead_code)] 4 | fn transform_no_iter(input: &[u8]) -> Vec { 5 | let mut output = Vec::new(); 6 | 7 | let mut index = 0; 8 | let len = input.len(); 9 | while index < len { 10 | let lead = input[index]; 11 | let mut count = 1; 12 | index += 1; 13 | while index < len && input[index] == lead { 14 | count += 1; 15 | index += 1; 16 | } 17 | output.push(count as u8); 18 | output.push(lead); 19 | } 20 | output 21 | } 22 | 23 | fn transform(mut input: &[u8]) -> Vec { 24 | let mut output = Vec::new(); 25 | 26 | while let Some(lead) = input.get(0) { 27 | let count = input.iter().take_while(|c| *c == lead).count(); 28 | output.push(count as u8); 29 | output.push(*lead); 30 | input = &input[count..]; 31 | } 32 | output 33 | } 34 | 35 | fn main() { 36 | let mut input_str = String::new(); 37 | io::stdin().read_line(&mut input_str).unwrap(); 38 | let mut input: Vec<_> = input_str 39 | .chars() 40 | .filter_map(|ch| ch.to_digit(10)) 41 | .map(|d| d as u8) 42 | .collect(); 43 | 44 | for _ in 0..40 { 45 | input = transform(&input); 46 | } 47 | println!("40 times: {}", input.len()); 48 | for _ in 0..10 { 49 | input = transform(&input); 50 | } 51 | println!("50 times: {}", input.len()); 52 | } 53 | -------------------------------------------------------------------------------- /2015/src/bin/day12.rs: -------------------------------------------------------------------------------- 1 | extern crate serde_json; 2 | 3 | use serde_json::Value; 4 | use std::io; 5 | use std::io::BufRead; 6 | 7 | fn sum_numbers(value: &Value) -> i64 { 8 | match *value { 9 | Value::I64(n) => n, 10 | Value::U64(n) => n as i64, 11 | Value::F64(n) => n as i64, 12 | Value::Array(ref vec) => vec.iter().map(sum_numbers).sum(), 13 | Value::Object(ref map) => map.values().map(sum_numbers).sum(), 14 | _ => 0, 15 | } 16 | } 17 | 18 | fn sum_non_red_numbers(value: &Value) -> i64 { 19 | match *value { 20 | Value::Array(ref vec) => vec.iter().map(sum_non_red_numbers).sum(), 21 | Value::Object(ref map) => { 22 | let blacklist = Value::String("red".to_string()); 23 | if map.values().any(|v| v == &blacklist) { 24 | 0 25 | } else { 26 | map.values().map(sum_non_red_numbers).sum() 27 | } 28 | } 29 | ref value => sum_numbers(value), 30 | } 31 | } 32 | 33 | fn main() { 34 | let (sum, non_red_sum) = io::stdin() 35 | .lock() 36 | .lines() 37 | .filter_map(|r| r.ok()) 38 | .filter_map(|ref line| serde_json::from_str(line).ok()) 39 | .map(|ref json| (sum_numbers(json), sum_non_red_numbers(json))) 40 | .fold((0, 0), |(total_n, total_non_red_n), (n, non_red_n)| { 41 | (total_n + n, total_non_red_n + non_red_n) 42 | }); 43 | 44 | println!("Total: {}", sum); 45 | println!("Non red total: {}", non_red_sum); 46 | } 47 | -------------------------------------------------------------------------------- /2015/src/bin/day13.rs: -------------------------------------------------------------------------------- 1 | extern crate permutohedron; 2 | extern crate regex; 3 | 4 | use permutohedron::Heap; 5 | use regex::Regex; 6 | use std::cmp::{max, min}; 7 | use std::collections::BTreeMap; 8 | use std::io; 9 | use std::io::BufRead; 10 | use std::iter::once; 11 | 12 | fn push(v: &mut Vec, item: T) -> usize { 13 | if let Some(position) = v.iter().position(|other| *other == item) { 14 | position 15 | } else { 16 | v.push(item); 17 | v.len() - 1 18 | } 19 | } 20 | 21 | fn compute_key(index_a: usize, index_b: usize) -> (usize, usize) { 22 | (min(index_a, index_b), max(index_a, index_b)) 23 | } 24 | 25 | fn compute_max_happiness i32>(n: usize, getter: F) -> i32 { 26 | let mut indexes: Vec<_> = (1..n).collect(); 27 | 28 | Heap::new(&mut indexes) 29 | .map(|sorted_indexes| { 30 | sorted_indexes 31 | .iter() 32 | .chain(once(&0)) 33 | .scan(0, |previous_index, current_index| { 34 | let result = getter(*previous_index, *current_index); 35 | *previous_index = *current_index; 36 | Some(result) 37 | }) 38 | .sum::() 39 | }) 40 | .max() 41 | .unwrap() 42 | } 43 | 44 | fn main() { 45 | let mut attendees: Vec = Vec::new(); 46 | let mut happiness: BTreeMap<(usize, usize), i32> = BTreeMap::new(); 47 | 48 | let re = Regex::new(r"(\w+) would (gain|lose) (\d+) happiness units by sitting next to (\w+)") 49 | .unwrap(); 50 | 51 | for line in io::stdin().lock().lines().filter_map(|l| l.ok()) { 52 | if let Some(ref m) = re.captures(&line) { 53 | let index_a = push(&mut attendees, String::from(m.at(1).unwrap())); 54 | let index_b = push(&mut attendees, String::from(m.at(4).unwrap())); 55 | let key = compute_key(index_a, index_b); 56 | 57 | let h = { 58 | let h = m.at(3).unwrap().parse::().unwrap(); 59 | if m.at(2).unwrap() == "lose" { 60 | -h 61 | } else { 62 | h 63 | } 64 | }; 65 | 66 | *happiness.entry(key).or_insert(0) += h; 67 | } 68 | } 69 | 70 | let max = compute_max_happiness(attendees.len(), |index_a, index_b| { 71 | happiness[&compute_key(index_a, index_b)] 72 | }); 73 | 74 | let max_with_me = compute_max_happiness(attendees.len() + 1, |index_a, index_b| { 75 | *happiness.get(&compute_key(index_a, index_b)).unwrap_or(&0) 76 | }); 77 | 78 | println!("max: {}", max); 79 | println!("max with me: {}", max_with_me); 80 | } 81 | -------------------------------------------------------------------------------- /2015/src/bin/day14.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | 3 | use regex::Regex; 4 | use std::cmp::min; 5 | use std::io; 6 | use std::io::BufRead; 7 | 8 | fn compute_distance(race_time: u32, kms: u32, run_time: u32, rest_time: u32) -> u32 { 9 | let sessions_count = race_time / (run_time + rest_time); 10 | let remaining_time = race_time % (run_time + rest_time); 11 | (min(run_time, remaining_time) + sessions_count * run_time) * kms 12 | } 13 | 14 | fn main() { 15 | let re = Regex::new( 16 | r"(\w+) can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds\.", 17 | ) 18 | .unwrap(); 19 | let race_time = 2503; 20 | 21 | let parameters: Vec<_> = io::stdin() 22 | .lock() 23 | .lines() 24 | .filter_map(|l| l.ok()) 25 | .filter_map(|ref line| { 26 | re.captures(line).map(|ref m| { 27 | ( 28 | m.at(2).unwrap().parse::().unwrap(), 29 | m.at(3).unwrap().parse::().unwrap(), 30 | m.at(4).unwrap().parse::().unwrap(), 31 | ) 32 | }) 33 | }) 34 | .collect(); 35 | 36 | let max = parameters 37 | .iter() 38 | .map(|&(kms, run_time, rest_time)| compute_distance(race_time, kms, run_time, rest_time)) 39 | .max() 40 | .unwrap(); 41 | 42 | println!("max: {}", max); 43 | 44 | let mut scores = vec![0; parameters.len()]; 45 | 46 | for r in 1..=race_time { 47 | let distances: Vec<_> = parameters 48 | .iter() 49 | .map(|&(kms, run_time, rest_time)| compute_distance(r, kms, run_time, rest_time)) 50 | .collect(); 51 | 52 | let max = distances.iter().max().unwrap(); 53 | for (index, d) in distances.iter().enumerate() { 54 | if d == max { 55 | scores[index] += 1; 56 | } 57 | } 58 | } 59 | 60 | println!("max score: {}", scores.iter().max().unwrap()); 61 | } 62 | -------------------------------------------------------------------------------- /2015/src/bin/day17.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::BufRead; 3 | 4 | fn combinations ()>( 5 | containers: &[u8], 6 | container_count: u8, 7 | liters: u8, 8 | fct: &mut F, 9 | ) { 10 | if !containers.is_empty() { 11 | let mut next_containers = containers.to_vec(); 12 | for (index, container) in containers.iter().enumerate().rev() { 13 | if *container == liters { 14 | fct(container_count); 15 | } else if *container < liters { 16 | next_containers.remove(index); 17 | combinations( 18 | &next_containers, 19 | container_count + 1, 20 | liters - container, 21 | fct, 22 | ); 23 | } 24 | } 25 | } 26 | } 27 | 28 | fn main() { 29 | let containers: Vec<_> = io::stdin() 30 | .lock() 31 | .lines() 32 | .filter_map(|l| l.ok()) 33 | .filter_map(|ref line| line.parse::().ok()) 34 | .collect(); 35 | 36 | let liters = 150; 37 | let mut total_combinations = 0; 38 | let mut min_containers_count = containers.len() as u8; 39 | let mut combinations_with_min_containers_count = 0; 40 | 41 | combinations(&containers, 0, liters, &mut |container_count| { 42 | total_combinations += 1; 43 | if container_count == min_containers_count { 44 | combinations_with_min_containers_count += 1; 45 | } else if container_count < min_containers_count { 46 | min_containers_count = container_count; 47 | combinations_with_min_containers_count = 1; 48 | } 49 | }); 50 | 51 | println!("Total combination: {}", total_combinations); 52 | println!( 53 | "Combinations with minimum containers count: {}", 54 | combinations_with_min_containers_count 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /2015/src/bin/day20.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::BufRead; 3 | 4 | struct Divisors { 5 | n: u32, 6 | max: u32, 7 | index: u32, 8 | } 9 | 10 | impl Divisors { 11 | fn new(n: u32) -> Self { 12 | let max = f64::from(n).sqrt() as u32; 13 | Divisors { n, max, index: 0 } 14 | } 15 | } 16 | 17 | impl Iterator for Divisors { 18 | type Item = (u32, u32); 19 | 20 | fn next(&mut self) -> Option { 21 | while self.index < self.max { 22 | self.index += 1; 23 | 24 | if self.n % self.index == 0 { 25 | return Some((self.index, self.n / self.index)); 26 | } 27 | } 28 | None 29 | } 30 | } 31 | 32 | struct HouseIterator { 33 | index: u32, 34 | max_houses: u32, 35 | present_factor: u32, 36 | } 37 | 38 | impl HouseIterator { 39 | fn new(present_factor: u32, max_houses: u32) -> Self { 40 | HouseIterator { 41 | index: 0, 42 | present_factor, 43 | max_houses, 44 | } 45 | } 46 | 47 | fn min_house(&mut self, min_presents: u32) -> Option { 48 | self.skip_while(|&(_, presents)| presents < min_presents) 49 | .next() 50 | .map(|(house, _)| house) 51 | } 52 | } 53 | 54 | impl Iterator for HouseIterator { 55 | type Item = (u32, u32); 56 | 57 | fn next(&mut self) -> Option { 58 | self.index += 1; 59 | let mut presents = 0; 60 | for (a, b) in Divisors::new(self.index) { 61 | if a > self.max_houses { 62 | break; 63 | } 64 | if a == b { 65 | presents += a; 66 | } else { 67 | presents += a + b; 68 | } 69 | } 70 | Some((self.index, presents * self.present_factor)) 71 | } 72 | } 73 | 74 | fn main() { 75 | let min_presents = io::stdin() 76 | .lock() 77 | .lines() 78 | .next() 79 | .unwrap() 80 | .unwrap() 81 | .parse::() 82 | .unwrap(); 83 | 84 | let mut infinite_delivery = HouseIterator::new(10, u32::max_value()); 85 | if let Some(house) = infinite_delivery.min_house(min_presents) { 86 | println!("Infinite delivery min house: {}", house); 87 | } 88 | 89 | let mut maxed_delivery = HouseIterator::new(11, 50); 90 | if let Some(house) = maxed_delivery.min_house(min_presents) { 91 | println!("Maxed delivery min house: {}", house); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /2015/src/bin/day25.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | 3 | use regex::Regex; 4 | use std::io; 5 | use std::io::BufRead; 6 | 7 | fn code_number(row: u32, column: u32) -> u32 { 8 | let n = row + column - 1; 9 | column + (n * (n - 1)) / 2 10 | } 11 | 12 | fn code(number: u32) -> u32 { 13 | let mut result = 20_151_125u64; 14 | for _ in 1..number { 15 | result = (result * 252_533) % 33_554_393 16 | } 17 | result as u32 18 | } 19 | 20 | #[test] 21 | fn code_number_test() { 22 | assert_eq!(code_number(4, 2), 12); 23 | assert_eq!(code_number(1, 5), 15); 24 | } 25 | 26 | #[test] 27 | fn code_test() { 28 | assert_eq!(code(1), 20151125); 29 | assert_eq!(code(2), 31916031); 30 | assert_eq!(code(3), 18749137); 31 | assert_eq!(code(11), 77061); 32 | } 33 | 34 | fn main() { 35 | let regex = Regex::new(r"row (\d+), column (\d+)").unwrap(); 36 | let line = io::stdin().lock().lines().next().unwrap().unwrap(); 37 | let cap = regex.captures(&line).unwrap(); 38 | let row: u32 = cap.at(1).unwrap().parse().unwrap(); 39 | let column: u32 = cap.at(2).unwrap().parse().unwrap(); 40 | 41 | let number = code_number(row, column); 42 | println!("Code to give to the machine: {}", code(number)); 43 | } 44 | -------------------------------------------------------------------------------- /2015/tests/day01.output: -------------------------------------------------------------------------------- 1 | Final floor: 138 2 | Position of the floor -1: 1771 3 | -------------------------------------------------------------------------------- /2015/tests/day02.output: -------------------------------------------------------------------------------- 1 | Total surface: 1586300 2 | Total length: 3737498 3 | -------------------------------------------------------------------------------- /2015/tests/day03.output: -------------------------------------------------------------------------------- 1 | Total first year: 2565 2 | Total next year: 2639 3 | -------------------------------------------------------------------------------- /2015/tests/day04.input: -------------------------------------------------------------------------------- 1 | bgvyzdsv 2 | -------------------------------------------------------------------------------- /2015/tests/day04.output: -------------------------------------------------------------------------------- 1 | 5 zeroes result: 254575 2 | 6 zeroes result: 1038736 3 | -------------------------------------------------------------------------------- /2015/tests/day05.output: -------------------------------------------------------------------------------- 1 | Nice strings: 236 2 | Better nice strings: 51 3 | -------------------------------------------------------------------------------- /2015/tests/day06.output: -------------------------------------------------------------------------------- 1 | Binary lights lit: 543903 2 | Multi level lights brightness: 14687245 3 | -------------------------------------------------------------------------------- /2015/tests/day07.output: -------------------------------------------------------------------------------- 1 | Signal on first pass: 46065 2 | Signal on second pass: 14134 3 | -------------------------------------------------------------------------------- /2015/tests/day08.output: -------------------------------------------------------------------------------- 1 | Extra characters: 1342 2 | Extra characters for encoded string: 2074 3 | -------------------------------------------------------------------------------- /2015/tests/day09.input: -------------------------------------------------------------------------------- 1 | Tristram to AlphaCentauri = 34 2 | Tristram to Snowdin = 100 3 | Tristram to Tambi = 63 4 | Tristram to Faerun = 108 5 | Tristram to Norrath = 111 6 | Tristram to Straylight = 89 7 | Tristram to Arbre = 132 8 | AlphaCentauri to Snowdin = 4 9 | AlphaCentauri to Tambi = 79 10 | AlphaCentauri to Faerun = 44 11 | AlphaCentauri to Norrath = 147 12 | AlphaCentauri to Straylight = 133 13 | AlphaCentauri to Arbre = 74 14 | Snowdin to Tambi = 105 15 | Snowdin to Faerun = 95 16 | Snowdin to Norrath = 48 17 | Snowdin to Straylight = 88 18 | Snowdin to Arbre = 7 19 | Tambi to Faerun = 68 20 | Tambi to Norrath = 134 21 | Tambi to Straylight = 107 22 | Tambi to Arbre = 40 23 | Faerun to Norrath = 11 24 | Faerun to Straylight = 66 25 | Faerun to Arbre = 144 26 | Norrath to Straylight = 115 27 | Norrath to Arbre = 135 28 | Straylight to Arbre = 127 29 | -------------------------------------------------------------------------------- /2015/tests/day09.output: -------------------------------------------------------------------------------- 1 | Shortest route: 251 2 | Longest route: 898 3 | -------------------------------------------------------------------------------- /2015/tests/day10.input: -------------------------------------------------------------------------------- 1 | 1113122113 2 | -------------------------------------------------------------------------------- /2015/tests/day10.output: -------------------------------------------------------------------------------- 1 | 40 times: 360154 2 | 50 times: 5103798 3 | -------------------------------------------------------------------------------- /2015/tests/day11.input: -------------------------------------------------------------------------------- 1 | vzbxkghb 2 | -------------------------------------------------------------------------------- /2015/tests/day11.output: -------------------------------------------------------------------------------- 1 | Next password: vzbxppqrr 2 | Next password: vzbxqqrss 3 | -------------------------------------------------------------------------------- /2015/tests/day12.output: -------------------------------------------------------------------------------- 1 | Total: 191164 2 | Non red total: 87842 3 | -------------------------------------------------------------------------------- /2015/tests/day13.output: -------------------------------------------------------------------------------- 1 | max: 709 2 | max with me: 668 3 | -------------------------------------------------------------------------------- /2015/tests/day14.input: -------------------------------------------------------------------------------- 1 | Vixen can fly 19 km/s for 7 seconds, but then must rest for 124 seconds. 2 | Rudolph can fly 3 km/s for 15 seconds, but then must rest for 28 seconds. 3 | Donner can fly 19 km/s for 9 seconds, but then must rest for 164 seconds. 4 | Blitzen can fly 19 km/s for 9 seconds, but then must rest for 158 seconds. 5 | Comet can fly 13 km/s for 7 seconds, but then must rest for 82 seconds. 6 | Cupid can fly 25 km/s for 6 seconds, but then must rest for 145 seconds. 7 | Dasher can fly 14 km/s for 3 seconds, but then must rest for 38 seconds. 8 | Dancer can fly 3 km/s for 16 seconds, but then must rest for 37 seconds. 9 | Prancer can fly 25 km/s for 6 seconds, but then must rest for 143 seconds. 10 | -------------------------------------------------------------------------------- /2015/tests/day14.output: -------------------------------------------------------------------------------- 1 | max: 2660 2 | max score: 1256 3 | -------------------------------------------------------------------------------- /2015/tests/day15.example.input: -------------------------------------------------------------------------------- 1 | Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8 2 | Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3 3 | -------------------------------------------------------------------------------- /2015/tests/day15.example.output: -------------------------------------------------------------------------------- 1 | Highest score: 62842880 2 | Highest score for 500 calories recipes: 57600000 3 | -------------------------------------------------------------------------------- /2015/tests/day15.input: -------------------------------------------------------------------------------- 1 | Sprinkles: capacity 2, durability 0, flavor -2, texture 0, calories 3 2 | Butterscotch: capacity 0, durability 5, flavor -3, texture 0, calories 3 3 | Chocolate: capacity 0, durability 0, flavor 5, texture -1, calories 8 4 | Candy: capacity 0, durability -1, flavor 0, texture 5, calories 8 5 | -------------------------------------------------------------------------------- /2015/tests/day15.output: -------------------------------------------------------------------------------- 1 | Highest score: 21367368 2 | Highest score for 500 calories recipes: 1766400 3 | -------------------------------------------------------------------------------- /2015/tests/day16.output: -------------------------------------------------------------------------------- 1 | Unadjusted Aunt Sue found: Sue 40 2 | Real Aunt Sue found: Sue 241 3 | -------------------------------------------------------------------------------- /2015/tests/day17.input: -------------------------------------------------------------------------------- 1 | 43 2 | 3 3 | 4 4 | 10 5 | 21 6 | 44 7 | 4 8 | 6 9 | 47 10 | 41 11 | 34 12 | 17 13 | 17 14 | 44 15 | 36 16 | 31 17 | 46 18 | 9 19 | 27 20 | 38 21 | -------------------------------------------------------------------------------- /2015/tests/day17.output: -------------------------------------------------------------------------------- 1 | Total combination: 1638 2 | Combinations with minimum containers count: 17 3 | -------------------------------------------------------------------------------- /2015/tests/day18.output: -------------------------------------------------------------------------------- 1 | Working grid lights count: 1061 2 | Bogus grid lights count: 1006 3 | -------------------------------------------------------------------------------- /2015/tests/day19.example1.input: -------------------------------------------------------------------------------- 1 | e => H 2 | e => O 3 | H => HO 4 | H => OH 5 | O => HH 6 | 7 | HOH 8 | -------------------------------------------------------------------------------- /2015/tests/day19.example1.output: -------------------------------------------------------------------------------- 1 | Mutated molecules count: 4 2 | Steps needed to find the molecule: 3 3 | -------------------------------------------------------------------------------- /2015/tests/day19.example2.input: -------------------------------------------------------------------------------- 1 | e => H 2 | e => O 3 | H => HO 4 | H => OH 5 | O => HH 6 | 7 | HOHOHO 8 | -------------------------------------------------------------------------------- /2015/tests/day19.example2.output: -------------------------------------------------------------------------------- 1 | Mutated molecules count: 7 2 | Steps needed to find the molecule: 6 3 | -------------------------------------------------------------------------------- /2015/tests/day19.input: -------------------------------------------------------------------------------- 1 | Al => ThF 2 | Al => ThRnFAr 3 | B => BCa 4 | B => TiB 5 | B => TiRnFAr 6 | Ca => CaCa 7 | Ca => PB 8 | Ca => PRnFAr 9 | Ca => SiRnFYFAr 10 | Ca => SiRnMgAr 11 | Ca => SiTh 12 | F => CaF 13 | F => PMg 14 | F => SiAl 15 | H => CRnAlAr 16 | H => CRnFYFYFAr 17 | H => CRnFYMgAr 18 | H => CRnMgYFAr 19 | H => HCa 20 | H => NRnFYFAr 21 | H => NRnMgAr 22 | H => NTh 23 | H => OB 24 | H => ORnFAr 25 | Mg => BF 26 | Mg => TiMg 27 | N => CRnFAr 28 | N => HSi 29 | O => CRnFYFAr 30 | O => CRnMgAr 31 | O => HP 32 | O => NRnFAr 33 | O => OTi 34 | P => CaP 35 | P => PTi 36 | P => SiRnFAr 37 | Si => CaSi 38 | Th => ThCa 39 | Ti => BP 40 | Ti => TiTi 41 | e => HF 42 | e => NAl 43 | e => OMg 44 | 45 | ORnPBPMgArCaCaCaSiThCaCaSiThCaCaPBSiRnFArRnFArCaCaSiThCaCaSiThCaCaCaCaCaCaSiRnFYFArSiRnMgArCaSiRnPTiTiBFYPBFArSiRnCaSiRnTiRnFArSiAlArPTiBPTiRnCaSiAlArCaPTiTiBPMgYFArPTiRnFArSiRnCaCaFArRnCaFArCaSiRnSiRnMgArFYCaSiRnMgArCaCaSiThPRnFArPBCaSiRnMgArCaCaSiThCaSiRnTiMgArFArSiThSiThCaCaSiRnMgArCaCaSiRnFArTiBPTiRnCaSiAlArCaPTiRnFArPBPBCaCaSiThCaPBSiThPRnFArSiThCaSiThCaSiThCaPTiBSiRnFYFArCaCaPRnFArPBCaCaPBSiRnTiRnFArCaPRnFArSiRnCaCaCaSiThCaRnCaFArYCaSiRnFArBCaCaCaSiThFArPBFArCaSiRnFArRnCaCaCaFArSiRnFArTiRnPMgArF 46 | -------------------------------------------------------------------------------- /2015/tests/day19.output: -------------------------------------------------------------------------------- 1 | Mutated molecules count: 576 2 | Steps needed to find the molecule: 207 3 | -------------------------------------------------------------------------------- /2015/tests/day20.input: -------------------------------------------------------------------------------- 1 | 29000000 2 | -------------------------------------------------------------------------------- /2015/tests/day20.output: -------------------------------------------------------------------------------- 1 | Infinite delivery min house: 665280 2 | Maxed delivery min house: 705600 3 | -------------------------------------------------------------------------------- /2015/tests/day21.input: -------------------------------------------------------------------------------- 1 | Hit Points: 104 2 | Damage: 8 3 | Armor: 1 4 | -------------------------------------------------------------------------------- /2015/tests/day21.output: -------------------------------------------------------------------------------- 1 | Minimal stuff cost to beat the boss: 78 2 | Maximal stuff cost to be defeated by the boss: 148 3 | -------------------------------------------------------------------------------- /2015/tests/day22.input: -------------------------------------------------------------------------------- 1 | Hit Points: 71 2 | Damage: 10 3 | -------------------------------------------------------------------------------- /2015/tests/day22.output: -------------------------------------------------------------------------------- 1 | Minimum mana on easy mode: 1824 2 | Minimum mana on hard mode: 1937 3 | -------------------------------------------------------------------------------- /2015/tests/day23.input: -------------------------------------------------------------------------------- 1 | jio a, +16 2 | inc a 3 | inc a 4 | tpl a 5 | tpl a 6 | tpl a 7 | inc a 8 | inc a 9 | tpl a 10 | inc a 11 | inc a 12 | tpl a 13 | tpl a 14 | tpl a 15 | inc a 16 | jmp +23 17 | tpl a 18 | inc a 19 | inc a 20 | tpl a 21 | inc a 22 | inc a 23 | tpl a 24 | tpl a 25 | inc a 26 | inc a 27 | tpl a 28 | inc a 29 | tpl a 30 | inc a 31 | tpl a 32 | inc a 33 | inc a 34 | tpl a 35 | inc a 36 | tpl a 37 | tpl a 38 | inc a 39 | jio a, +8 40 | inc b 41 | jie a, +4 42 | tpl a 43 | inc a 44 | jmp +2 45 | hlf a 46 | jmp -7 47 | -------------------------------------------------------------------------------- /2015/tests/day23.output: -------------------------------------------------------------------------------- 1 | Register 'b' after executing instructions: Some(170) 2 | Register 'b' after executing instructions with 'a' initialized to 1: Some(247) 3 | -------------------------------------------------------------------------------- /2015/tests/day24.input: -------------------------------------------------------------------------------- 1 | 1 2 | 3 3 | 5 4 | 11 5 | 13 6 | 17 7 | 19 8 | 23 9 | 29 10 | 31 11 | 37 12 | 41 13 | 43 14 | 47 15 | 53 16 | 59 17 | 67 18 | 71 19 | 73 20 | 79 21 | 83 22 | 89 23 | 97 24 | 101 25 | 103 26 | 107 27 | 109 28 | 113 29 | -------------------------------------------------------------------------------- /2015/tests/day24.output: -------------------------------------------------------------------------------- 1 | 3 packages: quantum entanglement of the first group of packages: 10439961859 2 | 4 packages: quantum entanglement of the first group of packages: 72050269 3 | -------------------------------------------------------------------------------- /2015/tests/day25.input: -------------------------------------------------------------------------------- 1 | To continue, please consult the code grid in the manual. Enter the code at row 3010, column 3019. 2 | -------------------------------------------------------------------------------- /2015/tests/day25.output: -------------------------------------------------------------------------------- 1 | Code to give to the machine: 8997277 2 | -------------------------------------------------------------------------------- /2016/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Benoît Zugmeyer "] 3 | name = "advent_of_code_2016" 4 | version = "0.1.0" 5 | edition = "2018" 6 | 7 | [dependencies] 8 | itertools = "0.5.6" 9 | regex = "0.1.80" 10 | rust-crypto = "0.2.36" 11 | permutohedron = "0.2.2" 12 | 13 | [dependencies.nom] 14 | version = "2.0.1" 15 | features = ["verbose-errors"] 16 | -------------------------------------------------------------------------------- /2016/dl.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | dayname=$(printf day%02d $2) 6 | mkdir -p tests/$dayname 7 | curl "http://adventofcode.com/2016/day/$2/input" -H "Cookie: session=$1" > tests/$dayname/input 8 | touch tests/$dayname/output 9 | git add tests/$dayname/input tests/$dayname/output 10 | -------------------------------------------------------------------------------- /2016/run.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | ROOT_DIR=$(dirname $0) 6 | 7 | for input_file in "$ROOT_DIR"/tests/*/input; do 8 | name=$(basename $(dirname "$input_file")) 9 | output_file=$(dirname "$input_file")/output 10 | 11 | echo -n "Running $name " 12 | if [[ -f "$ROOT_DIR/target/release/$name" ]]; then 13 | echo -n "using release target" 14 | bin="$ROOT_DIR/target/release/$name" 15 | elif [[ -f "$ROOT_DIR/target/debug/$name" ]]; then 16 | echo -n "using debug target" 17 | bin="$ROOT_DIR/target/debug/$name" 18 | else 19 | echo "no binary, skipping" 20 | continue 21 | fi 22 | 23 | echo -n "... " 24 | 25 | output=$("$bin" < "$input_file") 26 | diff_output=$(diff -u "$output_file" <(echo "$output") 2>&1 || true) 27 | if [[ -n $diff_output ]]; then 28 | echo "failed:" 29 | echo "$diff_output" 30 | echo 31 | else 32 | echo "succeed" 33 | fi 34 | done 35 | -------------------------------------------------------------------------------- /2016/src/bin/day01.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | use regex::Regex; 3 | use std::collections::BTreeSet; 4 | use std::io::stdin; 5 | use std::io::Read; 6 | 7 | #[derive(Ord, Eq, PartialOrd, PartialEq, Copy, Clone, Debug)] 8 | struct Coordinates { 9 | x: i16, 10 | y: i16, 11 | } 12 | 13 | impl Coordinates { 14 | fn new(x: i16, y: i16) -> Self { 15 | Coordinates { x, y } 16 | } 17 | 18 | fn distance(self) -> i16 { 19 | self.x.abs() + self.y.abs() 20 | } 21 | 22 | fn from(Coordinates { x, y }: Self, direction: u16, distance: i16) -> Self { 23 | match direction { 24 | 0 => Coordinates::new(x, y + distance), 25 | 90 => Coordinates::new(x + distance, y), 26 | 180 => Coordinates::new(x, y - distance), 27 | 270 => Coordinates::new(x - distance, y), 28 | _ => panic!("Invalid direction"), 29 | } 30 | } 31 | } 32 | 33 | fn main() { 34 | let mut input = String::new(); 35 | stdin() 36 | .read_to_string(&mut input) 37 | .expect("Failed to read stdin"); 38 | 39 | let re = Regex::new(r"(?P[RL])(?P\d+)").unwrap(); 40 | 41 | let mut previous_locations = BTreeSet::new(); 42 | 43 | let (location, _, cross_location) = re.captures_iter(&input).fold( 44 | (Coordinates::new(0, 0), 90u16, None), 45 | |(location, direction, cross_location), caps| { 46 | let turn = caps.name("turn").unwrap().chars().nth(0).unwrap(); 47 | let distance = caps 48 | .name("distance") 49 | .unwrap() 50 | .parse() 51 | .expect("Failed to parse distance"); 52 | 53 | let new_direction = match turn { 54 | 'L' => direction + 90, 55 | 'R' => direction + 270, 56 | _ => 0, 57 | } % 360; 58 | 59 | let new_location = Coordinates::from(location, new_direction, distance); 60 | 61 | let new_cross_location = cross_location.or_else(|| { 62 | (0..distance) 63 | .filter_map(|d| { 64 | let tmp_location = Coordinates::from(location, new_direction, d); 65 | if previous_locations.insert(tmp_location) { 66 | None 67 | } else { 68 | Some(tmp_location) 69 | } 70 | }) 71 | .nth(0) 72 | }); 73 | 74 | (new_location, new_direction, new_cross_location) 75 | }, 76 | ); 77 | 78 | println!("Part 1: {}", location.distance()); 79 | println!("Part 2: {}", cross_location.unwrap().distance()); 80 | } 81 | -------------------------------------------------------------------------------- /2016/src/bin/day02.rs: -------------------------------------------------------------------------------- 1 | use std::io::stdin; 2 | use std::io::Read; 3 | 4 | fn map_keypad1(ch: char, state: u8) -> u8 { 5 | match (ch, state) { 6 | ('U', s) if s >= 4 => s - 3, 7 | ('L', s) if s % 3 != 1 => s - 1, 8 | ('R', s) if s % 3 != 0 => s + 1, 9 | ('D', s) if s <= 6 => s + 3, 10 | (_, s) => s, 11 | } 12 | } 13 | 14 | fn keypad1_char(state: u8) -> char { 15 | (state + b'0') as char 16 | } 17 | 18 | fn map_keypad2(ch: char, state: (i8, i8)) -> (i8, i8) { 19 | let raw_new_state = match (ch, state) { 20 | ('U', (x, y)) => (x, y + 1), 21 | ('L', (x, y)) => (x - 1, y), 22 | ('R', (x, y)) => (x + 1, y), 23 | ('D', (x, y)) => (x, y - 1), 24 | (_, s) => s, 25 | }; 26 | if raw_new_state.0.abs() + raw_new_state.1.abs() <= 2 { 27 | raw_new_state 28 | } else { 29 | state 30 | } 31 | } 32 | 33 | fn keypad2_char(state: (i8, i8)) -> char { 34 | (match state { 35 | (i, 2) => i + ('1' as i8), 36 | (i, 1) => i + ('3' as i8), 37 | (i, 0) => i + ('7' as i8), 38 | (i, -1) => i + ('B' as i8), 39 | (i, -2) => i + ('D' as i8), 40 | _ => 'U' as i8, 41 | }) as u8 as char 42 | } 43 | 44 | fn main() { 45 | let (code_1, code_2) = stdin() 46 | .bytes() 47 | .filter_map(|b| b.ok()) 48 | .map(|b| b as char) 49 | .scan((5, (-2, 0)), |state, ch| { 50 | Some(if ch == '\n' { 51 | Some((keypad1_char(state.0), keypad2_char(state.1))) 52 | } else { 53 | *state = (map_keypad1(ch, state.0), map_keypad2(ch, state.1)); 54 | None 55 | }) 56 | }) 57 | .filter_map(|b| b) 58 | .fold( 59 | (String::new(), String::new()), 60 | |(mut s1, mut s2), (ch1, ch2)| { 61 | s1.push(ch1); 62 | s2.push(ch2); 63 | (s1, s2) 64 | }, 65 | ); 66 | println!("Part 1: {}", code_1); 67 | println!("Part 2: {}", code_2); 68 | } 69 | -------------------------------------------------------------------------------- /2016/src/bin/day03.rs: -------------------------------------------------------------------------------- 1 | extern crate itertools; 2 | use itertools::Itertools; 3 | use std::io::stdin; 4 | use std::io::Read; 5 | 6 | fn is_valid(mut lengths: Vec) -> usize { 7 | lengths.sort(); 8 | if lengths[0] + lengths[1] > lengths[2] { 9 | 1 10 | } else { 11 | 0 12 | } 13 | } 14 | 15 | fn main() { 16 | let (row_count, column_count) = stdin() 17 | .bytes() 18 | .filter_map(|b| b.ok()) 19 | .scan(0, |state, ch| { 20 | Some(if ch == b' ' || ch == b'\n' { 21 | if *state > 0 { 22 | let res = *state; 23 | *state = 0; 24 | Some(res) 25 | } else { 26 | None 27 | } 28 | } else { 29 | *state = *state * 10 + u32::from(ch - b'0'); 30 | None 31 | }) 32 | }) 33 | .filter_map(|b| b) 34 | .chunks(9) 35 | .into_iter() 36 | .fold((0, 0), |(row_count, column_count), lengths_iter| { 37 | let lengths = lengths_iter.collect::>(); 38 | 39 | let new_row_count = is_valid(lengths[0..3].to_vec()) 40 | + is_valid(lengths[3..6].to_vec()) 41 | + is_valid(lengths[6..9].to_vec()); 42 | 43 | let new_column_count = is_valid(vec![lengths[0], lengths[3], lengths[6]]) 44 | + is_valid(vec![lengths[1], lengths[4], lengths[7]]) 45 | + is_valid(vec![lengths[2], lengths[5], lengths[8]]); 46 | 47 | (row_count + new_row_count, column_count + new_column_count) 48 | }); 49 | 50 | println!("Part 1: {}", row_count); 51 | println!("Part 2: {}", column_count); 52 | } 53 | -------------------------------------------------------------------------------- /2016/src/bin/day05.rs: -------------------------------------------------------------------------------- 1 | extern crate crypto; 2 | use crypto::digest::Digest; 3 | use crypto::md5::Md5; 4 | use std::char; 5 | use std::io::stdin; 6 | use std::io::Read; 7 | use std::io::Write; 8 | 9 | fn main() { 10 | let salt: Vec<_> = stdin() 11 | .bytes() 12 | .filter_map(|b| b.ok()) 13 | .filter(|b| b != &b'\n') 14 | .collect(); 15 | 16 | let mut md5 = Md5::new(); 17 | let mut result = vec![0; md5.output_bytes()]; 18 | let mut formated_index = Vec::new(); 19 | 20 | let hashes = (0..).filter_map(|index| { 21 | formated_index.clear(); 22 | write!(&mut formated_index, "{}", index).unwrap(); 23 | 24 | md5.reset(); 25 | md5.input(&salt); 26 | md5.input(&formated_index); 27 | md5.result(&mut result); 28 | 29 | if result[0] == 0 && result[1] == 0 && result[2] & 0xf0 == 0 { 30 | Some(( 31 | char::from_digit(u32::from(result[2]) & 0x0f, 16).unwrap(), 32 | char::from_digit(u32::from(result[3] >> 4) & 0x0f, 16).unwrap(), 33 | )) 34 | } else { 35 | None 36 | } 37 | }); 38 | 39 | let mut password1 = String::new(); 40 | let mut password2 = vec![None; 8]; 41 | let mut password1_ok = false; 42 | let mut password2_ok = false; 43 | for (ch1, ch2) in hashes { 44 | if !password1_ok { 45 | password1.push(ch1); 46 | } 47 | 48 | if !password2_ok { 49 | let position = (ch1 as u8 - b'0') as usize; 50 | if position < 8 && password2[position].is_none() { 51 | password2[position] = Some(ch2); 52 | } 53 | } 54 | 55 | password1_ok = password1.len() == salt.len(); 56 | password2_ok = password2.iter().all(|a| a.is_some()); 57 | if password1_ok && password2_ok { 58 | break; 59 | } 60 | } 61 | println!("Part 1: {}", password1); 62 | println!( 63 | "Part 2: {}", 64 | password2.iter().map(|a| a.unwrap()).collect::() 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /2016/src/bin/day06.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::io::stdin; 3 | use std::io::Read; 4 | 5 | fn main() { 6 | let columns = stdin() 7 | .bytes() 8 | .filter_map(|b| b.ok()) 9 | .map(|b| b as char) 10 | .fold((0, Vec::new()), |(mut column_index, mut columns), ch| { 11 | if ch == '\n' { 12 | column_index = 0; 13 | } else { 14 | if columns.len() <= column_index { 15 | columns.push(HashMap::new()); 16 | } 17 | *columns[column_index].entry(ch).or_insert(0) += 1; 18 | column_index += 1; 19 | } 20 | (column_index, columns) 21 | }) 22 | .1; 23 | 24 | let message1: String = columns 25 | .iter() 26 | .map(|column| *column.iter().max_by_key(|&(_, count)| count).unwrap().0) 27 | .collect(); 28 | 29 | let message2: String = columns 30 | .iter() 31 | .map(|column| *column.iter().min_by_key(|&(_, count)| count).unwrap().0) 32 | .collect(); 33 | 34 | println!("Part 1: {}", message1); 35 | println!("Part 2: {}", message2); 36 | } 37 | -------------------------------------------------------------------------------- /2016/src/bin/day07.rs: -------------------------------------------------------------------------------- 1 | extern crate itertools; 2 | use itertools::Itertools; 3 | 4 | use std::collections::HashSet; 5 | use std::io::stdin; 6 | use std::io::Read; 7 | 8 | fn has_abba(s: &str) -> bool { 9 | s.chars() 10 | .tuple_windows() 11 | .any(|(a, b, c, d)| a == d && b == c && a != b) 12 | } 13 | 14 | fn get_aba(s: &str) -> Vec<(char, char, char)> { 15 | s.chars() 16 | .tuple_windows() 17 | .filter(|&(a, b, c)| a == c && a != b) 18 | .collect() 19 | } 20 | 21 | fn support_tls(ip: &[String]) -> bool { 22 | let mut result = false; 23 | for (index, chunk) in ip.iter().enumerate() { 24 | if index % 2 == 1 { 25 | if has_abba(chunk) { 26 | return false; 27 | } 28 | } else if !result { 29 | result = has_abba(chunk); 30 | } 31 | } 32 | result 33 | } 34 | 35 | fn support_ssl(ip: &[String]) -> bool { 36 | let mut abas = HashSet::new(); 37 | for (index, chunk) in ip.iter().enumerate() { 38 | if index % 2 == 0 { 39 | for t in get_aba(chunk) { 40 | abas.insert(t); 41 | } 42 | } 43 | } 44 | for (index, chunk) in ip.iter().enumerate() { 45 | if index % 2 == 1 { 46 | for &(a, b, _) in &abas { 47 | if chunk.contains(&format!("{}{}{}", b, a, b)) { 48 | return true; 49 | } 50 | } 51 | } 52 | } 53 | false 54 | } 55 | 56 | fn main() { 57 | let (count_tls, count_ssl) = stdin() 58 | .bytes() 59 | .filter_map(|b| b.ok()) 60 | .map(|b| b as char) 61 | .batching(|it| { 62 | let s: Vec<_> = it 63 | .take_while(|ch| ch != &'\n') 64 | .batching(|it| { 65 | let s: String = it.take_while(|ch| ch != &'[' && ch != &']').collect(); 66 | if s.is_empty() { 67 | None 68 | } else { 69 | Some(s) 70 | } 71 | }) 72 | .collect(); 73 | if s.is_empty() { 74 | None 75 | } else { 76 | Some(s) 77 | } 78 | }) 79 | .fold((0, 0), |(counttls, countssl), ip| { 80 | ( 81 | counttls + if support_tls(&ip) { 1 } else { 0 }, 82 | countssl + if support_ssl(&ip) { 1 } else { 0 }, 83 | ) 84 | }); 85 | 86 | println!("Part 1: {}", count_tls); 87 | println!("Part 2: {}", count_ssl); 88 | } 89 | -------------------------------------------------------------------------------- /2016/src/bin/day09.rs: -------------------------------------------------------------------------------- 1 | use std::io::stdin; 2 | use std::io::Read; 3 | 4 | fn read_int(chars: &mut B) -> u64 5 | where 6 | B: Iterator, 7 | { 8 | let mut result = 0u64; 9 | for ch in chars { 10 | if let Some(n) = ch.to_digit(10) { 11 | result = result * 10 + u64::from(n); 12 | } else { 13 | break; 14 | } 15 | } 16 | result 17 | } 18 | 19 | fn decompress_len(s: &str, recurse: bool) -> u64 { 20 | let mut result = 0; 21 | 22 | let mut chars = s.chars(); 23 | 24 | while let Some(ch) = chars.next() { 25 | if ch == '(' { 26 | let char_count = read_int(&mut chars); 27 | let times = read_int(&mut chars); 28 | if recurse { 29 | let slice: String = chars.by_ref().take(char_count as usize).collect(); 30 | result += times * decompress_len(&slice, recurse); 31 | } else if char_count > 0 { 32 | chars.by_ref().nth(char_count as usize - 1); 33 | result += times * char_count; 34 | } 35 | } else if ch != ' ' { 36 | result += 1; 37 | } 38 | } 39 | 40 | result 41 | } 42 | 43 | fn main() { 44 | let input: String = stdin() 45 | .bytes() 46 | .filter_map(|b| b.ok()) 47 | .map(|b| b as char) 48 | .take_while(|ch| ch != &'\n') 49 | .collect(); 50 | 51 | println!("Part 1: {}", decompress_len(&input, false)); 52 | println!("Part 2: {}", decompress_len(&input, true)); 53 | } 54 | -------------------------------------------------------------------------------- /2016/src/bin/day14.rs: -------------------------------------------------------------------------------- 1 | extern crate crypto; 2 | extern crate itertools; 3 | use crypto::digest::Digest; 4 | use crypto::md5::Md5; 5 | use std::char; 6 | use std::io::stdin; 7 | use std::io::Read; 8 | use std::iter; 9 | 10 | fn has_n_of_a_kind(s: &str, n: usize) -> Option { 11 | let mut current_ch = None; 12 | let mut current_count = 0; 13 | 14 | for ch in s.chars() { 15 | if current_ch == Some(ch) { 16 | current_count += 1; 17 | if current_count == n - 1 { 18 | return Some(ch); 19 | } 20 | } else { 21 | current_ch = Some(ch); 22 | current_count = 0; 23 | } 24 | } 25 | 26 | None 27 | } 28 | 29 | #[allow(clippy::while_let_on_iterator)] 30 | fn find_keys_index(hashes: B) -> u32 31 | where 32 | B: Iterator, 33 | { 34 | let mut index = 0; 35 | let mut count = 0; 36 | let mut iter = itertools::multipeek(hashes); 37 | 38 | while let Some(h) = iter.next() { 39 | if let Some(ch) = has_n_of_a_kind(&h, 3) { 40 | let five_of_a_kind: String = iter::repeat(ch).take(5).collect(); 41 | if (0..1000).any(|_| iter.peek().unwrap().contains(&five_of_a_kind)) { 42 | count += 1; 43 | if count == 64 { 44 | return index; 45 | } 46 | } 47 | } 48 | index += 1; 49 | } 50 | 51 | unreachable!(); 52 | } 53 | 54 | fn hash(salt: &[u8], index: u32) -> String { 55 | let mut md5 = Md5::new(); 56 | md5.input(salt); 57 | md5.input_str(&format!("{}", index)); 58 | md5.result_str() 59 | } 60 | 61 | fn stretched_hash(salt: &[u8], index: u32) -> String { 62 | let mut md5 = Md5::new(); 63 | md5.input(salt); 64 | md5.input_str(&format!("{}", index)); 65 | (0..2016).fold(md5.result_str(), |previous, _| { 66 | md5.reset(); 67 | md5.input_str(&previous); 68 | md5.result_str() 69 | }) 70 | } 71 | 72 | fn main() { 73 | let salt: Vec<_> = stdin() 74 | .bytes() 75 | .filter_map(|b| b.ok()) 76 | .filter(|b| b != &b'\n') 77 | .collect(); 78 | 79 | println!( 80 | "Part 1: {}", 81 | find_keys_index((0..).map(|index| hash(&salt, index))) 82 | ); 83 | 84 | println!( 85 | "Part 2: {}", 86 | find_keys_index((0..).map(|index| stretched_hash(&salt, index))) 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /2016/src/bin/day15.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | use regex::Regex; 3 | use std::io::stdin; 4 | use std::io::BufRead; 5 | 6 | #[derive(Debug)] 7 | struct Disc { 8 | positions: u8, 9 | position: u8, 10 | } 11 | 12 | impl Disc { 13 | fn has_slot_up(&self, time: u32) -> bool { 14 | (time + u32::from(self.position)) % u32::from(self.positions) == 0 15 | } 16 | } 17 | 18 | fn get_start_time(discs: &[Disc]) -> Option { 19 | (0..).find(|start_time| { 20 | discs 21 | .iter() 22 | .enumerate() 23 | .all(|(index, disc)| disc.has_slot_up(start_time + index as u32 + 1)) 24 | }) 25 | } 26 | 27 | fn main() { 28 | let re = Regex::new(r"^Disc #\d+ has (\d+) positions; at time=0, it is at position (\d+)\.$") 29 | .unwrap(); 30 | 31 | let stdin = stdin(); 32 | let mut discs: Vec<_> = stdin 33 | .lock() 34 | .lines() 35 | .filter_map(|l| l.ok()) 36 | .filter_map(|line| { 37 | re.captures(&line).and_then(|caps| { 38 | Some(Disc { 39 | positions: caps.at(1).unwrap().parse().unwrap(), 40 | position: caps.at(2).unwrap().parse().unwrap(), 41 | }) 42 | }) 43 | }) 44 | .collect(); 45 | 46 | println!("Part 1: {:?}", get_start_time(&discs)); 47 | discs.push(Disc { 48 | positions: 11, 49 | position: 0, 50 | }); 51 | println!("Part 2: {:?}", get_start_time(&discs)); 52 | } 53 | -------------------------------------------------------------------------------- /2016/src/bin/day16.rs: -------------------------------------------------------------------------------- 1 | extern crate itertools; 2 | use itertools::Itertools; 3 | use std::io::stdin; 4 | use std::io::Read; 5 | 6 | fn fill_until(vec: &mut Vec, len: usize) { 7 | vec.reserve(len); 8 | while vec.len() < len { 9 | vec.push(false); 10 | if vec.len() == len { 11 | return; 12 | } 13 | for index in (0..vec.len() - 1).rev() { 14 | let v = !vec[index]; 15 | vec.push(v); 16 | if vec.len() == len { 17 | return; 18 | } 19 | } 20 | } 21 | } 22 | 23 | fn checksum(vec: &[bool]) -> Vec { 24 | let mut current: Vec<_> = vec.iter().tuples().map(|(a, b)| a == b).collect(); 25 | while current.len() % 2 != 1 { 26 | current = current.iter().tuples().map(|(a, b)| a == b).collect(); 27 | } 28 | current 29 | } 30 | 31 | fn print(vec: &[bool]) { 32 | for v in vec { 33 | if *v { 34 | print!("1"); 35 | } else { 36 | print!("0"); 37 | } 38 | } 39 | println!(); 40 | } 41 | 42 | fn main() { 43 | let start: Vec<_> = stdin() 44 | .bytes() 45 | .filter_map(|b| b.ok()) 46 | .filter_map(|b| match b { 47 | b'1' => Some(true), 48 | b'0' => Some(false), 49 | _ => None, 50 | }) 51 | .collect(); 52 | 53 | let mut disk1 = start.clone(); 54 | fill_until(&mut disk1, 272); 55 | print!("Part 1: "); 56 | print(&checksum(&disk1)); 57 | 58 | let mut disk2 = start.clone(); 59 | fill_until(&mut disk2, 35_651_584); 60 | print!("Part 2: "); 61 | print(&checksum(&disk2)); 62 | } 63 | -------------------------------------------------------------------------------- /2016/src/bin/day17.rs: -------------------------------------------------------------------------------- 1 | extern crate crypto; 2 | extern crate itertools; 3 | use crypto::digest::Digest; 4 | use crypto::md5::Md5; 5 | use itertools::Itertools; 6 | use itertools::MinMaxResult; 7 | use std::io::stdin; 8 | use std::io::Read; 9 | 10 | type Coords = (u8, u8); 11 | 12 | struct MinMaxIntoIter { 13 | minmax: MinMaxResult, 14 | } 15 | 16 | impl Iterator for MinMaxIntoIter { 17 | type Item = T; 18 | 19 | fn next(&mut self) -> Option { 20 | match std::mem::replace(&mut self.minmax, MinMaxResult::NoElements) { 21 | MinMaxResult::OneElement(t) => Some(t), 22 | MinMaxResult::MinMax(min, max) => { 23 | self.minmax = MinMaxResult::OneElement(max); 24 | Some(min) 25 | } 26 | MinMaxResult::NoElements => None, 27 | } 28 | } 29 | } 30 | 31 | fn minmax_into_iter(minmax: MinMaxResult) -> MinMaxIntoIter { 32 | MinMaxIntoIter { minmax } 33 | } 34 | 35 | fn open_doors(passcode: &[u8], (x, y): Coords, path: &[u8]) -> Vec<(u8, Coords)> { 36 | let mut result = Vec::new(); 37 | let mut md5 = Md5::new(); 38 | md5.input(passcode); 39 | md5.input(path); 40 | let hash = md5.result_str().into_bytes(); 41 | if y > 0 && hash[0] > b'a' { 42 | result.push((b'U', (x, y - 1))); 43 | } 44 | if y < 3 && hash[1] > b'a' { 45 | result.push((b'D', (x, y + 1))); 46 | } 47 | if x > 0 && hash[2] > b'a' { 48 | result.push((b'L', (x - 1, y))); 49 | } 50 | if x < 3 && hash[3] > b'a' { 51 | result.push((b'R', (x + 1, y))); 52 | } 53 | result 54 | } 55 | 56 | fn find_path(passcode: &[u8], (x, y): Coords, mut path: &mut Vec) -> MinMaxResult> { 57 | if x == 3 && y == 3 { 58 | return MinMaxResult::OneElement(path.clone()); 59 | } 60 | 61 | open_doors(passcode, (x, y), path) 62 | .iter() 63 | .flat_map(|&(direction, coords)| { 64 | path.push(direction); 65 | let result = find_path(passcode, coords, &mut path); 66 | path.pop(); 67 | 68 | minmax_into_iter(result) 69 | }) 70 | .minmax_by_key(|p| p.len()) 71 | } 72 | 73 | fn main() { 74 | let passcode: Vec<_> = stdin() 75 | .bytes() 76 | .filter_map(|b| b.ok()) 77 | .take_while(|b| b != &b'\n') 78 | .collect(); 79 | 80 | if let MinMaxResult::MinMax(min, max) = find_path(&passcode, (0, 0), &mut Vec::new()) { 81 | println!("Part 1: {}", String::from_utf8_lossy(&min)); 82 | println!("Part 2: {}", max.len()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /2016/src/bin/day18.rs: -------------------------------------------------------------------------------- 1 | use std::io::stdin; 2 | use std::io::Read; 3 | 4 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] 5 | enum Tile { 6 | Trap, 7 | Safe, 8 | } 9 | 10 | type Row = Vec; 11 | 12 | fn generate_room(first_row: Row) -> Box> { 13 | Box::new((0..).scan(first_row, |next_row, _| { 14 | let new_row: Vec<_> = (0..next_row.len()) 15 | .map(|column| { 16 | let left = if column > 0 { 17 | next_row[column - 1] 18 | } else { 19 | Tile::Safe 20 | }; 21 | let right = if column < next_row.len() - 1 { 22 | next_row[column + 1] 23 | } else { 24 | Tile::Safe 25 | }; 26 | if left == right { 27 | Tile::Safe 28 | } else { 29 | Tile::Trap 30 | } 31 | }) 32 | .collect(); 33 | Some(std::mem::replace(next_row, new_row)) 34 | })) 35 | } 36 | 37 | fn main() { 38 | let first_row: Vec<_> = stdin() 39 | .bytes() 40 | .filter_map(|l| l.ok()) 41 | .filter_map(|b| match b { 42 | b'.' => Some(Tile::Safe), 43 | b'^' => Some(Tile::Trap), 44 | _ => None, 45 | }) 46 | .collect(); 47 | 48 | let safe_tile_count = generate_room(first_row.clone()) 49 | .take(40) 50 | .map(|row| row.iter().filter(|t| t == &&Tile::Safe).count()) 51 | .sum::(); 52 | 53 | println!("Part 1: {}", safe_tile_count); 54 | 55 | let safe_tile_count_400k = generate_room(first_row) 56 | .take(400_000) 57 | .map(|row| row.iter().filter(|t| t == &&Tile::Safe).count()) 58 | .sum::(); 59 | 60 | println!("Part 2: {}", safe_tile_count_400k); 61 | } 62 | -------------------------------------------------------------------------------- /2016/src/bin/day19.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::io::stdin; 3 | use std::io::BufRead; 4 | 5 | fn winner(elves: u32) -> u32 { 6 | if elves.is_power_of_two() { 7 | 1 8 | } else { 9 | ((elves << 1) ^ elves.next_power_of_two()) | 1 10 | } 11 | } 12 | 13 | fn next_power_of_three(mut n: u32) -> u32 { 14 | let mut result = 1; 15 | while n > 0 { 16 | n /= 3; 17 | result *= 3; 18 | } 19 | result 20 | } 21 | 22 | fn winner2(elves: u32) -> u32 { 23 | let next = next_power_of_three(elves); 24 | let prev = next / 3; 25 | if elves == prev { 26 | elves 27 | } else if elves > prev * 2 { 28 | elves * 2 - next 29 | } else { 30 | elves - prev 31 | } 32 | } 33 | 34 | #[allow(dead_code)] 35 | fn winner2_brute(elves: u32) -> u32 { 36 | let mut elves_vec: VecDeque<_> = (1..=elves).collect(); 37 | let mut index = 0; 38 | 39 | while elves_vec.len() > 1 { 40 | let opposite = (index + elves_vec.len() / 2) % elves_vec.len(); 41 | elves_vec.remove(opposite); 42 | index = if opposite > index { index + 1 } else { index } % elves_vec.len(); 43 | } 44 | 45 | elves_vec[0] 46 | } 47 | 48 | fn main() { 49 | let stdin = stdin(); 50 | let elves: u32 = stdin 51 | .lock() 52 | .lines() 53 | .next() 54 | .and_then(|line| line.ok().and_then(|line| line.parse().ok())) 55 | .unwrap_or(0); 56 | 57 | println!("Part 1: {}", winner(elves)); 58 | println!("Part 2: {}", winner2(elves)); 59 | } 60 | -------------------------------------------------------------------------------- /2016/src/bin/day20.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeSet; 2 | use std::io::stdin; 3 | use std::io::BufRead; 4 | 5 | fn main() { 6 | let stdin = stdin(); 7 | let blacklist: BTreeSet<(u32, u32)> = stdin 8 | .lock() 9 | .lines() 10 | .filter_map(|l| l.ok()) 11 | .filter_map(|line| { 12 | let mut parts = line.split('-'); 13 | if let (Some(low), Some(high)) = (parts.next(), parts.next()) { 14 | Some((low.parse().unwrap(), high.parse().unwrap())) 15 | } else { 16 | None 17 | } 18 | }) 19 | .collect(); 20 | 21 | let mut ip = 0; 22 | 23 | for &(low, high) in &blacklist { 24 | if ip < low { 25 | break; 26 | } 27 | ip = high + 1; 28 | } 29 | println!("Part 1: {}", ip); 30 | 31 | let mut count = 0; 32 | let mut max_high = 0; 33 | for &(low, high) in &blacklist { 34 | if low > max_high { 35 | count += low - max_high - 1; 36 | } 37 | max_high = std::cmp::max(high, max_high); 38 | } 39 | count += u32::max_value() - max_high; 40 | println!("Part 2: {}", count); 41 | } 42 | -------------------------------------------------------------------------------- /2016/tests/day01/input: -------------------------------------------------------------------------------- 1 | R3, L2, L2, R4, L1, R2, R3, R4, L2, R4, L2, L5, L1, R5, R2, R2, L1, R4, R1, L5, L3, R4, R3, R1, L1, L5, L4, L2, R5, L3, L4, R3, R1, L3, R1, L3, R3, L4, R2, R5, L190, R2, L3, R47, R4, L3, R78, L1, R3, R190, R4, L3, R4, R2, R5, R3, R4, R3, L1, L4, R3, L4, R1, L4, L5, R3, L3, L4, R1, R2, L4, L3, R3, R3, L2, L5, R1, L4, L1, R5, L5, R1, R5, L4, R2, L2, R1, L5, L4, R4, R4, R3, R2, R3, L1, R4, R5, L2, L5, L4, L1, R4, L4, R4, L4, R1, R5, L1, R1, L5, R5, R1, R1, L3, L1, R4, L1, L4, L4, L3, R1, R4, R1, R1, R2, L5, L2, R4, L1, R3, L5, L2, R5, L4, R5, L5, R3, R4, L3, L3, L2, R2, L5, L5, R3, R4, R3, R4, R3, R1 2 | -------------------------------------------------------------------------------- /2016/tests/day01/output: -------------------------------------------------------------------------------- 1 | Part 1: 262 2 | Part 2: 131 3 | -------------------------------------------------------------------------------- /2016/tests/day02/input: -------------------------------------------------------------------------------- 1 | LDUDDRUDRRURRRRDRUUDULDLULRRLLLUDDULRDLDDLRULLDDLRUURRLDUDDDDLUULUUDDDDLLLLLULLRURDRLRLRLLURDLLDDUULUUUUDLULLRLUUDDLRDRRURRLURRLLLRRDLRUDURRLRRRLULRDLUDRDRLUDDUUULDDDDDURLDULLRDDRRUDDDDRRURRULUDDLLRRDRURDLLLLLUUUDLULURLULLDRLRRDDLUDURUDRLRURURLRRDDLDUULURULRRLLLDRURDULRDUURRRLDLDUDDRLURRDRDRRLDLRRRLRURDRLDRUDLURRUURDLDRULULURRLDLLLUURRULUDDDRLDDUDDDRRLRDUDRUUDDULRDDULDDURULUDLUDRUDDDLRRRRRDLULDRLRRRRUULDUUDRRLURDLLUUDUDDDLUUURDRUULRURULRLLDDLLUDLURRLDRLDDDLULULLURLULRDLDRDDDLRDUDUURUUULDLLRDRUDRDURUUDDLRRRRLLLUULURRURLLDDLDDD 2 | DRURURLLUURRRULURRLRULLLURDULRLRRRLRUURRLRRURRRRUURRRLUDRDUDLUUDULURRLDLULURRLDURLUUDLDUDRUURDDRDLLLDDRDDLUUDRDUDDRRDLDUDRLDDDRLLDDLUDRULRLLURLDLURRDRUDUDLDLULLLRDLLRRDULLDRURRDLDRURDURDULUUURURDLUDRRURLRRLDULRRDURRDRDDULLDRRRLDRRURRRRUURDRLLLRRULLUDUDRRDDRURLULLUUDDRLDRRDUDLULUUDRDDDDLRLRULRLRLLDLLRRDDLDRDURRULLRLRRLULRULDDDRDRULDRUUDURDLLRDRURDRLRDDUDLLRUDLURURRULLUDRDRDURLLLDDDRDRURRDDRLRRRDLLDDLDURUULURULRLULRLLURLUDULDRRDDLRDLRRLRLLULLDDDRDRU 3 | URUUDUDRDDRDRRRDLLUDRUDRUUUURDRRDUDUULDUDLLUDRRUDLLRDLLULULDRRDDULDRLDLDDULLDDRDDDLRLLDLLRDUUDUURLUDURDRRRRLRRLDRRUULLDLDLRDURULRURULRRDRRDDUUURDURLLDDUUDLRLDURULURRRDRRUUUDRDDLRLRRLLULUDDRRLRRRRLRDRUDDUULULRRURUURURRLRUDLRRUUURUULLULULRRDDULDRRLLLDLUDRRRLLRDLLRLDUDDRRULULUDLURLDRDRRLULLRRDRDLUURLDDURRLDRLURULDLDRDLURRDRLUUDRUULLDRDURLLDLRUDDULLLLDLDDDLURDDUDUDDRLRDDUDDURURLULLRLUDRDDUDDLDRUURLDLUUURDUULRULLDDDURULDDLLD 4 | LRRLLRURUURRDLURRULDDDLURDUURLLDLRRRRULUUDDLULLDLLRDLUDUULLUDRLLDRULDDURURDUUULRUDRLLRDDDURLRDRRURDDRUDDRRULULLLDLRLULLDLLDRLLLUDLRURLDULRDDRDLDRRDLUUDDLURDLURLUDLRDLDUURLRRUULDLURULUURULLURLDDURRURDRLUULLRRLLLDDDURLURUURLLLLDLLLUDLDLRDULUULRRLUUUUDLURRURRULULULRURDDRRRRDRUDRURDUDDDDUDLURURRDRRDRUDRLDLDDDLURRRURRUDLDURDRLDLDLDDUDURLUDUUDRULLRLLUUDDUURRRUDURDRRUURLUDRRUDLUDDRUUDLULDLLDLRUUDUULLDULRRLDRUDRRDRLUUDDRUDDLLULRLULLDLDUULLDRUUDDUDLLLLDLDDLDLURLDLRUUDDUULLUDUUDRUDLRDDRDLDRUUDUDLLDUURRRLLLLRLLRLLRLUUDULLRLURDLLRUUDRULLULRDRDRRULRDLUDDURRRRURLLRDRLLDRUUULDUDDLRDRD 5 | DDLRRULRDURDURULLLLRLDDRDDRLLURLRDLULUDURRLUDLDUDRDULDDULURDRURLLDRRLDURRLUULLRUUDUUDLDDLRUUDRRDDRLURDRUDRRRDRUUDDRLLUURLURUDLLRRDRDLUUDLUDURUUDDUULUURLUDLLDDULLUURDDRDLLDRLLDDDRRDLDULLURRLDLRRRLRRURUUDRLURURUULDURUDRRLUDUDLRUDDUDDRLLLULUDULRURDRLUURRRRDLLRDRURRRUURULRUDULDULULUULULLURDUDUDRLDULDRDDULRULDLURLRLDDDDDDULDRURRRRDLLRUDDRDDLUUDUDDRLLRLDLUDRUDULDDDRLLLLURURLDLUUULRRRUDLLULUUULLDLRLDLLRLRDLDULLRLUDDDRDRDDLULUUR 6 | -------------------------------------------------------------------------------- /2016/tests/day02/output: -------------------------------------------------------------------------------- 1 | Part 1: 76792 2 | Part 2: A7AC3 3 | -------------------------------------------------------------------------------- /2016/tests/day03/output: -------------------------------------------------------------------------------- 1 | Part 1: 1050 2 | Part 2: 1921 3 | -------------------------------------------------------------------------------- /2016/tests/day04/output: -------------------------------------------------------------------------------- 1 | Part 1: 173787 2 | Part 2: 548 3 | -------------------------------------------------------------------------------- /2016/tests/day05/input: -------------------------------------------------------------------------------- 1 | cxdnnyjw 2 | -------------------------------------------------------------------------------- /2016/tests/day05/output: -------------------------------------------------------------------------------- 1 | Part 1: f77a0e6e 2 | Part 2: 999828ec 3 | -------------------------------------------------------------------------------- /2016/tests/day06/output: -------------------------------------------------------------------------------- 1 | Part 1: tsreykjj 2 | Part 2: hnfbujie 3 | -------------------------------------------------------------------------------- /2016/tests/day07/output: -------------------------------------------------------------------------------- 1 | Part 1: 118 2 | Part 2: 260 3 | -------------------------------------------------------------------------------- /2016/tests/day08/output: -------------------------------------------------------------------------------- 1 | Part 1: 123 2 | Part 2: 3 | .##..####.###..#..#.###..####.###....##.###...###. 4 | #..#.#....#..#.#..#.#..#....#.#..#....#.#..#.#.... 5 | #..#.###..###..#..#.#..#...#..###.....#.#..#.#.... 6 | ####.#....#..#.#..#.###...#...#..#....#.###...##.. 7 | #..#.#....#..#.#..#.#....#....#..#.#..#.#.......#. 8 | #..#.#....###...##..#....####.###...##..#....###.. 9 | -------------------------------------------------------------------------------- /2016/tests/day09/output: -------------------------------------------------------------------------------- 1 | Part 1: 150914 2 | Part 2: 11052855125 3 | -------------------------------------------------------------------------------- /2016/tests/day10/output: -------------------------------------------------------------------------------- 1 | Part 1: Some(Bot(56)) 2 | Part 2: 7847 3 | -------------------------------------------------------------------------------- /2016/tests/day11/input: -------------------------------------------------------------------------------- 1 | The first floor contains a promethium generator and a promethium-compatible microchip. 2 | The second floor contains a cobalt generator, a curium generator, a ruthenium generator, and a plutonium generator. 3 | The third floor contains a cobalt-compatible microchip, a curium-compatible microchip, a ruthenium-compatible microchip, and a plutonium-compatible microchip. 4 | The fourth floor contains nothing relevant. 5 | -------------------------------------------------------------------------------- /2016/tests/day11/output: -------------------------------------------------------------------------------- 1 | Part 1: Some(33) 2 | Part 2: Some(57) 3 | -------------------------------------------------------------------------------- /2016/tests/day12/input: -------------------------------------------------------------------------------- 1 | cpy 1 a 2 | cpy 1 b 3 | cpy 26 d 4 | jnz c 2 5 | jnz 1 5 6 | cpy 7 c 7 | inc d 8 | dec c 9 | jnz c -2 10 | cpy a c 11 | inc a 12 | dec b 13 | jnz b -2 14 | cpy c b 15 | dec d 16 | jnz d -6 17 | cpy 19 c 18 | cpy 11 d 19 | inc a 20 | dec d 21 | jnz d -2 22 | dec c 23 | jnz c -5 24 | -------------------------------------------------------------------------------- /2016/tests/day12/output: -------------------------------------------------------------------------------- 1 | Part 1: 318020 2 | Part 2: 9227674 3 | -------------------------------------------------------------------------------- /2016/tests/day13/input: -------------------------------------------------------------------------------- 1 | 1358 2 | -------------------------------------------------------------------------------- /2016/tests/day13/output: -------------------------------------------------------------------------------- 1 | Part 1: 96 2 | 0 1 2 3 4 5 6 7 8 9101112131415161718192021222324 3 | 0 O # # O O # . # O # # . # . . . . # # . . . # . . 4 | 1 O O # # O O # # O # # . # . . # . . . # # # . # . 5 | 2 # O O O # O # # O O # # # # # # # # . # . # # # # 6 | 3 . # # O O O O O O O O O O O O # # # . . . . . # # 7 | 4 # # # # # O # # O # # # # O O O # . # # . . . . # 8 | 5 . # # . # O O # O # # O # O # O # # # # # # . . # 9 | 6 . . O # # # O O O O O O # O O # . . # O O # # # # 10 | 7 # # O # # # # O O # # # . # O # # . # O # . . . # 11 | 8 O O O O # # # # # # O # # # O O # # # O O # # . # 12 | 9 # O # O O # # O O # O O O O O O O # # # O # . . # 13 | 10 # O O O O O O O O # # O # # O # O O O O O # . . . 14 | 11 . # # # # # # O # . # O # # O O O # # # O # # . . 15 | 12 # . . . . # # O O # # O # . # # # . . # O # # # . 16 | 13 # . . # . # # # O # O O # . . . # . # # O O O # . 17 | 14 # # # # . . # O O # O # # # # # # . # # # # # . # 18 | 15 # . . . . . # # O # O # # O O # . . . # # . # . # 19 | 16 # . # # . . . # O O O O O O O # . . . . . . # . . 20 | 17 # . # # # . # # # # # # # O # # # # # # # # . # # 21 | 18 # . . # # . # . . . # # # O # # O O O # . # # . # 22 | 19 . # . # # . # . . . . . # O O O O # O O # . # # . 23 | 20 # # . . . # # # . # # . # O # # # . # O # # . # # 24 | 21 . . . # . . # # . # . . # # . . # # O O O # . . . 25 | 22 # # # # # . . . . # . . . # # # . # O O O # # . # 26 | 23 . . . # . # # . # # # . # . . # . # # O # . # # # 27 | 24 # . . # # # # . . # # . . # . # . # # . . # . . . 28 | Part 2: 141 29 | -------------------------------------------------------------------------------- /2016/tests/day14/input: -------------------------------------------------------------------------------- 1 | ahsbgdzn 2 | -------------------------------------------------------------------------------- /2016/tests/day14/output: -------------------------------------------------------------------------------- 1 | Part 1: 23890 2 | Part 2: 22696 3 | -------------------------------------------------------------------------------- /2016/tests/day15/input: -------------------------------------------------------------------------------- 1 | Disc #1 has 7 positions; at time=0, it is at position 0. 2 | Disc #2 has 13 positions; at time=0, it is at position 0. 3 | Disc #3 has 3 positions; at time=0, it is at position 2. 4 | Disc #4 has 5 positions; at time=0, it is at position 2. 5 | Disc #5 has 17 positions; at time=0, it is at position 0. 6 | Disc #6 has 19 positions; at time=0, it is at position 7. 7 | -------------------------------------------------------------------------------- /2016/tests/day15/output: -------------------------------------------------------------------------------- 1 | Part 1: Some(121834) 2 | Part 2: Some(3208099) 3 | -------------------------------------------------------------------------------- /2016/tests/day16/input: -------------------------------------------------------------------------------- 1 | 10011111011011001 2 | -------------------------------------------------------------------------------- /2016/tests/day16/output: -------------------------------------------------------------------------------- 1 | Part 1: 10111110010110110 2 | Part 2: 01101100001100100 3 | -------------------------------------------------------------------------------- /2016/tests/day17/input: -------------------------------------------------------------------------------- 1 | hhhxzeay 2 | -------------------------------------------------------------------------------- /2016/tests/day17/output: -------------------------------------------------------------------------------- 1 | Part 1: DDRUDLRRRD 2 | Part 2: 398 3 | -------------------------------------------------------------------------------- /2016/tests/day18/input: -------------------------------------------------------------------------------- 1 | .^..^....^....^^.^^.^.^^.^.....^.^..^...^^^^^^.^^^^.^.^^^^^^^.^^^^^..^.^^^.^^..^.^^.^....^.^...^^.^. 2 | -------------------------------------------------------------------------------- /2016/tests/day18/output: -------------------------------------------------------------------------------- 1 | Part 1: 2035 2 | Part 2: 20000577 3 | -------------------------------------------------------------------------------- /2016/tests/day19/input: -------------------------------------------------------------------------------- 1 | 3014603 2 | -------------------------------------------------------------------------------- /2016/tests/day19/output: -------------------------------------------------------------------------------- 1 | Part 1: 1834903 2 | Part 2: 1420280 3 | -------------------------------------------------------------------------------- /2016/tests/day20/output: -------------------------------------------------------------------------------- 1 | Part 1: 32259706 2 | Part 2: 113 3 | -------------------------------------------------------------------------------- /2016/tests/day21/output: -------------------------------------------------------------------------------- 1 | Part 1: dgfaehcb 2 | Part 2: fdhgacbe 3 | -------------------------------------------------------------------------------- /2016/tests/day22/output: -------------------------------------------------------------------------------- 1 | Part 1: 1003 2 | Part 2: 192 3 | -------------------------------------------------------------------------------- /2016/tests/day23/input: -------------------------------------------------------------------------------- 1 | cpy a b 2 | dec b 3 | cpy a d 4 | cpy 0 a 5 | cpy b c 6 | inc a 7 | dec c 8 | jnz c -2 9 | dec d 10 | jnz d -5 11 | dec b 12 | cpy b c 13 | cpy c d 14 | dec d 15 | inc c 16 | jnz d -2 17 | tgl c 18 | cpy -16 c 19 | jnz 1 c 20 | cpy 89 c 21 | jnz 84 d 22 | inc a 23 | inc d 24 | jnz d -2 25 | inc c 26 | jnz c -5 27 | -------------------------------------------------------------------------------- /2016/tests/day23/output: -------------------------------------------------------------------------------- 1 | Part 1: 12516 2 | Part 2: 479009076 3 | -------------------------------------------------------------------------------- /2016/tests/day24/output: -------------------------------------------------------------------------------- 1 | Part 1: 448 2 | Part 2: 672 3 | -------------------------------------------------------------------------------- /2016/tests/day25/input: -------------------------------------------------------------------------------- 1 | cpy a d 2 | cpy 4 c 3 | cpy 633 b 4 | inc d 5 | dec b 6 | jnz b -2 7 | dec c 8 | jnz c -5 9 | cpy d a 10 | jnz 0 0 11 | cpy a b 12 | cpy 0 a 13 | cpy 2 c 14 | jnz b 2 15 | jnz 1 6 16 | dec b 17 | dec c 18 | jnz c -4 19 | inc a 20 | jnz 1 -7 21 | cpy 2 b 22 | jnz c 2 23 | jnz 1 4 24 | dec b 25 | dec c 26 | jnz 1 -4 27 | jnz 0 0 28 | out b 29 | jnz a -19 30 | jnz 1 -21 31 | -------------------------------------------------------------------------------- /2016/tests/day25/output: -------------------------------------------------------------------------------- 1 | Part 1: 198 2 | -------------------------------------------------------------------------------- /2017/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Benoît Zugmeyer "] 3 | name = "advent_of_code_2017" 4 | version = "0.1.0" 5 | 6 | [lib] 7 | name = "aoc2017" 8 | path = "src/lib.rs" 9 | 10 | [dependencies] 11 | itertools = "0.7.3" 12 | nom = "3.2.1" 13 | regex = "0.2.3" 14 | -------------------------------------------------------------------------------- /2017/dl.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | dayname=$(printf day%02d $2) 6 | mkdir -p tests/$dayname 7 | curl "https://adventofcode.com/2017/day/$2/input" -H "Cookie: session=$1" > tests/$dayname/input 8 | touch tests/$dayname/output 9 | git add tests/$dayname/input tests/$dayname/output 10 | -------------------------------------------------------------------------------- /2017/run.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | ROOT_DIR=$(dirname $0) 6 | 7 | files=$(find $ROOT_DIR/src/bin -printf "%f\n" -name "*.rs" | sort -n) 8 | echo $files 9 | 10 | for src_file in $files; do 11 | name="${src_file%.*}" 12 | test_name="${name%-*}" 13 | 14 | echo -n "Running $name " 15 | if [[ -f "$ROOT_DIR/target/release/$name" ]]; then 16 | echo -n "using release target" 17 | bin="$ROOT_DIR/target/release/$name" 18 | elif [[ -f "$ROOT_DIR/target/debug/$name" ]]; then 19 | echo -n "using debug target" 20 | bin="$ROOT_DIR/target/debug/$name" 21 | else 22 | echo "no binary, skipping" 23 | continue 24 | fi 25 | 26 | echo -n "... " 27 | 28 | output=$("$bin" < "tests/$test_name/input") 29 | diff_output=$(diff -u "tests/$test_name/output" <(echo "$output") 2>&1 || true) 30 | if [[ -n $diff_output ]]; then 31 | echo "failed:" 32 | echo "$diff_output" 33 | echo 34 | else 35 | echo "succeed" 36 | fi 37 | done 38 | -------------------------------------------------------------------------------- /2017/src/bin/day01.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | fn main() { 4 | let mut input = String::new(); 5 | io::stdin().read_line(&mut input).unwrap(); 6 | let numbers: Vec<_> = input.chars().flat_map(|ch| ch.to_digit(10)).collect(); 7 | 8 | let mut part_1 = 0; 9 | let mut part_2 = 0; 10 | for (index, n) in numbers.iter().enumerate() { 11 | if n == &numbers[(index + 1) % numbers.len()] { 12 | part_1 += n; 13 | } 14 | if n == &numbers[(index + numbers.len() / 2) % numbers.len()] { 15 | part_2 += n; 16 | } 17 | } 18 | 19 | println!("Part 1: {:?}", part_1); 20 | println!("Part 2: {:?}", part_2); 21 | } 22 | -------------------------------------------------------------------------------- /2017/src/bin/day02.rs: -------------------------------------------------------------------------------- 1 | extern crate itertools; 2 | 3 | use std::io::stdin; 4 | use std::io::BufRead; 5 | use std::iter::repeat; 6 | use itertools::Itertools; 7 | use itertools::MinMaxResult; 8 | 9 | macro_rules! product { 10 | ( $slice:expr ) => { 11 | $slice.iter().enumerate().flat_map(|(i, val)| { 12 | repeat(val).zip( 13 | $slice 14 | .iter() 15 | .enumerate() 16 | .filter_map(move |(ib, valb)| { 17 | if ib != i { Some(valb) } else { None } 18 | }) 19 | ) 20 | }) 21 | }; 22 | } 23 | 24 | fn main() { 25 | let stdin = stdin(); 26 | 27 | let checksum = stdin 28 | .lock() 29 | .lines() 30 | .filter_map(|l| l.ok()) 31 | .map(|line| { 32 | line.split('\t') 33 | .flat_map(|s| s.parse::().ok()) 34 | .collect::>() 35 | }) 36 | .fold((0, 0), |(total_1, total_2), row| { 37 | let minmax = row.iter().minmax(); 38 | 39 | ( 40 | total_1 + 41 | if let MinMaxResult::MinMax(min, max) = minmax { 42 | max - min 43 | } else { 44 | 0 45 | }, 46 | total_2 + 47 | if let Some((a, b)) = product!(row).find(|&(a, b)| a % b == 0) { 48 | a / b 49 | } else { 50 | 0 51 | }, 52 | ) 53 | }); 54 | 55 | println!("Part 1: {}", checksum.0); 56 | println!("Part 2: {}", checksum.1); 57 | } 58 | -------------------------------------------------------------------------------- /2017/src/bin/day04.rs: -------------------------------------------------------------------------------- 1 | extern crate itertools; 2 | 3 | use std::io::stdin; 4 | use std::io::BufRead; 5 | use std::collections::HashSet; 6 | 7 | fn is_valid_passphrase(line: &str) -> bool { 8 | let mut unique_words: HashSet<&str> = HashSet::new(); 9 | for word in line.split(' ') { 10 | if unique_words.contains(word) { 11 | return false; 12 | } 13 | unique_words.insert(word); 14 | } 15 | true 16 | } 17 | 18 | fn is_valid_passphrase2(line: &str) -> bool { 19 | let mut unique_words: HashSet> = HashSet::new(); 20 | for word in line.split(' ') { 21 | let mut chars: Vec<_> = word.chars().collect(); 22 | chars.sort(); 23 | if unique_words.contains(&chars) { 24 | return false; 25 | } 26 | unique_words.insert(chars); 27 | } 28 | true 29 | } 30 | 31 | fn main() { 32 | let stdin = stdin(); 33 | 34 | let counts = stdin.lock().lines().filter_map(|l| l.ok()).fold( 35 | (0, 0), 36 | |(count_1, 37 | count_2), 38 | line| { 39 | ( 40 | count_1 + if is_valid_passphrase(&line) { 1 } else { 0 }, 41 | count_2 + if is_valid_passphrase2(&line) { 1 } else { 0 }, 42 | ) 43 | }, 44 | ); 45 | println!("Part 1: {}", counts.0); 46 | println!("Part 2: {}", counts.1); 47 | } 48 | -------------------------------------------------------------------------------- /2017/src/bin/day05.rs: -------------------------------------------------------------------------------- 1 | use std::io::stdin; 2 | use std::io::BufRead; 3 | 4 | fn part_1(mut map: Vec) -> u32 { 5 | let mut position: i32 = 0; 6 | let mut move_count = 0; 7 | loop { 8 | let value = map[position as usize]; 9 | map[position as usize] += 1; 10 | position += value; 11 | move_count += 1; 12 | if position < 0 || position >= map.len() as i32 { 13 | break; 14 | } 15 | } 16 | move_count 17 | } 18 | 19 | fn part_2(mut map: Vec) -> u32 { 20 | let mut position: i32 = 0; 21 | let mut move_count = 0; 22 | let len = map.len() as i32; 23 | // while let Some(value) = map.get_mut(position as usize) { 24 | // position += *value; 25 | // *value += if *value >= 3 { -1 } else { 1 }; 26 | // move_count += 1; 27 | // } 28 | loop { 29 | unsafe { 30 | let value = map.get_unchecked_mut(position as usize); 31 | position += *value; 32 | *value += if *value >= 3 { -1 } else { 1 }; 33 | } 34 | move_count += 1; 35 | if position < 0 || position >= len { 36 | break; 37 | } 38 | } 39 | move_count 40 | } 41 | 42 | fn main() { 43 | let stdin = stdin(); 44 | let map: Vec = stdin 45 | .lock() 46 | .lines() 47 | .filter_map(|l| l.ok()) 48 | .filter_map(|line| line.parse().ok()) 49 | .collect(); 50 | 51 | println!("Part 1: {}", part_1(map.clone())); 52 | println!("Part 2: {}", part_2(map)); 53 | } 54 | -------------------------------------------------------------------------------- /2017/src/bin/day06.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, Read}; 2 | use std::collections::HashMap; 3 | 4 | fn main() { 5 | let mut input = String::new(); 6 | stdin().read_to_string(&mut input).expect( 7 | "Failed to read stdin", 8 | ); 9 | let mut banks: Vec = input 10 | .trim() 11 | .split('\t') 12 | .flat_map(|n| n.parse().ok()) 13 | .collect(); 14 | let bank_count = banks.len() as u16; 15 | let mut configurations: HashMap, usize> = HashMap::new(); 16 | let mut count = 0; 17 | while !configurations.contains_key(&banks) { 18 | let (max_index, max_blocks) = banks 19 | .iter() 20 | .cloned() 21 | .enumerate() 22 | .max_by(|&(index_a, blocks_a), &(index_b, blocks_b)| { 23 | blocks_a.cmp(&blocks_b).then( 24 | index_a.cmp(&index_b).reverse(), 25 | ) 26 | }) 27 | .unwrap(); 28 | let new_banks = banks 29 | .iter() 30 | .enumerate() 31 | .map(|(index, blocks)| { 32 | let base_part = if index == max_index { 0 } else { *blocks }; 33 | let equal_part = max_blocks / bank_count; 34 | let add_part = if (bank_count + index as u16 - max_index as u16 - 1) % 35 | bank_count < max_blocks % bank_count 36 | { 37 | 1 38 | } else { 39 | 0 40 | }; 41 | base_part + equal_part + add_part 42 | }) 43 | .collect(); 44 | configurations.insert(banks, count); 45 | banks = new_banks; 46 | count += 1; 47 | } 48 | println!("Part 1: {}", count); 49 | println!("Part 2: {}", count - configurations[&banks]); 50 | } 51 | -------------------------------------------------------------------------------- /2017/src/bin/day08.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | use regex::Regex; 3 | use std::io::stdin; 4 | use std::io::BufRead; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let stdin = stdin(); 9 | let re = Regex::new(r"^(\w+) (inc|dec) (-?\d+) if (\w+) (.*) (-?\d+)$") 10 | .expect("failed to parse regex"); 11 | let mut registers: HashMap = HashMap::new(); 12 | let mut highest_value: Option = None; 13 | for line in stdin.lock().lines().filter_map(|l| l.ok()) { 14 | if let Some(captures) = re.captures(&line) { 15 | let condition_register = *registers.entry(captures[4].to_string()).or_insert(0); 16 | let condition_value = captures[6].parse().unwrap(); 17 | let ok = match &captures[5] { 18 | "<" => condition_register < condition_value, 19 | ">" => condition_register > condition_value, 20 | "==" => condition_register == condition_value, 21 | "!=" => condition_register != condition_value, 22 | ">=" => condition_register >= condition_value, 23 | "<=" => condition_register <= condition_value, 24 | _ => panic!("Unknown operation {}", &captures[5]), 25 | }; 26 | if ok { 27 | let mut register = registers.entry(captures[1].to_string()).or_insert(0); 28 | let mut value: i32 = captures[3].parse().unwrap(); 29 | match &captures[2] { 30 | "inc" => *register += value, 31 | "dec" => *register -= value, 32 | _ => panic!("Unknown action {}", &captures[2]), 33 | } 34 | highest_value = highest_value.map(|hv| hv.max(*register)).or_else( 35 | || Some(*register), 36 | ); 37 | } 38 | } else { 39 | panic!(format!("Failed to parse line {}", line)); 40 | }; 41 | } 42 | 43 | println!("Part 1: {}", registers.values().max().unwrap()); 44 | println!("Part 2: {}", highest_value.unwrap()); 45 | } 46 | -------------------------------------------------------------------------------- /2017/src/bin/day10.rs: -------------------------------------------------------------------------------- 1 | extern crate aoc2017; 2 | 3 | use std::io::stdin; 4 | use std::io::Read; 5 | use aoc2017::knot; 6 | 7 | fn part_1(input: &str) -> u16 { 8 | let lengths: Vec = input 9 | .split(',') 10 | .flat_map(|n| n.trim().parse().ok()) 11 | .collect(); 12 | 13 | let list = knot::rotate_list(&lengths, 1); 14 | u16::from(list[0]) * u16::from(list[1]) 15 | } 16 | 17 | fn main() { 18 | let mut input = String::new(); 19 | stdin().read_to_string(&mut input).expect( 20 | "Failed to read stdin", 21 | ); 22 | 23 | println!("Part 1: {}", part_1(&input)); 24 | println!("Part 2: {}", knot::compute_hash(&input)); 25 | } 26 | -------------------------------------------------------------------------------- /2017/src/bin/day11.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, Read}; 2 | 3 | fn distance(point: (i16, i16, i16)) -> i16 { 4 | (point.0.abs() + point.1.abs() + point.2.abs()) / 2 5 | } 6 | 7 | fn main() { 8 | let mut input = String::new(); 9 | stdin().read_to_string(&mut input).expect( 10 | "Failed to read stdin", 11 | ); 12 | 13 | let (max_distance, coord) = input.trim().split(',').fold( 14 | (0i16, (0i16, 0i16, 0i16)), 15 | |(max_distance, pd), direction| { 16 | let new_position = match direction { 17 | "n" => (pd.0, pd.1 + 1, pd.2 - 1), 18 | "s" => (pd.0, pd.1 - 1, pd.2 + 1), 19 | "nw" => (pd.0 + 1, pd.1, pd.2 - 1), 20 | "se" => (pd.0 - 1, pd.1, pd.2 + 1), 21 | "ne" => (pd.0 - 1, pd.1 + 1, pd.2), 22 | "sw" => (pd.0 + 1, pd.1 - 1, pd.2), 23 | _ => unreachable!(), 24 | }; 25 | 26 | ( 27 | std::cmp::max(max_distance, distance(new_position)), 28 | new_position, 29 | ) 30 | }, 31 | ); 32 | 33 | println!("Part 1: {}", distance(coord)); 34 | println!("Part 2: {}", max_distance); 35 | } 36 | -------------------------------------------------------------------------------- /2017/src/bin/day12.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | use regex::Regex; 3 | use std::collections::{HashMap, HashSet}; 4 | use std::io::{stdin, BufRead}; 5 | 6 | type Program = u32; 7 | 8 | fn populate_group( 9 | programs: &HashMap>, 10 | mut group: &mut HashSet, 11 | program: Program, 12 | ) { 13 | if group.contains(&program) { 14 | return; 15 | } 16 | 17 | group.insert(program); 18 | for other in &programs[&program] { 19 | populate_group(programs, &mut group, *other); 20 | } 21 | } 22 | 23 | fn main() { 24 | let stdin = stdin(); 25 | 26 | let re = Regex::new(r"\d+").expect("failed to parse regex"); 27 | 28 | let programs = stdin 29 | .lock() 30 | .lines() 31 | .filter_map(|l| l.ok()) 32 | .map(|line| { 33 | let values = re.captures_iter(&line) 34 | .map(|capture| capture.get(0).unwrap().as_str().parse().unwrap()) 35 | .collect::>(); 36 | (values[0], values[1..].to_vec()) 37 | }) 38 | .collect::>>(); 39 | 40 | { 41 | let mut group = HashSet::new(); 42 | populate_group(&programs, &mut group, 0); 43 | println!("Part 1: {}", group.len()); 44 | } 45 | 46 | { 47 | let mut in_group = HashSet::new(); 48 | let mut count = 0; 49 | for program in programs.keys() { 50 | if !in_group.contains(program) { 51 | count += 1; 52 | populate_group(&programs, &mut in_group, *program); 53 | } 54 | } 55 | println!("Part 2: {}", count); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /2017/src/bin/day13.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, BufRead}; 2 | 3 | #[inline] 4 | fn is_at_top(range: u32, timestamp: u32) -> bool { 5 | timestamp % (range * 2 - 2) == 0 6 | } 7 | 8 | fn main() { 9 | let stdin = stdin(); 10 | 11 | let layers: Vec<(u32, u32)> = stdin 12 | .lock() 13 | .lines() 14 | .filter_map(|l| l.ok()) 15 | .map(|line| { 16 | let v: Vec = line.split(": ") 17 | .flat_map(|s| s.trim().parse().ok()) 18 | .collect(); 19 | (v[0], v[1]) 20 | }) 21 | .collect(); 22 | 23 | let mut severity = 0; 24 | for &(depth, range) in &layers { 25 | if is_at_top(range, depth) { 26 | severity += depth * range; 27 | } 28 | } 29 | 30 | println!("Part 1: {}", severity); 31 | 32 | for delay in 0.. { 33 | let mut success = true; 34 | for &(depth, range) in &layers { 35 | if is_at_top(range, depth + delay) { 36 | success = false; 37 | break; 38 | } 39 | } 40 | if success { 41 | println!("Part 2: {}", delay); 42 | break; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /2017/src/bin/day14.rs: -------------------------------------------------------------------------------- 1 | extern crate aoc2017; 2 | use std::io::{stdin, Read}; 3 | use aoc2017::knot; 4 | 5 | fn is_occupied(grid: &[Vec], row: usize, col: usize) -> bool { 6 | let byte = grid[row][col / 8]; 7 | byte & (0x80 >> (col % 8)) != 0 8 | } 9 | 10 | fn delete_group(mut grid: &mut [Vec], row: usize, col: usize) { 11 | grid[row][col / 8] &= !(0x80 >> (col % 8)); 12 | if col > 0 && is_occupied(grid, row, col - 1) { 13 | delete_group(&mut grid, row, col - 1); 14 | } 15 | if row > 0 && is_occupied(grid, row - 1, col) { 16 | delete_group(&mut grid, row - 1, col); 17 | } 18 | if col < grid[row].len() * 8 - 1 && is_occupied(grid, row, col + 1) { 19 | delete_group(&mut grid, row, col + 1); 20 | } 21 | if row < grid.len() - 1 && is_occupied(grid, row + 1, col) { 22 | delete_group(&mut grid, row + 1, col); 23 | } 24 | } 25 | 26 | fn main() { 27 | let mut input = String::new(); 28 | stdin().read_to_string(&mut input).expect( 29 | "Failed to read stdin", 30 | ); 31 | input = input.trim().to_string(); 32 | 33 | let mut grid: Vec> = (0..128) 34 | .map(|i| knot::compute_hash_bytes(&format!("{}-{}", input, i))) 35 | .collect(); 36 | let part_1 = grid.iter() 37 | .map(|row| row.iter().map(|byte| byte.count_ones()).sum::()) 38 | .sum::(); 39 | println!("Part 1: {}", part_1); 40 | 41 | let mut count = 0; 42 | for row_index in 0..128 { 43 | for col_index in 0..128 { 44 | if is_occupied(&grid, row_index, col_index) { 45 | delete_group(&mut grid, row_index, col_index); 46 | count += 1; 47 | } 48 | } 49 | } 50 | println!("Part 2: {}", count); 51 | } 52 | -------------------------------------------------------------------------------- /2017/src/bin/day15.rs: -------------------------------------------------------------------------------- 1 | extern crate regex; 2 | 3 | use std::io::{stdin, Read}; 4 | use regex::Regex; 5 | 6 | fn main() { 7 | let re = Regex::new(r"\d+").expect("failed to parse regex"); 8 | let mut input = String::new(); 9 | stdin().read_to_string(&mut input).expect( 10 | "Failed to read stdin", 11 | ); 12 | 13 | let values: Vec<_> = re.captures_iter(&input) 14 | .flat_map(|cap| cap.get(0).unwrap().as_str().parse::().ok()) 15 | .collect(); 16 | 17 | { 18 | let mut value_a = values[0]; 19 | let mut value_b = values[1]; 20 | let mask = (1 << 16) - 1; 21 | let mut count = 0; 22 | 23 | for _ in 0..40_000_000 { 24 | value_a = (value_a * 16_807) % 2_147_483_647; 25 | value_b = (value_b * 48_271) % 2_147_483_647; 26 | if value_a & mask == value_b & mask { 27 | count += 1; 28 | } 29 | } 30 | println!("Part 1: {}", count); 31 | } 32 | 33 | { 34 | let mut value_a = values[0]; 35 | let mut value_b = values[1]; 36 | let mask = (1 << 16) - 1; 37 | let mut count = 0; 38 | 39 | for _ in 0..5_000_000 { 40 | loop { 41 | value_a = (value_a * 16_807) % 2_147_483_647; 42 | if value_a % 4 == 0 { 43 | break; 44 | } 45 | } 46 | 47 | loop { 48 | value_b = (value_b * 48_271) % 2_147_483_647; 49 | if value_b % 8 == 0 { 50 | break; 51 | } 52 | } 53 | 54 | if value_a & mask == value_b & mask { 55 | count += 1; 56 | } 57 | } 58 | println!("Part 2: {}", count); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /2017/src/bin/day16.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, Read}; 2 | 3 | #[derive(Debug)] 4 | enum Action { 5 | Spin(usize), 6 | Exchange(usize, usize), 7 | Partner(char, char), 8 | } 9 | 10 | fn apply_actions(actions: &[Action], programs: &mut Vec) { 11 | for action in actions { 12 | match *action { 13 | Action::Exchange(i, j) => programs.swap(i, j), 14 | Action::Spin(n) => { 15 | let mut new_programs = Vec::with_capacity(programs.len()); 16 | let index = programs.len() - n; 17 | new_programs.extend_from_slice(&programs[index..]); 18 | new_programs.extend_from_slice(&programs[0..index]); 19 | *programs = new_programs 20 | } 21 | Action::Partner(a, b) => { 22 | let pa = programs.iter().position(|p| p == &a).unwrap(); 23 | let pb = programs.iter().position(|p| p == &b).unwrap(); 24 | programs.swap(pa, pb); 25 | } 26 | } 27 | } 28 | } 29 | 30 | fn main() { 31 | let mut input = String::new(); 32 | stdin().read_to_string(&mut input).expect( 33 | "Failed to read stdin", 34 | ); 35 | 36 | let actions: Vec<_> = input 37 | .trim() 38 | .split(',') 39 | .map(|desc| match desc.chars().nth(0).unwrap() { 40 | 'x' => { 41 | let pos = desc.chars().position(|ch| ch == '/').unwrap(); 42 | Action::Exchange( 43 | desc[1..pos].parse().unwrap(), 44 | desc[pos + 1..].parse().unwrap(), 45 | ) 46 | } 47 | 'p' => Action::Partner(desc.chars().nth(1).unwrap(), desc.chars().nth(3).unwrap()), 48 | 's' => Action::Spin(desc[1..].parse().unwrap()), 49 | _ => unreachable!(), 50 | }) 51 | .collect(); 52 | 53 | let programs: Vec<_> = (0..16).map(|i| (b'a' + i) as char).collect(); 54 | { 55 | let mut first_round = programs.clone(); 56 | apply_actions(&actions, &mut first_round); 57 | println!("Part 1: {}", first_round.iter().collect::()); 58 | } 59 | 60 | { 61 | let mut billion_rounds = programs.clone(); 62 | let mut period = 0; 63 | let first = programs.clone(); 64 | 65 | for _ in 0..1_000_000_000 { 66 | apply_actions(&actions, &mut billion_rounds); 67 | period += 1; 68 | if billion_rounds == first { 69 | break; 70 | } 71 | } 72 | 73 | // Take a shortcut! 74 | for _ in 0..(1_000_000_000 % period) { 75 | apply_actions(&actions, &mut billion_rounds); 76 | } 77 | 78 | println!("Part 2: {}", billion_rounds.iter().collect::()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /2017/src/bin/day17.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, Read}; 2 | 3 | fn main() { 4 | let mut input = String::new(); 5 | stdin().read_to_string(&mut input).expect( 6 | "Failed to read stdin", 7 | ); 8 | let steps_count: usize = input.trim().parse().unwrap(); 9 | { 10 | let max_steps = 2018; 11 | 12 | let mut buffer: Vec = Vec::with_capacity(max_steps); 13 | buffer.push(0); 14 | let mut position = 0; 15 | 16 | for value in 1..max_steps { 17 | position = (position + steps_count) % value + 1; 18 | buffer.insert(position, value); 19 | } 20 | 21 | println!("Part 1: {}", buffer[(position + 1) % buffer.len()]); 22 | } 23 | 24 | { 25 | let max_steps = 50_000_001; 26 | 27 | let mut next_to_zero_value = 0; 28 | let mut position = 0; 29 | 30 | for value in 1..max_steps { 31 | position = (position + steps_count) % value + 1; 32 | if position == 1 { 33 | next_to_zero_value = value; 34 | } 35 | } 36 | println!("Part 2: {}", next_to_zero_value); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /2017/src/knot.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | 3 | pub fn rotate_list(lengths: &[usize], rounds: u8) -> Vec { 4 | let mut position: usize = 0; 5 | let mut skip_size: usize = 0; 6 | 7 | let mut list: Vec<_> = (0..256u16).map(|n| n as u8).collect(); 8 | 9 | let list_len = list.len(); 10 | for _ in 0..rounds { 11 | for length in lengths.iter() { 12 | list = list.iter() 13 | .enumerate() 14 | .map(|(index, value)| { 15 | let relative_index = (list_len + index - position) % list_len; 16 | if relative_index < *length { 17 | list[(position + *length - relative_index - 1) % list_len] 18 | } else { 19 | *value 20 | } 21 | }) 22 | .collect(); 23 | 24 | position = (position + length + skip_size) % list_len; 25 | skip_size += 1; 26 | } 27 | } 28 | 29 | list 30 | } 31 | 32 | pub fn compute_hash(input: &str) -> String { 33 | compute_hash_bytes(input) 34 | .iter() 35 | .map(|n| format!("{:02x}", n)) 36 | .collect() 37 | } 38 | 39 | pub fn compute_hash_bytes(input: &str) -> Vec { 40 | let mut lengths: Vec<_> = input.trim().chars().map(|ch| ch as usize).collect(); 41 | lengths.extend(&[17, 31, 73, 47, 23]); 42 | let sparse_hash = rotate_list(&lengths, 64); 43 | sparse_hash 44 | .into_iter() 45 | .map(|n| n as u8) 46 | .chunks(16) 47 | .into_iter() 48 | .map(|chunk| chunk.fold1(|r, n| r ^ n).unwrap()) 49 | .collect() 50 | } 51 | -------------------------------------------------------------------------------- /2017/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate itertools; 2 | 3 | pub mod knot; 4 | 5 | // pub use knot; 6 | -------------------------------------------------------------------------------- /2017/tests/day01/input: -------------------------------------------------------------------------------- 1 | 5255443714755555317777152441826784321918285999594221531636242944998363716119294845838579943562543247239969555791772392681567883449837982119239536325341263524415397123824358467891963762948723327774545715851542429832119179139914471523515332247317441719184556891362179267368325486642376685657759623876854958721636574219871249645773738597751429959437466876166273755524873351452951411628479352522367714269718514838933283861425982562854845471512652555633922878128558926123935941858532446378815929573452775348599693982834699757734714187831337546474515678577158721751921562145591166634279699299418269158557557996583881642468274618196335267342897498486869925262896125146867124596587989531495891646681528259624674792728146526849711139146268799436334618974547539561587581268886449291817335232859391493839167111246376493191985145848531829344198536568987996894226585837348372958959535969651573516542581144462536574953764413723147957237298324458181291167587791714172674717898567269547766636143732438694473231473258452166457194797819423528139157452148236943283374193561963393846385622218535952591588353565319432285579711881559343544515461962846879685879431767963975654347569385354482226341261768547328749947163864645168428953445396361398873536434931823635522467754782422557998262858297563862492652464526366171218276176258582444923497181776129436396397333976215976731542182878979389362297155819461685361676414725597335759976285597713332688275241271664658286868697167515329811831234324698345159949135474463624749624626518247831448143876183133814263977611564339865466321244399177464822649611969896344874381978986453566979762911155931362394192663943526834148596342268321563885255765614418141828934971927998994739769141789185165461976425151855846739959338649499379657223196885539386154935586794548365861759354865453211721551776997576289811595654171672259129335243531518228282393326395241242185795828261319215164262237957743232558971289145639852148197184265766291885259847236646615935963759631145338159257538114359781854685695429348428884248972177278361353814766653996675994784195827214295462389532422825696456457332417366426619555 2 | -------------------------------------------------------------------------------- /2017/tests/day01/output: -------------------------------------------------------------------------------- 1 | Part 1: 1049 2 | Part 2: 1508 3 | -------------------------------------------------------------------------------- /2017/tests/day02/input: -------------------------------------------------------------------------------- 1 | 414 382 1515 319 83 1327 116 391 101 749 1388 1046 1427 105 1341 1590 2 | 960 930 192 147 932 621 1139 198 865 820 597 165 232 417 19 183 3 | 3379 987 190 3844 1245 1503 3151 3349 2844 4033 175 3625 3565 179 3938 184 4 | 116 51 32 155 102 92 65 42 48 91 74 69 52 89 20 143 5 | 221 781 819 121 821 839 95 117 626 127 559 803 779 543 44 369 6 | 199 2556 93 1101 122 124 2714 625 2432 1839 2700 2636 118 2306 1616 2799 7 | 56 804 52 881 1409 47 246 1368 1371 583 49 1352 976 400 1276 1240 8 | 1189 73 148 1089 93 76 3205 3440 3627 92 853 95 3314 3551 2929 3626 9 | 702 169 492 167 712 488 357 414 187 278 87 150 19 818 178 686 10 | 140 2220 1961 1014 2204 2173 1513 2225 443 123 148 580 833 1473 137 245 11 | 662 213 1234 199 1353 1358 1408 235 917 1395 1347 194 565 179 768 650 12 | 119 137 1908 1324 1085 661 1557 1661 1828 1865 432 110 658 821 1740 145 13 | 1594 222 4140 963 209 2782 180 2591 4390 244 4328 3748 4535 192 157 3817 14 | 334 275 395 128 347 118 353 281 430 156 312 386 160 194 63 141 15 | 146 1116 153 815 2212 2070 599 3018 2640 47 125 2292 165 2348 2694 184 16 | 1704 2194 1753 146 2063 1668 1280 615 163 190 2269 1856 150 158 2250 2459 17 | -------------------------------------------------------------------------------- /2017/tests/day02/output: -------------------------------------------------------------------------------- 1 | Part 1: 30994 2 | Part 2: 233 3 | -------------------------------------------------------------------------------- /2017/tests/day03/input: -------------------------------------------------------------------------------- 1 | 312051 2 | -------------------------------------------------------------------------------- /2017/tests/day03/output: -------------------------------------------------------------------------------- 1 | Part 1: 430 2 | Part 2: 312453 3 | -------------------------------------------------------------------------------- /2017/tests/day04/output: -------------------------------------------------------------------------------- 1 | Part 1: 386 2 | Part 2: 208 3 | -------------------------------------------------------------------------------- /2017/tests/day05/output: -------------------------------------------------------------------------------- 1 | Part 1: 342669 2 | Part 2: 25136209 3 | -------------------------------------------------------------------------------- /2017/tests/day06/input: -------------------------------------------------------------------------------- 1 | 4 10 4 1 8 4 9 14 5 1 14 15 0 15 3 5 2 | -------------------------------------------------------------------------------- /2017/tests/day06/output: -------------------------------------------------------------------------------- 1 | Part 1: 12841 2 | Part 2: 8038 3 | -------------------------------------------------------------------------------- /2017/tests/day07/output: -------------------------------------------------------------------------------- 1 | Part 1: vgzejbd 2 | Part 2: 1226 3 | -------------------------------------------------------------------------------- /2017/tests/day08/output: -------------------------------------------------------------------------------- 1 | Part 1: 5215 2 | Part 2: 6419 3 | -------------------------------------------------------------------------------- /2017/tests/day09/output: -------------------------------------------------------------------------------- 1 | Part 1: 12396 2 | Part 2: 6346 3 | -------------------------------------------------------------------------------- /2017/tests/day10/input: -------------------------------------------------------------------------------- 1 | 18,1,0,161,255,137,254,252,14,95,165,33,181,168,2,188 2 | -------------------------------------------------------------------------------- /2017/tests/day10/output: -------------------------------------------------------------------------------- 1 | Part 1: 46600 2 | Part 2: 23234babdc6afa036749cfa9b597de1b 3 | -------------------------------------------------------------------------------- /2017/tests/day11/output: -------------------------------------------------------------------------------- 1 | Part 1: 805 2 | Part 2: 1535 3 | -------------------------------------------------------------------------------- /2017/tests/day12/output: -------------------------------------------------------------------------------- 1 | Part 1: 283 2 | Part 2: 195 3 | -------------------------------------------------------------------------------- /2017/tests/day13/input: -------------------------------------------------------------------------------- 1 | 0: 4 2 | 1: 2 3 | 2: 3 4 | 4: 4 5 | 6: 8 6 | 8: 5 7 | 10: 8 8 | 12: 6 9 | 14: 6 10 | 16: 8 11 | 18: 6 12 | 20: 6 13 | 22: 12 14 | 24: 12 15 | 26: 10 16 | 28: 8 17 | 30: 12 18 | 32: 8 19 | 34: 12 20 | 36: 9 21 | 38: 12 22 | 40: 8 23 | 42: 12 24 | 44: 17 25 | 46: 14 26 | 48: 12 27 | 50: 10 28 | 52: 20 29 | 54: 12 30 | 56: 14 31 | 58: 14 32 | 60: 14 33 | 62: 12 34 | 64: 14 35 | 66: 14 36 | 68: 14 37 | 70: 14 38 | 72: 12 39 | 74: 14 40 | 76: 14 41 | 80: 14 42 | 84: 18 43 | 88: 14 44 | -------------------------------------------------------------------------------- /2017/tests/day13/output: -------------------------------------------------------------------------------- 1 | Part 1: 648 2 | Part 2: 3933124 3 | -------------------------------------------------------------------------------- /2017/tests/day14/input: -------------------------------------------------------------------------------- 1 | uugsqrei 2 | -------------------------------------------------------------------------------- /2017/tests/day14/output: -------------------------------------------------------------------------------- 1 | Part 1: 8194 2 | Part 2: 1141 3 | -------------------------------------------------------------------------------- /2017/tests/day15/input: -------------------------------------------------------------------------------- 1 | Generator A starts with 722 2 | Generator B starts with 354 3 | -------------------------------------------------------------------------------- /2017/tests/day15/output: -------------------------------------------------------------------------------- 1 | Part 1: 612 2 | Part 2: 285 3 | -------------------------------------------------------------------------------- /2017/tests/day16/output: -------------------------------------------------------------------------------- 1 | Part 1: ociedpjbmfnkhlga 2 | Part 2: gnflbkojhicpmead 3 | -------------------------------------------------------------------------------- /2017/tests/day17/input: -------------------------------------------------------------------------------- 1 | 314 2 | -------------------------------------------------------------------------------- /2017/tests/day17/output: -------------------------------------------------------------------------------- 1 | Part 1: 355 2 | Part 2: 6154117 3 | -------------------------------------------------------------------------------- /2017/tests/day18/input: -------------------------------------------------------------------------------- 1 | set i 31 2 | set a 1 3 | mul p 17 4 | jgz p p 5 | mul a 2 6 | add i -1 7 | jgz i -2 8 | add a -1 9 | set i 127 10 | set p 826 11 | mul p 8505 12 | mod p a 13 | mul p 129749 14 | add p 12345 15 | mod p a 16 | set b p 17 | mod b 10000 18 | snd b 19 | add i -1 20 | jgz i -9 21 | jgz a 3 22 | rcv b 23 | jgz b -1 24 | set f 0 25 | set i 126 26 | rcv a 27 | rcv b 28 | set p a 29 | mul p -1 30 | add p b 31 | jgz p 4 32 | snd a 33 | set a b 34 | jgz 1 3 35 | snd b 36 | set f 1 37 | add i -1 38 | jgz i -11 39 | snd a 40 | jgz f -16 41 | jgz a -19 42 | -------------------------------------------------------------------------------- /2017/tests/day18/output: -------------------------------------------------------------------------------- 1 | Part 1: 7071 2 | Part 2: 8001 3 | -------------------------------------------------------------------------------- /2017/tests/day19/output: -------------------------------------------------------------------------------- 1 | Part 1: UICRNSDOK 2 | Part 2: 16064 3 | -------------------------------------------------------------------------------- /2017/tests/day20/output: -------------------------------------------------------------------------------- 1 | Part 1: 91 2 | Part 2: 567 3 | -------------------------------------------------------------------------------- /2017/tests/day21/output: -------------------------------------------------------------------------------- 1 | Part 1: 188 2 | Part 2: 2758764 3 | -------------------------------------------------------------------------------- /2017/tests/day22/input: -------------------------------------------------------------------------------- 1 | .#.....##..##..###.###..# 2 | ..##..######.#.###.##.#.# 3 | ###..#..#####.##.##.#...# 4 | ###......##..###.#...#.#. 5 | .#.###.##..#.####.#..#... 6 | ..#.#.#####...##.####.### 7 | ..#..#.#..###.#..###.###. 8 | #########...#....##..#.#. 9 | .###..#######..####...### 10 | #####...#..##...###..##.. 11 | ..#......##.#....#...#### 12 | .##.#..#####.#####.##.##. 13 | ####.##.###.#..#.#.#..... 14 | #....##.####.#.#..#.#.##. 15 | ###...##...#.###.#.#.#### 16 | .#.#...#.#.##.##....##.#. 17 | #..##.#.#..#....###..#### 18 | #####...#..#.###...##.### 19 | ##.#..####.###...#....### 20 | ###.#####.....#....#.##.. 21 | ####.##.....######.#..#.# 22 | .#.....####.##...###..##. 23 | ....########.#..###.#..## 24 | ##.##..#...#...##.#....## 25 | .#.######.##....####.#.## 26 | -------------------------------------------------------------------------------- /2017/tests/day22/output: -------------------------------------------------------------------------------- 1 | Part 1: 5196 2 | Part 2: 2511633 3 | -------------------------------------------------------------------------------- /2017/tests/day23/input: -------------------------------------------------------------------------------- 1 | set b 57 2 | set c b 3 | jnz a 2 4 | jnz 1 5 5 | mul b 100 6 | sub b -100000 7 | set c b 8 | sub c -17000 9 | set f 1 10 | set d 2 11 | set e 2 12 | set g d 13 | mul g e 14 | sub g b 15 | jnz g 2 16 | set f 0 17 | sub e -1 18 | set g e 19 | sub g b 20 | jnz g -8 21 | sub d -1 22 | set g d 23 | sub g b 24 | jnz g -13 25 | jnz f 2 26 | sub h -1 27 | set g b 28 | sub g c 29 | jnz g 2 30 | jnz 1 3 31 | sub b -17 32 | jnz 1 -23 33 | -------------------------------------------------------------------------------- /2017/tests/day23/output: -------------------------------------------------------------------------------- 1 | Part 1: 3025 2 | Part 2: 915 3 | -------------------------------------------------------------------------------- /2017/tests/day24/input: -------------------------------------------------------------------------------- 1 | 50/41 2 | 19/43 3 | 17/50 4 | 32/32 5 | 22/44 6 | 9/39 7 | 49/49 8 | 50/39 9 | 49/10 10 | 37/28 11 | 33/44 12 | 14/14 13 | 14/40 14 | 8/40 15 | 10/25 16 | 38/26 17 | 23/6 18 | 4/16 19 | 49/25 20 | 6/39 21 | 0/50 22 | 19/36 23 | 37/37 24 | 42/26 25 | 17/0 26 | 24/4 27 | 0/36 28 | 6/9 29 | 41/3 30 | 13/3 31 | 49/21 32 | 19/34 33 | 16/46 34 | 22/33 35 | 11/6 36 | 22/26 37 | 16/40 38 | 27/21 39 | 31/46 40 | 13/2 41 | 24/7 42 | 37/45 43 | 49/2 44 | 32/11 45 | 3/10 46 | 32/49 47 | 36/21 48 | 47/47 49 | 43/43 50 | 27/19 51 | 14/22 52 | 13/43 53 | 29/0 54 | 33/36 55 | 2/6 56 | -------------------------------------------------------------------------------- /2017/tests/day24/output: -------------------------------------------------------------------------------- 1 | Part 1: 1859 2 | Part 2: 1799 3 | -------------------------------------------------------------------------------- /2017/tests/day25/input: -------------------------------------------------------------------------------- 1 | Begin in state A. 2 | Perform a diagnostic checksum after 12368930 steps. 3 | 4 | In state A: 5 | If the current value is 0: 6 | - Write the value 1. 7 | - Move one slot to the right. 8 | - Continue with state B. 9 | If the current value is 1: 10 | - Write the value 0. 11 | - Move one slot to the right. 12 | - Continue with state C. 13 | 14 | In state B: 15 | If the current value is 0: 16 | - Write the value 0. 17 | - Move one slot to the left. 18 | - Continue with state A. 19 | If the current value is 1: 20 | - Write the value 0. 21 | - Move one slot to the right. 22 | - Continue with state D. 23 | 24 | In state C: 25 | If the current value is 0: 26 | - Write the value 1. 27 | - Move one slot to the right. 28 | - Continue with state D. 29 | If the current value is 1: 30 | - Write the value 1. 31 | - Move one slot to the right. 32 | - Continue with state A. 33 | 34 | In state D: 35 | If the current value is 0: 36 | - Write the value 1. 37 | - Move one slot to the left. 38 | - Continue with state E. 39 | If the current value is 1: 40 | - Write the value 0. 41 | - Move one slot to the left. 42 | - Continue with state D. 43 | 44 | In state E: 45 | If the current value is 0: 46 | - Write the value 1. 47 | - Move one slot to the right. 48 | - Continue with state F. 49 | If the current value is 1: 50 | - Write the value 1. 51 | - Move one slot to the left. 52 | - Continue with state B. 53 | 54 | In state F: 55 | If the current value is 0: 56 | - Write the value 1. 57 | - Move one slot to the right. 58 | - Continue with state A. 59 | If the current value is 1: 60 | - Write the value 1. 61 | - Move one slot to the right. 62 | - Continue with state E. 63 | -------------------------------------------------------------------------------- /2017/tests/day25/output: -------------------------------------------------------------------------------- 1 | Part 1: 2725 2 | -------------------------------------------------------------------------------- /2018/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "advent_of_code_2018" 3 | version = "0.1.0" 4 | authors = ["Benoît Zugmeyer "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | itertools = "0.7.11" 9 | regex = "1.1.0" 10 | rayon = "1.0.3" 11 | lazy_static = "1.2.0" 12 | -------------------------------------------------------------------------------- /2018/dl.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | dayname=$(printf day%02d $2) 6 | mkdir -p tests/$dayname 7 | curl "https://adventofcode.com/2018/day/$2/input" -H "Cookie: session=$1" > tests/$dayname/input 8 | touch tests/$dayname/output 9 | git add tests/$dayname/input tests/$dayname/output 10 | -------------------------------------------------------------------------------- /2018/run.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | ROOT_DIR=$(dirname $0) 6 | 7 | exit_code=0 8 | files=$(find $ROOT_DIR/src/bin -name "*.rs" -printf "%f\n" | sort -n) 9 | echo $files 10 | 11 | for src_file in $files; do 12 | name="${src_file%.*}" 13 | test_name="${name%-*}" 14 | 15 | echo -n "Running $name " 16 | if [[ -f "$ROOT_DIR/target/release/$name" ]]; then 17 | echo -n "using release target" 18 | bin="$ROOT_DIR/target/release/$name" 19 | elif [[ -f "$ROOT_DIR/target/debug/$name" ]]; then 20 | echo -n "using debug target" 21 | bin="$ROOT_DIR/target/debug/$name" 22 | else 23 | echo "no binary, skipping" 24 | continue 25 | fi 26 | 27 | echo -n "... " 28 | 29 | output=$("$bin" < "tests/$test_name/input") 30 | diff_output=$(diff -u "tests/$test_name/output" <(echo "$output") 2>&1 || true) 31 | if [[ -n $diff_output ]]; then 32 | echo "failed:" 33 | echo "$diff_output" 34 | echo 35 | exit_code=1 36 | else 37 | echo "succeed" 38 | fi 39 | done 40 | 41 | exit $exit_code 42 | -------------------------------------------------------------------------------- /2018/src/bin/day01.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::io::{stdin, BufRead}; 3 | 4 | fn main() { 5 | let changes: Vec = stdin() 6 | .lock() 7 | .lines() 8 | .filter_map(|l| l.ok()) 9 | .filter_map(|l| l.parse().ok()) 10 | .collect(); 11 | 12 | println!("Part 1: {}", changes.iter().sum::()); 13 | 14 | let mut reached_frequencies = HashSet::new(); 15 | let frequency = changes 16 | .iter() 17 | .cycle() 18 | .take(1_000_000) 19 | .scan(0, |frequency, &change| { 20 | *frequency += change; 21 | Some(*frequency) 22 | }) 23 | .find(|frequency| !reached_frequencies.insert(*frequency)) 24 | .unwrap(); 25 | println!("Part 2: {}", frequency); 26 | } 27 | -------------------------------------------------------------------------------- /2018/src/bin/day02.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | use std::collections::HashMap; 3 | use std::io::{stdin, BufRead}; 4 | 5 | fn main() { 6 | let box_ids: Vec = stdin().lock().lines().filter_map(|l| l.ok()).collect(); 7 | 8 | let mut two_letters = 0; 9 | let mut three_letters = 0; 10 | for box_id in &box_ids { 11 | let mut letter_counts = HashMap::new(); 12 | for letter in box_id.chars() { 13 | *letter_counts.entry(letter).or_insert(0) += 1 14 | } 15 | if letter_counts.values().any(|&count| count == 2) { 16 | two_letters += 1; 17 | } 18 | if letter_counts.values().any(|&count| count == 3) { 19 | three_letters += 1; 20 | } 21 | } 22 | println!("Part 1: {}", two_letters * three_letters); 23 | 24 | let mut common_letters: Option = None; 25 | for (id1, id2) in box_ids.iter().tuple_combinations() { 26 | let are_close = id1 27 | .chars() 28 | .zip(id2.chars()) 29 | .scan(0, |total, (l1, l2)| { 30 | if l1 != l2 { 31 | *total += 1 32 | } 33 | Some(*total) 34 | }) 35 | .all(|d| d <= 1); 36 | if are_close { 37 | common_letters = Some( 38 | id1.chars() 39 | .zip(id2.chars()) 40 | .filter_map(|(l1, l2)| if l1 == l2 { Some(l1) } else { None }) 41 | .collect(), 42 | ); 43 | break; 44 | } 45 | } 46 | println!( 47 | "Part 2: {}", 48 | common_letters.unwrap_or_else(|| "Not found".to_string()) 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /2018/src/bin/day05.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::io::{stdin, BufRead}; 3 | 4 | fn are_reacting(a: char, b: char) -> bool { 5 | a.is_ascii_uppercase() && b == a.to_ascii_lowercase() 6 | || a.is_ascii_lowercase() && b == a.to_ascii_uppercase() 7 | } 8 | 9 | fn react_polymer_size(input: T) -> usize 10 | where 11 | T: Iterator, 12 | { 13 | let mut mutated_polymer = Vec::new(); 14 | 15 | for a in input { 16 | if let Some(b) = mutated_polymer.last() { 17 | if are_reacting(a, *b) { 18 | mutated_polymer.pop(); 19 | } else { 20 | mutated_polymer.push(a); 21 | } 22 | } else { 23 | mutated_polymer.push(a); 24 | } 25 | } 26 | 27 | mutated_polymer.len() 28 | } 29 | 30 | fn main() { 31 | let input = stdin() 32 | .lock() 33 | .lines() 34 | .next() 35 | .expect("No line in input") 36 | .unwrap(); 37 | 38 | println!("Part 1: {}", react_polymer_size(input.chars())); 39 | 40 | let all_units: HashSet<_> = input.chars().map(|ch| ch.to_ascii_lowercase()).collect(); 41 | 42 | let shortest = all_units 43 | .iter() 44 | .map(|unit| { 45 | react_polymer_size( 46 | input 47 | .chars() 48 | .filter(|ch| ch != unit && *ch != unit.to_ascii_uppercase()), 49 | ) 50 | }) 51 | .min() 52 | .unwrap(); 53 | println!("Part 2: {}", shortest); 54 | } 55 | -------------------------------------------------------------------------------- /2018/src/bin/day06.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | use std::io::{stdin, BufRead}; 3 | 4 | fn main() { 5 | let coordinates: Vec<(i32, i32)> = stdin() 6 | .lock() 7 | .lines() 8 | .filter_map(|l| l.ok()) 9 | .filter_map(|l| { 10 | let mut values = l.split(", "); 11 | Some((values.next()?.parse().ok()?, values.next()?.parse().ok()?)) 12 | }) 13 | .collect(); 14 | 15 | let (min_x, max_x) = coordinates 16 | .iter() 17 | .map(|(x, _)| *x) 18 | .minmax() 19 | .into_option() 20 | .unwrap(); 21 | 22 | let (min_y, max_y) = coordinates 23 | .iter() 24 | .map(|(_, y)| *y) 25 | .minmax() 26 | .into_option() 27 | .unwrap(); 28 | 29 | let mut distances = vec![Some(0); coordinates.len()]; 30 | for x in min_x..=max_x { 31 | for y in min_y..=max_y { 32 | let mut min_coordinate = None; 33 | let mut min_distance = 1_000_000; 34 | for (index, coordinate) in coordinates.iter().enumerate() { 35 | let distance = i32::abs(coordinate.0 - x) + i32::abs(coordinate.1 - y); 36 | if distance == min_distance { 37 | // Two coordinates have the same distance, discard the coordinate 38 | min_coordinate = None; 39 | } else if distance < min_distance { 40 | min_coordinate = Some(index); 41 | min_distance = distance; 42 | } 43 | } 44 | if let Some(index) = min_coordinate { 45 | if x == max_x || y == max_y { 46 | distances[index] = None; 47 | } else if let Some(d) = distances[index].as_mut() { 48 | *d += 1; 49 | } 50 | } 51 | } 52 | } 53 | 54 | let max = distances.iter().filter_map(|d| *d).max().unwrap(); 55 | 56 | println!("Part 1: {:?}", max); 57 | 58 | let mut safe_region_size = 0; 59 | 60 | for x in min_x..=max_x { 61 | for y in min_y..=max_y { 62 | let distances_sum = coordinates 63 | .iter() 64 | .map(|coordinate| i32::abs(coordinate.0 - x) + i32::abs(coordinate.1 - y)) 65 | .sum::(); 66 | if distances_sum < 10_000 { 67 | safe_region_size += 1; 68 | } 69 | } 70 | } 71 | println!("Part 2: {}", safe_region_size); 72 | } 73 | -------------------------------------------------------------------------------- /2018/src/bin/day07.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{BTreeMap, BTreeSet}; 2 | use std::io::{stdin, BufRead}; 3 | 4 | fn main() { 5 | let mut remaining_steps = BTreeMap::new(); 6 | 7 | for (a, b) in stdin() 8 | .lock() 9 | .lines() 10 | .filter_map(|l| l.ok()) 11 | .filter_map(|l| Some((l.chars().nth(5)?, l.chars().nth(36)?))) 12 | { 13 | remaining_steps 14 | .entry(b) 15 | .or_insert_with(BTreeSet::new) 16 | .insert(a); 17 | remaining_steps.entry(a).or_insert_with(BTreeSet::new); 18 | } 19 | 20 | { 21 | let mut remaining_steps = remaining_steps.clone(); 22 | let mut steps_done = BTreeSet::new(); 23 | let mut steps_order = String::new(); 24 | while let Some((&next_step, _)) = remaining_steps 25 | .iter() 26 | .find(|(_, requirements)| steps_done.is_superset(requirements)) 27 | { 28 | steps_done.insert(next_step); 29 | remaining_steps.remove(&next_step); 30 | steps_order.push(next_step); 31 | } 32 | 33 | println!("Part 1: {}", steps_order); 34 | } 35 | 36 | { 37 | let mut remaining_steps = remaining_steps.clone(); 38 | 39 | let max_workers = 5; 40 | let mut working_workers = BTreeSet::new(); 41 | let mut time = 0; 42 | 43 | loop { 44 | // Collect the next steps to do 45 | let next_steps: Vec = remaining_steps 46 | .iter() 47 | // Filter out steps with unfinished requirements 48 | .filter(|(_, requirements)| requirements.is_empty()) 49 | // Take at most N steps where N is the number of free workers 50 | .take(max_workers - working_workers.len()) 51 | .map(|(s, _)| *s) 52 | .collect(); 53 | 54 | for &next_step in &next_steps { 55 | let duration = next_step as u16 - 'A' as u16 + 61; 56 | remaining_steps.remove(&next_step); 57 | working_workers.insert((time + duration, next_step)); 58 | } 59 | 60 | if let Some((end, step)) = working_workers.iter().cloned().next() { 61 | // The work is finished, consider the step done 62 | working_workers.remove(&(end, step)); 63 | for requirements in remaining_steps.values_mut() { 64 | requirements.remove(&step); 65 | } 66 | time = end 67 | } else { 68 | println!("Part 2: {}", time); 69 | break; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /2018/src/bin/day08.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, BufRead}; 2 | 3 | #[derive(Debug)] 4 | struct Node { 5 | children: Vec, 6 | metadata: Vec, 7 | } 8 | 9 | fn create_tree(input: &mut impl Iterator) -> Node { 10 | let child_nodes_count = input.next().unwrap(); 11 | let metadata_count = input.next().unwrap(); 12 | Node { 13 | children: (0..child_nodes_count).map(|_| create_tree(input)).collect(), 14 | metadata: input.take(metadata_count).collect(), 15 | } 16 | } 17 | 18 | fn metadata_sum(root: &Node) -> usize { 19 | root.metadata.iter().sum::() + root.children.iter().map(metadata_sum).sum::() 20 | } 21 | 22 | fn node_value(root: &Node) -> usize { 23 | if root.children.is_empty() { 24 | root.metadata.iter().sum::() 25 | } else { 26 | root.metadata 27 | .iter() 28 | .filter_map(|m| root.children.get(m.wrapping_sub(1)).map(node_value)) 29 | .sum::() 30 | } 31 | } 32 | 33 | fn main() { 34 | let line = stdin() 35 | .lock() 36 | .lines() 37 | .filter_map(|l| l.ok()) 38 | .next() 39 | .unwrap_or_else(String::new); 40 | 41 | let root = create_tree(&mut line.split(' ').filter_map(|l| l.parse().ok())); 42 | 43 | println!("Part 1: {}", metadata_sum(&root)); 44 | println!("Part 2: {}", node_value(&root)); 45 | } 46 | -------------------------------------------------------------------------------- /2018/src/bin/day09-vec_deque.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | /// Solution using a `VecDeque` to represent the board, inspired by 5 | /// [Frank de Jong solution](https://github.com/foo-jin/advent-of-code/blob/master/2018/day09/src/main.rs) 6 | /// This is slightly more efficient than my solution using a double linked list. 7 | use regex::Regex; 8 | use std::collections::VecDeque; 9 | use std::io::{stdin, BufRead}; 10 | 11 | fn max_score(player_count: usize, max_marble: usize) -> usize { 12 | let mut board = VecDeque::with_capacity(max_marble); 13 | board.push_front(0); 14 | let mut scores = vec![0; player_count]; 15 | 16 | for marble in 1..=max_marble { 17 | let player = (marble - 1) % player_count; 18 | if marble % 23 == 0 { 19 | // Move backward 7 times, compute the score and remove the marble 20 | for _ in 0..7 { 21 | let value = board.pop_back().unwrap(); 22 | board.push_front(value); 23 | } 24 | scores[player] += marble + board.pop_front().unwrap(); 25 | } else { 26 | // Move forward two times and insert the marble into the board 27 | for _ in 0..2 { 28 | let value = board.pop_front().unwrap(); 29 | board.push_back(value); 30 | } 31 | board.push_front(marble); 32 | } 33 | } 34 | 35 | *scores.iter().max().unwrap() 36 | } 37 | 38 | fn main() { 39 | let line = stdin() 40 | .lock() 41 | .lines() 42 | .filter_map(|l| l.ok()) 43 | .next() 44 | .unwrap_or_else(String::new); 45 | 46 | let re = Regex::new(r"\d+").unwrap(); 47 | let mut iter = re 48 | .captures_iter(&line) 49 | .filter_map(|capture| capture.get(0)?.as_str().parse::().ok()); 50 | let player_count = iter.next().unwrap(); 51 | let max_marble = iter.next().unwrap(); 52 | 53 | println!("Part 1: {}", max_score(player_count, max_marble)); 54 | println!("Part 2: {}", max_score(player_count, max_marble * 100)); 55 | } 56 | 57 | #[cfg(test)] 58 | mod tests { 59 | use super::*; 60 | use test::Bencher; 61 | 62 | #[bench] 63 | fn bench(b: &mut Bencher) { 64 | b.iter(|| max_score(468, 71010 * 100)) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /2018/src/bin/day10.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | use regex::Regex; 3 | use std::collections::HashSet; 4 | use std::io::{stdin, BufRead}; 5 | 6 | #[derive(Debug)] 7 | struct Point { 8 | x: i32, 9 | y: i32, 10 | dx: i32, 11 | dy: i32, 12 | } 13 | 14 | fn print(points: &[Point]) { 15 | let (min_x, max_x) = points.iter().map(|p| p.x).minmax().into_option().unwrap(); 16 | let (min_y, max_y) = points.iter().map(|p| p.y).minmax().into_option().unwrap(); 17 | let points_set: HashSet<_> = points.iter().map(|p| (p.x, p.y)).collect(); 18 | for y in min_y..=max_y { 19 | for x in min_x..=max_x { 20 | if points_set.contains(&(x, y)) { 21 | print!("# "); 22 | } else { 23 | print!(". "); 24 | } 25 | } 26 | println!(); 27 | } 28 | } 29 | 30 | fn main() { 31 | let re = 32 | Regex::new(r"position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>").unwrap(); 33 | let mut points: Vec = stdin() 34 | .lock() 35 | .lines() 36 | .filter_map(|l| l.ok()) 37 | .filter_map(|l| { 38 | let caps = re.captures(&l)?; 39 | Some(Point { 40 | x: caps.get(1)?.as_str().parse().ok()?, 41 | y: caps.get(2)?.as_str().parse().ok()?, 42 | dx: caps.get(3)?.as_str().parse().ok()?, 43 | dy: caps.get(4)?.as_str().parse().ok()?, 44 | }) 45 | }) 46 | .collect(); 47 | 48 | let mut width = i32::max_value(); 49 | for time in 0.. { 50 | let (min_x, max_x) = points 51 | .iter() 52 | .map(|p| p.x + p.dx) 53 | .minmax() 54 | .into_option() 55 | .unwrap(); 56 | let new_width = max_x - min_x; 57 | if new_width > width { 58 | println!("Time: {}", time); 59 | print(&points); 60 | break; 61 | } 62 | width = new_width; 63 | for point in &mut points { 64 | point.x += point.dx; 65 | point.y += point.dy; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /2018/src/bin/day25.rs: -------------------------------------------------------------------------------- 1 | use std::io::{stdin, BufRead}; 2 | 3 | type Coords = (isize, isize, isize, isize); 4 | 5 | fn distance(a: &Coords, b: &Coords) -> isize { 6 | (a.0 - b.0).abs() + (a.1 - b.1).abs() + (a.2 - b.2).abs() + (a.3 - b.3).abs() 7 | } 8 | 9 | fn main() { 10 | let mut constellations: Vec> = Vec::new(); 11 | stdin() 12 | .lock() 13 | .lines() 14 | .filter_map(|l| l.ok()) 15 | .filter_map(|l| -> Option { 16 | let mut parts = l.split(','); 17 | Some(( 18 | parts.next()?.parse().ok()?, 19 | parts.next()?.parse().ok()?, 20 | parts.next()?.parse().ok()?, 21 | parts.next()?.parse().ok()?, 22 | )) 23 | }) 24 | .for_each(|coords| { 25 | #[allow(clippy::filter_map)] 26 | let indexes: Vec<_> = constellations 27 | .iter() 28 | .enumerate() 29 | .filter(|&(_, constellation)| { 30 | constellation 31 | .iter() 32 | .any(|other| distance(&coords, other) <= 3) 33 | }) 34 | .map(|(index, _)| index) 35 | .collect(); 36 | 37 | if indexes.is_empty() { 38 | constellations.push(vec![coords]); 39 | } else { 40 | let target = indexes[0]; 41 | constellations[target].push(coords); 42 | for index in indexes.into_iter().skip(1).rev() { 43 | let a = constellations.remove(index); 44 | constellations[target].extend(a); 45 | } 46 | } 47 | }); 48 | 49 | println!("{}", constellations.len()); 50 | } 51 | -------------------------------------------------------------------------------- /2018/tests/day01/output: -------------------------------------------------------------------------------- 1 | Part 1: 416 2 | Part 2: 56752 3 | -------------------------------------------------------------------------------- /2018/tests/day02/output: -------------------------------------------------------------------------------- 1 | Part 1: 6642 2 | Part 2: cvqlbidheyujgtrswxmckqnap 3 | -------------------------------------------------------------------------------- /2018/tests/day03/output: -------------------------------------------------------------------------------- 1 | Part 1: 120419 2 | Part 2: 445 3 | -------------------------------------------------------------------------------- /2018/tests/day04/output: -------------------------------------------------------------------------------- 1 | Part 1: 98680 2 | Part 2: 9763 3 | -------------------------------------------------------------------------------- /2018/tests/day05/output: -------------------------------------------------------------------------------- 1 | Part 1: 9562 2 | Part 2: 4934 3 | -------------------------------------------------------------------------------- /2018/tests/day06/input: -------------------------------------------------------------------------------- 1 | 66, 204 2 | 55, 226 3 | 231, 196 4 | 69, 211 5 | 69, 335 6 | 133, 146 7 | 321, 136 8 | 220, 229 9 | 148, 138 10 | 42, 319 11 | 304, 181 12 | 101, 329 13 | 72, 244 14 | 242, 117 15 | 83, 237 16 | 169, 225 17 | 311, 212 18 | 348, 330 19 | 233, 268 20 | 99, 301 21 | 142, 293 22 | 239, 288 23 | 200, 216 24 | 44, 215 25 | 353, 289 26 | 54, 73 27 | 73, 317 28 | 55, 216 29 | 305, 134 30 | 343, 233 31 | 227, 75 32 | 139, 285 33 | 264, 179 34 | 349, 263 35 | 48, 116 36 | 223, 60 37 | 247, 148 38 | 320, 232 39 | 60, 230 40 | 292, 78 41 | 247, 342 42 | 59, 326 43 | 333, 210 44 | 186, 291 45 | 218, 146 46 | 205, 246 47 | 124, 204 48 | 76, 121 49 | 333, 137 50 | 117, 68 51 | -------------------------------------------------------------------------------- /2018/tests/day06/output: -------------------------------------------------------------------------------- 1 | Part 1: 3647 2 | Part 2: 41605 3 | -------------------------------------------------------------------------------- /2018/tests/day07/output: -------------------------------------------------------------------------------- 1 | Part 1: ACHOQRXSEKUGMYIWDZLNBFTJVP 2 | Part 2: 985 3 | -------------------------------------------------------------------------------- /2018/tests/day08/output: -------------------------------------------------------------------------------- 1 | Part 1: 36566 2 | Part 2: 30548 3 | -------------------------------------------------------------------------------- /2018/tests/day09/input: -------------------------------------------------------------------------------- 1 | 468 players; last marble is worth 71010 points 2 | -------------------------------------------------------------------------------- /2018/tests/day09/output: -------------------------------------------------------------------------------- 1 | Part 1: 374287 2 | Part 2: 3083412635 3 | -------------------------------------------------------------------------------- /2018/tests/day10/output: -------------------------------------------------------------------------------- 1 | Time: 10081 2 | . # # # # . . . # # # # # . . . # . . . . # . . # . . . . # . . # # # # # # . . # # # # # # . . # # # # # . . . # # # # # # 3 | # . . . . # . . # . . . . # . . # . . . . # . . # . . . # . . . # . . . . . . . . . . . . # . . # . . . . # . . . . . . . # 4 | # . . . . . . . # . . . . # . . . # . . # . . . # . . # . . . . # . . . . . . . . . . . . # . . # . . . . # . . . . . . . # 5 | # . . . . . . . # . . . . # . . . # . . # . . . # . # . . . . . # . . . . . . . . . . . # . . . # . . . . # . . . . . . # . 6 | # . . . . . . . # # # # # . . . . . # # . . . . # # . . . . . . # # # # # . . . . . . # . . . . # # # # # . . . . . . # . . 7 | # . . . . . . . # . . # . . . . . . # # . . . . # # . . . . . . # . . . . . . . . . # . . . . . # . . . . . . . . . # . . . 8 | # . . . . . . . # . . . # . . . . # . . # . . . # . # . . . . . # . . . . . . . . # . . . . . . # . . . . . . . . # . . . . 9 | # . . . . . . . # . . . # . . . . # . . # . . . # . . # . . . . # . . . . . . . # . . . . . . . # . . . . . . . # . . . . . 10 | # . . . . # . . # . . . . # . . # . . . . # . . # . . . # . . . # . . . . . . . # . . . . . . . # . . . . . . . # . . . . . 11 | . # # # # . . . # . . . . # . . # . . . . # . . # . . . . # . . # # # # # # . . # # # # # # . . # . . . . . . . # # # # # # 12 | -------------------------------------------------------------------------------- /2018/tests/day11/input: -------------------------------------------------------------------------------- 1 | 9424 2 | -------------------------------------------------------------------------------- /2018/tests/day11/output: -------------------------------------------------------------------------------- 1 | Part 1: (243, 72) 2 | Part 2: (229, 192, 11) 3 | -------------------------------------------------------------------------------- /2018/tests/day12/input: -------------------------------------------------------------------------------- 1 | initial state: ###.......##....#.#.#..###.##..##.....#....#.#.....##.###...###.#...###.###.#.###...#.####.##.#....# 2 | 3 | ..... => . 4 | #..## => . 5 | ..### => # 6 | ..#.# => # 7 | .#.#. => . 8 | ####. => . 9 | ##.## => # 10 | #.... => . 11 | #...# => . 12 | ...## => . 13 | ##..# => . 14 | .###. => # 15 | ##### => # 16 | #.#.. => # 17 | .##.. => # 18 | .#.## => . 19 | ...#. => # 20 | #.##. => # 21 | ..#.. => # 22 | ##... => # 23 | ....# => . 24 | ###.# => # 25 | #..#. => # 26 | #.### => # 27 | ##.#. => . 28 | ###.. => # 29 | .#### => . 30 | .#... => # 31 | ..##. => . 32 | .##.# => . 33 | #.#.# => # 34 | .#..# => . 35 | -------------------------------------------------------------------------------- /2018/tests/day12/output: -------------------------------------------------------------------------------- 1 | Part 1: 3221 2 | Part 2: 2600000001872 3 | -------------------------------------------------------------------------------- /2018/tests/day13/output: -------------------------------------------------------------------------------- 1 | Part 1: 124,130 2 | Part 2: 143,123 3 | -------------------------------------------------------------------------------- /2018/tests/day14/input: -------------------------------------------------------------------------------- 1 | 890691 2 | -------------------------------------------------------------------------------- /2018/tests/day14/output: -------------------------------------------------------------------------------- 1 | Part 1: 8176111038 2 | Part 2: 20225578 3 | -------------------------------------------------------------------------------- /2018/tests/day15/input: -------------------------------------------------------------------------------- 1 | ################################ 2 | ###############..........####### 3 | ######.##########G.......####### 4 | #####..###..######...G...####### 5 | #####..#...G..##........######## 6 | #####..G......#GG.......######## 7 | ######..G..#G.......G....####### 8 | ########...###...#........###### 9 | ######....G###.GG#.........##### 10 | ######G...####...#..........#### 11 | ###.##.....G................#### 12 | ###.......................#.#### 13 | ##.......G....#####.......E.#### 14 | ###.......G..#######....##E.#### 15 | ####........#########..G.#.##### 16 | #.#..##.....#########..#..###### 17 | #....####.G.#########......##### 18 | #.##G#####..#########.....###.E# 19 | ###########.#########...E.E....# 20 | ###########..#######..........## 21 | ###########..E#####.......###### 22 | ###########............E.####### 23 | #########.E.....E..##.#..####### 24 | #######.G.###.......E########### 25 | ######...#######....############ 26 | ################...############# 27 | ###############....############# 28 | ###############...############## 29 | #################.############## 30 | #################.############## 31 | #################.############## 32 | ################################ 33 | -------------------------------------------------------------------------------- /2018/tests/day15/output: -------------------------------------------------------------------------------- 1 | Part 1: 319410 2 | Part 2: 63168 3 | -------------------------------------------------------------------------------- /2018/tests/day16/output: -------------------------------------------------------------------------------- 1 | Part 1: 596 2 | Part 2: 554 3 | -------------------------------------------------------------------------------- /2018/tests/day17/output: -------------------------------------------------------------------------------- 1 | Part 1: 30495 2 | Part 2: 24899 3 | -------------------------------------------------------------------------------- /2018/tests/day18/input: -------------------------------------------------------------------------------- 1 | ..#..#.||.|.#.#..##..##|.....|..|....#|....|...... 2 | |....|.#|#.#|.|..##.#.#..#|.|.##.#........|||#.... 3 | ..|.#...|.#...|#||..|..|..#|#..#.....|...|......#. 4 | |.#|####.#..|#........#.|.....#.|###....##.....|#. 5 | ..|...####....|#.#..|.|.|.|..#..|.....#..|.......| 6 | #.....|.#||.#..|#......#|#.....|...|..#...#|...|#| 7 | #....|.||#.|.#...#.#.|.....|.........#...#.|#....| 8 | .#...||.#.#..|..#|.....|.#..|.#....|.|#.#||.##|... 9 | |#.|.#.#|||...#..|#..|..|#..|.|...#....|##|....|#. 10 | #|###..|#|.||.....|#...#...####.#.|#|.#....||..||# 11 | #....#...#...#.|#.......#..#||.....#.#.....|#|..#. 12 | #|...#.|.#.|.|.........#.|.|#...|...|###|.#..|#... 13 | .||##.####|#.#.#.|...#.||.#.......|......|...|..|| 14 | ..||#.#.|.#|.#.#||...#|......##..|..|.||..#....#.. 15 | ...##........##|#..#.|||.......|...#.#.|##|.#.|#|# 16 | |.#..|#.|.#...#.|..##.......|..|..|........#|....| 17 | ##.........##.#|..|...|.#...........|######....#.. 18 | .#.|.##|#..#|...|#.|.....|.#.#.#|...|..#|...|#|#.. 19 | .|..|.|#.|...#....|..|.#.|........#.||.....#..|#.. 20 | ..#||#..#|......|..|##|..#|..|..#.......#.#||...|. 21 | #.#.###...#..........##..#.#.|#.|..||.#||.|.##|..# 22 | ..|...##....|.|#..||..|##.....|#.|..||#.#|.#...|.. 23 | ...#.#||......#............#.........|.|..#...|..| 24 | ..|.....|...|#|##|...###....|....##.|||.|#|...#... 25 | |.|#.|......||##.##..|.###..#..#..#.#.|.#..|.||... 26 | ..#|..........|.|...#.#..##.|#.|...|.#........||.. 27 | ...##|....#..#.#|....|#|#|..#|.|..#||||.#.#...|..| 28 | .....|....||.....|...........#.#.#..|.|.#..#...... 29 | .||#...|.|||.##.||...|.#.#.#.|.#...#..........||#. 30 | .#.|..#|#....#.#....|||.......||.#.#..||..|.....#. 31 | ....||#.#|..|....##.|.#....#.#.||...#.|.....###..# 32 | |..#|#..|.|.....|..|...#..|.........|..#..|.....|| 33 | |.|..#...##|..#|#.#......|.#.|##.||.##.#...#.#|... 34 | |.#|#.##.||..#..#.|#..|###.||..|...|#|..##....#||# 35 | #..|#..#..........||...|.....|...#....|..||..#..#. 36 | |.........|||.|.#.|..............|.###.#....##|.|. 37 | ##....#|.#.....|...|..#||....|..####..|.##.|.#.... 38 | |.|..||......|.##|..|.....#||.|#.|...||....|....## 39 | #.#.|..|.##.#|..#..#.#|.|....||..##.#|.##.....|... 40 | ..#|.|.|#.......#|..|.|..||#.....|##|.###..|.##... 41 | .#..|.|.||...||..#..|.....|.#.#.|###.|....|.#...#| 42 | ....|#|#.|..#...#......|.||..|#|#||..#.#.|......#| 43 | #..|..#......#|.#..|||#.||.......#.....|.#.#|...#. 44 | ..|##.#...|.##.#.#.#|#.......||.....||##..#|.#..#. 45 | ....|.|#|#..|....|#||.##|....#...|.#..#|||....##.. 46 | .#.|.##...|#.##..|.#.#.#..#.||||.|...#......##.... 47 | #...|#..|..|..|||.|...||......#..|#..|.......||.#. 48 | ..|#.||||##.|......|..|#.##.....##|..#..|..#||#.|| 49 | #..|.##.#...|.|#.#.|||##...|....|..|.#.##|#.##|..| 50 | .|####.#...||..#..|.##|...#..........|.|....#|.... 51 | -------------------------------------------------------------------------------- /2018/tests/day18/output: -------------------------------------------------------------------------------- 1 | Part 1: 483840 2 | Part 2: 219919 3 | -------------------------------------------------------------------------------- /2018/tests/day19/input: -------------------------------------------------------------------------------- 1 | #ip 3 2 | addi 3 16 3 3 | seti 1 2 1 4 | seti 1 1 2 5 | mulr 1 2 5 6 | eqrr 5 4 5 7 | addr 5 3 3 8 | addi 3 1 3 9 | addr 1 0 0 10 | addi 2 1 2 11 | gtrr 2 4 5 12 | addr 3 5 3 13 | seti 2 3 3 14 | addi 1 1 1 15 | gtrr 1 4 5 16 | addr 5 3 3 17 | seti 1 6 3 18 | mulr 3 3 3 19 | addi 4 2 4 20 | mulr 4 4 4 21 | mulr 3 4 4 22 | muli 4 11 4 23 | addi 5 5 5 24 | mulr 5 3 5 25 | addi 5 15 5 26 | addr 4 5 4 27 | addr 3 0 3 28 | seti 0 6 3 29 | setr 3 5 5 30 | mulr 5 3 5 31 | addr 3 5 5 32 | mulr 3 5 5 33 | muli 5 14 5 34 | mulr 5 3 5 35 | addr 4 5 4 36 | seti 0 5 0 37 | seti 0 1 3 38 | -------------------------------------------------------------------------------- /2018/tests/day19/output: -------------------------------------------------------------------------------- 1 | Part 1: 993 2 | Part 2: 10708912 3 | -------------------------------------------------------------------------------- /2018/tests/day20/output: -------------------------------------------------------------------------------- 1 | Part 1: 3788 2 | Part 2: 8568 3 | -------------------------------------------------------------------------------- /2018/tests/day21/input: -------------------------------------------------------------------------------- 1 | #ip 5 2 | seti 123 0 4 3 | bani 4 456 4 4 | eqri 4 72 4 5 | addr 4 5 5 6 | seti 0 0 5 7 | seti 0 8 4 8 | bori 4 65536 3 9 | seti 707129 0 4 10 | bani 3 255 2 11 | addr 4 2 4 12 | bani 4 16777215 4 13 | muli 4 65899 4 14 | bani 4 16777215 4 15 | gtir 256 3 2 16 | addr 2 5 5 17 | addi 5 1 5 18 | seti 27 6 5 19 | seti 0 7 2 20 | addi 2 1 1 21 | muli 1 256 1 22 | gtrr 1 3 1 23 | addr 1 5 5 24 | addi 5 1 5 25 | seti 25 2 5 26 | addi 2 1 2 27 | seti 17 1 5 28 | setr 2 4 3 29 | seti 7 4 5 30 | eqrr 4 0 2 31 | addr 2 5 5 32 | seti 5 2 5 33 | -------------------------------------------------------------------------------- /2018/tests/day21/output: -------------------------------------------------------------------------------- 1 | Part 1: 2985446 2 | Part 2: 12502875 3 | -------------------------------------------------------------------------------- /2018/tests/day22/input: -------------------------------------------------------------------------------- 1 | depth: 8112 2 | target: 13,743 3 | -------------------------------------------------------------------------------- /2018/tests/day22/output: -------------------------------------------------------------------------------- 1 | Part 1: 10395 2 | Part 2: 1010 3 | -------------------------------------------------------------------------------- /2018/tests/day23/output: -------------------------------------------------------------------------------- 1 | Part 1: 305 2 | Part 2: 78687716 3 | -------------------------------------------------------------------------------- /2018/tests/day24/input: -------------------------------------------------------------------------------- 1 | Immune System: 2 | 197 units each with 6697 hit points (weak to bludgeoning, fire) with an attack that does 312 slashing damage at initiative 3 3 | 3803 units each with 8760 hit points (weak to bludgeoning) with an attack that does 21 slashing damage at initiative 9 4 | 5279 units each with 4712 hit points with an attack that does 8 cold damage at initiative 7 5 | 3727 units each with 11858 hit points (weak to slashing) with an attack that does 25 cold damage at initiative 19 6 | 494 units each with 3486 hit points (weak to radiation; immune to bludgeoning) with an attack that does 70 cold damage at initiative 6 7 | 1700 units each with 8138 hit points (weak to slashing) with an attack that does 41 slashing damage at initiative 18 8 | 251 units each with 4061 hit points (weak to bludgeoning) with an attack that does 157 radiation damage at initiative 15 9 | 87 units each with 1699 hit points with an attack that does 161 cold damage at initiative 11 10 | 1518 units each with 9528 hit points (weak to cold, slashing) with an attack that does 60 slashing damage at initiative 2 11 | 347 units each with 6624 hit points (immune to fire; weak to bludgeoning) with an attack that does 148 slashing damage at initiative 12 12 | 13 | Infection: 14 | 6929 units each with 51693 hit points with an attack that does 13 slashing damage at initiative 5 15 | 1638 units each with 32400 hit points (weak to bludgeoning) with an attack that does 27 bludgeoning damage at initiative 16 16 | 2311 units each with 12377 hit points (weak to fire; immune to cold) with an attack that does 9 slashing damage at initiative 8 17 | 685 units each with 29080 hit points (weak to bludgeoning, fire; immune to radiation) with an attack that does 57 bludgeoning damage at initiative 10 18 | 1225 units each with 7657 hit points (weak to slashing) with an attack that does 12 cold damage at initiative 14 19 | 734 units each with 52884 hit points with an attack that does 102 bludgeoning damage at initiative 13 20 | 608 units each with 49797 hit points (weak to radiation; immune to slashing) with an attack that does 162 bludgeoning damage at initiative 1 21 | 3434 units each with 49977 hit points with an attack that does 28 radiation damage at initiative 4 22 | 1918 units each with 14567 hit points (weak to slashing) with an attack that does 13 bludgeoning damage at initiative 20 23 | 519 units each with 18413 hit points (immune to slashing) with an attack that does 69 fire damage at initiative 17 24 | -------------------------------------------------------------------------------- /2018/tests/day24/output: -------------------------------------------------------------------------------- 1 | Part 1: 17542 2 | Part 2: 868 3 | -------------------------------------------------------------------------------- /2018/tests/day25/output: -------------------------------------------------------------------------------- 1 | 381 2 | -------------------------------------------------------------------------------- /2019/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-2019" 3 | version = "0.1.0" 4 | authors = ["Benoît Zugmeyer "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | native-tls = "0.2.3" 9 | itertools = "0.8.2" 10 | bytecount = "0.6.0" 11 | lazy_static = "1.4.0" 12 | -------------------------------------------------------------------------------- /2019/cache/answer_01_1: -------------------------------------------------------------------------------- 1 | 3464735 -------------------------------------------------------------------------------- /2019/cache/answer_01_2: -------------------------------------------------------------------------------- 1 | 5194211 -------------------------------------------------------------------------------- /2019/cache/answer_02_1: -------------------------------------------------------------------------------- 1 | 4023471 -------------------------------------------------------------------------------- /2019/cache/answer_02_2: -------------------------------------------------------------------------------- 1 | 8051 -------------------------------------------------------------------------------- /2019/cache/answer_03_1: -------------------------------------------------------------------------------- 1 | 303 -------------------------------------------------------------------------------- /2019/cache/answer_03_2: -------------------------------------------------------------------------------- 1 | 11222 -------------------------------------------------------------------------------- /2019/cache/answer_04_1: -------------------------------------------------------------------------------- 1 | 2779 -------------------------------------------------------------------------------- /2019/cache/answer_04_2: -------------------------------------------------------------------------------- 1 | 1972 -------------------------------------------------------------------------------- /2019/cache/answer_05_1: -------------------------------------------------------------------------------- 1 | 15097178 -------------------------------------------------------------------------------- /2019/cache/answer_05_2: -------------------------------------------------------------------------------- 1 | 1558663 -------------------------------------------------------------------------------- /2019/cache/answer_06_1: -------------------------------------------------------------------------------- 1 | 160040 -------------------------------------------------------------------------------- /2019/cache/answer_06_2: -------------------------------------------------------------------------------- 1 | 373 -------------------------------------------------------------------------------- /2019/cache/answer_07_1: -------------------------------------------------------------------------------- 1 | 273814 -------------------------------------------------------------------------------- /2019/cache/answer_07_2: -------------------------------------------------------------------------------- 1 | 34579864 -------------------------------------------------------------------------------- /2019/cache/answer_08_1: -------------------------------------------------------------------------------- 1 | 2562 -------------------------------------------------------------------------------- /2019/cache/answer_08_2: -------------------------------------------------------------------------------- 1 | ZFLBY -------------------------------------------------------------------------------- /2019/cache/answer_09_1: -------------------------------------------------------------------------------- 1 | 2714716640 -------------------------------------------------------------------------------- /2019/cache/answer_09_2: -------------------------------------------------------------------------------- 1 | 58879 -------------------------------------------------------------------------------- /2019/cache/answer_10_1: -------------------------------------------------------------------------------- 1 | 309 -------------------------------------------------------------------------------- /2019/cache/answer_10_2: -------------------------------------------------------------------------------- 1 | 416 -------------------------------------------------------------------------------- /2019/cache/answer_11_1: -------------------------------------------------------------------------------- 1 | 2418 -------------------------------------------------------------------------------- /2019/cache/answer_11_2: -------------------------------------------------------------------------------- 1 | GREJALPR -------------------------------------------------------------------------------- /2019/cache/answer_12_1: -------------------------------------------------------------------------------- 1 | 12351 -------------------------------------------------------------------------------- /2019/cache/answer_12_2: -------------------------------------------------------------------------------- 1 | 380635029877596 -------------------------------------------------------------------------------- /2019/cache/answer_13_1: -------------------------------------------------------------------------------- 1 | 216 -------------------------------------------------------------------------------- /2019/cache/answer_13_2: -------------------------------------------------------------------------------- 1 | 10025 -------------------------------------------------------------------------------- /2019/cache/answer_14_1: -------------------------------------------------------------------------------- 1 | 399063 -------------------------------------------------------------------------------- /2019/cache/answer_14_2: -------------------------------------------------------------------------------- 1 | 4215654 -------------------------------------------------------------------------------- /2019/cache/answer_15_1: -------------------------------------------------------------------------------- 1 | 232 -------------------------------------------------------------------------------- /2019/cache/answer_15_2: -------------------------------------------------------------------------------- 1 | 320 -------------------------------------------------------------------------------- /2019/cache/answer_16_1: -------------------------------------------------------------------------------- 1 | 30379585 -------------------------------------------------------------------------------- /2019/cache/answer_16_2: -------------------------------------------------------------------------------- 1 | 22808931 -------------------------------------------------------------------------------- /2019/cache/answer_17_1: -------------------------------------------------------------------------------- 1 | 5068 -------------------------------------------------------------------------------- /2019/cache/answer_17_2: -------------------------------------------------------------------------------- 1 | 1415975 -------------------------------------------------------------------------------- /2019/cache/answer_18_1: -------------------------------------------------------------------------------- 1 | 4762 -------------------------------------------------------------------------------- /2019/cache/answer_18_2: -------------------------------------------------------------------------------- 1 | 1876 -------------------------------------------------------------------------------- /2019/cache/answer_19_1: -------------------------------------------------------------------------------- 1 | 121 -------------------------------------------------------------------------------- /2019/cache/answer_19_2: -------------------------------------------------------------------------------- 1 | 15090773 -------------------------------------------------------------------------------- /2019/cache/answer_20_1: -------------------------------------------------------------------------------- 1 | 448 -------------------------------------------------------------------------------- /2019/cache/answer_20_2: -------------------------------------------------------------------------------- 1 | 5678 -------------------------------------------------------------------------------- /2019/cache/answer_21_1: -------------------------------------------------------------------------------- 1 | 19353619 -------------------------------------------------------------------------------- /2019/cache/answer_21_2: -------------------------------------------------------------------------------- 1 | 1142785329 -------------------------------------------------------------------------------- /2019/cache/answer_22_1: -------------------------------------------------------------------------------- 1 | 6794 -------------------------------------------------------------------------------- /2019/cache/answer_23_1: -------------------------------------------------------------------------------- 1 | 16250 -------------------------------------------------------------------------------- /2019/cache/answer_23_2: -------------------------------------------------------------------------------- 1 | 11046 -------------------------------------------------------------------------------- /2019/cache/answer_24_1: -------------------------------------------------------------------------------- 1 | 18371095 -------------------------------------------------------------------------------- /2019/cache/answer_24_2: -------------------------------------------------------------------------------- 1 | 2075 -------------------------------------------------------------------------------- /2019/cache/input_01: -------------------------------------------------------------------------------- 1 | 141923 2 | 145715 3 | 63157 4 | 142712 5 | 147191 6 | 96667 7 | 117032 8 | 98123 9 | 135120 10 | 90609 11 | 132022 12 | 61962 13 | 110315 14 | 78993 15 | 130183 16 | 102188 17 | 128800 18 | 140640 19 | 144402 20 | 133746 21 | 66157 22 | 136169 23 | 88585 24 | 82083 25 | 78884 26 | 66913 27 | 142607 28 | 62297 29 | 116267 30 | 92283 31 | 108383 32 | 142698 33 | 53334 34 | 139604 35 | 144184 36 | 89522 37 | 142032 38 | 68327 39 | 111034 40 | 58033 41 | 72836 42 | 90483 43 | 111008 44 | 91385 45 | 115528 46 | 66856 47 | 76318 48 | 63000 49 | 61721 50 | 86102 51 | 89367 52 | 91018 53 | 126390 54 | 135550 55 | 106711 56 | 118434 57 | 117698 58 | 108304 59 | 98998 60 | 82998 61 | 147998 62 | 83344 63 | 149309 64 | 53964 65 | 111042 66 | 112244 67 | 114337 68 | 134419 69 | 76114 70 | 147869 71 | 107076 72 | 78626 73 | 66552 74 | 133785 75 | 112234 76 | 52693 77 | 73606 78 | 116199 79 | 72505 80 | 137500 81 | 64873 82 | 147893 83 | 56938 84 | 87481 85 | 146006 86 | 82226 87 | 133657 88 | 84149 89 | 123742 90 | 137593 91 | 55372 92 | 64696 93 | 54386 94 | 83466 95 | 135058 96 | 133268 97 | 84234 98 | 119067 99 | 143566 100 | 134224 -------------------------------------------------------------------------------- /2019/cache/input_02: -------------------------------------------------------------------------------- 1 | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,6,19,1,5,19,23,1,23,6,27,1,5,27,31,1,31,6,35,1,9,35,39,2,10,39,43,1,43,6,47,2,6,47,51,1,5,51,55,1,55,13,59,1,59,10,63,2,10,63,67,1,9,67,71,2,6,71,75,1,5,75,79,2,79,13,83,1,83,5,87,1,87,9,91,1,5,91,95,1,5,95,99,1,99,13,103,1,10,103,107,1,107,9,111,1,6,111,115,2,115,13,119,1,10,119,123,2,123,6,127,1,5,127,131,1,5,131,135,1,135,6,139,2,139,10,143,2,143,9,147,1,147,6,151,1,151,13,155,2,155,9,159,1,6,159,163,1,5,163,167,1,5,167,171,1,10,171,175,1,13,175,179,1,179,2,183,1,9,183,0,99,2,14,0,0 -------------------------------------------------------------------------------- /2019/cache/input_04: -------------------------------------------------------------------------------- 1 | 108457-562041 -------------------------------------------------------------------------------- /2019/cache/input_05: -------------------------------------------------------------------------------- 1 | 3,225,1,225,6,6,1100,1,238,225,104,0,2,106,196,224,101,-1157,224,224,4,224,102,8,223,223,1001,224,7,224,1,224,223,223,1002,144,30,224,1001,224,-1710,224,4,224,1002,223,8,223,101,1,224,224,1,224,223,223,101,82,109,224,1001,224,-111,224,4,224,102,8,223,223,1001,224,4,224,1,223,224,223,1102,10,50,225,1102,48,24,224,1001,224,-1152,224,4,224,1002,223,8,223,101,5,224,224,1,223,224,223,1102,44,89,225,1101,29,74,225,1101,13,59,225,1101,49,60,225,1101,89,71,224,1001,224,-160,224,4,224,1002,223,8,223,1001,224,6,224,1,223,224,223,1101,27,57,225,102,23,114,224,1001,224,-1357,224,4,224,102,8,223,223,101,5,224,224,1,224,223,223,1001,192,49,224,1001,224,-121,224,4,224,1002,223,8,223,101,3,224,224,1,223,224,223,1102,81,72,225,1102,12,13,225,1,80,118,224,1001,224,-110,224,4,224,102,8,223,223,101,2,224,224,1,224,223,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,7,677,226,224,102,2,223,223,1005,224,329,101,1,223,223,108,226,226,224,102,2,223,223,1006,224,344,101,1,223,223,1108,226,677,224,102,2,223,223,1006,224,359,1001,223,1,223,107,677,677,224,1002,223,2,223,1005,224,374,1001,223,1,223,1107,226,677,224,102,2,223,223,1005,224,389,1001,223,1,223,107,677,226,224,1002,223,2,223,1005,224,404,101,1,223,223,8,226,677,224,102,2,223,223,1005,224,419,101,1,223,223,7,226,677,224,1002,223,2,223,1005,224,434,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,449,1001,223,1,223,107,226,226,224,1002,223,2,223,1006,224,464,1001,223,1,223,1007,226,226,224,102,2,223,223,1006,224,479,1001,223,1,223,1008,226,226,224,102,2,223,223,1006,224,494,101,1,223,223,7,677,677,224,102,2,223,223,1005,224,509,1001,223,1,223,108,677,226,224,102,2,223,223,1005,224,524,101,1,223,223,1108,677,226,224,1002,223,2,223,1006,224,539,101,1,223,223,1108,677,677,224,102,2,223,223,1005,224,554,101,1,223,223,8,677,226,224,102,2,223,223,1005,224,569,101,1,223,223,8,677,677,224,102,2,223,223,1005,224,584,101,1,223,223,1107,226,226,224,102,2,223,223,1006,224,599,101,1,223,223,108,677,677,224,102,2,223,223,1006,224,614,101,1,223,223,1008,677,226,224,1002,223,2,223,1005,224,629,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,644,101,1,223,223,1008,677,677,224,1002,223,2,223,1005,224,659,101,1,223,223,1007,677,226,224,1002,223,2,223,1005,224,674,1001,223,1,223,4,223,99,226 -------------------------------------------------------------------------------- /2019/cache/input_07: -------------------------------------------------------------------------------- 1 | 3,8,1001,8,10,8,105,1,0,0,21,34,59,76,101,114,195,276,357,438,99999,3,9,1001,9,4,9,1002,9,4,9,4,9,99,3,9,102,4,9,9,101,2,9,9,102,4,9,9,1001,9,3,9,102,2,9,9,4,9,99,3,9,101,4,9,9,102,5,9,9,101,5,9,9,4,9,99,3,9,102,2,9,9,1001,9,4,9,102,4,9,9,1001,9,4,9,1002,9,3,9,4,9,99,3,9,101,2,9,9,1002,9,3,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99 -------------------------------------------------------------------------------- /2019/cache/input_10: -------------------------------------------------------------------------------- 1 | #.#................#..............#......#...... 2 | .......##..#..#....#.#.....##...#.........#.#... 3 | .#...............#....#.##...................... 4 | ......#..####.........#....#.......#..#.....#... 5 | .....#............#......#................#.#... 6 | ....##...#.#.#.#.............#..#.#.......#..... 7 | ..#.#.........#....#..#.#.........####.......... 8 | ....#...#.#...####..#..#..#.....#............... 9 | .............#......#..........#...........#.... 10 | ......#.#.........#...............#............. 11 | ..#......#..#.....##...##.....#....#.#......#... 12 | ...#.......##.........#.#..#......#........#.#.. 13 | #.............#..........#....#.#.....#......... 14 | #......#.#................#.......#..#.#........ 15 | #..#.#.....#.....###..#.................#..#.... 16 | ...............................#..........#..... 17 | ###.#.....#.....#.............#.......#....#.... 18 | .#.....#.........#.....#....#................... 19 | ........#....................#..#............... 20 | .....#...#.##......#............#......#.....#.. 21 | ..#..#..............#..#..#.##........#......... 22 | ..#.#...#.......#....##...#........#...#.#....#. 23 | .....#.#..####...........#.##....#....#......#.. 24 | .....#..#..##...............................#... 25 | .#....#..#......#.#............#........##...#.. 26 | .......#.....................#..#....#.....#.... 27 | #......#..###...........#.#....#......#......... 28 | ..............#..#.#...#.......#..#.#...#......# 29 | .......#...........#.....#...#.............#.#.. 30 | ..##..##.............#........#........#........ 31 | ......#.............##..#.........#...#.#.#..... 32 | #........#.........#...#.....#................#. 33 | ...#.#...........#.....#.........#......##...... 34 | ..#..#...........#..........#................... 35 | .........#..#.......................#.#......... 36 | ......#.#.#.....#...........#...............#... 37 | ......#.##...........#....#............#........ 38 | #...........##.#.#........##...........##....... 39 | ......#....#..#.......#.....#.#.......#.##...... 40 | .#....#......#..............#.......#........... 41 | ......##.#..........#..................#........ 42 | ......##.##...#..#........#............#........ 43 | ..#.....#.................###...#.....###.#..#.. 44 | ....##...............#....#..................#.. 45 | .....#................#.#.#.......#..........#.. 46 | #........................#.##..........#....##.. 47 | .#.........#.#.#...#...#....#........#..#....... 48 | ...#..#.#......................#...............# -------------------------------------------------------------------------------- /2019/cache/input_11: -------------------------------------------------------------------------------- 1 | 3,8,1005,8,328,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,101,0,8,28,1006,0,13,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,1002,8,1,54,1,1103,9,10,1006,0,97,2,1003,0,10,1,105,6,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,1001,8,0,91,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,113,2,109,5,10,1006,0,96,1,2,5,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,146,2,103,2,10,1006,0,69,2,9,8,10,1006,0,25,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,182,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,1001,8,0,203,2,5,9,10,1006,0,0,2,6,2,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,1002,8,1,236,2,4,0,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1002,8,1,263,2,105,9,10,1,103,15,10,1,4,4,10,2,109,7,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,301,1006,0,63,2,105,6,10,101,1,9,9,1007,9,1018,10,1005,10,15,99,109,650,104,0,104,1,21102,387508441116,1,1,21102,1,345,0,1106,0,449,21102,1,387353256852,1,21102,1,356,0,1105,1,449,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,179410308315,0,1,21102,1,403,0,1106,0,449,21101,206199495827,0,1,21102,414,1,0,1105,1,449,3,10,104,0,104,0,3,10,104,0,104,0,21102,718086758760,1,1,21102,1,437,0,1105,1,449,21101,838429573908,0,1,21102,448,1,0,1106,0,449,99,109,2,21202,-1,1,1,21102,1,40,2,21102,480,1,3,21101,470,0,0,1105,1,513,109,-2,2105,1,0,0,1,0,0,1,109,2,3,10,204,-1,1001,475,476,491,4,0,1001,475,1,475,108,4,475,10,1006,10,507,1102,0,1,475,109,-2,2106,0,0,0,109,4,2101,0,-1,512,1207,-3,0,10,1006,10,530,21101,0,0,-3,21202,-3,1,1,21201,-2,0,2,21102,1,1,3,21102,549,1,0,1105,1,554,109,-4,2106,0,0,109,5,1207,-3,1,10,1006,10,577,2207,-4,-2,10,1006,10,577,22102,1,-4,-4,1106,0,645,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21101,596,0,0,1106,0,554,22101,0,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,615,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,637,21201,-1,0,1,21101,637,0,0,106,0,512,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0 -------------------------------------------------------------------------------- /2019/cache/input_12: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /2019/cache/input_14: -------------------------------------------------------------------------------- 1 | 180 ORE => 9 DQFL 2 | 3 HGCR, 9 TKRT => 8 ZBLC 3 | 1 MZQLG, 12 RPLCK, 8 PDTP => 8 VCFX 4 | 3 ZBLC, 19 VFZX => 1 SJQL 5 | 1 CRPGK => 4 TPRT 6 | 7 HGCR, 4 TGCW, 1 VFZX => 9 JBPHS 7 | 8 GJHX => 4 NSDBV 8 | 1 VFTG => 2 QNWD 9 | 1 WDKW, 2 DWRH, 6 VNMV, 2 HFHL, 55 GJHX, 4 NSDBV, 15 KLJMS, 17 KZDJ => 1 FUEL 10 | 2 JHSJ, 15 JNWJ, 1 ZMFXQ => 4 GVRK 11 | 1 PJFBD => 3 MZQLG 12 | 1 SJQL, 11 LPVWN => 9 DLZS 13 | 3 PRMJ, 2 XNWV => 6 JHSJ 14 | 4 SJQL => 8 PJFBD 15 | 14 QNWD => 6 STHQ 16 | 5 CNLFV, 2 VFTG => 9 XNWV 17 | 17 LWNKB, 6 KBWF, 3 PLSCB => 8 KZDJ 18 | 6 LHWZQ, 5 LWNKB => 3 ZDWX 19 | 5 RPLCK, 2 LPVWN => 8 ZMFXQ 20 | 1 QNWD, 2 TKRT => 3 CRPGK 21 | 1 JBPHS, 1 XNWV => 6 TLRST 22 | 21 ZDWX, 3 FZDP, 4 CRPGK => 6 PDTP 23 | 1 JCVP => 1 WXDVT 24 | 2 CRPGK => 9 FGVL 25 | 4 DQFL, 2 VNMV => 1 HGCR 26 | 2 GVRK, 2 VCFX, 3 PJFBD, 1 PLSCB, 23 FZDP, 22 PCSM, 1 JLVQ => 6 HFHL 27 | 1 CRPGK, 5 PJFBD, 4 XTCP => 8 PLSCB 28 | 1 HTZW, 17 FGVL => 3 LHWZQ 29 | 2 KBWF => 4 DQKLC 30 | 2 LHWZQ => 2 PRMJ 31 | 2 DLZS, 2 VCFX, 15 PDTP, 14 ZDWX, 35 NBZC, 20 JVMF, 1 BGWMS => 3 DWRH 32 | 2 TKVCX, 6 RPLCK, 2 HTZW => 4 XTCP 33 | 8 CNLFV, 1 NRSD, 1 VFTG => 9 VFZX 34 | 1 TLRST => 4 WDKW 35 | 9 VFCZG => 7 GJHX 36 | 4 FZDP => 8 JLVQ 37 | 2 ZMFXQ, 2 STHQ => 6 QDZB 38 | 2 SJQL, 8 ZDWX, 6 LPRL, 6 WXDVT, 1 TPRT, 1 JNWJ => 8 KLJMS 39 | 6 JBPHS, 2 ZBLC => 6 HTZW 40 | 1 PDTP, 2 LHWZQ => 8 JNWJ 41 | 8 ZBLC => 7 TKVCX 42 | 2 WDKW, 31 QDZB => 4 PCSM 43 | 15 GJHX, 5 TKVCX => 7 FZDP 44 | 15 SJQL, 3 PRMJ => 4 JCVP 45 | 31 CNLFV => 1 TGCW 46 | 1 TLRST, 2 WDKW => 9 KBWF 47 | 102 ORE => 7 VNMV 48 | 103 ORE => 5 CNLFV 49 | 163 ORE => 2 VFTG 50 | 5 NRSD, 1 STHQ => 3 VFCZG 51 | 16 LPVWN, 13 KBWF => 2 BGWMS 52 | 5 BGWMS, 11 SJQL, 9 FZDP => 6 NBZC 53 | 175 ORE => 7 NRSD 54 | 5 HTZW => 4 LPVWN 55 | 4 PRMJ => 7 JVMF 56 | 6 PCSM, 8 DQKLC => 7 LPRL 57 | 2 CNLFV => 7 TKRT 58 | 3 FZDP => 3 LWNKB 59 | 1 HTZW => 4 RPLCK -------------------------------------------------------------------------------- /2019/cache/input_16: -------------------------------------------------------------------------------- 1 | 59758034323742284979562302567188059299994912382665665642838883745982029056376663436508823581366924333715600017551568562558429576180672045533950505975691099771937719816036746551442321193912312169741318691856211013074397344457854784758130321667776862471401531789634126843370279186945621597012426944937230330233464053506510141241904155782847336539673866875764558260690223994721394144728780319578298145328345914839568238002359693873874318334948461885586664697152894541318898569630928429305464745641599948619110150923544454316910363268172732923554361048379061622935009089396894630658539536284162963303290768551107950942989042863293547237058600513191659935 -------------------------------------------------------------------------------- /2019/cache/input_19: -------------------------------------------------------------------------------- 1 | 109,424,203,1,21102,11,1,0,1105,1,282,21101,18,0,0,1106,0,259,1202,1,1,221,203,1,21101,0,31,0,1106,0,282,21102,38,1,0,1105,1,259,20101,0,23,2,22102,1,1,3,21102,1,1,1,21102,57,1,0,1105,1,303,2101,0,1,222,21002,221,1,3,20101,0,221,2,21102,1,259,1,21101,0,80,0,1105,1,225,21102,40,1,2,21101,0,91,0,1105,1,303,1201,1,0,223,20101,0,222,4,21101,0,259,3,21101,0,225,2,21101,0,225,1,21102,118,1,0,1105,1,225,21001,222,0,3,21102,1,144,2,21101,0,133,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21102,148,1,0,1105,1,259,1202,1,1,223,20101,0,221,4,21001,222,0,3,21102,1,14,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,195,1,0,106,0,109,20207,1,223,2,20101,0,23,1,21101,0,-1,3,21102,214,1,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2101,0,-4,249,22101,0,-3,1,21201,-2,0,2,22101,0,-1,3,21101,0,250,0,1105,1,225,21202,1,1,-4,109,-5,2105,1,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2106,0,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21202,-2,1,3,21101,343,0,0,1106,0,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21202,-4,1,1,21102,384,1,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22101,0,1,-4,109,-5,2106,0,0 -------------------------------------------------------------------------------- /2019/cache/input_22: -------------------------------------------------------------------------------- 1 | deal into new stack 2 | cut 7990 3 | deal into new stack 4 | cut -5698 5 | deal with increment 29 6 | cut 1503 7 | deal with increment 65 8 | cut -9095 9 | deal with increment 56 10 | cut 9104 11 | deal into new stack 12 | deal with increment 5 13 | cut -7708 14 | deal with increment 20 15 | cut 4813 16 | deal with increment 2 17 | cut 4728 18 | deal into new stack 19 | cut -5429 20 | deal with increment 47 21 | cut 1739 22 | deal with increment 63 23 | cut 6707 24 | deal with increment 29 25 | cut 4293 26 | deal with increment 44 27 | cut 8873 28 | deal with increment 53 29 | cut 6046 30 | deal into new stack 31 | cut 8054 32 | deal into new stack 33 | deal with increment 14 34 | cut 2426 35 | deal with increment 11 36 | cut 4006 37 | deal with increment 49 38 | cut -6277 39 | deal with increment 3 40 | cut 2231 41 | deal with increment 45 42 | cut -5059 43 | deal with increment 7 44 | cut 4251 45 | deal with increment 16 46 | cut -6081 47 | deal with increment 25 48 | cut -4067 49 | deal with increment 29 50 | cut 7656 51 | deal into new stack 52 | cut 5091 53 | deal with increment 57 54 | deal into new stack 55 | deal with increment 63 56 | cut 4047 57 | deal with increment 24 58 | cut -8596 59 | deal with increment 13 60 | cut 1946 61 | deal with increment 16 62 | cut -1656 63 | deal into new stack 64 | deal with increment 15 65 | cut -6557 66 | deal with increment 10 67 | cut 2378 68 | deal with increment 24 69 | cut -2162 70 | deal with increment 7 71 | deal into new stack 72 | deal with increment 37 73 | cut -4310 74 | deal into new stack 75 | deal with increment 48 76 | cut 6842 77 | deal with increment 13 78 | cut 2960 79 | deal into new stack 80 | cut 7128 81 | deal with increment 30 82 | cut -2529 83 | deal with increment 31 84 | cut -2500 85 | deal with increment 28 86 | deal into new stack 87 | deal with increment 37 88 | cut -8133 89 | deal with increment 74 90 | cut -7823 91 | deal with increment 42 92 | cut 2092 93 | deal with increment 41 94 | cut -6752 95 | deal with increment 56 96 | cut -9577 97 | deal into new stack 98 | cut -4736 99 | deal with increment 8 100 | cut -3584 -------------------------------------------------------------------------------- /2019/cache/input_24: -------------------------------------------------------------------------------- 1 | .#.## 2 | .#.#. 3 | ##.#. 4 | ####. 5 | #.### -------------------------------------------------------------------------------- /2019/src/day01.rs: -------------------------------------------------------------------------------- 1 | fn fuel_required(mass: u32) -> u32 { 2 | (mass / 3).saturating_sub(2) 3 | } 4 | 5 | fn fuel_required_with_requirement(mut mass: u32) -> u32 { 6 | let mut result = 0; 7 | while mass != 0 { 8 | mass = fuel_required(mass); 9 | result += mass; 10 | } 11 | result 12 | } 13 | 14 | #[allow(dead_code)] 15 | fn total_fuel_required>(iterator: T) -> u32 { 16 | iterator.map(fuel_required).sum() 17 | } 18 | 19 | #[allow(dead_code)] 20 | fn total_fuel_required_with_requirement>(iterator: T) -> u32 { 21 | iterator.map(fuel_required_with_requirement).sum() 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | use crate::util; 28 | 29 | #[test] 30 | fn fuel_required_test() { 31 | assert_eq!(fuel_required(1), 0); 32 | assert_eq!(fuel_required(12), 2); 33 | assert_eq!(fuel_required(14), 2); 34 | assert_eq!(fuel_required(1969), 654); 35 | assert_eq!(fuel_required(100_756), 33583); 36 | } 37 | 38 | #[test] 39 | fn fuel_required_with_requirement_test() { 40 | assert_eq!(fuel_required_with_requirement(12), 2); 41 | assert_eq!(fuel_required_with_requirement(1969), 966); 42 | assert_eq!(fuel_required_with_requirement(100_756), 50346); 43 | } 44 | 45 | #[test] 46 | fn part_1() { 47 | assert_eq!( 48 | Some(total_fuel_required( 49 | util::input(1).flat_map(|line| line.parse()) 50 | )), 51 | util::answer(1, 1) 52 | ); 53 | } 54 | 55 | #[test] 56 | fn part_2() { 57 | assert_eq!( 58 | Some(total_fuel_required_with_requirement( 59 | util::input(1).flat_map(|line| line.parse()) 60 | )), 61 | util::answer(1, 2), 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /2019/src/day05.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use crate::intcode::Program; 4 | use crate::util; 5 | 6 | fn get_program() -> Program { 7 | util::input(5).next().expect("No input").parse().unwrap() 8 | } 9 | 10 | #[test] 11 | fn part_1() { 12 | let mut program = get_program(); 13 | assert_eq!( 14 | program.run(&[1]).unwrap().into_iter().last(), 15 | util::answer(5, 1) 16 | ); 17 | } 18 | 19 | #[test] 20 | fn part_2() { 21 | let mut program = get_program(); 22 | assert_eq!( 23 | program.run(&[5]).unwrap().into_iter().last(), 24 | util::answer(5, 2) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /2019/src/day08.rs: -------------------------------------------------------------------------------- 1 | use itertools::iproduct; 2 | 3 | const WIDTH: usize = 25; 4 | const HEIGHT: usize = 6; 5 | 6 | fn layer(image: &[u8], n: usize) -> Option<&[u8]> { 7 | let pixels_in_layer = WIDTH * HEIGHT; 8 | if n * pixels_in_layer < image.len() { 9 | Some(&image[n * pixels_in_layer..(n + 1) * pixels_in_layer]) 10 | } else { 11 | None 12 | } 13 | } 14 | 15 | #[allow(dead_code)] 16 | fn iter_layers(image: &[u8]) -> impl Iterator { 17 | (0..) 18 | .map(move |n| layer(image, n)) 19 | .take_while(|layer| !layer.is_none()) 20 | .filter_map(|layer| layer) 21 | } 22 | 23 | #[allow(dead_code)] 24 | fn format_image(image: &[u8]) -> String { 25 | let mut result = String::new(); 26 | for (y, x) in iproduct!(0..HEIGHT, 0..WIDTH) { 27 | let pixel = iter_layers(image) 28 | .map(|layer| layer[x + y * WIDTH]) 29 | .find(|px| *px != 2); 30 | result.push(if pixel == Some(0) { ' ' } else { '#' }); 31 | if x == WIDTH - 1 { 32 | result.push('\n'); 33 | } 34 | } 35 | result 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | use crate::ocr::ocr; 42 | use crate::util; 43 | 44 | fn get_image() -> Vec { 45 | util::input(8) 46 | .flat_map(|line| line.into_bytes().into_iter().map(|b| b - b'0')) 47 | .collect() 48 | } 49 | 50 | #[test] 51 | fn part_1() { 52 | let image = get_image(); 53 | let layer = iter_layers(&image) 54 | .min_by_key(|layer| bytecount::count(layer, 0)) 55 | .expect("Layer not found"); 56 | 57 | assert_eq!( 58 | Some(bytecount::count(layer, 1) * bytecount::count(layer, 2)), 59 | util::answer(8, 1) 60 | ); 61 | } 62 | 63 | #[test] 64 | fn part_2() { 65 | let image = get_image(); 66 | let formated_image = format_image(&image); 67 | assert_eq!(Some(ocr(&formated_image)), util::answer(8, 2)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /2019/src/day09.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use crate::intcode::Program; 4 | use crate::util; 5 | 6 | fn get_program() -> Program { 7 | util::input(9).next().expect("No input").parse().unwrap() 8 | } 9 | 10 | #[test] 11 | fn complete_lintcode_test() { 12 | assert_eq!( 13 | "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99" 14 | .parse::() 15 | .unwrap() 16 | .run(&[]) 17 | .unwrap(), 18 | vec![109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99] 19 | ); 20 | assert_eq!( 21 | "1102,34915192,34915192,7,4,7,99,0" 22 | .parse::() 23 | .unwrap() 24 | .run(&[]) 25 | .unwrap(), 26 | vec![1_219_070_632_396_864] 27 | ); 28 | assert_eq!( 29 | "104,1125899906842624,99" 30 | .parse::() 31 | .unwrap() 32 | .run(&[]) 33 | .unwrap(), 34 | vec![1_125_899_906_842_624] 35 | ); 36 | } 37 | 38 | #[test] 39 | fn part_1() { 40 | let mut program = get_program(); 41 | let result = program.run(&[1]).unwrap(); 42 | assert_eq!(result.len(), 1); 43 | assert_eq!(Some(result[0]), util::answer(9, 1)); 44 | } 45 | 46 | #[test] 47 | fn part_2() { 48 | let mut program = get_program(); 49 | let result = program.run(&[2]).unwrap(); 50 | assert_eq!(result.len(), 1); 51 | assert_eq!(Some(result[0]), util::answer(9, 2)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /2019/src/day11.rs: -------------------------------------------------------------------------------- 1 | use crate::intcode::{Program, ProgramResult, Value}; 2 | use crate::point::Point; 3 | use itertools::Itertools; 4 | use std::collections::{HashMap, HashSet}; 5 | 6 | #[allow(dead_code)] 7 | fn run_robot(program: &mut Program, start_color: Value) -> HashMap { 8 | let mut point = Point::new(0, 0); 9 | let mut points = HashMap::new(); 10 | let mut direction = 0; 11 | points.insert(point, start_color); 12 | 13 | while let ProgramResult::NeedInput(output) = 14 | program.run(&[points.get(&point).cloned().unwrap_or(0)]) 15 | { 16 | points.insert(point, output[0]); 17 | direction = if output[1] == 0 { 18 | direction + 3 19 | } else { 20 | direction + 1 21 | } % 4; 22 | match direction { 23 | 0 => point.y -= 1, 24 | 1 => point.x += 1, 25 | 2 => point.y += 1, 26 | 3 => point.x -= 1, 27 | _ => unreachable!(), 28 | } 29 | } 30 | 31 | points 32 | } 33 | 34 | #[allow(dead_code)] 35 | fn format_image(points: &HashMap) -> String { 36 | let white_points: HashSet<_> = points 37 | .iter() 38 | .filter_map(|(point, color)| if *color == 1 { Some(point) } else { None }) 39 | .collect(); 40 | 41 | let (min_x, max_x) = white_points 42 | .iter() 43 | .map(|p| p.x) 44 | .minmax() 45 | .into_option() 46 | .unwrap(); 47 | let (min_y, max_y) = white_points 48 | .iter() 49 | .map(|p| p.y) 50 | .minmax() 51 | .into_option() 52 | .unwrap(); 53 | let mut result = String::new(); 54 | for y in min_y..=max_y { 55 | for x in min_x..=max_x { 56 | result.push(if white_points.contains(&Point::new(x, y)) { 57 | '#' 58 | } else { 59 | ' ' 60 | }); 61 | } 62 | result.push('\n'); 63 | } 64 | result 65 | } 66 | 67 | #[cfg(test)] 68 | mod tests { 69 | use super::*; 70 | use crate::ocr::ocr; 71 | use crate::util; 72 | 73 | fn get_program() -> Program { 74 | util::input(11).next().expect("No input").parse().unwrap() 75 | } 76 | 77 | #[test] 78 | fn part_1() { 79 | let mut program = get_program(); 80 | let points = run_robot(&mut program, 0); 81 | assert_eq!(Some(points.len()), util::answer(11, 1)); 82 | } 83 | 84 | #[test] 85 | fn part_2() { 86 | let mut program = get_program(); 87 | let points = run_robot(&mut program, 1); 88 | let formated_image = format_image(&points); 89 | assert_eq!(Some(ocr(&formated_image)), util::answer(11, 2)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /2019/src/day19.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use crate::intcode::{Program, Value}; 4 | use crate::util; 5 | use itertools::iproduct; 6 | 7 | fn get_program() -> Program { 8 | util::input(19).next().expect("No input").parse().unwrap() 9 | } 10 | 11 | fn is_in_beam(program: &Program, x: Value, y: Value) -> bool { 12 | program.clone().run(&[x, y]).get_output()[0] == 1 13 | } 14 | 15 | #[test] 16 | fn part_1() { 17 | let program = get_program(); 18 | assert_eq!( 19 | Some( 20 | iproduct!(0..50, 0..50) 21 | .filter(|(x, y)| is_in_beam(&program, *x, *y)) 22 | .count() 23 | ), 24 | util::answer(19, 1) 25 | ); 26 | } 27 | 28 | #[test] 29 | #[allow(clippy::maybe_infinite_iter)] 30 | fn part_2() { 31 | let program = get_program(); 32 | let ship_size = 100; 33 | let mut x = 0; 34 | let mut y = 0; 35 | while !is_in_beam(&program, x + ship_size - 1, y - ship_size + 1) { 36 | y += 1; 37 | x = (x..).find(|x| is_in_beam(&program, *x, y)).unwrap(); 38 | } 39 | y -= ship_size - 1; 40 | assert_eq!(Some(x * 10_000 + y), util::answer(19, 2)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /2019/src/day21.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use crate::intcode::{Program, ProgramResult, Value}; 4 | use crate::util; 5 | 6 | fn get_program() -> Program { 7 | util::input(21).next().expect("No input").parse().unwrap() 8 | } 9 | 10 | fn get_damages(result: &ProgramResult) -> Option { 11 | match result.get_output().last().cloned() { 12 | Some(last) if last > 255 => Some(last), 13 | _ => { 14 | result.print_ascii(); 15 | None 16 | } 17 | } 18 | } 19 | 20 | #[test] 21 | fn part_1() { 22 | let mut program = get_program(); 23 | 24 | // !A | !B | !C -> J 25 | program.run_str("NOT A J\n"); 26 | program.run_str("NOT B T\n"); 27 | program.run_str("OR T J\n"); 28 | program.run_str("NOT C T\n"); 29 | program.run_str("OR T J\n"); 30 | 31 | // D & J -> J 32 | program.run_str("AND D J\n"); 33 | 34 | let result = program.run_str("WALK\n"); 35 | assert_eq!(get_damages(&result), util::answer(21, 1)); 36 | } 37 | 38 | #[test] 39 | fn part_2() { 40 | let mut program = get_program(); 41 | 42 | // Goal: 43 | // !(A & B & C) & D & (H | (E & (F | I))) -> J 44 | 45 | // F | I -> J 46 | program.run_str("OR F J\n"); 47 | program.run_str("OR I J\n"); 48 | 49 | // E & J -> J 50 | program.run_str("AND E J\n"); 51 | 52 | // H | J -> J 53 | program.run_str("OR H J\n"); 54 | 55 | // D & J -> J 56 | program.run_str("AND D J\n"); 57 | 58 | // !(A & B & C) -> T 59 | program.run_str("OR A T\n"); 60 | program.run_str("AND B T\n"); 61 | program.run_str("AND C T\n"); 62 | program.run_str("NOT T T\n"); 63 | 64 | // T & J -> J 65 | program.run_str("AND T J\n"); 66 | 67 | let result = program.run_str("RUN\n"); 68 | 69 | assert_eq!(get_damages(&result), util::answer(21, 2)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /2019/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod day01; 2 | mod day02; 3 | mod day03; 4 | mod day04; 5 | mod day05; 6 | mod day06; 7 | mod day07; 8 | mod day08; 9 | mod day09; 10 | mod day10; 11 | mod day11; 12 | mod day12; 13 | mod day13; 14 | mod day14; 15 | mod day15; 16 | mod day16; 17 | mod day17; 18 | mod day18; 19 | mod day19; 20 | mod day20; 21 | mod day21; 22 | mod day22; 23 | mod day23; 24 | mod day24; 25 | mod day25; 26 | mod intcode; 27 | mod ocr; 28 | mod point; 29 | mod util; 30 | -------------------------------------------------------------------------------- /2019/src/ocr.rs: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | use std::collections::HashMap; 3 | 4 | const CHAR_WIDTH: usize = 4; 5 | lazy_static! { 6 | static ref CHARS: HashMap<&'static str, char> = { 7 | [ 8 | (" ## # ## ###### ## #", 'A'), 9 | ("### # #### # ## #### ", 'B'), 10 | ("##### ### # # ####", 'E'), 11 | ("##### ### # # # ", 'F'), 12 | (" ## # ## # ### # ###", 'G'), 13 | (" ## # # ## # ## ", 'J'), 14 | ("# # # # # ####", 'L'), 15 | ("### # ## #### # # ", 'P'), 16 | ("### # ## #### # # # #", 'R'), 17 | ("# # # # # # # ", 'Y'), 18 | ("#### # # # # ####", 'Z'), 19 | ] 20 | .iter() 21 | .cloned() 22 | .collect() 23 | }; 24 | } 25 | 26 | #[allow(dead_code)] 27 | pub fn ocr(image: &str) -> String { 28 | let image: Vec<_> = image.split('\n').filter(|line| !line.is_empty()).collect(); 29 | 30 | let height = image.len(); 31 | let width = image[0].len(); 32 | (0..width) 33 | .step_by(CHAR_WIDTH + 1) 34 | .map(|i| { 35 | let image_char: String = (0..height).map(|y| &image[y][i..i + CHAR_WIDTH]).collect(); 36 | if let Some(ch) = CHARS.get(image_char.as_str()) { 37 | ch 38 | } else { 39 | panic!("Character not found: {:?}", image_char); 40 | } 41 | }) 42 | .collect() 43 | } 44 | -------------------------------------------------------------------------------- /2019/src/point.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 2 | pub struct Point { 3 | pub x: i32, 4 | pub y: i32, 5 | } 6 | 7 | impl Point { 8 | pub fn new(x: i32, y: i32) -> Self { 9 | Self { x, y } 10 | } 11 | 12 | pub fn relative_to(self, origin: Self) -> Self { 13 | Self::new(self.x - origin.x, self.y - origin.y) 14 | } 15 | 16 | pub fn distance(self, other: Self) -> i32 { 17 | (self.x - other.x).abs() + (self.y - other.y).abs() 18 | } 19 | 20 | pub fn walk(self, direction: Direction) -> Self { 21 | match direction { 22 | Direction::North => Self::new(self.x, self.y - 1), 23 | Direction::South => Self::new(self.x, self.y + 1), 24 | Direction::East => Self::new(self.x + 1, self.y), 25 | Direction::West => Self::new(self.x - 1, self.y), 26 | } 27 | } 28 | 29 | #[allow(dead_code)] 30 | pub fn iter_nearby(self) -> impl Iterator { 31 | Direction::iter().map(move |d| self.walk(d)) 32 | } 33 | } 34 | 35 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 36 | pub enum Direction { 37 | North, 38 | East, 39 | West, 40 | South, 41 | } 42 | 43 | impl Direction { 44 | pub fn iter() -> impl Iterator { 45 | [Self::North, Self::East, Self::West, Self::South] 46 | .iter() 47 | .cloned() 48 | } 49 | 50 | pub fn left(self) -> Self { 51 | match self { 52 | Self::North => Self::West, 53 | Self::West => Self::South, 54 | Self::South => Self::East, 55 | Self::East => Self::North, 56 | } 57 | } 58 | 59 | pub fn right(self) -> Self { 60 | match self { 61 | Self::North => Self::East, 62 | Self::East => Self::South, 63 | Self::South => Self::West, 64 | Self::West => Self::North, 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /2020/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aoc-2020" 3 | version = "0.1.0" 4 | authors = ["Benoît Zugmeyer "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | native-tls = "0.2.3" 9 | itertools = "0.9.0" 10 | bytecount = "0.6.0" 11 | lazy_static = "1.4.0" 12 | -------------------------------------------------------------------------------- /2020/cache/answer_01_1: -------------------------------------------------------------------------------- 1 | 224436 -------------------------------------------------------------------------------- /2020/cache/answer_01_2: -------------------------------------------------------------------------------- 1 | 303394260 -------------------------------------------------------------------------------- /2020/cache/answer_02_1: -------------------------------------------------------------------------------- 1 | 416 -------------------------------------------------------------------------------- /2020/cache/answer_02_2: -------------------------------------------------------------------------------- 1 | 688 -------------------------------------------------------------------------------- /2020/cache/answer_03_1: -------------------------------------------------------------------------------- 1 | 220 -------------------------------------------------------------------------------- /2020/cache/answer_03_2: -------------------------------------------------------------------------------- 1 | 2138320800 -------------------------------------------------------------------------------- /2020/cache/answer_04_1: -------------------------------------------------------------------------------- 1 | 222 -------------------------------------------------------------------------------- /2020/cache/answer_04_2: -------------------------------------------------------------------------------- 1 | 140 -------------------------------------------------------------------------------- /2020/cache/answer_05_1: -------------------------------------------------------------------------------- 1 | 944 -------------------------------------------------------------------------------- /2020/cache/answer_05_2: -------------------------------------------------------------------------------- 1 | 554 -------------------------------------------------------------------------------- /2020/cache/answer_06_1: -------------------------------------------------------------------------------- 1 | 6625 -------------------------------------------------------------------------------- /2020/cache/answer_06_2: -------------------------------------------------------------------------------- 1 | 3360 -------------------------------------------------------------------------------- /2020/cache/answer_07_1: -------------------------------------------------------------------------------- 1 | 101 -------------------------------------------------------------------------------- /2020/cache/answer_07_2: -------------------------------------------------------------------------------- 1 | 108636 -------------------------------------------------------------------------------- /2020/cache/example_01_1: -------------------------------------------------------------------------------- 1 | 1721 2 | 979 3 | 366 4 | 299 5 | 675 6 | 1456 7 | -------------------------------------------------------------------------------- /2020/cache/example_02_1: -------------------------------------------------------------------------------- 1 | 1-3 a: abcde 2 | 1-3 b: cdefg 3 | 2-9 c: ccccccccc 4 | -------------------------------------------------------------------------------- /2020/cache/example_03_1: -------------------------------------------------------------------------------- 1 | ..##....... 2 | #...#...#.. 3 | .#....#..#. 4 | ..#.#...#.# 5 | .#...##..#. 6 | ..#.##..... 7 | .#.#.#....# 8 | .#........# 9 | #.##...#... 10 | #...##....# 11 | .#..#...#.# 12 | -------------------------------------------------------------------------------- /2020/cache/example_04_1: -------------------------------------------------------------------------------- 1 | ecl:gry pid:860033327 eyr:2020 hcl:#fffffd 2 | byr:1937 iyr:2017 cid:147 hgt:183cm 3 | 4 | iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 5 | hcl:#cfa07d byr:1929 6 | 7 | hcl:#ae17e1 iyr:2013 8 | eyr:2024 9 | ecl:brn pid:760753108 byr:1931 10 | hgt:179cm 11 | 12 | hcl:#cfa07d eyr:2025 pid:166559648 13 | iyr:2011 ecl:brn hgt:59in 14 | -------------------------------------------------------------------------------- /2020/cache/example_04_3: -------------------------------------------------------------------------------- 1 | eyr:1972 cid:100 2 | hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926 3 | 4 | iyr:2019 5 | hcl:#602927 eyr:1967 hgt:170cm 6 | ecl:grn pid:012533040 byr:1946 7 | 8 | hcl:dab227 iyr:2012 9 | ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277 10 | 11 | hgt:59cm ecl:zzz 12 | eyr:2038 hcl:74454a iyr:2023 13 | pid:3556412378 byr:2007 14 | -------------------------------------------------------------------------------- /2020/cache/example_04_4: -------------------------------------------------------------------------------- 1 | pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 2 | hcl:#623a2f 3 | 4 | eyr:2029 ecl:blu cid:129 byr:1989 5 | iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm 6 | 7 | hcl:#888785 8 | hgt:164cm byr:2001 iyr:2015 cid:88 9 | pid:545766238 ecl:hzl 10 | eyr:2022 11 | 12 | iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719 13 | -------------------------------------------------------------------------------- /2020/cache/example_06_1: -------------------------------------------------------------------------------- 1 | abcx 2 | abcy 3 | abcz 4 | -------------------------------------------------------------------------------- /2020/cache/example_06_2: -------------------------------------------------------------------------------- 1 | abc 2 | 3 | a 4 | b 5 | c 6 | 7 | ab 8 | ac 9 | 10 | a 11 | a 12 | a 13 | a 14 | 15 | b 16 | -------------------------------------------------------------------------------- /2020/cache/example_06_3: -------------------------------------------------------------------------------- 1 | abc 2 | 3 | a 4 | b 5 | c 6 | 7 | ab 8 | ac 9 | 10 | a 11 | a 12 | a 13 | a 14 | 15 | b 16 | -------------------------------------------------------------------------------- /2020/cache/example_07_1: -------------------------------------------------------------------------------- 1 | light red bags contain 1 bright white bag, 2 muted yellow bags. 2 | dark orange bags contain 3 bright white bags, 4 muted yellow bags. 3 | bright white bags contain 1 shiny gold bag. 4 | muted yellow bags contain 2 shiny gold bags, 9 faded blue bags. 5 | shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags. 6 | dark olive bags contain 3 faded blue bags, 4 dotted black bags. 7 | vibrant plum bags contain 5 faded blue bags, 6 dotted black bags. 8 | faded blue bags contain no other bags. 9 | dotted black bags contain no other bags. 10 | -------------------------------------------------------------------------------- /2020/cache/example_07_2: -------------------------------------------------------------------------------- 1 | shiny gold bags contain 2 dark red bags. 2 | dark red bags contain 2 dark orange bags. 3 | dark orange bags contain 2 dark yellow bags. 4 | dark yellow bags contain 2 dark green bags. 5 | dark green bags contain 2 dark blue bags. 6 | dark blue bags contain 2 dark violet bags. 7 | dark violet bags contain no other bags. 8 | -------------------------------------------------------------------------------- /2020/cache/input_01: -------------------------------------------------------------------------------- 1 | 2010 2 | 1856 3 | 1905 4 | 1786 5 | 1557 6 | 1995 7 | 1830 8 | 1971 9 | 1909 10 | 1500 11 | 1806 12 | 1846 13 | 2003 14 | 1839 15 | 1943 16 | 1977 17 | 1537 18 | 689 19 | 1861 20 | 1886 21 | 1815 22 | 1763 23 | 1834 24 | 1881 25 | 1952 26 | 1853 27 | 1775 28 | 1835 29 | 1874 30 | 1948 31 | 1978 32 | 347 33 | 1672 34 | 885 35 | 1709 36 | 1826 37 | 1911 38 | 1644 39 | 1064 40 | 1561 41 | 1966 42 | 1352 43 | 1347 44 | 1928 45 | 1756 46 | 615 47 | 1513 48 | 1932 49 | 1968 50 | 1762 51 | 1842 52 | 1475 53 | 1921 54 | 1716 55 | 1533 56 | 1975 57 | 1924 58 | 1850 59 | 1456 60 | 1783 61 | 1587 62 | 1913 63 | 1908 64 | 1502 65 | 1993 66 | 1635 67 | 1691 68 | 1706 69 | 1871 70 | 1857 71 | 1915 72 | 1604 73 | 1618 74 | 1902 75 | 1860 76 | 1648 77 | 1933 78 | 1999 79 | 1960 80 | 1389 81 | 1858 82 | 1793 83 | 1609 84 | 1484 85 | 1735 86 | 1535 87 | 1891 88 | 1879 89 | 1517 90 | 1766 91 | 1926 92 | 1668 93 | 1495 94 | 1585 95 | 1831 96 | 1308 97 | 1767 98 | 1479 99 | 1638 100 | 1600 101 | 710 102 | 1685 103 | 1818 104 | 1859 105 | 1822 106 | 1844 107 | 1550 108 | 1872 109 | 1719 110 | 1863 111 | 1987 112 | 199 113 | 1840 114 | 1817 115 | 1752 116 | 1612 117 | 1983 118 | 1838 119 | 1504 120 | 1997 121 | 716 122 | 1862 123 | 1931 124 | 1356 125 | 1645 126 | 1962 127 | 1574 128 | 1914 129 | 1869 130 | 1919 131 | 1487 132 | 1961 133 | 1728 134 | 1867 135 | 1177 136 | 1757 137 | 1316 138 | 1875 139 | 1991 140 | 1646 141 | 700 142 | 1972 143 | 2004 144 | 1577 145 | 118 146 | 1954 147 | 1483 148 | 1516 149 | 2007 150 | 1506 151 | 1588 152 | 1698 153 | 1725 154 | 2006 155 | 179 156 | 1849 157 | 1894 158 | 1695 159 | 1399 160 | 1726 161 | 1658 162 | 1920 163 | 1825 164 | 1837 165 | 1878 166 | 1591 167 | 1611 168 | 1409 169 | 1553 170 | 1705 171 | 1845 172 | 1718 173 | 1732 174 | 1639 175 | 1885 176 | 1929 177 | 1887 178 | 1787 179 | 1541 180 | 1946 181 | 1391 182 | 1884 183 | 1938 184 | 1496 185 | 1720 186 | 1669 187 | 1965 188 | 1967 189 | 1890 190 | 1743 191 | 1889 192 | 1970 193 | 1866 194 | 1912 195 | 1785 196 | 1998 197 | 1708 198 | 1810 199 | 1939 200 | 2005 -------------------------------------------------------------------------------- /2020/src/day01.rs: -------------------------------------------------------------------------------- 1 | use itertools::Itertools; 2 | 3 | #[allow(dead_code)] 4 | fn part_1>(expenses: T) -> i32 { 5 | expenses 6 | .combinations(2) 7 | .find(|t| t[0] + t[1] == 2020) 8 | .map(|t| t[0] * t[1]) 9 | .unwrap() 10 | } 11 | 12 | #[allow(dead_code)] 13 | fn part_2>(expenses: T) -> i32 { 14 | let expenses: Vec<_> = expenses.collect(); 15 | expenses 16 | .iter() 17 | .combinations(2) 18 | .find_map(|t| { 19 | if t[0] + t[1] < 2020 { 20 | expenses 21 | .iter() 22 | .find(|e| t[0] + t[1] + *e == 2020) 23 | .map(|e| *t[0] * *t[1] * *e) 24 | } else { 25 | None 26 | } 27 | }) 28 | .unwrap() 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | use crate::util; 35 | 36 | #[test] 37 | fn test() { 38 | assert_eq!( 39 | part_1(util::example(1, 1).flat_map(|line| line.parse())), 40 | 514579 41 | ); 42 | } 43 | 44 | #[test] 45 | fn test2() { 46 | assert_eq!( 47 | part_2(util::example(1, 1).flat_map(|line| line.parse())), 48 | 241861950 49 | ); 50 | } 51 | 52 | #[test] 53 | fn part_1_test() { 54 | assert_eq!( 55 | Some(part_1(util::input(1).flat_map(|line| line.parse()))), 56 | util::answer(1, 1) 57 | ); 58 | } 59 | 60 | #[test] 61 | fn part_2_test() { 62 | assert_eq!( 63 | Some(part_2(util::input(1).flat_map(|line| line.parse()))), 64 | util::answer(1, 2) 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /2020/src/day02.rs: -------------------------------------------------------------------------------- 1 | fn parse, F: Fn(usize, usize, char, &str) -> bool>( 2 | lines: T, 3 | validator: F, 4 | ) -> usize { 5 | lines 6 | .filter(|line| { 7 | dbg!(&line); 8 | let mut iter = line.split(|ch| ch == ' ' || ch == ':' || ch == '-'); 9 | let min: usize = iter.next().unwrap().parse().unwrap(); 10 | let max: usize = iter.next().unwrap().parse().unwrap(); 11 | let ch: char = iter.next().unwrap().chars().next().unwrap(); 12 | iter.next(); 13 | let password = iter.next().unwrap(); 14 | validator(min, max, ch, password) 15 | }) 16 | .count() 17 | } 18 | 19 | #[allow(dead_code)] 20 | fn part_1>(lines: T) -> usize { 21 | parse(lines, |min, max, ch, password| { 22 | let count = password.chars().filter(|chp| *chp == ch).count(); 23 | min <= count && count <= max 24 | }) 25 | } 26 | 27 | #[allow(dead_code)] 28 | fn part_2>(lines: T) -> usize { 29 | parse(lines, |position1, position2, ch, password| { 30 | matches!( 31 | ( 32 | password.chars().nth(position1 - 1), 33 | password.chars().nth(position2 - 1), 34 | ), 35 | (Some(chp), Some(other)) | (Some(other), Some(chp)) if other != ch && ch == chp 36 | ) 37 | }) 38 | } 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | use crate::util; 44 | 45 | #[test] 46 | fn test() { 47 | assert_eq!(part_1(util::example(2, 1)), 2); 48 | } 49 | 50 | #[test] 51 | fn test2() { 52 | assert_eq!(part_2(util::example(2, 1)), 1); 53 | } 54 | 55 | #[test] 56 | fn part_1_test() { 57 | assert_eq!(Some(part_1(util::input(2))), util::answer(2, 1)); 58 | } 59 | 60 | #[test] 61 | fn part_2_test() { 62 | assert_eq!(Some(part_2(util::input(2))), util::answer(2, 2)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /2020/src/day03.rs: -------------------------------------------------------------------------------- 1 | fn run_slope, T: Iterator>(lines: T, dx: usize, dy: usize) -> usize { 2 | lines 3 | .step_by(dy) 4 | .scan(0, |position, line| { 5 | let result = line.as_ref().chars().nth(*position % line.as_ref().len()); 6 | *position += dx; 7 | result 8 | }) 9 | .filter(|ch| *ch == '#') 10 | .count() 11 | } 12 | 13 | #[allow(dead_code)] 14 | fn part_1>(lines: T) -> usize { 15 | run_slope(lines, 3, 1) 16 | } 17 | 18 | #[allow(dead_code)] 19 | fn part_2>(lines: T) -> usize { 20 | let lines: Vec<_> = lines.collect(); 21 | run_slope(lines.iter(), 1, 1) 22 | * run_slope(lines.iter(), 3, 1) 23 | * run_slope(lines.iter(), 5, 1) 24 | * run_slope(lines.iter(), 7, 1) 25 | * run_slope(lines.iter(), 1, 2) 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | use crate::util; 32 | 33 | #[test] 34 | fn test() { 35 | assert_eq!(part_1(util::example(3, 1)), 7); 36 | } 37 | 38 | #[test] 39 | fn test2() { 40 | assert_eq!(part_2(util::example(3, 1)), 336); 41 | } 42 | 43 | #[test] 44 | fn part_1_test() { 45 | assert_eq!(Some(part_1(util::input(3))), util::answer(3, 1)); 46 | } 47 | 48 | #[test] 49 | fn part_2_test() { 50 | assert_eq!(Some(part_2(util::input(3))), util::answer(3, 2)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /2020/src/day05.rs: -------------------------------------------------------------------------------- 1 | fn decode_id(s: &str) -> u32 { 2 | s.chars().fold(0, |total, ch| { 3 | (total << 1) 4 | + match ch { 5 | 'B' | 'R' => 1, 6 | 'F' | 'L' => 0, 7 | _ => panic!("Unexpected character {}", ch), 8 | } 9 | }) 10 | } 11 | 12 | #[allow(dead_code)] 13 | fn part_1>(lines: T) -> Option { 14 | lines.map(|line| decode_id(&line)).max() 15 | } 16 | 17 | #[allow(dead_code)] 18 | fn part_2>(lines: T) -> Option { 19 | let mut seats: Vec<_> = lines.map(|line| decode_id(&line)).collect(); 20 | seats.sort(); 21 | seats 22 | .windows(2) 23 | .find(|couple| couple[0] + 1 != couple[1]) 24 | .map(|couple| couple[0] + 1) 25 | } 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | use crate::util; 31 | 32 | #[test] 33 | fn test() { 34 | assert_eq!(decode_id("BFFFBBFRRR"), 567); 35 | assert_eq!(decode_id("FFFBBBFRRR"), 119); 36 | assert_eq!(decode_id("BBFFBBFRLL"), 820); 37 | } 38 | 39 | #[test] 40 | fn part_1_test() { 41 | assert_eq!(part_1(util::input(5)), util::answer(5, 1)); 42 | } 43 | 44 | #[test] 45 | fn part_2_test() { 46 | assert_eq!(part_2(util::input(5)), util::answer(5, 2)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /2020/src/day06.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | #[allow(dead_code)] 4 | fn part_1>(lines: T) -> usize { 5 | lines 6 | .chain(std::iter::once(String::new())) 7 | .scan(HashSet::new(), |group, line| { 8 | Some(if line.is_empty() { 9 | Some(std::mem::replace(group, HashSet::new())) 10 | } else { 11 | for ch in line.chars() { 12 | group.insert(ch); 13 | } 14 | None 15 | }) 16 | }) 17 | .flatten() 18 | .map(|group| group.len()) 19 | .sum() 20 | } 21 | 22 | #[allow(dead_code)] 23 | fn part_2>(lines: T) -> usize { 24 | lines 25 | .chain(std::iter::once(String::new())) 26 | .scan(Option::>::None, |group, line| { 27 | Some(if line.is_empty() { 28 | group.take() 29 | } else { 30 | let line_group: HashSet<_> = line.chars().collect(); 31 | if let Some(group) = group { 32 | group.retain(|ch| line_group.contains(ch)); 33 | } else { 34 | *group = Some(line_group); 35 | } 36 | None 37 | }) 38 | }) 39 | .flatten() 40 | .map(|group| group.len()) 41 | .sum() 42 | } 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | use super::*; 47 | use crate::util; 48 | 49 | #[test] 50 | fn test() { 51 | assert_eq!(part_1(util::example(6, 1)), 6); 52 | } 53 | 54 | #[test] 55 | fn test2() { 56 | assert_eq!(part_1(util::example(6, 2)), 11); 57 | } 58 | 59 | #[test] 60 | fn test3() { 61 | assert_eq!(part_2(util::example(6, 3)), 6); 62 | } 63 | 64 | #[test] 65 | fn part_1_test() { 66 | assert_eq!(Some(part_1(util::input(6))), util::answer(6, 1)); 67 | } 68 | 69 | #[test] 70 | fn part_2_test() { 71 | assert_eq!(Some(part_2(util::input(6))), util::answer(6, 2)); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /2020/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod day01; 2 | mod day02; 3 | mod day03; 4 | mod day04; 5 | mod day05; 6 | mod day06; 7 | mod day07; 8 | mod util; 9 | -------------------------------------------------------------------------------- /2020/src/point.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 2 | pub struct Point { 3 | pub x: i32, 4 | pub y: i32, 5 | } 6 | 7 | impl Point { 8 | pub fn new(x: i32, y: i32) -> Self { 9 | Self { x, y } 10 | } 11 | 12 | pub fn relative_to(self, origin: Self) -> Self { 13 | Self::new(self.x - origin.x, self.y - origin.y) 14 | } 15 | 16 | pub fn distance(self, other: Self) -> i32 { 17 | (self.x - other.x).abs() + (self.y - other.y).abs() 18 | } 19 | 20 | pub fn walk(self, direction: Direction) -> Self { 21 | match direction { 22 | Direction::North => Self::new(self.x, self.y - 1), 23 | Direction::South => Self::new(self.x, self.y + 1), 24 | Direction::East => Self::new(self.x + 1, self.y), 25 | Direction::West => Self::new(self.x - 1, self.y), 26 | } 27 | } 28 | 29 | #[allow(dead_code)] 30 | pub fn iter_nearby(self) -> impl Iterator { 31 | Direction::iter().map(move |d| self.walk(d)) 32 | } 33 | } 34 | 35 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 36 | pub enum Direction { 37 | North, 38 | East, 39 | West, 40 | South, 41 | } 42 | 43 | impl Direction { 44 | pub fn iter() -> impl Iterator { 45 | [Self::North, Self::East, Self::West, Self::South] 46 | .iter() 47 | .cloned() 48 | } 49 | 50 | pub fn left(self) -> Self { 51 | match self { 52 | Self::North => Self::West, 53 | Self::West => Self::South, 54 | Self::South => Self::East, 55 | Self::East => Self::North, 56 | } 57 | } 58 | 59 | pub fn right(self) -> Self { 60 | match self { 61 | Self::North => Self::East, 62 | Self::East => Self::South, 63 | Self::South => Self::West, 64 | Self::West => Self::North, 65 | } 66 | } 67 | } 68 | --------------------------------------------------------------------------------