├── rustfmt.toml ├── docs ├── index.html ├── logo.png └── pie-2015.svg ├── .gitignore ├── tests ├── year2021 │ ├── day24.rs │ ├── day06.rs │ ├── day07.rs │ ├── day17.rs │ ├── day12.rs │ ├── day02.rs │ ├── day09.rs │ ├── day01.rs │ ├── day21.rs │ ├── day23.rs │ ├── day03.rs │ ├── day25.rs │ ├── day05.rs │ ├── day11.rs │ ├── day15.rs │ ├── day14.rs │ ├── day10.rs │ ├── day13.rs │ ├── day04.rs │ ├── day18.rs │ ├── day20.rs │ ├── day08.rs │ └── day16.rs ├── year2024 │ ├── day14.rs │ ├── day18.rs │ ├── day20.rs │ ├── day11.rs │ ├── day09.rs │ ├── day01.rs │ ├── day21.rs │ ├── day02.rs │ ├── day10.rs │ ├── day19.rs │ ├── day22.rs │ ├── day04.rs │ ├── day06.rs │ ├── day08.rs │ ├── day03.rs │ ├── day17.rs │ ├── day05.rs │ ├── day13.rs │ ├── day23.rs │ ├── day12.rs │ ├── day16.rs │ ├── day25.rs │ ├── day07.rs │ ├── day24.rs │ └── day15.rs ├── year2015 │ ├── day16.rs │ ├── day17.rs │ ├── day18.rs │ ├── day19.rs │ ├── day20.rs │ ├── day21.rs │ ├── day22.rs │ ├── day23.rs │ ├── day25.rs │ ├── day01.rs │ ├── day03.rs │ ├── day04.rs │ ├── day10.rs │ ├── day24.rs │ ├── day02.rs │ ├── day11.rs │ ├── day12.rs │ ├── day08.rs │ ├── day09.rs │ ├── day07.rs │ ├── day14.rs │ ├── day06.rs │ ├── day05.rs │ ├── day15.rs │ └── day13.rs ├── year2016 │ ├── day05.rs │ ├── day08.rs │ ├── day10.rs │ ├── day13.rs │ ├── day16.rs │ ├── day18.rs │ ├── day22.rs │ ├── day23.rs │ ├── day25.rs │ ├── day19.rs │ ├── day14.rs │ ├── day09.rs │ ├── day17.rs │ ├── day20.rs │ ├── day02.rs │ ├── day03.rs │ ├── day01.rs │ ├── day04.rs │ ├── day24.rs │ ├── day15.rs │ ├── day06.rs │ ├── day07.rs │ ├── day11.rs │ ├── day21.rs │ └── day12.rs ├── year2017 │ ├── day06.rs │ ├── day16.rs │ ├── day18.rs │ ├── day21.rs │ ├── day17.rs │ ├── day23.rs │ ├── day11.rs │ ├── day14.rs │ ├── day05.rs │ ├── day10.rs │ ├── day22.rs │ ├── day13.rs │ ├── day01.rs │ ├── day03.rs │ ├── day15.rs │ ├── day24.rs │ ├── day08.rs │ ├── day09.rs │ ├── day12.rs │ ├── day02.rs │ ├── day20.rs │ ├── day19.rs │ ├── day04.rs │ ├── day07.rs │ └── day25.rs ├── year2018 │ ├── day10.rs │ ├── day16.rs │ ├── day18.rs │ ├── day19.rs │ ├── day21.rs │ ├── day05.rs │ ├── day11.rs │ ├── day14.rs │ ├── day01.rs │ ├── day08.rs │ ├── day22.rs │ ├── day03.rs │ ├── day09.rs │ ├── day20.rs │ ├── day06.rs │ ├── day15.rs │ ├── day25.rs │ ├── day17.rs │ ├── day02.rs │ ├── day12.rs │ ├── day13.rs │ ├── day07.rs │ ├── day23.rs │ ├── day24.rs │ └── day04.rs ├── year2019 │ ├── day07.rs │ ├── day08.rs │ ├── day11.rs │ ├── day13.rs │ ├── day15.rs │ ├── day17.rs │ ├── day19.rs │ ├── day21.rs │ ├── day23.rs │ ├── day25.rs │ ├── day01.rs │ ├── day04.rs │ ├── day03.rs │ ├── day24.rs │ ├── day12.rs │ ├── day16.rs │ ├── day09.rs │ ├── day06.rs │ ├── day22.rs │ ├── day05.rs │ ├── day14.rs │ ├── day18.rs │ ├── day02.rs │ └── day10.rs ├── year2023 │ ├── day20.rs │ ├── day21.rs │ ├── day23.rs │ ├── day15.rs │ ├── day06.rs │ ├── day09.rs │ ├── day07.rs │ ├── day24.rs │ ├── day22.rs │ ├── day12.rs │ ├── day14.rs │ ├── day03.rs │ ├── day11.rs │ ├── day16.rs │ ├── day13.rs │ ├── day17.rs │ ├── day01.rs │ ├── day25.rs │ ├── day10.rs │ ├── day18.rs │ ├── day04.rs │ ├── day08.rs │ ├── day02.rs │ ├── day19.rs │ └── day05.rs ├── year2025 │ ├── day12.rs │ ├── day09.rs │ ├── day01.rs │ ├── day05.rs │ ├── day06.rs │ ├── day03.rs │ ├── day10.rs │ ├── day04.rs │ ├── day02.rs │ ├── day07.rs │ ├── day08.rs │ └── day11.rs ├── year2020 │ ├── day15.rs │ ├── day23.rs │ ├── day17.rs │ ├── day05.rs │ ├── day13.rs │ ├── day25.rs │ ├── day12.rs │ ├── day02.rs │ ├── day01.rs │ ├── day09.rs │ ├── day06.rs │ ├── day10.rs │ ├── day08.rs │ ├── day22.rs │ ├── day11.rs │ ├── day21.rs │ ├── day18.rs │ ├── day14.rs │ ├── day16.rs │ ├── day07.rs │ ├── day24.rs │ ├── day03.rs │ ├── day19.rs │ └── day04.rs └── year2022 │ ├── day06.rs │ ├── day02.rs │ ├── day17.rs │ ├── day08.rs │ ├── day20.rs │ ├── day12.rs │ ├── day14.rs │ ├── day09.rs │ ├── day04.rs │ ├── day24.rs │ ├── day23.rs │ ├── day01.rs │ ├── day25.rs │ ├── day18.rs │ ├── day05.rs │ ├── day03.rs │ ├── day22.rs │ ├── day21.rs │ ├── day13.rs │ ├── day07.rs │ ├── day19.rs │ ├── day16.rs │ ├── day11.rs │ └── day15.rs ├── justfile ├── src ├── year2025 │ ├── day12.rs │ ├── day07.rs │ ├── day03.rs │ ├── day01.rs │ ├── day05.rs │ ├── day06.rs │ ├── day11.rs │ ├── day02.rs │ └── day04.rs ├── util │ ├── ansi.rs │ ├── bitset.rs │ └── integer.rs ├── year2015 │ ├── day01.rs │ ├── day02.rs │ ├── day03.rs │ └── day16.rs ├── year2019 │ ├── day09.rs │ ├── day05.rs │ ├── day01.rs │ └── day21.rs ├── year2017 │ ├── day01.rs │ ├── day09.rs │ ├── day02.rs │ ├── day19.rs │ ├── day08.rs │ └── day17.rs ├── year2016 │ ├── day03.rs │ ├── day20.rs │ ├── day06.rs │ ├── day02.rs │ ├── day09.rs │ ├── day25.rs │ ├── day15.rs │ └── day23.rs ├── year2020 │ ├── day03.rs │ ├── day05.rs │ └── day10.rs ├── year2022 │ ├── day02.rs │ ├── day01.rs │ ├── day10.rs │ └── day04.rs ├── year2024 │ ├── day01.rs │ ├── day25.rs │ └── day05.rs ├── year2021 │ ├── day06.rs │ ├── day01.rs │ └── day07.rs ├── year2023 │ ├── day04.rs │ └── day02.rs └── year2018 │ └── day02.rs ├── .github └── workflows │ ├── checks.yml │ └── docs.yml └── LICENSE.md /rustfmt.toml: -------------------------------------------------------------------------------- 1 | use_small_heuristics = "Max" 2 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maneatingape/advent-of-code-rust/HEAD/docs/logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Cargo 2 | target/ 3 | Cargo.lock 4 | 5 | # macOS 6 | .DS_Store 7 | 8 | # Don't commit input files 9 | input 10 | -------------------------------------------------------------------------------- /tests/year2021/day24.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No test 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No test 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2024/day14.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No test 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No test 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2024/day18.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No test 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No test 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2024/day20.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No test 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No test 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day16.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day17.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day18.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day19.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day20.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day21.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day22.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day23.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2015/day25.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day05.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day08.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day10.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day13.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day16.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day18.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day22.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day23.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day25.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2017/day06.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2017/day16.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2017/day18.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2017/day21.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2018/day10.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2018/day16.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2018/day18.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2018/day19.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2018/day21.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day07.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day08.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day11.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day13.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day15.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day17.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day19.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day21.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day23.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2019/day25.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2023/day20.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2023/day21.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // No example data 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // No example data 9 | } 10 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | lint: 2 | cargo fmt -- `find . -name "*.rs"` 3 | cargo clippy --all-targets --all-features 4 | 5 | docs: 6 | cargo doc --document-private-items --open 7 | -------------------------------------------------------------------------------- /tests/year2025/day12.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // Specific to real actual input. 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // Not applicable. 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2023/day23.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn part1_test() { 3 | // Dependent on actual input structure. 4 | } 5 | 6 | #[test] 7 | fn part2_test() { 8 | // Dependent on actual input structure. 9 | } 10 | -------------------------------------------------------------------------------- /tests/year2016/day19.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day19::*; 2 | 3 | const EXAMPLE: &str = "5"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 3); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 2); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day01::*; 2 | 3 | const EXAMPLE: &str = "()())"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), -1); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 5); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day03::*; 2 | 3 | const EXAMPLE: &str = "^v^v^v^v^v"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 2); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 11); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day04::*; 2 | 3 | const EXAMPLE: &str = "cxsaadws"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 218); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 455); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day10::*; 2 | 3 | const EXAMPLE: &str = "12"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 124496); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 1766402); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2016/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day14::*; 2 | 3 | const EXAMPLE: &str = "abc"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(input), 22728); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(input), 22551); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2017/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day17::*; 2 | 3 | const EXAMPLE: &str = "3"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 638); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 1222153); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2017/day23.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day23::*; 2 | 3 | const EXAMPLE: &str = "123"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 14641); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 913); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2020/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day15::*; 2 | 3 | const EXAMPLE: &str = "0,3,6"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 436); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 175594); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2016/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day09::*; 2 | 3 | const EXAMPLE: &str = "X(8x2)(3x3)ABCY"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(input), 18); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(input), 20); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2016/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day17::*; 2 | 3 | const EXAMPLE: &str = "ihgpwlah"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), "DDRRRD"); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 370); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2017/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day11::*; 2 | 3 | const EXAMPLE: &str = "se,sw,se,sw,sw,s,n"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 3); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 4); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2017/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day14::*; 2 | 3 | const EXAMPLE: &str = "flqrgnkx"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 8108); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 1242); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2018/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day05::*; 2 | 3 | const EXAMPLE: &str = "dabAcCaCBAcCcaDA"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 10); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 4); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2018/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day11::*; 2 | 3 | const EXAMPLE: &str = "18"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), "33,45"); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), "90,269,16"); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2019/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day01::*; 2 | 3 | const EXAMPLE: &str = "100756"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 33583); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 50346); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2019/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day04::*; 2 | 3 | const EXAMPLE: &str = "100000-200000"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 1231); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 898); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day24::*; 2 | 3 | const EXAMPLE: &str = "1 2 3 4 5 7 8 9 10 11"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 99); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 44); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2018/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day14::*; 2 | 3 | const EXAMPLE: &str = "594142"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), "1291321443"); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 2018); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2021/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day06::*; 2 | 3 | const EXAMPLE: &str = "3,4,3,1,2"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 5934); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 26984457539); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2024/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day11::*; 2 | 3 | const EXAMPLE: &str = "125 17"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 55312); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 65601038650482); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 2x3x4 5 | 1x1x10"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 101); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 48); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2015/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day11::*; 2 | 3 | const EXAMPLE: &str = "ghijklmn"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), "ghjaabcc"); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), "ghjbbcdd"); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2015/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day12::*; 2 | 3 | const EXAMPLE: &str = r#"[1,{"c":"red","b":2},3]"#; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(input), 6); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(input), 4); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2020/day23.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day23::*; 2 | 3 | const EXAMPLE: &str = "389125467"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 67384529); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 149245887792); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2021/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day07::*; 2 | 3 | const EXAMPLE: &str = "16,1,2,0,4,2,7,1,2,14"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 37); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 168); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2024/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day09::*; 2 | 3 | const EXAMPLE: &str = "2333133121414131402"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 1928); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 2858); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2018/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day01::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | +1 5 | -2 6 | +3 7 | +1"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 3); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 2); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2020/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day17::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | .#. 5 | ..# 6 | ###"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 112); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 848); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2022/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day06::*; 2 | 3 | const EXAMPLE: &str = "mjqjpqmgbljsphdztnvjfqwrcgsmlb"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(input), 7); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(input), 19); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2017/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 0 5 | 3 6 | 0 7 | 1 8 | -3"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 5); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 10); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2017/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day10::*; 2 | 3 | const EXAMPLE: &str = "1,2,3"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(input), 0); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(input), "3efbe78a8d82f29979031a4aa0b16a9d"); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2017/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day22::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ..# 5 | #.. 6 | ..."; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 5587); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 2511944); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2018/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day08::*; 2 | 3 | const EXAMPLE: &str = "2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 138); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 66); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2019/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | R8,U5,L5,D3 5 | U7,R6,D4,L4"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 6); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 30); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2020/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | FBFBBFFLRR 5 | FBFBBFFRLR"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 357); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 356); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2021/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day17::*; 2 | 3 | const EXAMPLE: &str = "target area: x=20..30, y=-10..-5"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 45); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 112); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2022/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | A Y 5 | B X 6 | C Z 7 | "; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 15); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 12); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2017/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 0: 3 5 | 1: 2 6 | 4: 4 7 | 6: 4"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 24); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 10); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2018/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day22::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | depth: 510 5 | target: 10,10"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 114); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 45); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2020/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 939 5 | 7,13,x,x,59,x,31,19"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 295); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 1068781); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2020/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 5764801 5 | 17807724"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 14897079); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), "n/a"); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2016/day20.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day20::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 5-8 5 | 0-2 6 | 4-7 7 | 10-4294967295"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 3); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 2); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2020/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | F10 5 | N3 6 | F7 7 | R90 8 | F11"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 25); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 286); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2015/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day08::*; 2 | 3 | const EXAMPLE: &str = r#""" 4 | "abc" 5 | "aaa\"aaa" 6 | "\x27" 7 | "#; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(input), 12); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(input), 19); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2016/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ULL 5 | RRDDD 6 | LURDL 7 | UUUUD"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), "1985"); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), "5DB3"); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2016/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 101 201 301 5 | 102 102 402 6 | 203 203 303"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 2); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 2); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2022/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day17::*; 2 | 3 | const EXAMPLE: &str = ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(input), 3068); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(input), 1514285714288); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2018/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | #1 @ 1,3: 4x4 5 | #2 @ 3,1: 4x4 6 | #3 @ 5,5: 2x2"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 4); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 3); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2018/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day09::*; 2 | 3 | const EXAMPLE: &str = "10 players; last marble is worth 1618 points"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 8317); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 74765078); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2022/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day08::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 30373 5 | 25512 6 | 65332 7 | 33549 8 | 35390"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 21); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 8); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2023/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day15::*; 2 | 3 | const EXAMPLE: &str = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 1320); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 145); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2020/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1-3 a: abcde 5 | 1-3 b: cdefg 6 | 2-9 c: ccccccccc"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 2); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 1); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2022/day20.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day20::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1 5 | 2 6 | -3 7 | 3 8 | -2 9 | 0 10 | 4"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 3); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 1623178306); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2023/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Time: 7 15 30 5 | Distance: 9 40 200"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 288); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 71503); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2018/day20.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day20::*; 2 | 3 | const EXAMPLE: &str = "^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$"; 4 | 5 | #[test] 6 | fn part1_test() { 7 | let input = parse(EXAMPLE); 8 | assert_eq!(part1(&input), 31); 9 | } 10 | 11 | #[test] 12 | fn part2_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part2(&input), 0); 15 | } 16 | -------------------------------------------------------------------------------- /tests/year2023/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day09::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 0 3 6 9 12 15 5 | 1 3 6 10 15 21 6 | 10 13 16 21 30 45"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 114); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 2); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2017/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day01::*; 2 | 3 | const FIRST_EXAMPLE: &str = "1122"; 4 | 5 | const SECOND_EXAMPLE: &str = "1212"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(FIRST_EXAMPLE); 10 | assert_eq!(part1(input), 3); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(SECOND_EXAMPLE); 16 | assert_eq!(part2(input), 6); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2017/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day03::*; 2 | 3 | const FIRST_EXAMPLE: &str = "1024"; 4 | 5 | const SECOND_EXAMPLE: &str = "805"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(FIRST_EXAMPLE); 10 | assert_eq!(part1(&input), 31); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(SECOND_EXAMPLE); 16 | assert_eq!(part2(&input), 806); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2017/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Generator A starts with 65 5 | Generator B starts with 8921"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 588); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 309); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2020/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day01::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1721 5 | 979 6 | 366 7 | 299 8 | 675 9 | 1456"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 514579); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 241861950); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2022/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Sabqponm 5 | abcryxxl 6 | accszExk 7 | acctuvwj 8 | abdefghi"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 31); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 29); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2022/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day14::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 498,4 -> 498,6 -> 496,6 5 | 503,4 -> 502,4 -> 502,9 -> 494,9"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 24); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 93); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2024/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day01::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 3 4 5 | 4 3 6 | 2 5 7 | 1 3 8 | 3 9 9 | 3 3"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 11); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 31); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2024/day21.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day21::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 029A 5 | 980A 6 | 179A 7 | 456A 8 | 379A"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 126384); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 154115708116294); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2017/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 0/2 5 | 2/2 6 | 2/3 7 | 3/4 8 | 3/5 9 | 0/1 10 | 10/1 11 | 9/10"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part1(&input), 31); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part2(&input), 19); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2018/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1, 1 5 | 1, 6 6 | 8, 3 7 | 3, 4 8 | 5, 5 9 | 8, 9"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 17); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2_testable(&input, 32), 16); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2019/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ....# 5 | #..#. 6 | #..## 7 | ..#.. 8 | #...."; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 2129920); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2_testable(&input, 10), 99); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2021/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | start-A 5 | start-b 6 | A-c 7 | A-b 8 | b-d 9 | A-end 10 | b-end"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 10); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 36); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2022/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day09::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | R 4 5 | U 4 6 | L 3 7 | D 1 8 | R 4 9 | D 1 10 | L 5 11 | R 2"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part1(&input), 13); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part2(&input), 1); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2025/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day09::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 7,1 5 | 11,1 6 | 11,7 7 | 9,7 8 | 9,5 9 | 2,5 10 | 2,3 11 | 7,3"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part1(&input), 50); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part2(&input), 24); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2022/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 2-4,6-8 5 | 2-3,4-5 6 | 5-7,7-9 7 | 2-8,3-7 8 | 6-6,4-6 9 | 2-6,4-8"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 2); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 4); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2023/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 32T3K 765 5 | T55J5 684 6 | KK677 28 7 | KTJJT 220 8 | QQQJA 483"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 6440); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 5905); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2016/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day01::*; 2 | 3 | const FIRST_EXAMPLE: &str = "R5, L5, R5, R3"; 4 | const SECOND_EXAMPLE: &str = "R8, R4, R4, R8"; 5 | 6 | #[test] 7 | fn part1_test() { 8 | let input = parse(FIRST_EXAMPLE); 9 | assert_eq!(part1(&input), 12); 10 | } 11 | 12 | #[test] 13 | fn part2_test() { 14 | let input = parse(SECOND_EXAMPLE); 15 | assert_eq!(part2(&input), 4); 16 | } 17 | -------------------------------------------------------------------------------- /tests/year2016/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | aaaaa-bbb-z-y-x-123[abxyz] 5 | a-b-c-d-e-f-g-h-987[abcde] 6 | not-a-real-room-404[oarel] 7 | totally-real-room-200[decoy]"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 1514); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | // No example data 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2016/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ########### 5 | #0.1.....2# 6 | #.#######.# 7 | #4.......3# 8 | ###########"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 14); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 20); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2021/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | forward 5 5 | down 5 6 | forward 8 7 | up 3 8 | down 8 9 | forward 2"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 150); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 900); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2021/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day09::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 2199943210 5 | 3987894921 6 | 9856789892 7 | 8767896789 8 | 9899965678"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 15); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 1134); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2022/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | #.###### 5 | #>>.<^<# 6 | #.<..<<# 7 | #>v.><># 8 | #<^v^^># 9 | ######.#"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 18); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 54); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2015/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day09::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | London to Dublin = 464 5 | London to Belfast = 518 6 | Dublin to Belfast = 141"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 605); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 982); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2021/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day01::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 199 5 | 200 6 | 208 7 | 210 8 | 200 9 | 207 10 | 240 11 | 269 12 | 260 13 | 263"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 7); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 5); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2021/day21.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day21::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Player 1 starting position: 4 5 | Player 2 starting position: 8"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 739785); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 444356092776315); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2024/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 7 6 4 2 1 5 | 1 2 7 8 9 6 | 9 7 6 2 1 7 | 1 3 2 4 5 8 | 8 6 4 4 1 9 | 1 3 6 7 9"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 2); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 4); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2025/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day01::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | L68 5 | L30 6 | R48 7 | L5 8 | R60 9 | L55 10 | L1 11 | L99 12 | R14 13 | L82"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 3); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 6); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2017/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day08::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | b inc 5 if a > 1 5 | a inc 1 if b < 5 6 | c dec -10 if a >= 1 7 | c inc -20 if c == 10"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 1); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 10); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2022/day23.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day23::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ....#.. 5 | ..###.# 6 | #...#.# 7 | .#...## 8 | #.###.. 9 | ##.#.## 10 | .#..#.."; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 110); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 20); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2025/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 3-5 5 | 10-14 6 | 16-20 7 | 12-18 8 | 9 | 1 10 | 5 11 | 8 12 | 11 13 | 17 14 | 32"; 15 | 16 | #[test] 17 | fn part1_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part1(&input), 3); 20 | } 21 | 22 | #[test] 23 | fn part2_test() { 24 | let input = parse(EXAMPLE); 25 | assert_eq!(part2(&input), 14); 26 | } 27 | -------------------------------------------------------------------------------- /tests/year2025/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 123 328 51 64 5 | 45 64 387 23 6 | 6 98 215 314 7 | * + * + "; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 4277556); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 3263827); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2018/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ####### 5 | #.G...# 6 | #...EG# 7 | #.#.#G# 8 | #..G#E# 9 | #.....# 10 | #######"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 27730); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 4988); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2020/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day09::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 35 20 15 25 47 5 | 40 62 55 65 95 6 | 102 117 150 182 127 7 | 219 299 277 309 576"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let result = decrypt::<5>(EXAMPLE); 12 | assert_eq!(result.0, 127); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let result = decrypt::<5>(EXAMPLE); 18 | assert_eq!(result.1, 62); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2021/day23.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day23::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ############# 5 | #...........# 6 | ###B#C#B#D### 7 | #A#D#C#A# 8 | #########"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 12521); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 44169); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2023/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 19, 13, 30 @ -2, 1, -2 5 | 18, 19, 22 @ -1, -1, -2 6 | 20, 25, 34 @ -2, -2, -4 7 | 12, 31, 28 @ -1, -2, -1 8 | 20, 19, 15 @ 1, -5, -3"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | // No example data 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 47); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2025/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 987654321111111 5 | 811111111111119 6 | 234234234234278 7 | 818181911112111"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 357); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 3121910778619); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2017/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day09::*; 2 | 3 | const FIRST_EXAMPLE: &str = "{{},{},{},{}}"; 4 | 5 | const SECOND_EXAMPLE: &str = "<{o\"i!a,<{i"; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(FIRST_EXAMPLE); 10 | assert_eq!(part1(&input), 3); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(SECOND_EXAMPLE); 16 | assert_eq!(part2(&input), 10); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2019/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day12::*; 2 | 3 | const EXAMPLE: &str = " 4 | 5 | 6 | 7 | "; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 14645); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 4686774924); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2020/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | abc 5 | 6 | a 7 | b 8 | c 9 | 10 | ab 11 | ac 12 | 13 | a 14 | a 15 | a 16 | a 17 | 18 | b"; 19 | 20 | #[test] 21 | fn part1_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part1(&input), 11); 24 | } 25 | 26 | #[test] 27 | fn part2_test() { 28 | let input = parse(EXAMPLE); 29 | assert_eq!(part2(&input), 6); 30 | } 31 | -------------------------------------------------------------------------------- /tests/year2020/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day10::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 28 33 18 42 31 14 46 20 48 47 5 | 24 23 49 45 19 38 39 11 1 32 6 | 25 35 8 17 7 9 4 2 34 10 3"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 220); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 19208); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2017/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 0 <-> 2 5 | 1 <-> 1 6 | 2 <-> 0, 3, 4 7 | 3 <-> 2, 4 8 | 4 <-> 2, 3, 6 9 | 5 <-> 6 10 | 6 <-> 4, 5"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 6); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 2); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2020/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day08::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | nop +0 5 | acc +1 6 | jmp +4 7 | acc +3 8 | jmp -3 9 | acc -99 10 | acc +1 11 | jmp -4 12 | acc +6"; 13 | 14 | #[test] 15 | fn part1_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part1(&input), 5); 18 | } 19 | 20 | #[test] 21 | fn part2_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part2(&input), 8); 24 | } 25 | -------------------------------------------------------------------------------- /tests/year2020/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day22::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Player 1: 5 | 9 6 | 2 7 | 6 8 | 3 9 | 1 10 | 11 | Player 2: 12 | 5 13 | 8 14 | 4 15 | 7 16 | 10"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), 306); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), 291); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2024/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day10::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 89010123 5 | 78121874 6 | 87430965 7 | 96549874 8 | 45678903 9 | 32019012 10 | 01329801 11 | 10456732"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part1(&input), 36); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part2(&input), 81); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2023/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day22::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1,0,1~1,2,1 5 | 0,0,2~2,0,2 6 | 0,2,3~2,2,3 7 | 0,0,4~0,2,4 8 | 2,0,5~2,2,5 9 | 0,1,6~2,1,6 10 | 1,1,8~1,1,9"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 5); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 7); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2016/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Disc #1 has 5 positions; at time=0, it is at position 4. 5 | Disc #2 has 2 positions; at time=0, it is at position 1."; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1(&input), 5); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2(&input), 85); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2024/day19.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day19::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | r, wr, b, g, bwu, rb, gb, br 5 | 6 | brwrr 7 | bggr 8 | gbbr 9 | rrbgbr 10 | ubwu 11 | bwurrg 12 | brgr 13 | bbrgwb"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 6); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 16); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2019/day16.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day16::*; 2 | 3 | const FIRST_EXAMPLE: &str = "80871224585914546619083218645595"; 4 | const SECOND_EXAMPLE: &str = "03036732577212944063491565474664"; 5 | 6 | #[test] 7 | fn part1_test() { 8 | let input = parse(FIRST_EXAMPLE); 9 | assert_eq!(part1(&input), 24176176); 10 | } 11 | 12 | #[test] 13 | fn part2_test() { 14 | let input = parse(SECOND_EXAMPLE); 15 | assert_eq!(part2(&input), 84462026); 16 | } 17 | -------------------------------------------------------------------------------- /tests/year2021/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 00100 5 | 11110 6 | 10110 7 | 10111 8 | 10101 9 | 01111 10 | 00111 11 | 11100 12 | 10000 13 | 11001 14 | 00010 15 | 01010"; 16 | 17 | #[test] 18 | fn part1_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part1(&input), 198); 21 | } 22 | 23 | #[test] 24 | fn part2_test() { 25 | let input = parse(EXAMPLE); 26 | assert_eq!(part2(&input), 230); 27 | } 28 | -------------------------------------------------------------------------------- /tests/year2022/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day01::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1000 5 | 2000 6 | 3000 7 | 8 | 4000 9 | 10 | 5000 11 | 6000 12 | 13 | 7000 14 | 8000 15 | 9000 16 | 17 | 10000"; 18 | 19 | #[test] 20 | fn part1_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part1(&input), 24000); 23 | } 24 | 25 | #[test] 26 | fn part2_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part2(&input), 45000); 29 | } 30 | -------------------------------------------------------------------------------- /tests/year2022/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1=-0-2 5 | 12111 6 | 2=0= 7 | 21 8 | 2=01 9 | 111 10 | 20012 11 | 112 12 | 1=-1= 13 | 1-12 14 | 12 15 | 1= 16 | 122"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), "2=-1=0"); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), "n/a"); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2024/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day22::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | 1 5 | 10 6 | 100 7 | 2024"; 8 | 9 | const SECOND_EXAMPLE: &str = "\ 10 | 1 11 | 2 12 | 3 13 | 2024"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(FIRST_EXAMPLE); 18 | assert_eq!(part1(&input), 37327623); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(SECOND_EXAMPLE); 24 | assert_eq!(part2(&input), 23); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2017/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day02::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | 5 1 9 5 5 | 7 5 3 6 | 2 4 6 8"; 7 | 8 | const SECOND_EXAMPLE: &str = "\ 9 | 5 9 2 8 10 | 9 4 7 3 11 | 3 8 6 5"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(FIRST_EXAMPLE); 16 | assert_eq!(part1(&input), 18); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(SECOND_EXAMPLE); 22 | assert_eq!(part2(&input), 9); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2015/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 123 -> b 5 | 456 -> c 6 | b AND c -> d 7 | b OR c -> e 8 | d LSHIFT 2 -> f 9 | e RSHIFT 2 -> g 10 | f OR g -> h 11 | NOT h -> a"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part1(&input), 65153); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part2(&input), 49165); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2018/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1,-1,0,1 5 | 2,0,-1,0 6 | 3,2,-1,0 7 | 0,0,3,1 8 | 0,0,-1,-1 9 | 2,3,-2,0 10 | -2,2,0,0 11 | 2,-2,0,-1 12 | 1,-1,0,-1 13 | 3,2,0,2"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 3); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), "n/a"); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2022/day18.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day18::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 2,2,2 5 | 1,2,2 6 | 3,2,2 7 | 2,1,2 8 | 2,3,2 9 | 2,2,1 10 | 2,2,3 11 | 2,2,4 12 | 2,2,6 13 | 1,2,5 14 | 3,2,5 15 | 2,1,5 16 | 2,3,5"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), 64); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), 58); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2021/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | v...>>.vv> 5 | .vv>>.vv.. 6 | >>.>v>...v 7 | >>v>>.>.v. 8 | v>v.vv.v.. 9 | >.>>..v... 10 | .vv..>.>v. 11 | v.v..>>v.v 12 | ....v..v.>"; 13 | 14 | #[test] 15 | fn part1_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part1(&input), 58); 18 | } 19 | 20 | #[test] 21 | fn part2_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part2(&input), "n/a"); 24 | } 25 | -------------------------------------------------------------------------------- /tests/year2025/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day10::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} 5 | [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} 6 | [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 7); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | // No working part two yet. 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2017/day20.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day20::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | p=<-6,0,0>, v=< 3,0,0>, a=< 0,0,0> 5 | p=<-4,0,0>, v=< 2,0,0>, a=< 0,0,0> 6 | p=<-2,0,0>, v=< 1,0,0>, a=< 0,0,0> 7 | p=< 3,0,0>, v=<-1,0,0>, a=< 0,0,0>"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 3); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 1); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2020/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day11::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | L.LL.LL.LL 5 | LLLLLLL.LL 6 | L.L.L..L.. 7 | LLLL.LL.LL 8 | L.LL.LL.LL 9 | L.LLLLL.LL 10 | ..L.L..... 11 | LLLLLLLLLL 12 | L.LLLLLL.L 13 | L.LLLLL.LL"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 37); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 26); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2021/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 0,9 -> 5,9 5 | 8,0 -> 0,8 6 | 9,4 -> 3,4 7 | 2,2 -> 2,1 8 | 7,0 -> 7,4 9 | 6,4 -> 2,0 10 | 0,9 -> 2,9 11 | 3,4 -> 1,4 12 | 0,0 -> 8,8 13 | 5,5 -> 8,2"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 5); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 12); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2023/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ???.### 1,1,3 5 | .??..??...?##. 1,1,3 6 | ?#?#?#?#?#?#?#? 1,3,1,6 7 | ????.#...#... 4,1,1 8 | ????.######..#####. 1,6,5 9 | ?###???????? 3,2,1"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 21); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 525152); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2024/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | MMMSXXMASM 5 | MSAMXMSMSA 6 | AMXSXMAAMM 7 | MSAMASMSMX 8 | XMASAMXAMM 9 | XXAMMXXAMA 10 | SMSMSASXSS 11 | SAXAMASAAA 12 | MAMMMXMMMM 13 | MXMXAXMASX"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 18); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 9); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2024/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ....#..... 5 | .........# 6 | .......... 7 | ..#....... 8 | .......#.. 9 | .......... 10 | .#..^..... 11 | ........#. 12 | #......... 13 | ......#..."; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 41); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 6); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2025/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ..@@.@@@@. 5 | @@@.@.@.@@ 6 | @@@@@.@.@@ 7 | @.@@@@..@. 8 | @@.@@@@.@@ 9 | .@@@@@@@.@ 10 | .@.@.@.@@@ 11 | @.@@@.@@@@ 12 | .@@@@@@@@. 13 | @.@.@@@.@."; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 13); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 43); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2018/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day17::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | x=495, y=2..7 5 | y=7, x=495..501 6 | x=501, y=3..7 7 | x=498, y=2..4 8 | x=506, y=1..2 9 | x=498, y=10..13 10 | x=504, y=10..13 11 | y=13, x=498..504"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part1(&input), 57); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part2(&input), 29); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2019/day09.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day09::*; 2 | 3 | const FIRST_EXAMPLE: &str = "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99"; 4 | const SECOND_EXAMPLE: &str = "1102,34915192,34915192,7,4,7,99,0"; 5 | 6 | #[test] 7 | fn part1_test() { 8 | let input = parse(FIRST_EXAMPLE); 9 | assert_eq!(part1(&input), 109); 10 | } 11 | 12 | #[test] 13 | fn part2_test() { 14 | let input = parse(SECOND_EXAMPLE); 15 | assert_eq!(part2(&input), 1219070632396864); 16 | } 17 | -------------------------------------------------------------------------------- /tests/year2021/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day11::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 5483143223 5 | 2745854711 6 | 5264556173 7 | 6141336146 8 | 6357385478 9 | 4167524645 10 | 2176841721 11 | 6882881134 12 | 4846848554 13 | 5283751526"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 1656); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 195); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2021/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1163751742 5 | 1381373672 6 | 2136511328 7 | 3694931569 8 | 7463417111 9 | 1319128137 10 | 1359912421 11 | 3125421639 12 | 1293138521 13 | 2311944581"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 40); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 315); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2023/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day14::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | O....#.... 5 | O.OO#....# 6 | .....##... 7 | OO.#O....O 8 | .O.....O#. 9 | O.#..O.#.# 10 | ..O..#O..O 11 | .......O.. 12 | #....###.. 13 | #OO..#...."; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 136); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 64); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2019/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | COM)BBB 5 | BBB)CCC 6 | CCC)DDD 7 | DDD)EEE 8 | EEE)FFF 9 | BBB)GGG 10 | GGG)HHH 11 | DDD)III 12 | EEE)JJJ 13 | JJJ)KKK 14 | KKK)LLL 15 | KKK)YOU 16 | III)SAN"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), 54); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), 4); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2023/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 467..114.. 5 | ...*...... 6 | ..35..633. 7 | ......#... 8 | 617*...... 9 | .....+.58. 10 | ..592..... 11 | ......755. 12 | ...$.*.... 13 | .664.598.."; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 4361); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 467835); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2023/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day11::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ...#...... 5 | .......#.. 6 | #......... 7 | .......... 8 | ......#... 9 | .#........ 10 | .........# 11 | .......... 12 | .......#.. 13 | #...#....."; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 374); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 82000210); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2023/day16.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day16::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | .|...\\.... 5 | |.-.\\..... 6 | .....|-... 7 | ........|. 8 | .......... 9 | .........\\ 10 | ..../.\\\\.. 11 | .-.-/..|.. 12 | .|....-|.\\ 13 | ..//.|...."; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 46); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 51); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2017/day19.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day19::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | . | . 5 | . | +--+ . 6 | . A | C . 7 | . F---|----E|--+ . 8 | . | | | D . 9 | . +B-+ +--+ . 10 | . ."; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), "ABCDEF"); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 38); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2022/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ....[D].... 5 | [N].[C].... 6 | [Z].[M].[P] 7 | .1...2...3. 8 | 9 | move 1 from 2 to 1 10 | move 3 from 1 to 3 11 | move 2 from 2 to 1 12 | move 1 from 1 to 2"; 13 | 14 | #[test] 15 | fn part1_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part1(&input), "CMZ"); 18 | } 19 | 20 | #[test] 21 | fn part2_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part2(&input), "MCD"); 24 | } 25 | -------------------------------------------------------------------------------- /tests/year2022/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | vJrwpWtwJgWrhcsFMMfFFhFp 5 | jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL 6 | PmmdzqPrVvPwwTWBwg 7 | wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn 8 | ttgJtRGJQctTZtZT 9 | CrZsJsPPZsGzwwsLwLmpwMDw"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 157); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 70); 21 | } 22 | -------------------------------------------------------------------------------- /src/year2025/day12.rs: -------------------------------------------------------------------------------- 1 | //! # Christmas Tree Farm 2 | use crate::util::iter::*; 3 | use crate::util::parse::*; 4 | 5 | pub fn parse(input: &str) -> &str { 6 | input 7 | } 8 | 9 | pub fn part1(input: &str) -> usize { 10 | input 11 | .iter_unsigned::() 12 | .skip(6) 13 | .chunk::<8>() 14 | .filter(|[w, h, presents @ ..]| (w / 3) * (h / 3) >= presents.iter().sum::()) 15 | .count() 16 | } 17 | 18 | pub fn part2(_input: &str) -> &'static str { 19 | "n/a" 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2020/day21.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day21::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | mxmxvkd kfcds sqjhc nhms (contains dairy, fish) 5 | trh fvjkl sbzzf mxmxvkd (contains dairy) 6 | sqjhc fvjkl (contains soy) 7 | sqjhc mxmxvkd sbzzf (contains fish)"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 5); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), "mxmxvkd,sqjhc,fvjkl"); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2015/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day14::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds. 5 | Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds."; 6 | 7 | #[test] 8 | fn part1_test() { 9 | let input = parse(EXAMPLE); 10 | assert_eq!(part1_testable(&input, 1000), 1120); 11 | } 12 | 13 | #[test] 14 | fn part2_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(part2_testable(&input, 1000), 689); 17 | } 18 | -------------------------------------------------------------------------------- /tests/year2025/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day02::*; 2 | 3 | const EXAMPLE: &str = " 4 | 11-22,95-115,998-1012,1188511880-1188511890,222220-222224, 5 | 1698522-1698528,446443-446449,38593856-38593862,565653-565659, 6 | 824824821-824824827,2121212118-2121212124"; 7 | 8 | #[test] 9 | fn part1_test() { 10 | let input = parse(EXAMPLE); 11 | assert_eq!(part1(&input), 1227775554); 12 | } 13 | 14 | #[test] 15 | fn part2_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part2(&input), 4174379265); 18 | } 19 | -------------------------------------------------------------------------------- /tests/year2016/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day06::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | eedadn 5 | drvtee 6 | eandsr 7 | raavrd 8 | atevrs 9 | tsrnev 10 | sdttsa 11 | rasrtv 12 | nssdts 13 | ntnada 14 | svetve 15 | tesnvt 16 | vntsnd 17 | vrdear 18 | dvrsen 19 | enarar"; 20 | 21 | #[test] 22 | fn part1_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part1(&input), "easter"); 25 | } 26 | 27 | #[test] 28 | fn part2_test() { 29 | let input = parse(EXAMPLE); 30 | assert_eq!(part2(&input), "advent"); 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2019/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day22::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | deal into new stack 5 | cut -2 6 | deal with increment 7 7 | cut 8 8 | cut -4 9 | deal with increment 7 10 | cut 3 11 | deal with increment 9 12 | deal with increment 3 13 | cut -1"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(input), 1219); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(input), 117607927195067); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2016/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day07::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | abba[mnop]qrst 5 | abcd[bddb]xyyx 6 | aaaa[qwer]tyui 7 | ioxxoj[asdfgh]zxcvbn"; 8 | 9 | const SECOND_EXAMPLE: &str = "\ 10 | aba[bab]xyz 11 | xyx[xyx]xyx 12 | aaa[kek]eke 13 | zazbz[bzb]cdb"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(FIRST_EXAMPLE); 18 | assert_eq!(part1(&input), 2); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(SECOND_EXAMPLE); 24 | assert_eq!(part2(&input), 3); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2023/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | #.##..##. 5 | ..#.##.#. 6 | ##......# 7 | ##......# 8 | ..#.##.#. 9 | ..##..##. 10 | #.#.##.#. 11 | 12 | #...##..# 13 | #....#..# 14 | ..##..### 15 | #####.##. 16 | #####.##. 17 | ..##..### 18 | #....#..#"; 19 | 20 | #[test] 21 | fn part1_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part1(&input), 405); 24 | } 25 | 26 | #[test] 27 | fn part2_test() { 28 | let input = parse(EXAMPLE); 29 | assert_eq!(part2(&input), 400); 30 | } 31 | -------------------------------------------------------------------------------- /tests/year2024/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day08::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ............ 5 | ........0... 6 | .....0...... 7 | .......0.... 8 | ....0....... 9 | ......A..... 10 | ............ 11 | ............ 12 | ........A... 13 | .........A.. 14 | ............ 15 | ............"; 16 | 17 | #[test] 18 | fn part1_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part1(&input), 14); 21 | } 22 | 23 | #[test] 24 | fn part2_test() { 25 | let input = parse(EXAMPLE); 26 | assert_eq!(part2(&input), 34); 27 | } 28 | -------------------------------------------------------------------------------- /tests/year2020/day18.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day18::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1 + 2 * 3 + 4 * 5 + 6 5 | 1 + (2 * 3) + (4 * (5 + 6)) 6 | 2 * 3 + (4 * 5) 7 | 5 + (8 * 3 + 9 + 3 * 4 * 3) 8 | 5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4)) 9 | ((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 26457); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 694173); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2024/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day03::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"; 5 | 6 | const SECOND_EXAMPLE: &str = "\ 7 | xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(FIRST_EXAMPLE); 12 | assert_eq!(part1(&input), 161); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(SECOND_EXAMPLE); 18 | assert_eq!(part2(&input), 48); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2018/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day02::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | abcdef 5 | bababc 6 | abbcde 7 | abcccd 8 | aabcdd 9 | abcdee 10 | ababab"; 11 | 12 | const SECOND_EXAMPLE: &str = "\ 13 | abcde 14 | fghij 15 | klmno 16 | pqrst 17 | fguij 18 | axcye 19 | wvxyz"; 20 | 21 | #[test] 22 | fn part1_test() { 23 | let input = parse(FIRST_EXAMPLE); 24 | assert_eq!(part1(&input), 12); 25 | } 26 | 27 | #[test] 28 | fn part2_test() { 29 | let input = parse(SECOND_EXAMPLE); 30 | assert_eq!(part2(&input), "fgij"); 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2015/day06.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day06::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | turn on 0,0 through 999,999 5 | toggle 0,0 through 999,0 6 | turn off 499,499 through 500,500"; 7 | 8 | const SECOND_EXAMPLE: &str = "\ 9 | turn on 0,0 through 0,0 10 | toggle 0,0 through 999,999"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(FIRST_EXAMPLE); 15 | assert_eq!(part1(&input), 998996); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(SECOND_EXAMPLE); 21 | assert_eq!(part2(&input), 2000001); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2015/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day05::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | ugknbfddgicrmopn 5 | aaa 6 | jchzalrnumimnmhp 7 | haegwjzuvuyypxyu 8 | dvszwmarrgswjxmb"; 9 | 10 | const SECOND_EXAMPLE: &str = "\ 11 | qjhvhtzxzqqjkmpb 12 | xxyxx 13 | uurcxstgmygtbstg 14 | ieodomkazucvgmuy"; 15 | 16 | #[test] 17 | fn part1_test() { 18 | let input = parse(FIRST_EXAMPLE); 19 | assert_eq!(part1(&input), 2); 20 | } 21 | 22 | #[test] 23 | fn part2_test() { 24 | let input = parse(SECOND_EXAMPLE); 25 | assert_eq!(part2(&input), 2); 26 | } 27 | -------------------------------------------------------------------------------- /tests/year2021/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day14::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | NNCB 5 | 6 | CH -> B 7 | HH -> N 8 | CB -> H 9 | NH -> C 10 | HB -> C 11 | HC -> B 12 | HN -> C 13 | NN -> C 14 | BH -> H 15 | NC -> B 16 | NB -> B 17 | BN -> B 18 | BB -> N 19 | BC -> B 20 | CC -> N 21 | CN -> C"; 22 | 23 | #[test] 24 | fn part1_test() { 25 | let input = parse(EXAMPLE); 26 | assert_eq!(part1(&input), 1588); 27 | } 28 | 29 | #[test] 30 | fn part2_test() { 31 | let input = parse(EXAMPLE); 32 | assert_eq!(part2(&input), 2188189693529); 33 | } 34 | -------------------------------------------------------------------------------- /tests/year2017/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day04::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | aa bb cc dd ee 5 | aa bb cc dd aa 6 | aa bb cc dd aaa"; 7 | 8 | const SECOND_EXAMPLE: &str = "\ 9 | abcde fghij 10 | abcde xyz ecdab 11 | a ab abc abd abf abj 12 | iiii oiii ooii oooi oooo 13 | oiii ioii iioi iiio"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(FIRST_EXAMPLE); 18 | assert_eq!(part1(&input), 2); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(SECOND_EXAMPLE); 24 | assert_eq!(part2(&input), 3); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2019/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day05::*; 2 | 3 | const FIRST_EXAMPLE: &str = "3,0,4,0,99"; 4 | 5 | const SECOND_EXAMPLE: &str = "\ 6 | 3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31, 7 | 1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104, 8 | 999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(FIRST_EXAMPLE); 13 | assert_eq!(part1(&input), 1); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(SECOND_EXAMPLE); 19 | assert_eq!(part2(&input), 999); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2023/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day17::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 2413432311323 5 | 3215453535623 6 | 3255245654254 7 | 3446585845452 8 | 4546657867536 9 | 1438598798454 10 | 4457876987766 11 | 3637877979653 12 | 4654967986887 13 | 4564679986453 14 | 1224686865563 15 | 2546548887735 16 | 4322674655533"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), 102); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), 94); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2016/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day11::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip. 5 | The second floor contains a hydrogen generator. 6 | The third floor contains a lithium generator. 7 | The fourth floor contains nothing relevant."; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 11); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 35); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2023/day01.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day01::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | 1abc2 5 | pqr3stu8vwx 6 | a1b2c3d4e5f 7 | treb7uchet"; 8 | 9 | const SECOND_EXAMPLE: &str = "\ 10 | two1nine 11 | eightwothree 12 | abcone2threexyz 13 | xtwone3four 14 | 4nineeightseven2 15 | zoneight234 16 | 7pqrstsixteen"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(FIRST_EXAMPLE); 21 | assert_eq!(part1(&input), 142); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(SECOND_EXAMPLE); 27 | assert_eq!(part2(&input), 281); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2022/day22.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day22::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | @ ...# 5 | .#.. 6 | #... 7 | .... 8 | ...#.......# 9 | ........#... 10 | ..#....#.... 11 | ..........#. 12 | ...#.... 13 | .....#.. 14 | .#...... 15 | ......#. 16 | 17 | 10R5L5R10L4R5L5"; 18 | 19 | #[test] 20 | fn part1_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part1(&input), 6032); 23 | } 24 | 25 | #[test] 26 | fn part2_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part2(&input), 5031); 29 | } 30 | -------------------------------------------------------------------------------- /tests/year2023/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | jqt: rhn xhk nvd 5 | rsh: frs pzl lsr 6 | xhk: hfx 7 | cmg: qnr nvd lhk bvb 8 | rhn: xhk bvb hfx 9 | bvb: xhk hfx 10 | pzl: lsr hfx nvd 11 | qnr: nvd 12 | ntq: jqt hfx bvb xhk 13 | nvd: lhk 14 | lsr: lhk 15 | rzs: qnr cmg lsr rsh 16 | frs: qnr lhk lsr"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), 54); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), "n/a"); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2022/day21.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day21::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | root: pppw + sjmn 5 | dbpl: 5 6 | cczh: sllz + lgvd 7 | zczc: 2 8 | ptdq: humn - dvpt 9 | dvpt: 3 10 | lfqf: 4 11 | humn: 5 12 | ljgn: 2 13 | sjmn: drzm * dbpl 14 | sllz: 4 15 | pppw: cczh / lfqf 16 | lgvd: ljgn * ptdq 17 | drzm: hmdt - zczc 18 | hmdt: 32"; 19 | 20 | #[test] 21 | fn part1_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part1(&input), 152); 24 | } 25 | 26 | #[test] 27 | fn part2_test() { 28 | let input = parse(EXAMPLE); 29 | assert_eq!(part2(&input), 301); 30 | } 31 | -------------------------------------------------------------------------------- /tests/year2023/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day10::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | ..... 5 | .S-7. 6 | .|.|. 7 | .L-J. 8 | ....."; 9 | 10 | const SECOND_EXAMPLE: &str = "\ 11 | ........... 12 | .S-------7. 13 | .|F-----7|. 14 | .||.....||. 15 | .||.....||. 16 | .|L-7.F-J|. 17 | .|..|.|..|. 18 | .L--J.L--J. 19 | ..........."; 20 | 21 | #[test] 22 | fn part1_test() { 23 | let input = parse(FIRST_EXAMPLE); 24 | assert_eq!(part1(&input), 4); 25 | } 26 | 27 | #[test] 28 | fn part2_test() { 29 | let input = parse(SECOND_EXAMPLE); 30 | assert_eq!(part2(&input), 4); 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2024/day17.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day17::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | Register A: 729 5 | Register B: 0 6 | Register C: 0 7 | 8 | Program: 0,1,5,4,3,0"; 9 | 10 | const SECOND_EXAMPLE: &str = "\ 11 | Register A: 2024 12 | Register B: 0 13 | Register C: 0 14 | 15 | Program: 0,3,5,4,3,0"; 16 | 17 | #[test] 18 | fn part1_test() { 19 | let input = parse(FIRST_EXAMPLE); 20 | assert_eq!(part1(&input), "4,6,3,5,6,3,5,2,1,0"); 21 | } 22 | 23 | #[test] 24 | fn part2_test() { 25 | let input = parse(SECOND_EXAMPLE); 26 | assert_eq!(part2(&input), 117440); 27 | } 28 | -------------------------------------------------------------------------------- /tests/year2017/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | pbga (66) 5 | xhth (57) 6 | ebii (61) 7 | havc (66) 8 | ktlj (57) 9 | fwft (72) -> ktlj, cntj, xhth 10 | qoyq (66) 11 | padx (45) -> pbga, havc, qoyq 12 | tknk (41) -> ugml, padx, fwft 13 | jptl (61) 14 | ugml (68) -> gyxo, ebii, jptl 15 | gyxo (61) 16 | cntj (57)"; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part1(&input), "tknk"); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part2(&input), 60); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2023/day18.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day18::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | R 6 (#70c710) 5 | D 5 (#0dc571) 6 | L 2 (#5713f0) 7 | D 2 (#d2c081) 8 | R 2 (#59c680) 9 | D 2 (#411b91) 10 | L 5 (#8ceee2) 11 | U 2 (#caa173) 12 | L 1 (#1b58a2) 13 | U 2 (#caa171) 14 | R 2 (#7807d2) 15 | U 3 (#a77fa3) 16 | L 2 (#015232) 17 | U 2 (#7a21e3)"; 18 | 19 | #[test] 20 | fn part1_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part1(&input), 62); 23 | } 24 | 25 | #[test] 26 | fn part2_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part2(&input), 952408144115); 29 | } 30 | -------------------------------------------------------------------------------- /src/util/ansi.rs: -------------------------------------------------------------------------------- 1 | //! [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) 2 | //! 3 | //! These codes allow command line applications to show colored or styled text in most terminals. 4 | //! Advanced commands can move the cursor or clear the screen. 5 | pub const RESET: &str = "\x1b[0m"; 6 | pub const BOLD: &str = "\x1b[1m"; 7 | pub const RED: &str = "\x1b[31m"; 8 | pub const GREEN: &str = "\x1b[32m"; 9 | pub const YELLOW: &str = "\x1b[33m"; 10 | pub const BLUE: &str = "\x1b[94m"; 11 | pub const WHITE: &str = "\x1b[97m"; 12 | pub const HOME: &str = "\x1b[H"; 13 | pub const CLEAR: &str = "\x1b[J"; 14 | -------------------------------------------------------------------------------- /tests/year2018/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | initial state: #..#.#..##......###...### 5 | 6 | ...## => # 7 | ..#.. => # 8 | .#... => # 9 | .#.#. => # 10 | .#.## => # 11 | .##.. => # 12 | .#### => # 13 | #.#.# => # 14 | #.### => # 15 | ##.#. => # 16 | ##.## => # 17 | ###.. => # 18 | ###.# => # 19 | ####. => #"; 20 | 21 | #[test] 22 | fn part1_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part1(&input), 325); 25 | } 26 | 27 | #[test] 28 | fn part2_test() { 29 | let input = parse(EXAMPLE); 30 | assert_eq!(part2(&input), 50000000501); 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2018/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day13::*; 2 | 3 | const FIRST_EXAMPLE: &str = r"/->-\ . 4 | | | /----\ . 5 | | /-+--+-\ | . 6 | | | | | v | . 7 | \-+-/ \-+--/ . 8 | \------/ ."; 9 | 10 | const SECOND_EXAMPLE: &str = r"/>-<\ . 11 | | | . 12 | | /<+-\ . 13 | | | | v . 14 | \>+/ ."; 17 | 18 | #[test] 19 | fn part1_test() { 20 | let input = parse(FIRST_EXAMPLE); 21 | assert_eq!(part1(&input), "7,3"); 22 | } 23 | 24 | #[test] 25 | fn part2_test() { 26 | let input = parse(SECOND_EXAMPLE); 27 | assert_eq!(part2(&input), "6,4"); 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2020/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day14::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X 5 | mem[8] = 11 6 | mem[7] = 101 7 | mem[8] = 0"; 8 | 9 | const SECOND_EXAMPLE: &str = "\ 10 | mask = 000000000000000000000000000000X1001X 11 | mem[42] = 100 12 | mask = 00000000000000000000000000000000X0XX 13 | mem[26] = 1"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(FIRST_EXAMPLE); 18 | assert_eq!(part1(&input), 165); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(SECOND_EXAMPLE); 24 | assert_eq!(part2(&input), 208); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2021/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day10::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | [({(<(())[]>[[{[]{<()<>> 5 | [(()[<>])]({[<{<<[]>>( 6 | {([(<{}[<>[]}>{[]{[(<()> 7 | (((({<>}<{<{<>}{[]{[]{} 8 | [[<[([]))<([[{}[[()]]] 9 | [{[{({}]{}}([{[{{{}}([] 10 | {<[[]]>}<{[{[{[]{()[[[] 11 | [<(<(<(<{}))><([]([]() 12 | <{([([[(<>()){}]>(<<{{ 13 | <{([{{}}[<[[[<>{}]]]>[]]"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 26397); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 288957); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2022/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | [1,1,3,1,1] 5 | [1,1,5,1,1] 6 | 7 | [[1],[2,3,4]] 8 | [[1],4] 9 | 10 | [9] 11 | [[8,7,6]] 12 | 13 | [[4,4],4,4] 14 | [[4,4],4,4,4] 15 | 16 | [7,7,7,7] 17 | [7,7,7] 18 | 19 | [] 20 | [3] 21 | 22 | [[[]]] 23 | [[]] 24 | 25 | [1,[2,[3,[4,[5,6,7]]]],8,9] 26 | [1,[2,[3,[4,[5,6,0]]]],8,9]"; 27 | 28 | #[test] 29 | fn part1_test() { 30 | let input = parse(EXAMPLE); 31 | assert_eq!(part1(&input), 13); 32 | } 33 | 34 | #[test] 35 | fn part2_test() { 36 | let input = parse(EXAMPLE); 37 | assert_eq!(part2(&input), 140); 38 | } 39 | -------------------------------------------------------------------------------- /tests/year2019/day14.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day14::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 157 ORE => 5 NZVS 5 | 165 ORE => 6 DCFZ 6 | 44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL 7 | 12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ 8 | 179 ORE => 7 PSHF 9 | 177 ORE => 5 HKGWZ 10 | 7 DCFZ, 7 PSHF => 2 XJWVT 11 | 165 ORE => 2 GPVTF 12 | 3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT"; 13 | 14 | #[test] 15 | fn part1_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part1(&input), 13312); 18 | } 19 | 20 | #[test] 21 | fn part2_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part2(&input), 82892753); 24 | } 25 | -------------------------------------------------------------------------------- /tests/year2022/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | $ cd / 5 | $ ls 6 | dir a 7 | 14848514 b.txt 8 | 8504156 c.dat 9 | dir d 10 | $ cd a 11 | $ ls 12 | dir e 13 | 29116 f 14 | 2557 g 15 | 62596 h.lst 16 | $ cd e 17 | $ ls 18 | 584 i 19 | $ cd .. 20 | $ cd .. 21 | $ cd d 22 | $ ls 23 | 4060174 j 24 | 8033020 d.log 25 | 5626152 d.ext 26 | 7214296 k"; 27 | 28 | #[test] 29 | fn part1_test() { 30 | let input = parse(EXAMPLE); 31 | assert_eq!(part1(&input), 95437); 32 | } 33 | 34 | #[test] 35 | fn part2_test() { 36 | let input = parse(EXAMPLE); 37 | assert_eq!(part2(&input), 24933642); 38 | } 39 | -------------------------------------------------------------------------------- /tests/year2016/day21.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day21::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | swap position 4 with position 0 5 | swap letter d with letter b 6 | reverse positions 0 through 4 7 | rotate left 1 step 8 | move position 1 to position 4 9 | move position 3 to position 0 10 | rotate based on position of letter b 11 | rotate based on position of letter d"; 12 | 13 | #[test] 14 | fn part1_test() { 15 | let input = parse(EXAMPLE); 16 | assert_eq!(scramble(&input, b"abcde"), "decab"); 17 | } 18 | 19 | #[test] 20 | fn part2_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(unscramble(&input, b"decab"), "abcde"); 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2023/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 5 | Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 6 | Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 7 | Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 8 | Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 9 | Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"; 10 | 11 | #[test] 12 | fn part1_test() { 13 | let input = parse(EXAMPLE); 14 | assert_eq!(part1(&input), 13); 15 | } 16 | 17 | #[test] 18 | fn part2_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part2(&input), 30); 21 | } 22 | -------------------------------------------------------------------------------- /tests/year2016/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2016::day12::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | cpy 1 a 5 | cpy 1 b 6 | cpy 26 d 7 | jnz c 2 8 | jnz 1 5 9 | cpy 7 c 10 | inc d 11 | dec c 12 | jnz c -2 13 | cpy a c 14 | inc a 15 | dec b 16 | jnz b -2 17 | cpy c b 18 | dec d 19 | jnz d -6 20 | cpy 1000 c // Test value 21 | cpy 1000 d // Test value 22 | inc a 23 | dec d 24 | jnz d -2 25 | dec c 26 | jnz c -5"; 27 | 28 | #[test] 29 | fn part1_test() { 30 | let input = parse(EXAMPLE); 31 | assert_eq!(part1(&input), 1317811); 32 | } 33 | 34 | #[test] 35 | fn part2_test() { 36 | let input = parse(EXAMPLE); 37 | assert_eq!(part2(&input), 10227465); 38 | } 39 | -------------------------------------------------------------------------------- /tests/year2023/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day08::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | LLR 5 | 6 | AAA = (BBB, BBB) 7 | BBB = (AAA, ZZZ) 8 | ZZZ = (ZZZ, ZZZ)"; 9 | 10 | const SECOND_EXAMPLE: &str = "\ 11 | LR 12 | 13 | 11A = (11B, XXX) 14 | 11B = (XXX, 11Z) 15 | 11Z = (11B, XXX) 16 | 22A = (22B, XXX) 17 | 22B = (22C, 22C) 18 | 22C = (22Z, 22Z) 19 | 22Z = (22B, 22B) 20 | XXX = (XXX, XXX)"; 21 | 22 | #[test] 23 | fn part1_test() { 24 | let input = parse(FIRST_EXAMPLE); 25 | assert_eq!(part1(&input), 6); 26 | } 27 | 28 | #[test] 29 | fn part2_test() { 30 | let input = parse(SECOND_EXAMPLE); 31 | assert_eq!(part2(&input), 6); 32 | } 33 | -------------------------------------------------------------------------------- /tests/year2015/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8 5 | Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3 6 | Filler 1: capacity -200, durability -300, flavor -600, texture -300, calories 0 7 | Filler 2: capacity -200, durability -300, flavor -600, texture -300, calories 0"; 8 | 9 | #[test] 10 | fn part1_test() { 11 | let input = parse(EXAMPLE); 12 | assert_eq!(part1(&input), 62842880); 13 | } 14 | 15 | #[test] 16 | fn part2_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part2(&input), 57600000); 19 | } 20 | -------------------------------------------------------------------------------- /tests/year2025/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | .......S....... 5 | ............... 6 | .......^....... 7 | ............... 8 | ......^.^...... 9 | ............... 10 | .....^.^.^..... 11 | ............... 12 | ....^.^...^.... 13 | ............... 14 | ...^.^...^.^... 15 | ............... 16 | ..^...^.....^.. 17 | ............... 18 | .^.^.^.^.^...^. 19 | ..............."; 20 | 21 | #[test] 22 | fn part1_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part1(&input), 21); 25 | } 26 | 27 | #[test] 28 | fn part2_test() { 29 | let input = parse(EXAMPLE); 30 | assert_eq!(part2(&input), 40); 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2021/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 6,10 5 | 0,14 6 | 9,10 7 | 0,3 8 | 10,4 9 | 4,11 10 | 6,0 11 | 6,12 12 | 4,1 13 | 0,13 14 | 10,12 15 | 3,4 16 | 3,0 17 | 8,4 18 | 1,10 19 | 2,14 20 | 8,10 21 | 9,0 22 | 23 | fold along y=7 24 | fold along x=5"; 25 | 26 | const EXPECTED: &str = " 27 | ##### 28 | #...# 29 | #...# 30 | #...# 31 | ##### 32 | ..... 33 | ....."; 34 | 35 | #[test] 36 | fn part1_test() { 37 | let input = parse(EXAMPLE); 38 | assert_eq!(part1(&input), 17); 39 | } 40 | 41 | #[test] 42 | fn part2_test() { 43 | let input = parse(EXAMPLE); 44 | assert_eq!(part2(&input), EXPECTED); 45 | } 46 | -------------------------------------------------------------------------------- /tests/year2023/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green 5 | Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue 6 | Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red 7 | Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red 8 | Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"; 9 | 10 | #[test] 11 | fn part1_test() { 12 | let input = parse(EXAMPLE); 13 | assert_eq!(part1(&input), 8); 14 | } 15 | 16 | #[test] 17 | fn part2_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part2(&input), 2286); 20 | } 21 | -------------------------------------------------------------------------------- /tests/year2024/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 47|53 5 | 97|13 6 | 97|61 7 | 97|47 8 | 75|29 9 | 61|13 10 | 75|53 11 | 29|13 12 | 97|29 13 | 53|29 14 | 61|53 15 | 97|53 16 | 61|29 17 | 47|13 18 | 75|47 19 | 97|75 20 | 47|61 21 | 75|61 22 | 47|29 23 | 75|13 24 | 53|13 25 | 26 | 75,47,61,53,29 27 | 97,61,53,29,13 28 | 75,29,13 29 | 75,97,47,61,53 30 | 61,13,29 31 | 97,13,75,29,47"; 32 | 33 | #[test] 34 | fn part1_test() { 35 | let input = parse(EXAMPLE); 36 | assert_eq!(part1(&input), 143); 37 | } 38 | 39 | #[test] 40 | fn part2_test() { 41 | let input = parse(EXAMPLE); 42 | assert_eq!(part2(&input), 123); 43 | } 44 | -------------------------------------------------------------------------------- /tests/year2024/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Button A: X+94, Y+34 5 | Button B: X+22, Y+67 6 | Prize: X=8400, Y=5400 7 | 8 | Button A: X+26, Y+66 9 | Button B: X+67, Y+21 10 | Prize: X=12748, Y=12176 11 | 12 | Button A: X+17, Y+86 13 | Button B: X+84, Y+37 14 | Prize: X=7870, Y=6450 15 | 16 | Button A: X+69, Y+23 17 | Button B: X+27, Y+71 18 | Prize: X=18641, Y=10279"; 19 | 20 | #[test] 21 | fn part1_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part1(&input), 480); 24 | } 25 | 26 | #[test] 27 | fn part2_test() { 28 | let input = parse(EXAMPLE); 29 | assert_eq!(part2(&input), 875318608908); 30 | } 31 | -------------------------------------------------------------------------------- /tests/year2025/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day08::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 162,817,812 5 | 57,618,57 6 | 906,360,560 7 | 592,479,940 8 | 352,342,300 9 | 466,668,158 10 | 542,29,236 11 | 431,825,988 12 | 739,650,466 13 | 52,470,668 14 | 216,146,977 15 | 819,987,18 16 | 117,168,530 17 | 805,96,715 18 | 346,949,466 19 | 970,615,88 20 | 941,993,340 21 | 862,61,35 22 | 984,92,344 23 | 425,690,689"; 24 | 25 | #[test] 26 | fn part1_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part1_testable(&input, 10), 40); 29 | } 30 | 31 | #[test] 32 | fn part2_test() { 33 | let input = parse(EXAMPLE); 34 | assert_eq!(part2(&input), 25272); 35 | } 36 | -------------------------------------------------------------------------------- /src/year2015/day01.rs: -------------------------------------------------------------------------------- 1 | //! # Not Quite Lisp 2 | //! 3 | //! The input is first converted into bytes. This is safe as it contains only ASCII characters. 4 | //! Then each parenthesis is parsed into either +1 or -1. 5 | pub fn parse(input: &str) -> Vec { 6 | input.trim().bytes().map(|b| if b == b'(' { 1 } else { -1 }).collect() 7 | } 8 | 9 | pub fn part1(input: &[i32]) -> i32 { 10 | input.iter().sum() 11 | } 12 | 13 | pub fn part2(input: &[i32]) -> usize { 14 | let mut floor = 0; 15 | input 16 | .iter() 17 | .position(|&b| { 18 | floor += b; 19 | floor < 0 20 | }) 21 | .map(|i| i + 1) 22 | .unwrap() 23 | } 24 | -------------------------------------------------------------------------------- /tests/year2024/day23.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day23::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | kh-tc 5 | qp-kh 6 | de-cg 7 | ka-co 8 | yn-aq 9 | qp-ub 10 | cg-tb 11 | vc-aq 12 | tb-ka 13 | wh-tc 14 | yn-cg 15 | kh-ub 16 | ta-co 17 | de-co 18 | tc-td 19 | tb-wq 20 | wh-td 21 | ta-ka 22 | td-qp 23 | aq-cg 24 | wq-ub 25 | ub-vc 26 | de-ta 27 | wq-aq 28 | wq-vc 29 | wh-yn 30 | ka-de 31 | kh-ta 32 | co-tc 33 | wh-qp 34 | tb-vc 35 | td-yn"; 36 | 37 | #[test] 38 | fn part1_test() { 39 | let input = parse(EXAMPLE); 40 | assert_eq!(part1(&input), 7); 41 | } 42 | 43 | #[test] 44 | fn part2_test() { 45 | let input = parse(EXAMPLE); 46 | assert_eq!(part2(&input), "co,de,ka,ta"); 47 | } 48 | -------------------------------------------------------------------------------- /src/year2019/day09.rs: -------------------------------------------------------------------------------- 1 | //! # Sensor Boost 2 | //! 3 | //! This problem is essentially a unit test for the full intcode computer. 4 | use super::intcode::*; 5 | use crate::util::parse::*; 6 | 7 | pub fn parse(input: &str) -> Vec { 8 | input.iter_signed().collect() 9 | } 10 | 11 | pub fn part1(input: &[i64]) -> i64 { 12 | run(input, 1) 13 | } 14 | 15 | pub fn part2(input: &[i64]) -> i64 { 16 | run(input, 2) 17 | } 18 | 19 | fn run(input: &[i64], value: i64) -> i64 { 20 | let mut computer = Computer::new(input); 21 | computer.input(value); 22 | 23 | match computer.run() { 24 | State::Output(result) => result, 25 | _ => unreachable!(), 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/year2022/day19.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day19::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Blueprint 1: 5 | Each ore robot costs 4 ore. 6 | Each clay robot costs 2 ore. 7 | Each obsidian robot costs 3 ore and 14 clay. 8 | Each geode robot costs 2 ore and 7 obsidian. 9 | 10 | Blueprint 2: 11 | Each ore robot costs 2 ore. 12 | Each clay robot costs 3 ore. 13 | Each obsidian robot costs 3 ore and 8 clay. 14 | Each geode robot costs 3 ore and 12 obsidian."; 15 | 16 | #[test] 17 | fn part1_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part1(&input), 33); 20 | } 21 | 22 | #[test] 23 | fn part2_test() { 24 | let input = parse(EXAMPLE); 25 | assert_eq!(part2(&input), 3472); 26 | } 27 | -------------------------------------------------------------------------------- /tests/year2024/day12.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day12::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | RRRRIICCFF 5 | RRRRIICCCF 6 | VVRRRCCFFF 7 | VVRCCCJFFF 8 | VVVVCJJCFE 9 | VVIVCCJJEE 10 | VVIIICJJEE 11 | MIIIIIJJEE 12 | MIIISIJEEE 13 | MMMISSJEEE"; 14 | 15 | const SECOND_EXAMPLE: &str = "\ 16 | AAAAAA 17 | AAABBA 18 | AAABBA 19 | ABBAAA 20 | ABBAAA 21 | AAAAAA"; 22 | 23 | #[test] 24 | fn part1_test() { 25 | let input = parse(FIRST_EXAMPLE); 26 | assert_eq!(part1(&input), 1930); 27 | } 28 | 29 | #[test] 30 | fn part2_test() { 31 | let input = parse(FIRST_EXAMPLE); 32 | assert_eq!(part2(&input), 1206); 33 | let input = parse(SECOND_EXAMPLE); 34 | assert_eq!(part2(&input), 368); 35 | } 36 | -------------------------------------------------------------------------------- /tests/year2024/day16.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day16::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ################# 5 | #...#...#...#..E# 6 | #.#.#.#.#.#.#.#.# 7 | #.#.#.#...#...#.# 8 | #.#.#.#.###.#.#.# 9 | #...#.#.#.....#.# 10 | #.#.#.#.#.#####.# 11 | #.#...#.#.#.....# 12 | #.#.#####.#.###.# 13 | #.#.#.......#...# 14 | #.#.###.#####.### 15 | #.#.#...#.....#.# 16 | #.#.#.#####.###.# 17 | #.#.#.........#.# 18 | #.#.#.#########.# 19 | #S#.............# 20 | #################"; 21 | 22 | #[test] 23 | fn part1_test() { 24 | let input = parse(EXAMPLE); 25 | assert_eq!(part1(&input), 11048); 26 | } 27 | 28 | #[test] 29 | fn part2_test() { 30 | let input = parse(EXAMPLE); 31 | assert_eq!(part2(&input), 64); 32 | } 33 | -------------------------------------------------------------------------------- /tests/year2018/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Step C must be finished before step A can begin. 5 | Step C must be finished before step F can begin. 6 | Step A must be finished before step B can begin. 7 | Step A must be finished before step D can begin. 8 | Step B must be finished before step E can begin. 9 | Step D must be finished before step E can begin. 10 | Step F must be finished before step E can begin."; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), "CABDFE"); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2_testable(&input, 2, 0), 15); 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2021/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 5 | 6 | 22 13 17 11 0 7 | 8 2 23 4 24 8 | 21 9 14 16 7 9 | 6 10 3 18 5 10 | 1 12 20 15 19 11 | 12 | 3 15 0 2 22 13 | 9 18 13 17 5 14 | 19 8 7 25 23 15 | 20 11 10 24 4 16 | 14 21 16 12 6 17 | 18 | 14 21 17 24 4 19 | 10 16 15 9 19 20 | 18 8 23 26 20 21 | 22 11 13 6 5 22 | 2 0 12 3 7"; 23 | 24 | #[test] 25 | fn part1_test() { 26 | let input = parse(EXAMPLE); 27 | assert_eq!(part1(&input), 4512); 28 | } 29 | 30 | #[test] 31 | fn part2_test() { 32 | let input = parse(EXAMPLE); 33 | assert_eq!(part2(&input), 1924); 34 | } 35 | -------------------------------------------------------------------------------- /tests/year2024/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 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 | #[test] 45 | fn part1_test() { 46 | let input = parse(EXAMPLE); 47 | assert_eq!(part1(input), 3); 48 | } 49 | 50 | #[test] 51 | fn part2_test() { 52 | let input = parse(EXAMPLE); 53 | assert_eq!(part2(input), "n/a"); 54 | } 55 | -------------------------------------------------------------------------------- /tests/year2018/day23.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day23::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | pos=<0,0,0>, r=4 5 | pos=<1,0,0>, r=1 6 | pos=<4,0,0>, r=3 7 | pos=<0,2,0>, r=1 8 | pos=<0,5,0>, r=3 9 | pos=<0,0,3>, r=1 10 | pos=<1,1,1>, r=1 11 | pos=<1,1,2>, r=1 12 | pos=<1,3,1>, r=1"; 13 | 14 | const SECOND_EXAMPLE: &str = "\ 15 | pos=<10,12,12>, r=2 16 | pos=<12,14,12>, r=2 17 | pos=<16,12,12>, r=4 18 | pos=<14,14,14>, r=6 19 | pos=<50,50,50>, r=200 20 | pos=<10,10,10>, r=5"; 21 | 22 | #[test] 23 | fn part1_test() { 24 | let input = parse(FIRST_EXAMPLE); 25 | assert_eq!(part1(&input), 7); 26 | } 27 | 28 | #[test] 29 | fn part2_test() { 30 | let input = parse(SECOND_EXAMPLE); 31 | assert_eq!(part2(&input), 36); 32 | } 33 | -------------------------------------------------------------------------------- /tests/year2021/day18.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day18::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | [[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] 5 | [[[5,[2,8]],4],[5,[[9,9],0]]] 6 | [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] 7 | [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] 8 | [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] 9 | [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] 10 | [[[[5,4],[7,7]],8],[[8,3],8]] 11 | [[9,3],[[9,9],[6,[4,9]]]] 12 | [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] 13 | [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 4140); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 3993); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2025/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2025::day11::*; 2 | 3 | const EXAMPLE_ONE: &str = "\ 4 | aaa: you hhh 5 | you: bbb ccc 6 | bbb: ddd eee 7 | ccc: ddd eee fff 8 | ddd: ggg 9 | eee: out 10 | fff: out 11 | ggg: out 12 | hhh: ccc fff iii 13 | iii: out"; 14 | 15 | const EXAMPLE_TWO: &str = "\ 16 | svr: aaa bbb 17 | aaa: fft 18 | fft: ccc 19 | bbb: tty 20 | tty: ccc 21 | ccc: ddd eee 22 | ddd: hub 23 | hub: fff 24 | eee: dac 25 | dac: fff 26 | fff: ggg hhh 27 | ggg: out 28 | hhh: out"; 29 | 30 | #[test] 31 | fn part1_test() { 32 | let input = parse(EXAMPLE_ONE); 33 | assert_eq!(part1(&input), 5); 34 | } 35 | 36 | #[test] 37 | fn part2_test() { 38 | let input = parse(EXAMPLE_TWO); 39 | assert_eq!(part2(&input), 2); 40 | } 41 | -------------------------------------------------------------------------------- /tests/year2020/day16.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day16::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | class: 1-3 or 5-7 5 | row: 6-11 or 33-44 6 | seat: 13-40 or 45-50 7 | 8 | your ticket: 9 | 7,1,14 10 | 11 | nearby tickets: 12 | 7,3,47 13 | 40,4,50 14 | 55,2,20 15 | 38,6,12"; 16 | 17 | const SECOND_EXAMPLE: &str = "\ 18 | departure: 0-1 or 4-19 19 | row: 0-5 or 8-19 20 | seat: 0-13 or 16-19 21 | 22 | your ticket: 23 | 11,12,13 24 | 25 | nearby tickets: 26 | 3,9,18 27 | 15,1,5 28 | 5,14,9"; 29 | 30 | #[test] 31 | fn part1_test() { 32 | let input = parse(FIRST_EXAMPLE); 33 | assert_eq!(part1(&input), 71); 34 | } 35 | 36 | #[test] 37 | fn part2_test() { 38 | let input = parse(SECOND_EXAMPLE); 39 | assert_eq!(part2(&input), 12); 40 | } 41 | -------------------------------------------------------------------------------- /tests/year2024/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 190: 10 19 5 | 3267: 81 40 27 6 | 83: 17 5 7 | 156: 15 6 8 | 7290: 6 8 6 15 9 | 161011: 16 10 13 10 | 192: 17 8 14 11 | 21037: 9 7 18 13 12 | 292: 11 6 16 20"; 13 | 14 | const EXAMPLE2: &str = "\ 15 | 190: 10 19 16 | 11174: 15 8 9 79 74 17 | 729: 6 6 7 37 650"; 18 | 19 | #[test] 20 | fn part1_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part1(&input), 3749); 23 | let input2 = parse(EXAMPLE2); 24 | assert_eq!(part1(&input2), 190); 25 | } 26 | 27 | #[test] 28 | fn part2_test() { 29 | let input = parse(EXAMPLE); 30 | assert_eq!(part2(&input), 11387); 31 | let input2 = parse(EXAMPLE2); 32 | assert_eq!(part2(&input2), 11364); 33 | } 34 | -------------------------------------------------------------------------------- /tests/year2019/day18.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day18::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | ################# 5 | #i.G..c...e..H.p# 6 | ########.######## 7 | #j.A..b...f..D.o# 8 | ########@######## 9 | #k.E..a...g..B.n# 10 | ########.######## 11 | #l.F..d...h..C.m# 12 | #################"; 13 | 14 | const SECOND_EXAMPLE: &str = "\ 15 | ############# 16 | #g#f.D#..h#l# 17 | #F###e#E###.# 18 | #dCba@#@BcIJ# 19 | ############# 20 | #nK.L@#@G...# 21 | #M###N#H###.# 22 | #o#m..#i#jk.# 23 | #############"; 24 | 25 | #[test] 26 | fn part1_test() { 27 | let input = parse(FIRST_EXAMPLE); 28 | assert_eq!(part1(&input), 136); 29 | } 30 | 31 | #[test] 32 | fn part2_test() { 33 | let input = parse(SECOND_EXAMPLE); 34 | assert_eq!(part2(&input), 72); 35 | } 36 | -------------------------------------------------------------------------------- /tests/year2019/day02.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day02::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 1, 0, 0, 0, 5 | 2, 32, 0, 0, 6 | 2, 33, 1, 1, 7 | 2, 34, 2, 2, 8 | 1, 35, 0, 0, 9 | 1, 1, 0, 0, 10 | 1, 2, 0, 0, 11 | 99, 0, 0, 0, 12 | 0, 1000000, 10000, 7350720, 13 | 0, 0, 0, 0, 14 | 0, 0, 0, 0, 15 | 0, 0, 0, 0, 16 | 0, 0, 0, 0, 17 | 0, 0, 0, 0, 18 | 0, 0, 0, 0, 19 | 0, 0, 0, 0, 20 | 0, 0, 0, 0, 21 | 0, 0, 0, 0, 22 | 0, 0, 0, 0, 23 | 0, 0, 0, 0, 24 | 0, 0, 0, 0, 25 | 0, 0, 0, 0, 26 | 0, 0, 0, 0, 27 | 0, 0, 0, 0, 28 | 0, 0, 0, 0"; 29 | 30 | #[test] 31 | fn part1_test() { 32 | let input = parse(EXAMPLE); 33 | assert_eq!(part1(&input), 19370720); 34 | } 35 | 36 | #[test] 37 | fn part2_test() { 38 | let input = parse(EXAMPLE); 39 | assert_eq!(part2(&input), 1234); 40 | } 41 | -------------------------------------------------------------------------------- /tests/year2023/day19.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day19::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | px{a<2006:qkq,m>2090:A,rfg} 5 | pv{a>1716:R,A} 6 | lnx{m>1548:A,A} 7 | rfg{s<537:gd,x>2440:R,A} 8 | qs{s>3448:A,lnx} 9 | qkq{x<1416:A,crn} 10 | crn{x>2662:A,R} 11 | in{s<1351:px,qqz} 12 | qqz{s>2770:qs,m<1801:hdj,R} 13 | gd{a>3333:R,R} 14 | hdj{m>838:A,pv} 15 | 16 | {x=787,m=2655,a=1222,s=2876} 17 | {x=1679,m=44,a=2067,s=496} 18 | {x=2036,m=264,a=79,s=2244} 19 | {x=2461,m=1339,a=466,s=291} 20 | {x=2127,m=1623,a=2188,s=1013}"; 21 | 22 | #[test] 23 | fn part1_test() { 24 | let input = parse(EXAMPLE); 25 | assert_eq!(part1(&input), 19114); 26 | } 27 | 28 | #[test] 29 | fn part2_test() { 30 | let input = parse(EXAMPLE); 31 | assert_eq!(part2(&input), 167409079868000); 32 | } 33 | -------------------------------------------------------------------------------- /src/year2019/day05.rs: -------------------------------------------------------------------------------- 1 | //! # Sunny with a Chance of Asteroids 2 | use super::intcode::*; 3 | use crate::util::parse::*; 4 | 5 | pub fn parse(input: &str) -> Vec { 6 | input.iter_signed().collect() 7 | } 8 | 9 | pub fn part1(input: &[i64]) -> i64 { 10 | run(input, 1) 11 | } 12 | 13 | pub fn part2(input: &[i64]) -> i64 { 14 | run(input, 5) 15 | } 16 | 17 | /// Start `IntCode` computer sending a single initial value. 18 | /// Receives multiple values from the output channel returning only the last one. 19 | fn run(input: &[i64], value: i64) -> i64 { 20 | let mut computer = Computer::new(input); 21 | computer.input(value); 22 | 23 | let mut result = 0; 24 | while let State::Output(next) = computer.run() { 25 | result = next; 26 | } 27 | result 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2023/day05.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2023::day05::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | seeds: 79 14 55 13 5 | 6 | seed-to-soil map: 7 | 50 98 2 8 | 52 50 48 9 | 10 | soil-to-fertilizer map: 11 | 0 15 37 12 | 37 52 2 13 | 39 0 15 14 | 15 | fertilizer-to-water map: 16 | 49 53 8 17 | 0 11 42 18 | 42 0 7 19 | 57 7 4 20 | 21 | water-to-light map: 22 | 88 18 7 23 | 18 25 70 24 | 25 | light-to-temperature map: 26 | 45 77 23 27 | 81 45 19 28 | 68 64 13 29 | 30 | temperature-to-humidity map: 31 | 0 69 1 32 | 1 0 69 33 | 34 | humidity-to-location map: 35 | 60 56 37 36 | 56 93 4"; 37 | 38 | #[test] 39 | fn part1_test() { 40 | let input = parse(EXAMPLE); 41 | assert_eq!(part1(&input), 35); 42 | } 43 | 44 | #[test] 45 | fn part2_test() { 46 | let input = parse(EXAMPLE); 47 | assert_eq!(part2(&input), 46); 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | 3 | on: 4 | push: 5 | branches: main 6 | pull_request: 7 | branches: main 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - run: rustup install nightly --profile default 15 | - run: rustup default nightly 16 | - run: cargo fmt --check -- `find . -name "*.rs"` 17 | - run: cargo clippy --all-targets --all-features -- --deny warnings 18 | 19 | test-stable: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - run: rustup default 1.92 24 | - run: cargo test 25 | 26 | test-nightly: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v4 30 | - run: rustup default nightly 31 | - run: cargo test --features simd 32 | -------------------------------------------------------------------------------- /tests/year2019/day10.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2019::day10::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | .#..##.###...####### 5 | ##.############..##. 6 | .#.######.########.# 7 | .###.#######.####.#. 8 | #####.##.#.##.###.## 9 | ..#####..#.######### 10 | #################### 11 | #.####....###.#.#.## 12 | ##.################# 13 | #####.##.###..####.. 14 | ..######..##.####### 15 | ####.##.####...##..# 16 | .#####..#.######.### 17 | ##...#.##########... 18 | #.##########.####### 19 | .####.#.###.###.#.## 20 | ....##.##.###..##### 21 | .#.#.###########.### 22 | #.#.#.#####.####.### 23 | ###.##.####.##.#..##"; 24 | 25 | #[test] 26 | fn part1_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part1(&input), 210); 29 | } 30 | 31 | #[test] 32 | fn part2_test() { 33 | let input = parse(EXAMPLE); 34 | assert_eq!(part2(&input), 802); 35 | } 36 | -------------------------------------------------------------------------------- /src/year2017/day01.rs: -------------------------------------------------------------------------------- 1 | //! # Inverse Captcha 2 | //! 3 | //! Modern hardware is so good at shuffling memory around that it's faster to rotate the entire 4 | //! array instead of stepping through elements one at a time with an index modulo array length. 5 | use crate::util::parse::*; 6 | 7 | pub fn parse(input: &str) -> &[u8] { 8 | input.trim().as_bytes() 9 | } 10 | 11 | pub fn part1(input: &[u8]) -> u32 { 12 | captcha(input, 1) 13 | } 14 | 15 | pub fn part2(input: &[u8]) -> u32 { 16 | captcha(input, input.len() / 2) 17 | } 18 | 19 | fn captcha(input: &[u8], offset: usize) -> u32 { 20 | let mut rotated = input.to_vec(); 21 | rotated.rotate_left(offset); 22 | 23 | input 24 | .iter() 25 | .zip(rotated.iter()) 26 | .filter_map(|(a, b)| (a == b).then_some(a.to_decimal() as u32)) 27 | .sum() 28 | } 29 | -------------------------------------------------------------------------------- /src/year2016/day03.rs: -------------------------------------------------------------------------------- 1 | //! # Squares With Three Sides 2 | //! 3 | //! We rely on the [`iter`] and [`parse`] utility modules to extract integers from surrounding 4 | //! text then group together in chunks of three. 5 | //! 6 | //! [`iter`]: crate::util::iter 7 | //! [`parse`]: crate::util::parse 8 | use crate::util::iter::*; 9 | use crate::util::parse::*; 10 | 11 | pub fn parse(input: &str) -> Vec { 12 | input.iter_unsigned().collect() 13 | } 14 | 15 | pub fn part1(input: &[u32]) -> usize { 16 | count(input.iter()) 17 | } 18 | 19 | pub fn part2(input: &[u32]) -> usize { 20 | (0..3).map(|skip| count(input.iter().skip(skip).step_by(3))).sum() 21 | } 22 | 23 | fn count<'a, I>(iter: I) -> usize 24 | where 25 | I: Iterator, 26 | { 27 | iter.chunk::<3>().filter(|&[&a, &b, &c]| a + b > c && a + c > b && b + c > a).count() 28 | } 29 | -------------------------------------------------------------------------------- /tests/year2020/day07.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day07::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | light red bags contain 1 bright white bag, 2 muted yellow bags. 5 | dark orange bags contain 3 bright white bags, 4 muted yellow bags. 6 | bright white bags contain 1 shiny gold bag. 7 | muted yellow bags contain 2 shiny gold bags, 9 faded blue bags. 8 | shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags. 9 | dark olive bags contain 3 faded blue bags, 4 dotted black bags. 10 | vibrant plum bags contain 5 faded blue bags, 6 dotted black bags. 11 | faded blue bags contain no other bags. 12 | dotted black bags contain no other bags."; 13 | 14 | #[test] 15 | fn part1_test() { 16 | let input = parse(EXAMPLE); 17 | assert_eq!(part1(&input), 4); 18 | } 19 | 20 | #[test] 21 | fn part2_test() { 22 | let input = parse(EXAMPLE); 23 | assert_eq!(part2(&input), 32); 24 | } 25 | -------------------------------------------------------------------------------- /src/util/bitset.rs: -------------------------------------------------------------------------------- 1 | //! Add `biterator` method that treats an integer as a set, iterating over each element where 2 | //! the respective bit is set. For example `1101` would return 0, 2 and 3. 3 | use crate::util::integer::*; 4 | 5 | pub trait BitOps { 6 | fn biterator(self) -> Bitset; 7 | } 8 | 9 | impl> BitOps for T { 10 | fn biterator(self) -> Bitset { 11 | Bitset { t: self } 12 | } 13 | } 14 | 15 | pub struct Bitset { 16 | t: T, 17 | } 18 | 19 | impl> Iterator for Bitset { 20 | type Item = usize; 21 | 22 | #[inline] 23 | fn next(&mut self) -> Option { 24 | if self.t == T::ZERO { 25 | None 26 | } else { 27 | let tz = self.t.trailing_zeros(); 28 | self.t = self.t ^ (T::ONE << tz); 29 | Some(tz as usize) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/year2018/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Immune System: 5 | 17 units each with 5390 hit points (weak to radiation, bludgeoning) with an attack that does 4507 fire damage at initiative 2 6 | 989 units each with 1274 hit points (immune to fire; weak to bludgeoning, slashing) with an attack that does 25 slashing damage at initiative 3 7 | 8 | Infection: 9 | 801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1 10 | 4485 units each with 2961 hit points (immune to radiation; weak to fire, cold) with an attack that does 12 slashing damage at initiative 4"; 11 | 12 | #[test] 13 | fn part1_test() { 14 | let input = parse(EXAMPLE); 15 | assert_eq!(part1(&input), 5216); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse(EXAMPLE); 21 | assert_eq!(part2(&input), 51); 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: docs 6 | 7 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 8 | permissions: 9 | contents: read 10 | pages: write 11 | id-token: write 12 | 13 | jobs: 14 | deploy: 15 | runs-on: ubuntu-latest 16 | environment: 17 | name: github-pages 18 | url: ${{ steps.deployment.outputs.page_url }} 19 | steps: 20 | - uses: actions/checkout@v4 21 | - run: rustup default 1.92 22 | - run: cargo doc 23 | env: 24 | RUSTDOCFLAGS: "--document-private-items --default-theme=ayu --deny warnings" 25 | - run: rm target/doc/.lock 26 | - run: cp docs/* target/doc 27 | - uses: actions/upload-pages-artifact@v3 28 | with: 29 | path: 'target/doc' 30 | - uses: actions/configure-pages@v4 31 | - uses: actions/deploy-pages@v4 32 | id: deployment 33 | -------------------------------------------------------------------------------- /tests/year2022/day16.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day16::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Valve AA has flow rate=0; tunnels lead to valves DD, II, BB 5 | Valve BB has flow rate=13; tunnels lead to valves CC, AA 6 | Valve CC has flow rate=2; tunnels lead to valves DD, BB 7 | Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE 8 | Valve EE has flow rate=3; tunnels lead to valves FF, DD 9 | Valve FF has flow rate=0; tunnels lead to valves EE, GG 10 | Valve GG has flow rate=0; tunnels lead to valves FF, HH 11 | Valve HH has flow rate=22; tunnel leads to valve GG 12 | Valve II has flow rate=0; tunnels lead to valves AA, JJ 13 | Valve JJ has flow rate=21; tunnel leads to valve II"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 1651); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 1707); 25 | } 26 | -------------------------------------------------------------------------------- /tests/year2021/day20.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day20::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#.\ 5 | .#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..\ 6 | #.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....\ 7 | #.#....###..#.##......#.....#..#..#..##..#...##.######.####.####\ 8 | .#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.\ 9 | #.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..\ 10 | #.##.#....##..#.####....##...##..#...#......#.#.......#.......##\ 11 | ..####..#...#.#.#...##..#.#..###..#####........#..####......#..# 12 | 13 | #..#. 14 | #.... 15 | ##..# 16 | ..#.. 17 | ..###"; 18 | 19 | #[test] 20 | fn part1_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part1(&input), 35); 23 | } 24 | 25 | #[test] 26 | fn part2_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part2(&input), 3351); 29 | } 30 | -------------------------------------------------------------------------------- /src/year2020/day03.rs: -------------------------------------------------------------------------------- 1 | //! # Toboggan Trajectory 2 | //! 3 | //! Two dimensional grids of ASCII characters are a common Advent of Code theme, 4 | //! so we use our utility [`Grid`] class to parse the data. 5 | //! 6 | //! [`Grid`]: crate::util::grid 7 | use crate::util::grid::*; 8 | use crate::util::point::*; 9 | 10 | pub fn parse(input: &str) -> Grid { 11 | Grid::parse(input) 12 | } 13 | 14 | pub fn part1(input: &Grid) -> usize { 15 | toboggan(input, 3, 1) 16 | } 17 | 18 | pub fn part2(input: &Grid) -> usize { 19 | [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)] 20 | .into_iter() 21 | .map(|(dx, dy)| toboggan(input, dx, dy)) 22 | .product() 23 | } 24 | 25 | fn toboggan(grid: &Grid, dx: i32, dy: i32) -> usize { 26 | (0..grid.height / dy) 27 | .filter(|&i| { 28 | let point = Point::new((i * dx) % grid.width, i * dy); 29 | grid[point] == b'#' 30 | }) 31 | .count() 32 | } 33 | -------------------------------------------------------------------------------- /src/year2022/day02.rs: -------------------------------------------------------------------------------- 1 | //! # Rock Paper Scissors 2 | //! 3 | //! With so few combinations it's possible to precompute the values for each scenario by hand 4 | //! then quickly look them up for each game. 5 | 6 | /// Map each line from one of the 9 possible combinations ("A", "B" or "C" followed by "X", "Y" or "Z") 7 | /// to between 0 and 8 inclusive. 8 | pub fn parse(input: &str) -> Vec { 9 | input.as_bytes().chunks_exact(4).map(|c| (3 * (c[0] - b'A') + c[2] - b'X') as usize).collect() 10 | } 11 | 12 | /// Map each index to a score using a small precomputed lookup table. 13 | pub fn part1(input: &[usize]) -> u32 { 14 | let score = [4, 8, 3, 1, 5, 9, 7, 2, 6]; 15 | input.iter().map(|&i| score[i]).sum() 16 | } 17 | 18 | /// Map each index to a (different) score using a second small precomputed lookup table. 19 | pub fn part2(input: &[usize]) -> u32 { 20 | let score = [3, 4, 8, 1, 5, 9, 2, 6, 7]; 21 | input.iter().map(|&i| score[i]).sum() 22 | } 23 | -------------------------------------------------------------------------------- /tests/year2018/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2018::day04::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | [1518-11-01 00:00] Guard #10 begins shift 5 | [1518-11-01 00:05] falls asleep 6 | [1518-11-01 00:25] wakes up 7 | [1518-11-01 00:30] falls asleep 8 | [1518-11-01 00:55] wakes up 9 | [1518-11-01 23:58] Guard #99 begins shift 10 | [1518-11-02 00:40] falls asleep 11 | [1518-11-02 00:50] wakes up 12 | [1518-11-03 00:05] Guard #10 begins shift 13 | [1518-11-03 00:24] falls asleep 14 | [1518-11-03 00:29] wakes up 15 | [1518-11-04 00:02] Guard #99 begins shift 16 | [1518-11-04 00:36] falls asleep 17 | [1518-11-04 00:46] wakes up 18 | [1518-11-05 00:03] Guard #99 begins shift 19 | [1518-11-05 00:45] falls asleep 20 | [1518-11-05 00:55] wakes up"; 21 | 22 | #[test] 23 | fn part1_test() { 24 | let input = parse(EXAMPLE); 25 | assert_eq!(part1(&input), 240); 26 | } 27 | 28 | #[test] 29 | fn part2_test() { 30 | let input = parse(EXAMPLE); 31 | assert_eq!(part2(&input), 4455); 32 | } 33 | -------------------------------------------------------------------------------- /tests/year2017/day25.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2017::day25::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Begin in state A. 5 | Perform a diagnostic checksum after 6 steps. 6 | 7 | In state A: 8 | If the current value is 0: 9 | - Write the value 1. 10 | - Move one slot to the right. 11 | - Continue with state B. 12 | If the current value is 1: 13 | - Write the value 0. 14 | - Move one slot to the left. 15 | - Continue with state B. 16 | 17 | In state B: 18 | If the current value is 0: 19 | - Write the value 1. 20 | - Move one slot to the left. 21 | - Continue with state A. 22 | If the current value is 1: 23 | - Write the value 1. 24 | - Move one slot to the right. 25 | - Continue with state A."; 26 | 27 | #[test] 28 | fn part1_test() { 29 | let input = parse(EXAMPLE); 30 | assert_eq!(part1(&input), 3); 31 | } 32 | 33 | #[test] 34 | fn part2_test() { 35 | let input = parse(EXAMPLE); 36 | assert_eq!(part2(&input), "n/a"); 37 | } 38 | -------------------------------------------------------------------------------- /src/year2025/day07.rs: -------------------------------------------------------------------------------- 1 | //! # Laboratories 2 | type Input = (u64, u64); 3 | 4 | pub fn parse(input: &str) -> Input { 5 | let lines: Vec<_> = input.lines().map(str::as_bytes).collect(); 6 | let width = lines[0].len(); 7 | let center = width / 2; 8 | 9 | let mut splits = 0; 10 | let mut timelines = vec![0; width]; 11 | timelines[center] = 1; 12 | 13 | for (y, row) in lines.iter().skip(2).step_by(2).enumerate() { 14 | for x in ((center - y)..(center + y + 1)).step_by(2) { 15 | let count = timelines[x]; 16 | 17 | if count > 0 && row[x] == b'^' { 18 | splits += 1; 19 | timelines[x] = 0; 20 | timelines[x - 1] += count; 21 | timelines[x + 1] += count; 22 | } 23 | } 24 | } 25 | 26 | (splits, timelines.iter().sum()) 27 | } 28 | 29 | pub fn part1(input: &Input) -> u64 { 30 | input.0 31 | } 32 | 33 | pub fn part2(input: &Input) -> u64 { 34 | input.1 35 | } 36 | -------------------------------------------------------------------------------- /src/year2024/day01.rs: -------------------------------------------------------------------------------- 1 | //! # Historian Hysteria 2 | //! 3 | //! For part 2, the time needed to allocate memory and grow the map is a large percentage 4 | //! of the total. Creating the [`FastMap`] with capacity 1000 reduces this. 5 | use crate::util::hash::*; 6 | use crate::util::iter::*; 7 | use crate::util::parse::*; 8 | 9 | type Input = (Vec, Vec); 10 | 11 | pub fn parse(input: &str) -> Input { 12 | input.iter_unsigned::().chunk::<2>().map(|[l, r]| (l, r)).unzip() 13 | } 14 | 15 | pub fn part1(input: &Input) -> u32 { 16 | let (mut left, mut right) = input.clone(); 17 | 18 | left.sort_unstable(); 19 | right.sort_unstable(); 20 | 21 | left.iter().zip(right).map(|(l, r)| l.abs_diff(r)).sum() 22 | } 23 | 24 | pub fn part2(input: &Input) -> u32 { 25 | let (left, right) = input; 26 | 27 | let mut freq = FastMap::with_capacity(1_000); 28 | right.iter().for_each(|r| *freq.entry(r).or_insert(0) += 1); 29 | 30 | left.iter().filter_map(|l| freq.get(l).map(|f| l * f)).sum() 31 | } 32 | -------------------------------------------------------------------------------- /src/year2022/day01.rs: -------------------------------------------------------------------------------- 1 | //! # Calorie Counting 2 | //! Sums groups of numbers separated by blank lines into a `vec` sorted in ascending order. 3 | //! 4 | //! Since we don't care what order the highest values are returned in [`select_nth_unstable`] would 5 | //! also work, and in theory is a little faster, however the difference was negligible when benchmarking. 6 | //! 7 | //! [`select_nth_unstable`]: slice::select_nth_unstable 8 | use crate::util::parse::*; 9 | 10 | /// Parse and group lines. 11 | pub fn parse(input: &str) -> Vec { 12 | let mut elves: Vec = input.split("\n\n").map(|s| s.iter_unsigned::().sum()).collect(); 13 | elves.sort_unstable(); 14 | elves 15 | } 16 | 17 | /// Use a reverse iterator to find the elf with the most calories. 18 | pub fn part1(input: &[u32]) -> u32 { 19 | input.iter().rev().take(1).sum() 20 | } 21 | 22 | /// Use a reverse iterator to sum the calories of the 3 highest elves. 23 | pub fn part2(input: &[u32]) -> u32 { 24 | input.iter().rev().take(3).sum() 25 | } 26 | -------------------------------------------------------------------------------- /src/year2015/day02.rs: -------------------------------------------------------------------------------- 1 | //! # I Was Told There Would Be No Math 2 | //! 3 | //! To extract the numbers when parsing the input we use our utility [`iter_unsigned`] and [`chunk`] 4 | //! functions. 5 | //! 6 | //! Sorting the dimensions in ascending order makes calculating the smallest side or smallest 7 | //! perimeter straightforward. 8 | //! 9 | //! [`iter_unsigned`]: crate::util::parse 10 | //! [`chunk`]: crate::util::iter 11 | use crate::util::iter::*; 12 | use crate::util::parse::*; 13 | 14 | type Input = Vec<[u32; 3]>; 15 | 16 | pub fn parse(input: &str) -> Input { 17 | input 18 | .iter_unsigned() 19 | .chunk::<3>() 20 | .map(|mut chunk| { 21 | chunk.sort_unstable(); 22 | chunk 23 | }) 24 | .collect() 25 | } 26 | 27 | pub fn part1(input: &Input) -> u32 { 28 | input.iter().map(|[l, w, h]| 2 * (l * w + w * h + h * l) + l * w).sum() 29 | } 30 | 31 | pub fn part2(input: &Input) -> u32 { 32 | input.iter().map(|[l, w, h]| 2 * (l + w) + (l * w * h)).sum() 33 | } 34 | -------------------------------------------------------------------------------- /tests/year2022/day11.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day11::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Monkey 0: 5 | Starting items: 79, 98 6 | Operation: new = old * 19 7 | Test: divisible by 23 8 | If true: throw to monkey 2 9 | If false: throw to monkey 3 10 | 11 | Monkey 1: 12 | Starting items: 54, 65, 75, 74 13 | Operation: new = old + 6 14 | Test: divisible by 19 15 | If true: throw to monkey 2 16 | If false: throw to monkey 0 17 | 18 | Monkey 2: 19 | Starting items: 79, 60, 97 20 | Operation: new = old * old 21 | Test: divisible by 13 22 | If true: throw to monkey 1 23 | If false: throw to monkey 3 24 | 25 | Monkey 3: 26 | Starting items: 74 27 | Operation: new = old + 3 28 | Test: divisible by 17 29 | If true: throw to monkey 0 30 | If false: throw to monkey 1"; 31 | 32 | #[test] 33 | fn part1_test() { 34 | let input = parse(EXAMPLE); 35 | assert_eq!(part1(&input), 10605); 36 | } 37 | 38 | #[test] 39 | fn part2_test() { 40 | let input = parse(EXAMPLE); 41 | assert_eq!(part2(&input), 2713310158); 42 | } 43 | -------------------------------------------------------------------------------- /src/year2025/day03.rs: -------------------------------------------------------------------------------- 1 | //! # Lobby 2 | use std::mem::replace; 3 | 4 | pub fn parse(input: &str) -> Vec<&str> { 5 | input.lines().collect() 6 | } 7 | 8 | pub fn part1(input: &[&str]) -> u64 { 9 | solve::<2>(input) 10 | } 11 | 12 | pub fn part2(input: &[&str]) -> u64 { 13 | solve::<12>(input) 14 | } 15 | 16 | fn solve(input: &[&str]) -> u64 { 17 | let mut batteries = [0; N]; 18 | 19 | input 20 | .iter() 21 | .map(|&bank| { 22 | let end = bank.len() - N; 23 | batteries.copy_from_slice(&bank.as_bytes()[end..]); 24 | 25 | for mut next in bank[..end].bytes().rev() { 26 | for battery in &mut batteries { 27 | if next < *battery { 28 | break; 29 | } 30 | next = replace(battery, next); 31 | } 32 | } 33 | 34 | batteries.iter().fold(0, |joltage, &b| 10 * joltage + (b - b'0') as u64) 35 | }) 36 | .sum() 37 | } 38 | -------------------------------------------------------------------------------- /tests/year2020/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | sesenwnenenewseeswwswswwnenewsewsw 5 | neeenesenwnwwswnenewnwwsewnenwseswesw 6 | seswneswswsenwwnwse 7 | nwnwneseeswswnenewneswwnewseswneseene 8 | swweswneswnenwsewnwneneseenw 9 | eesenwseswswnenwswnwnwsewwnwsene 10 | sewnenenenesenwsewnenwwwse 11 | wenwwweseeeweswwwnwwe 12 | wsweesenenewnwwnwsenewsenwwsesesenwne 13 | neeswseenwwswnwswswnw 14 | nenwswwsewswnenenewsenwsenwnesesenew 15 | enewnwewneswsewnwswenweswnenwsenwsw 16 | sweneswneswneneenwnewenewwneswswnese 17 | swwesenesewenwneswnwwneseswwne 18 | enesenwswwswneneswsenwnewswseenwsese 19 | wnwnesenesenenwwnenwsewesewsesesew 20 | nenewswnwewswnenesenwnesewesw 21 | eneswnwswnwsenenwnwnwwseeswneewsenese 22 | neswnwewnwnwseenwseesewsenwsweewe 23 | wseweeenwnesenwwwswnew"; 24 | 25 | #[test] 26 | fn part1_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part1(&input), 10); 29 | } 30 | 31 | #[test] 32 | fn part2_test() { 33 | let input = parse(EXAMPLE); 34 | assert_eq!(part2(&input), 2208); 35 | } 36 | -------------------------------------------------------------------------------- /src/year2021/day06.rs: -------------------------------------------------------------------------------- 1 | //! # Lanternfish 2 | //! 3 | //! The key observation is that all fish of the same age behave the same, so we only 4 | //! need to store the *total* of each fish per day, rather than each fish individually. 5 | //! 6 | //! Another optimization trick is rather than modifying the array by removing the fish at day 0, 7 | //! then shifting each fish total down by 1, we can simply increment what we consider the 8 | //! head of the array modulo 9 to achieve the same effect in place. 9 | use crate::util::parse::*; 10 | 11 | type Input = [u64; 9]; 12 | 13 | pub fn parse(input: &str) -> Input { 14 | let mut fish = [0_u64; 9]; 15 | input.iter_unsigned().for_each(|i: usize| fish[i] += 1); 16 | fish 17 | } 18 | 19 | pub fn part1(input: &Input) -> u64 { 20 | simulate(input, 80) 21 | } 22 | 23 | pub fn part2(input: &Input) -> u64 { 24 | simulate(input, 256) 25 | } 26 | 27 | fn simulate(input: &Input, days: usize) -> u64 { 28 | let mut fish = *input; 29 | (0..days).for_each(|day| fish[(day + 7) % 9] += fish[day % 9]); 30 | fish.iter().sum() 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2015/day13.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2015::day13::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Alice would gain 54 happiness units by sitting next to Bob. 5 | Alice would lose 79 happiness units by sitting next to Carol. 6 | Alice would lose 2 happiness units by sitting next to David. 7 | Bob would gain 83 happiness units by sitting next to Alice. 8 | Bob would lose 7 happiness units by sitting next to Carol. 9 | Bob would lose 63 happiness units by sitting next to David. 10 | Carol would lose 62 happiness units by sitting next to Alice. 11 | Carol would gain 60 happiness units by sitting next to Bob. 12 | Carol would gain 55 happiness units by sitting next to David. 13 | David would gain 46 happiness units by sitting next to Alice. 14 | David would lose 7 happiness units by sitting next to Bob. 15 | David would gain 41 happiness units by sitting next to Carol."; 16 | 17 | #[test] 18 | fn part1_test() { 19 | let input = parse(EXAMPLE); 20 | assert_eq!(part1(&input), 330); 21 | } 22 | 23 | #[test] 24 | fn part2_test() { 25 | let input = parse(EXAMPLE); 26 | assert_eq!(part2(&input), 286); 27 | } 28 | -------------------------------------------------------------------------------- /tests/year2020/day03.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day03::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ..##.........##.........##.........##.........##.........##....... 5 | #...#...#..#...#...#..#...#...#..#...#...#..#...#...#..#...#...#.. 6 | .#....#..#..#....#..#..#....#..#..#....#..#..#....#..#..#....#..#. 7 | ..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.# 8 | .#...##..#..#...##..#..#...##..#..#...##..#..#...##..#..#...##..#. 9 | ..#.##.......#.##.......#.##.......#.##.......#.##.......#.##..... 10 | .#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....# 11 | .#........#.#........#.#........#.#........#.#........#.#........# 12 | #.##...#...#.##...#...#.##...#...#.##...#...#.##...#...#.##...#... 13 | #...##....##...##....##...##....##...##....##...##....##...##....# 14 | .#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#"; 15 | 16 | #[test] 17 | fn part1_test() { 18 | let input = parse(EXAMPLE); 19 | assert_eq!(part1(&input), 7); 20 | } 21 | 22 | #[test] 23 | fn part2_test() { 24 | let input = parse(EXAMPLE); 25 | assert_eq!(part2(&input), 336); 26 | } 27 | -------------------------------------------------------------------------------- /src/year2016/day20.rs: -------------------------------------------------------------------------------- 1 | //! # Firewall Rules 2 | use crate::util::iter::*; 3 | use crate::util::parse::*; 4 | 5 | type Range = [u64; 2]; 6 | 7 | /// The trick to merge ranges efficiently is to sort by the *starting* index. 8 | pub fn parse(input: &str) -> Vec { 9 | let mut ranges: Vec<_> = input.iter_unsigned().chunk::<2>().collect(); 10 | ranges.sort_unstable_by_key(|r| r[0]); 11 | ranges 12 | } 13 | 14 | pub fn part1(input: &[Range]) -> u64 { 15 | let mut index = 0; 16 | 17 | for &[start, end] in input { 18 | if index < start { 19 | return index; 20 | } 21 | // Ends are not sorted so only increase. 22 | index = index.max(end + 1); 23 | } 24 | 25 | unreachable!() 26 | } 27 | 28 | pub fn part2(input: &[Range]) -> u64 { 29 | let mut index = 0; 30 | let mut total = 0; 31 | 32 | for &[start, end] in input { 33 | if index < start { 34 | total += start - index; 35 | } 36 | // Ends are not sorted so only increase. 37 | index = index.max(end + 1); 38 | } 39 | 40 | total 41 | } 42 | -------------------------------------------------------------------------------- /src/year2025/day01.rs: -------------------------------------------------------------------------------- 1 | //! # Secret Entrance 2 | //! 3 | //! Part two left turns are easier if we first "reverse" the dial, then treat it as a right turn. 4 | use crate::util::parse::*; 5 | 6 | type Input = (i32, i32); 7 | 8 | pub fn parse(input: &str) -> Input { 9 | let directions = input.bytes().filter(|&b| b.is_ascii_uppercase()); 10 | let amounts = input.iter_signed::(); 11 | 12 | let mut dial = 50; 13 | let mut part_one = 0; 14 | let mut part_two = 0; 15 | 16 | for (direction, amount) in directions.zip(amounts) { 17 | if direction == b'R' { 18 | part_two += (dial + amount) / 100; 19 | dial = (dial + amount) % 100; 20 | } else { 21 | let reversed = (100 - dial) % 100; 22 | part_two += (reversed + amount) / 100; 23 | dial = (dial - amount).rem_euclid(100); 24 | } 25 | part_one += i32::from(dial == 0); 26 | } 27 | 28 | (part_one, part_two) 29 | } 30 | 31 | pub fn part1(input: &Input) -> i32 { 32 | input.0 33 | } 34 | 35 | pub fn part2(input: &Input) -> i32 { 36 | input.1 37 | } 38 | -------------------------------------------------------------------------------- /src/year2021/day01.rs: -------------------------------------------------------------------------------- 1 | //! # Sonar Sweep 2 | //! 3 | //! The built-in [`windows`] method comes in handy for this solution. For part 1 a straightforward 4 | //! sliding window of size 2 allows us to compare each 2 consecutive values. 5 | //! 6 | //! For part 2 we can use a trick to simplify. If we consider the first 2 windows of 3 elements 7 | //! each: 8 | //! 9 | //! ```none 10 | //! A1 A2 A3 11 | //! B1 B2 B3 12 | //! ``` 13 | //! 14 | //! then the middle 2 elements are always in common, so the subsequent window is greater only 15 | //! if the last element is greater than the first. This means we can pick a sliding window of 16 | //! size 4 and compare the first and last elements, without having to sum intermediate elements. 17 | //! 18 | //! [`windows`]: slice::windows 19 | use crate::util::parse::*; 20 | 21 | pub fn parse(input: &str) -> Vec { 22 | input.iter_unsigned().collect() 23 | } 24 | 25 | pub fn part1(input: &[u32]) -> usize { 26 | input.windows(2).filter(|w| w[0] < w[1]).count() 27 | } 28 | 29 | pub fn part2(input: &[u32]) -> usize { 30 | input.windows(4).filter(|w| w[0] < w[3]).count() 31 | } 32 | -------------------------------------------------------------------------------- /tests/year2022/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2022::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | Sensor at x=2, y=18: closest beacon is at x=-2, y=15 5 | Sensor at x=9, y=16: closest beacon is at x=10, y=16 6 | Sensor at x=13, y=2: closest beacon is at x=15, y=3 7 | Sensor at x=12, y=14: closest beacon is at x=10, y=16 8 | Sensor at x=10, y=20: closest beacon is at x=10, y=16 9 | Sensor at x=14, y=17: closest beacon is at x=10, y=16 10 | Sensor at x=8, y=7: closest beacon is at x=2, y=10 11 | Sensor at x=2, y=0: closest beacon is at x=2, y=10 12 | Sensor at x=0, y=11: closest beacon is at x=2, y=10 13 | Sensor at x=20, y=14: closest beacon is at x=25, y=17 14 | Sensor at x=17, y=20: closest beacon is at x=21, y=22 15 | Sensor at x=16, y=7: closest beacon is at x=15, y=3 16 | Sensor at x=14, y=3: closest beacon is at x=15, y=3 17 | Sensor at x=20, y=1: closest beacon is at x=15, y=3"; 18 | 19 | #[test] 20 | fn part1_test() { 21 | let input = parse(EXAMPLE); 22 | assert_eq!(part1_testable(&input, 10), 26); 23 | } 24 | 25 | #[test] 26 | fn part2_test() { 27 | let input = parse(EXAMPLE); 28 | assert_eq!(part2_testable(&input, 20), 56000011); 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | **Copyright © 2023-2025 maneatingape** 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/year2019/day01.rs: -------------------------------------------------------------------------------- 1 | //! # The Tyranny of the Rocket Equation 2 | //! 3 | //! The title of the problem is a reference to the 4 | //! [real life equation](https://en.wikipedia.org/wiki/Tsiolkovsky_rocket_equation). 5 | use crate::util::parse::*; 6 | 7 | /// The [`iter_unsigned`] utility method extracts and parses numbers from surrounding text. 8 | /// 9 | /// [`iter_unsigned`]: crate::util::parse 10 | pub fn parse(input: &str) -> Vec { 11 | input.iter_unsigned().collect() 12 | } 13 | 14 | /// Calculate fuel requirements following the formula. 15 | pub fn part1(input: &[u32]) -> u32 { 16 | input.iter().map(|mass| mass / 3 - 2).sum() 17 | } 18 | 19 | /// Calculate the fuel requirements taking into account that fuel needs more fuel to lift it. 20 | /// Mass of 8 or below results in zero or negative fuel so we can stop. 21 | pub fn part2(input: &[u32]) -> u32 { 22 | input 23 | .iter() 24 | .copied() 25 | .map(|mut mass| { 26 | let mut fuel = 0; 27 | while mass > 8 { 28 | mass = mass / 3 - 2; 29 | fuel += mass; 30 | } 31 | fuel 32 | }) 33 | .sum() 34 | } 35 | -------------------------------------------------------------------------------- /tests/year2021/day08.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day08::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe 5 | edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc 6 | fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg 7 | fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb 8 | aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea 9 | fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb 10 | dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe 11 | bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef 12 | egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb 13 | gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce"; 14 | 15 | #[test] 16 | fn part1_test() { 17 | let input = parse(EXAMPLE); 18 | assert_eq!(part1(&input), 26); 19 | } 20 | 21 | #[test] 22 | fn part2_test() { 23 | let input = parse(EXAMPLE); 24 | assert_eq!(part2(&input), 61229); 25 | } 26 | -------------------------------------------------------------------------------- /src/year2020/day05.rs: -------------------------------------------------------------------------------- 1 | //! # Binary Boarding 2 | //! 3 | //! The entire part one description is an obfuscated way to describe that each seat id is a 10 bit 4 | //! binary number, where `B` and `R` mean a 1 bit in that position and `F` and `L` mean a 0 bit. 5 | //! 6 | //! To solve part two we can have a little fun. Since we know that only a single seat is missing 7 | //! if we [XOR](https://en.wikipedia.org/wiki/XOR_gate) together all the seat ids from 8 | //! `min` to `max` then XOR with the actual seat ids, the result will be our missing seat id. 9 | pub struct Input { 10 | min: u32, 11 | max: u32, 12 | xor: u32, 13 | } 14 | 15 | pub fn parse(input: &str) -> Input { 16 | let (min, max, xor) = input.lines().fold((u32::MAX, u32::MIN, 0), |(min, max, xor), line| { 17 | let id = line.bytes().fold(0, |acc, b| (acc << 1) | (b == b'B' || b == b'R') as u32); 18 | (min.min(id), max.max(id), xor ^ id) 19 | }); 20 | 21 | Input { min, max, xor } 22 | } 23 | 24 | pub fn part1(input: &Input) -> u32 { 25 | input.max 26 | } 27 | 28 | pub fn part2(input: &Input) -> u32 { 29 | let rows = (input.min..=input.max).fold(0, |acc, b| acc ^ b); 30 | rows ^ input.xor 31 | } 32 | -------------------------------------------------------------------------------- /src/year2023/day04.rs: -------------------------------------------------------------------------------- 1 | //! # Scratchcards 2 | //! 3 | //! Part two is a dynamic programming problem. Starting with 1 copy of each card we add the extra 4 | //! number of copies to the number of following cards equal to the number of winning numbers. 5 | use crate::util::parse::*; 6 | 7 | pub fn parse(input: &str) -> Vec { 8 | input 9 | .lines() 10 | .map(|line| { 11 | // Numbers are at most 99 so we can use a fixed size array instead of a HashSet. 12 | let mut found = [false; 100]; 13 | let (win, have) = line.split_once('|').unwrap(); 14 | win.iter_unsigned::().skip(1).for_each(|i| found[i] = true); 15 | have.iter_unsigned::().filter(|&i| found[i]).count() 16 | }) 17 | .collect() 18 | } 19 | 20 | pub fn part1(input: &[usize]) -> u32 { 21 | input.iter().map(|&n| (1 << n) >> 1).sum() 22 | } 23 | 24 | pub fn part2(input: &[usize]) -> u32 { 25 | // Start with a single copy of each card. 26 | let mut copies = vec![1; input.len()]; 27 | 28 | for (i, &n) in input.iter().enumerate() { 29 | (0..n).for_each(|j| copies[i + j + 1] += copies[i]); 30 | } 31 | 32 | copies.iter().sum() 33 | } 34 | -------------------------------------------------------------------------------- /src/year2016/day06.rs: -------------------------------------------------------------------------------- 1 | //! # Signals and Noise 2 | //! 3 | //! The cardinality of uppercase letters is only 26 so we can use a fixed size array to 4 | //! count the frequency of each character efficiently. 5 | type Input = (String, String); 6 | 7 | pub fn parse(input: &str) -> Input { 8 | let width = input.lines().next().unwrap().len(); 9 | let stride = width + 1; 10 | let input = input.as_bytes(); 11 | 12 | let to_index = |b: u8| (b - b'a') as usize; 13 | let to_char = |i: usize| ((i as u8) + b'a') as char; 14 | 15 | (0..width) 16 | .map(|offset| { 17 | let mut freq = [0; 26]; 18 | input.iter().skip(offset).step_by(stride).for_each(|&b| freq[to_index(b)] += 1); 19 | 20 | let (max, _) = 21 | freq.iter().enumerate().filter(|&(_, &f)| f > 0).max_by_key(|&(_, &f)| f).unwrap(); 22 | let (min, _) = 23 | freq.iter().enumerate().filter(|&(_, &f)| f > 0).min_by_key(|&(_, &f)| f).unwrap(); 24 | 25 | (to_char(max), to_char(min)) 26 | }) 27 | .unzip() 28 | } 29 | 30 | pub fn part1(input: &Input) -> &str { 31 | &input.0 32 | } 33 | 34 | pub fn part2(input: &Input) -> &str { 35 | &input.1 36 | } 37 | -------------------------------------------------------------------------------- /src/year2017/day09.rs: -------------------------------------------------------------------------------- 1 | //! # Stream Processing 2 | //! 3 | //! Computes both parts in a single pass. 4 | type Input = (u32, u32); 5 | 6 | pub fn parse(input: &str) -> Input { 7 | let mut iter = input.bytes(); 8 | let mut groups = 0; 9 | let mut depth = 1; 10 | let mut characters = 0; 11 | 12 | while let Some(b) = iter.next() { 13 | match b { 14 | b'<' => { 15 | // Inner loop for garbage. 16 | while let Some(b) = iter.next() { 17 | match b { 18 | b'!' => { 19 | iter.next(); 20 | } 21 | b'>' => break, 22 | _ => characters += 1, 23 | } 24 | } 25 | } 26 | b'{' => { 27 | groups += depth; 28 | depth += 1; 29 | } 30 | b'}' => { 31 | depth -= 1; 32 | } 33 | _ => (), 34 | } 35 | } 36 | 37 | (groups, characters) 38 | } 39 | 40 | pub fn part1(input: &Input) -> u32 { 41 | input.0 42 | } 43 | 44 | pub fn part2(input: &Input) -> u32 { 45 | input.1 46 | } 47 | -------------------------------------------------------------------------------- /tests/year2024/day24.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day24::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | x00: 1 5 | x01: 0 6 | x02: 1 7 | x03: 1 8 | x04: 0 9 | y00: 1 10 | y01: 1 11 | y02: 1 12 | y03: 1 13 | y04: 1 14 | 15 | ntg XOR fgs -> mjb 16 | y02 OR x01 -> tnw 17 | kwq OR kpj -> z05 18 | x00 OR x03 -> fst 19 | tgd XOR rvg -> z01 20 | vdt OR tnw -> bfw 21 | bfw AND frj -> z10 22 | ffh OR nrd -> bqk 23 | y00 AND y03 -> djm 24 | y03 OR y00 -> psh 25 | bqk OR frj -> z08 26 | tnw OR fst -> frj 27 | gnj AND tgd -> z11 28 | bfw XOR mjb -> z00 29 | x03 OR x00 -> vdt 30 | gnj AND wpb -> z02 31 | x04 AND y00 -> kjc 32 | djm OR pbm -> qhw 33 | nrd AND vdt -> hwm 34 | kjc AND fst -> rvg 35 | y04 OR y02 -> fgs 36 | y01 AND x02 -> pbm 37 | ntg OR kjc -> kwq 38 | psh XOR fgs -> tgd 39 | qhw XOR tgd -> z09 40 | pbm OR djm -> kpj 41 | x03 XOR y03 -> ffh 42 | x00 XOR y04 -> ntg 43 | bfw OR bqk -> z06 44 | nrd XOR fgs -> wpb 45 | frj XOR qhw -> z04 46 | bqk OR frj -> z07 47 | y03 OR x01 -> nrd 48 | hwm AND bqk -> z03 49 | tgd XOR rvg -> z12 50 | tnw OR pbm -> gnj"; 51 | 52 | #[test] 53 | fn part1_test() { 54 | let input = parse(EXAMPLE); 55 | assert_eq!(part1(&input), 2024); 56 | } 57 | 58 | #[test] 59 | fn part2_test() { 60 | // No test 61 | } 62 | -------------------------------------------------------------------------------- /tests/year2024/day15.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2024::day15::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | ########## 5 | #..O..O.O# 6 | #......O.# 7 | #.OO..O.O# 8 | #..O@..O.# 9 | #O#..O...# 10 | #O..O..O.# 11 | #.OO.O.OO# 12 | #....O...# 13 | ########## 14 | 15 | ^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ 16 | vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< 18 | <>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ 19 | ^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< 20 | ^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ 22 | <><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> 23 | ^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< 24 | v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^"; 25 | 26 | #[test] 27 | fn part1_test() { 28 | let input = parse(EXAMPLE); 29 | assert_eq!(part1(&input), 10092); 30 | } 31 | 32 | #[test] 33 | fn part2_test() { 34 | let input = parse(EXAMPLE); 35 | assert_eq!(part2(&input), 9021); 36 | } 37 | -------------------------------------------------------------------------------- /tests/year2021/day16.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2021::day16::*; 2 | 3 | #[test] 4 | fn part1_test() { 5 | let input = parse("8A004A801A8002F478"); 6 | assert_eq!(part1(&input), 16); 7 | 8 | let input = parse("620080001611562C8802118E34"); 9 | assert_eq!(part1(&input), 12); 10 | 11 | let input = parse("C0015000016115A2E0802F182340"); 12 | assert_eq!(part1(&input), 23); 13 | 14 | let input = parse("A0016C880162017C3686B18A3D4780"); 15 | assert_eq!(part1(&input), 31); 16 | } 17 | 18 | #[test] 19 | fn part2_test() { 20 | let input = parse("C200B40A82"); 21 | assert_eq!(part2(&input), 3); 22 | 23 | let input = parse("04005AC33890"); 24 | assert_eq!(part2(&input), 54); 25 | 26 | let input = parse("880086C3E88112"); 27 | assert_eq!(part2(&input), 7); 28 | 29 | let input = parse("CE00C43D881120"); 30 | assert_eq!(part2(&input), 9); 31 | 32 | let input = parse("D8005AC2A8F0"); 33 | assert_eq!(part2(&input), 1); 34 | 35 | let input = parse("F600BC2D8F"); 36 | assert_eq!(part2(&input), 0); 37 | 38 | let input = parse("9C005AC2F8F0"); 39 | assert_eq!(part2(&input), 0); 40 | 41 | let input = parse("9C0141080250320F1802104A08"); 42 | assert_eq!(part2(&input), 1); 43 | } 44 | -------------------------------------------------------------------------------- /src/year2025/day05.rs: -------------------------------------------------------------------------------- 1 | //! # Cafeteria 2 | use crate::util::iter::*; 3 | use crate::util::parse::*; 4 | use std::ops::Range; 5 | 6 | type Input = (Vec>, Vec); 7 | 8 | pub fn parse(input: &str) -> Input { 9 | let (prefix, suffix) = input.split_once("\n\n").unwrap(); 10 | let mut ranges: Vec<_> = prefix.iter_unsigned().chunk::<2>().collect(); 11 | let mut ids: Vec<_> = suffix.iter_unsigned().collect(); 12 | let mut range = 0..0; 13 | let mut merged = Vec::new(); 14 | 15 | ranges.sort_unstable(); 16 | ids.sort_unstable(); 17 | 18 | for [from, to] in ranges { 19 | if from < range.end { 20 | range.end = range.end.max(to + 1); 21 | } else { 22 | merged.push(range); 23 | range = from..to + 1; 24 | } 25 | } 26 | 27 | merged.push(range); 28 | (merged, ids) 29 | } 30 | 31 | pub fn part1(input: &Input) -> usize { 32 | let (merged, ids) = input; 33 | let position = |id: u64| ids.binary_search(&id).unwrap_or_else(|e| e); 34 | merged.iter().map(|range| position(range.end) - position(range.start)).sum() 35 | } 36 | 37 | pub fn part2(input: &Input) -> u64 { 38 | let (merged, _) = input; 39 | merged.iter().map(|range| range.end - range.start).sum() 40 | } 41 | -------------------------------------------------------------------------------- /src/year2017/day02.rs: -------------------------------------------------------------------------------- 1 | //! # Corruption Checksum 2 | //! 3 | //! Part two is `O(n²)` complexity but at least we can reduce by a factor of two by sorting 4 | //! each line first, allowing us to only compare each number against those that are greater. 5 | //! As a minor benefit this makes part one faster too. 6 | use crate::util::parse::*; 7 | 8 | type Input = Vec>; 9 | 10 | pub fn parse(input: &str) -> Input { 11 | input 12 | .lines() 13 | .map(|line| { 14 | let mut values: Vec<_> = line.iter_unsigned().collect(); 15 | values.sort_unstable(); 16 | values 17 | }) 18 | .collect() 19 | } 20 | 21 | pub fn part1(input: &Input) -> u32 { 22 | input.iter().map(|values| values.last().unwrap() - values.first().unwrap()).sum() 23 | } 24 | 25 | pub fn part2(input: &Input) -> u32 { 26 | input 27 | .iter() 28 | .map(|values| { 29 | for (i, &smaller) in values.iter().enumerate() { 30 | for &larger in &values[i + 1..] { 31 | if larger.is_multiple_of(smaller) { 32 | return larger / smaller; 33 | } 34 | } 35 | } 36 | unreachable!() 37 | }) 38 | .sum() 39 | } 40 | -------------------------------------------------------------------------------- /src/year2025/day06.rs: -------------------------------------------------------------------------------- 1 | //! # Trash Compactor 2 | use crate::util::grid::*; 3 | use crate::util::point::*; 4 | 5 | type Input = (u64, u64); 6 | 7 | pub fn parse(input: &str) -> Input { 8 | let grid = Grid::parse(input); 9 | let bottom = grid.height - 1; 10 | let mut right = grid.width; 11 | 12 | let block = |(part_one, part_two), left| { 13 | let rows = (0..bottom).map(|y| (left..right).fold(0, |num, x| acc(&grid, num, x, y))); 14 | let cols = (left..right).map(|x| (0..bottom).fold(0, |num, y| acc(&grid, num, x, y))); 15 | 16 | let plus = grid[Point::new(left, bottom)] == b'+'; 17 | let first: u64 = if plus { rows.sum() } else { rows.product() }; 18 | let second: u64 = if plus { cols.sum() } else { cols.product() }; 19 | 20 | right = left - 1; 21 | (part_one + first, part_two + second) 22 | }; 23 | 24 | (0..grid.width).rev().filter(|&x| grid[Point::new(x, bottom)] != b' ').fold((0, 0), block) 25 | } 26 | 27 | pub fn part1(input: &Input) -> u64 { 28 | input.0 29 | } 30 | 31 | pub fn part2(input: &Input) -> u64 { 32 | input.1 33 | } 34 | 35 | fn acc(grid: &Grid, number: u64, x: i32, y: i32) -> u64 { 36 | let digit = grid[Point::new(x, y)]; 37 | if digit == b' ' { number } else { 10 * number + u64::from(digit - b'0') } 38 | } 39 | -------------------------------------------------------------------------------- /src/year2015/day03.rs: -------------------------------------------------------------------------------- 1 | //! # Perfectly Spherical Houses in a Vacuum 2 | //! 3 | //! We store Santa's path in a [`FastSet`] of [`Point`] objects that deduplicates visited points. 4 | //! For part two we alternate between Santa and the robot, tracking two points simultaneously and 5 | //! reusing the same deduplicating logic as part one. 6 | //! 7 | //! [`FastSet`]: crate::util::hash 8 | //! [`Point`]: crate::util::point 9 | use crate::util::hash::*; 10 | use crate::util::point::*; 11 | 12 | pub fn parse(input: &str) -> Vec { 13 | input.trim().bytes().map(Point::from).collect() 14 | } 15 | 16 | pub fn part1(input: &[Point]) -> usize { 17 | deliver(input, |_| true) 18 | } 19 | 20 | pub fn part2(input: &[Point]) -> usize { 21 | deliver(input, |i| i.is_multiple_of(2)) 22 | } 23 | 24 | fn deliver(input: &[Point], predicate: fn(usize) -> bool) -> usize { 25 | let mut santa = ORIGIN; 26 | let mut robot = ORIGIN; 27 | 28 | let mut set = FastSet::with_capacity(input.len()); 29 | set.insert(ORIGIN); 30 | 31 | for (index, &point) in input.iter().enumerate() { 32 | if predicate(index) { 33 | santa += point; 34 | set.insert(santa); 35 | } else { 36 | robot += point; 37 | set.insert(robot); 38 | } 39 | } 40 | 41 | set.len() 42 | } 43 | -------------------------------------------------------------------------------- /src/year2017/day19.rs: -------------------------------------------------------------------------------- 1 | //! # A Series of Tubes 2 | //! 3 | //! Uses the utility [`Grid`] to parse the input, then the [`Point`] class to follow the path. 4 | //! 5 | //! [`Grid`]: crate::util::grid 6 | //! [`Point`]: crate::util::point 7 | use crate::util::grid::*; 8 | use crate::util::point::*; 9 | 10 | type Input = (String, u32); 11 | 12 | pub fn parse(input: &str) -> Input { 13 | let grid = Grid::parse(input); 14 | 15 | let mut position = grid.find(b'|').unwrap(); 16 | let mut direction = DOWN; 17 | 18 | let mut part_one = String::new(); 19 | let mut part_two = 0; 20 | 21 | loop { 22 | let next = grid[position]; 23 | 24 | match next { 25 | b'+' => { 26 | let left = direction.counter_clockwise(); 27 | let right = direction.clockwise(); 28 | direction = if grid[position + right] == b' ' { left } else { right }; 29 | } 30 | b' ' => break, 31 | _ if next.is_ascii_alphabetic() => part_one.push(next as char), 32 | _ => (), 33 | } 34 | 35 | position += direction; 36 | part_two += 1; 37 | } 38 | 39 | (part_one, part_two) 40 | } 41 | 42 | pub fn part1(input: &Input) -> &str { 43 | input.0.as_str() 44 | } 45 | 46 | pub fn part2(input: &Input) -> u32 { 47 | input.1 48 | } 49 | -------------------------------------------------------------------------------- /src/year2022/day10.rs: -------------------------------------------------------------------------------- 1 | //! # Cathode-Ray Tube 2 | use crate::util::parse::*; 3 | 4 | /// Tokenizes the input treating both "noop" and "addx" as no-ops to obtain the correct 5 | /// instruction timing. Produces a `vec` of the absolute values of `x` from cycle 0 to 241. 6 | pub fn parse(input: &str) -> Vec { 7 | let mut x = 1; 8 | let mut xs = vec![1]; 9 | 10 | for token in input.split_ascii_whitespace() { 11 | match token { 12 | "noop" | "addx" => (), 13 | delta => x += delta.signed::(), 14 | } 15 | xs.push(x); 16 | } 17 | 18 | xs 19 | } 20 | 21 | /// Converts between the 0-based indexing produced by the `parse` function and the 1-based indexing 22 | /// used by the problem statement. 23 | pub fn part1(input: &[i32]) -> i32 { 24 | input.iter().enumerate().skip(19).step_by(40).map(|(i, &x)| ((i + 1) as i32) * x).sum() 25 | } 26 | 27 | /// Returns pixels as a multi-line [`String`] so that the entire function can be integration tested. 28 | pub fn part2(input: &[i32]) -> String { 29 | let mut result = String::new(); 30 | 31 | for row in input.chunks_exact(40) { 32 | result.push('\n'); 33 | for (i, &c) in row.iter().enumerate() { 34 | result.push(if ((i as i32) - c).abs() <= 1 { '#' } else { '.' }); 35 | } 36 | } 37 | 38 | result 39 | } 40 | -------------------------------------------------------------------------------- /src/year2023/day02.rs: -------------------------------------------------------------------------------- 1 | //! # Cube Conundrum 2 | use crate::util::iter::*; 3 | use crate::util::parse::*; 4 | 5 | type Game = (u32, u32, u32); 6 | 7 | /// Parse each game into the maximum red, green and blue values. 8 | pub fn parse(input: &str) -> Vec { 9 | input 10 | .lines() 11 | .map(|line| { 12 | line.split_ascii_whitespace().chunk::<2>().skip(1).fold( 13 | (0, 0, 0), 14 | |(r, g, b), [amount, color]| { 15 | let amount = amount.unsigned(); 16 | match color.as_bytes()[0] { 17 | b'r' => (r.max(amount), g, b), 18 | b'g' => (r, g.max(amount), b), 19 | b'b' => (r, g, b.max(amount)), 20 | _ => unreachable!(), 21 | } 22 | }, 23 | ) 24 | }) 25 | .collect() 26 | } 27 | 28 | /// Sum the ids for all valid games. 29 | pub fn part1(input: &[Game]) -> usize { 30 | input 31 | .iter() 32 | .enumerate() 33 | .filter_map(|(id, &(r, g, b))| (r <= 12 && g <= 13 && b <= 14).then_some(id + 1)) 34 | .sum() 35 | } 36 | 37 | /// Sum the product of maximum red, green and blue values. 38 | pub fn part2(input: &[Game]) -> u32 { 39 | input.iter().map(|(r, g, b)| r * g * b).sum() 40 | } 41 | -------------------------------------------------------------------------------- /tests/year2020/day19.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day19::*; 2 | 3 | const EXAMPLE: &str = "\ 4 | 42: 9 14 | 10 1 5 | 9: 14 27 | 1 26 6 | 10: 23 14 | 28 1 7 | 1: \"a\" 8 | 11: 42 31 9 | 5: 1 14 | 15 1 10 | 19: 14 1 | 14 14 11 | 12: 24 14 | 19 1 12 | 16: 15 1 | 14 14 13 | 31: 14 17 | 1 13 14 | 6: 14 14 | 1 14 15 | 2: 1 24 | 14 4 16 | 0: 8 11 17 | 13: 14 3 | 1 12 18 | 15: 1 | 14 19 | 17: 14 2 | 1 7 20 | 23: 25 1 | 22 14 21 | 28: 16 1 22 | 4: 1 1 23 | 20: 14 14 | 1 15 24 | 3: 5 14 | 16 1 25 | 27: 1 6 | 14 18 26 | 14: \"b\" 27 | 21: 14 1 | 1 14 28 | 25: 1 1 | 1 14 29 | 22: 14 14 30 | 8: 42 31 | 26: 14 22 | 1 20 32 | 18: 15 15 33 | 7: 14 5 | 1 21 34 | 24: 14 1 35 | 36 | abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa 37 | bbabbbbaabaabba 38 | babbbbaabbbbbabbbbbbaabaaabaaa 39 | aaabbbbbbaaaabaababaabababbabaaabbababababaaa 40 | bbbbbbbaaaabbbbaaabbabaaa 41 | bbbababbbbaaaaaaaabbababaaababaabab 42 | ababaaaaaabaaab 43 | ababaaaaabbbaba 44 | baabbaaaabbaaaababbaababb 45 | abbbbabbbbaaaababbbbbbaaaababb 46 | aaaaabbaabaaaaababaa 47 | aaaabbaaaabbaaa 48 | aaaabbaabbaaaaaaabbbabbbaaabbaabaaa 49 | babaaabbbaaabaababbaabababaaab 50 | aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba"; 51 | 52 | #[test] 53 | fn part1_test() { 54 | let input = parse(EXAMPLE); 55 | assert_eq!(part1(&input), 3); 56 | } 57 | 58 | #[test] 59 | fn part2_test() { 60 | let input = parse(EXAMPLE); 61 | assert_eq!(part2(&input), 12); 62 | } 63 | -------------------------------------------------------------------------------- /src/year2018/day02.rs: -------------------------------------------------------------------------------- 1 | //! # Inventory Management System 2 | use crate::util::hash::*; 3 | 4 | pub fn parse(input: &str) -> Vec<&[u8]> { 5 | input.lines().map(str::as_bytes).collect() 6 | } 7 | 8 | pub fn part1(input: &[&[u8]]) -> u32 { 9 | let mut twos = 0; 10 | let mut threes = 0; 11 | 12 | for &id in input { 13 | // Ids are lowercase ASCII only with cardinality of 26. 14 | let mut freq = [0_u8; 26]; 15 | 16 | for &b in id { 17 | freq[(b - b'a') as usize] += 1; 18 | } 19 | 20 | twos += freq.contains(&2) as u32; 21 | threes += freq.contains(&3) as u32; 22 | } 23 | 24 | twos * threes 25 | } 26 | 27 | pub fn part2(input: &[&[u8]]) -> String { 28 | let width = input[0].len(); 29 | let mut seen = FastSet::with_capacity(input.len()); 30 | 31 | // Use a set to check for duplicates by comparing the prefix and suffix of IDs excluding one 32 | // column at a time. 33 | for column in 0..width { 34 | for &id in input { 35 | let prefix = &id[..column]; 36 | let suffix = &id[column + 1..]; 37 | 38 | if !seen.insert([prefix, suffix]) { 39 | // Convert to String 40 | return prefix.iter().chain(suffix).copied().map(char::from).collect(); 41 | } 42 | } 43 | 44 | seen.clear(); 45 | } 46 | 47 | unreachable!() 48 | } 49 | -------------------------------------------------------------------------------- /src/year2016/day02.rs: -------------------------------------------------------------------------------- 1 | //! # Bathroom Security 2 | //! 3 | //! Relies heavily on the [`point`] and [`grid`] modules. 4 | //! 5 | //! [`grid`]: crate::util::grid 6 | //! [`point`]: crate::util::point 7 | use crate::util::grid::*; 8 | use crate::util::point::*; 9 | 10 | pub fn parse(input: &str) -> Vec<&str> { 11 | input.lines().collect() 12 | } 13 | 14 | pub fn part1(input: &[&str]) -> String { 15 | let digits = Grid::parse("123\n456\n789"); 16 | let mut position = ORIGIN; 17 | let mut result = String::new(); 18 | 19 | for line in input { 20 | for b in line.bytes() { 21 | let next = position + Point::from(b); 22 | if next.x.abs() <= 1 && next.y.abs() <= 1 { 23 | position = next; 24 | } 25 | } 26 | result.push(digits[position + Point::new(1, 1)] as char); 27 | } 28 | 29 | result 30 | } 31 | 32 | pub fn part2(input: &[&str]) -> String { 33 | let digits = Grid::parse("##1##\n#234#\n56789\n#ABC#\n##D##"); 34 | let mut position = Point::new(-2, 0); 35 | let mut result = String::new(); 36 | 37 | for line in input { 38 | for b in line.bytes() { 39 | let next = position + Point::from(b); 40 | if next.manhattan(ORIGIN) <= 2 { 41 | position = next; 42 | } 43 | } 44 | result.push(digits[position + Point::new(2, 2)] as char); 45 | } 46 | 47 | result 48 | } 49 | -------------------------------------------------------------------------------- /tests/year2020/day04.rs: -------------------------------------------------------------------------------- 1 | use aoc::year2020::day04::*; 2 | 3 | const FIRST_EXAMPLE: &str = "\ 4 | ecl:gry pid:860033327 eyr:2020 hcl:#fffffd 5 | byr:1937 iyr:2017 cid:147 hgt:183cm 6 | 7 | iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 8 | hcl:#cfa07d byr:1929 9 | 10 | hcl:#ae17e1 iyr:2013 11 | eyr:2024 12 | ecl:brn pid:760753108 byr:1931 13 | hgt:179cm 14 | 15 | hcl:#cfa07d eyr:2025 pid:166559648 16 | iyr:2011 ecl:brn hgt:59in"; 17 | 18 | const SECOND_EXAMPLE: &str = "\ 19 | eyr:1972 cid:100 20 | hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926 21 | 22 | iyr:2019 23 | hcl:#602927 eyr:1967 hgt:170cm 24 | ecl:grn pid:012533040 byr:1946 25 | 26 | hcl:dab227 iyr:2012 27 | ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277 28 | 29 | hgt:59cm ecl:zzz 30 | eyr:2038 hcl:74454a iyr:2023 31 | pid:3556412378 byr:2007 32 | 33 | pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 34 | hcl:#623a2f 35 | 36 | eyr:2029 ecl:blu cid:129 byr:1989 37 | iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm 38 | 39 | hcl:#888785 40 | hgt:164cm byr:2001 iyr:2015 cid:88 41 | pid:545766238 ecl:hzl 42 | eyr:2022 43 | 44 | iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719"; 45 | 46 | #[test] 47 | fn part1_test() { 48 | let input = parse(FIRST_EXAMPLE); 49 | assert_eq!(part1(&input), 2); 50 | } 51 | 52 | #[test] 53 | fn part2_test() { 54 | let input = parse(SECOND_EXAMPLE); 55 | assert_eq!(part2(&input), 4); 56 | } 57 | -------------------------------------------------------------------------------- /src/year2020/day10.rs: -------------------------------------------------------------------------------- 1 | //! # Adapter Array 2 | //! 3 | //! Part one uses the [`windows`] function to iterate over all pairs counting the differences. 4 | //! 5 | //! Part two is a classic [dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming) 6 | //! problem. The charging outlet can be arranged in exactly one way. Each subsequent adapter can be 7 | //! arranged in the sum of the number of ways that the adapters at -1, -2 and -3 jolts can be 8 | //! arranged. 9 | //! 10 | //! [`windows`]: slice::windows 11 | use crate::util::parse::*; 12 | 13 | pub fn parse(input: &str) -> Vec { 14 | let mut adapters: Vec<_> = input.iter_unsigned().collect(); 15 | adapters.sort_unstable(); 16 | adapters 17 | } 18 | 19 | pub fn part1(input: &[usize]) -> usize { 20 | let mut total = [0, 0, 0, 1]; 21 | total[input[0]] += 1; 22 | 23 | for w in input.windows(2) { 24 | let diff = w[0].abs_diff(w[1]); 25 | total[diff] += 1; 26 | } 27 | 28 | total[1] * total[3] 29 | } 30 | 31 | pub fn part2(input: &[usize]) -> usize { 32 | let last = input.last().unwrap(); 33 | let mut sum = vec![0; last + 1]; 34 | sum[0] = 1; 35 | 36 | for &i in input { 37 | match i { 38 | 1 => sum[i] = sum[i - 1], 39 | 2 => sum[i] = sum[i - 1] + sum[i - 2], 40 | _ => sum[i] = sum[i - 1] + sum[i - 2] + sum[i - 3], 41 | } 42 | } 43 | 44 | *sum.last().unwrap() 45 | } 46 | -------------------------------------------------------------------------------- /src/year2025/day11.rs: -------------------------------------------------------------------------------- 1 | //! # Reactor 2 | type Input = Vec>; 3 | 4 | pub fn parse(input: &str) -> Input { 5 | let mut graph = vec![vec![]; 26 * 26 * 26]; 6 | 7 | for line in input.lines() { 8 | let mut edges = line.split_ascii_whitespace(); 9 | let from = edges.next().unwrap(); 10 | graph[to_index(from)].extend(edges.map(to_index)); 11 | } 12 | 13 | graph 14 | } 15 | 16 | pub fn part1(input: &Input) -> u64 { 17 | paths(input, "you", "out") 18 | } 19 | 20 | pub fn part2(input: &Input) -> u64 { 21 | let one = paths(input, "svr", "fft") * paths(input, "fft", "dac") * paths(input, "dac", "out"); 22 | let two = paths(input, "svr", "dac") * paths(input, "dac", "fft") * paths(input, "fft", "out"); 23 | one + two 24 | } 25 | 26 | fn paths(input: &Input, from: &str, to: &str) -> u64 { 27 | let mut cache = vec![u64::MAX; input.len()]; 28 | dfs(input, &mut cache, to_index(from), to_index(to)) 29 | } 30 | 31 | fn dfs(input: &Input, cache: &mut [u64], node: usize, end: usize) -> u64 { 32 | if node == end { 33 | 1 34 | } else if cache[node] == u64::MAX { 35 | let result = input[node].iter().map(|&next| dfs(input, cache, next, end)).sum(); 36 | cache[node] = result; 37 | result 38 | } else { 39 | cache[node] 40 | } 41 | } 42 | 43 | fn to_index(s: &str) -> usize { 44 | s.bytes().take(3).fold(0, |acc, b| 26 * acc + usize::from(b - b'a')) 45 | } 46 | -------------------------------------------------------------------------------- /src/year2024/day25.rs: -------------------------------------------------------------------------------- 1 | //! # Code Chronicle 2 | //! 3 | //! Efficiently checks if locks and keys overlap using bitwise logic. The ASCII character 4 | //! `#` (35) is odd and `.` (46) is even so bitwise AND with 1 results in either 1 or 0. 5 | //! The newline character `\n` (10) is even so will result in 0 and not contribute to matches. 6 | //! There are 25 bits plus 4 newline bits so each lock or key can be stored in an `u32`. 7 | //! For example: 8 | //! 9 | //! ```none 10 | //! ##### 11 | //! ##.## 11011 12 | //! .#.## 01011 13 | //! ...## => 00011 => 110110_010110_000110_000100_00010 14 | //! ...#. 00010 15 | //! ...#. 00010 16 | //! ..... 17 | //! ``` 18 | pub fn parse(input: &str) -> &str { 19 | input 20 | } 21 | 22 | pub fn part1(input: &str) -> u32 { 23 | let mut locks = Vec::with_capacity(250); 24 | let mut keys = Vec::with_capacity(250); 25 | let mut result = 0; 26 | 27 | for slice in input.as_bytes().chunks(43) { 28 | let bits = slice[6..35].iter().fold(0, |bits, &n| (bits << 1) | (n & 1) as u32); 29 | 30 | if slice[0] == b'#' { 31 | locks.push(bits); 32 | } else { 33 | keys.push(bits); 34 | } 35 | } 36 | 37 | for lock in &locks { 38 | for key in &keys { 39 | result += (lock & key == 0) as u32; 40 | } 41 | } 42 | 43 | result 44 | } 45 | 46 | pub fn part2(_input: &str) -> &'static str { 47 | "n/a" 48 | } 49 | -------------------------------------------------------------------------------- /src/year2021/day07.rs: -------------------------------------------------------------------------------- 1 | //! # The Treachery of Whales 2 | //! 3 | //! Part 1 is a disguised definition of the mathematical [median](https://en.wikipedia.org/wiki/Median). 4 | //! We can calculate the result immediately using the standard algorithm. 5 | //! 6 | //! Part 2 is found by using the [mean](https://en.wikipedia.org/wiki/Mean). 7 | //! However since this could a floating point value and we are using integers we need to check 8 | //! 3 values total, the rounded result and one value on either side to ensure the correct answer. 9 | use crate::util::parse::*; 10 | 11 | pub fn parse(input: &str) -> Vec { 12 | input.iter_signed().collect() 13 | } 14 | 15 | pub fn part1(input: &[i32]) -> i32 { 16 | let median = median(input); 17 | input.iter().map(|n| (n - median).abs()).sum() 18 | } 19 | 20 | pub fn part2(input: &[i32]) -> i32 { 21 | let mean = mean(input); 22 | let triangle = |x: i32, mean: i32| { 23 | let n = (x - mean).abs(); 24 | (n * (n + 1)) / 2 25 | }; 26 | 27 | (-1..=1).map(|delta| input.iter().map(|&x| triangle(x, mean + delta)).sum()).min().unwrap() 28 | } 29 | 30 | fn median(input: &[i32]) -> i32 { 31 | let mut crabs = input.to_vec(); 32 | crabs.sort_unstable(); 33 | 34 | let half = input.len() / 2; 35 | if crabs.len().is_multiple_of(2) { crabs[half - 1].midpoint(crabs[half]) } else { crabs[half] } 36 | } 37 | 38 | fn mean(input: &[i32]) -> i32 { 39 | let sum: i32 = input.iter().sum(); 40 | sum / (input.len() as i32) 41 | } 42 | -------------------------------------------------------------------------------- /src/year2016/day09.rs: -------------------------------------------------------------------------------- 1 | //! # Explosives in Cyberspace 2 | //! 3 | //! The only difference between part one and two is that we recursively decompress inner sequences. 4 | use crate::util::parse::*; 5 | 6 | pub fn parse(input: &str) -> &[u8] { 7 | input.trim().as_bytes() 8 | } 9 | 10 | pub fn part1(input: &[u8]) -> usize { 11 | decompress(input, false) 12 | } 13 | 14 | pub fn part2(input: &[u8]) -> usize { 15 | decompress(input, true) 16 | } 17 | 18 | fn decompress(mut slice: &[u8], part_two: bool) -> usize { 19 | let mut length = 0; 20 | 21 | // Find the next marker. 22 | while let Some(start) = slice.iter().position(|&b| b == b'(') { 23 | let (next, amount) = number(&slice[start + 1..]); 24 | let (next, repeat) = number(next); 25 | 26 | // For part two, recursively decompress data. 27 | let result = if part_two { decompress(&next[..amount], true) } else { amount }; 28 | 29 | slice = &next[amount..]; 30 | length += start + result * repeat; 31 | } 32 | 33 | // Add remaining plain data that doesn't contain any marker. 34 | length + slice.len() 35 | } 36 | 37 | fn number(slice: &[u8]) -> (&[u8], usize) { 38 | // Parse number digit by digit. 39 | let mut index = 0; 40 | let mut acc = 0; 41 | 42 | while slice[index].is_ascii_digit() { 43 | acc = 10 * acc + slice[index].to_decimal() as usize; 44 | index += 1; 45 | } 46 | 47 | // Skip over trailing delimeter. 48 | (&slice[index + 1..], acc) 49 | } 50 | -------------------------------------------------------------------------------- /src/year2025/day02.rs: -------------------------------------------------------------------------------- 1 | //! # Gift Shop 2 | use crate::util::iter::*; 3 | use crate::util::parse::*; 4 | 5 | type Range = [u32; 2]; 6 | type Pair = [u64; 2]; 7 | 8 | const FIRST: [Range; 5] = [[2, 1], [4, 2], [6, 3], [8, 4], [10, 5]]; 9 | const SECOND: [Range; 6] = [[3, 1], [5, 1], [6, 2], [7, 1], [9, 3], [10, 2]]; 10 | const THIRD: [Range; 2] = [[6, 1], [10, 1]]; 11 | 12 | pub fn parse(input: &str) -> Vec { 13 | input.iter_unsigned::().chunk::<2>().collect() 14 | } 15 | 16 | pub fn part1(input: &[Pair]) -> u64 { 17 | sum(&FIRST, input) 18 | } 19 | 20 | pub fn part2(input: &[Pair]) -> u64 { 21 | sum(&FIRST, input) + sum(&SECOND, input) - sum(&THIRD, input) 22 | } 23 | 24 | fn sum(ranges: &[Range], input: &[Pair]) -> u64 { 25 | let mut result = 0; 26 | 27 | for &[digits, size] in ranges { 28 | let digits_power = 10_u64.pow(digits); 29 | let size_power = 10_u64.pow(size); 30 | 31 | let step = (digits_power - 1) / (size_power - 1); 32 | let start = step * (size_power / 10); 33 | let end = step * (size_power - 1); 34 | 35 | for &[from, to] in input { 36 | let lower = from.next_multiple_of(step).max(start); 37 | let upper = to.min(end); 38 | 39 | if lower <= upper { 40 | let n = (upper - lower) / step; 41 | let triangular = n * (n + 1) / 2; 42 | result += lower * (n + 1) + step * triangular; 43 | } 44 | } 45 | } 46 | 47 | result 48 | } 49 | -------------------------------------------------------------------------------- /src/util/integer.rs: -------------------------------------------------------------------------------- 1 | //! Combines common [operators](https://doc.rust-lang.org/book/appendix-02-operators.html) 2 | //! and constants `0`, `1` and `10` to enable generic methods on integer types. 3 | use std::ops::*; 4 | 5 | pub trait Integer: 6 | Copy 7 | + From 8 | + PartialEq 9 | + PartialOrd 10 | + Add 11 | + BitAnd 12 | + BitOr 13 | + BitXor 14 | + Div 15 | + Mul 16 | + Rem 17 | + Shl 18 | + Shr 19 | + Sub 20 | { 21 | const ZERO: T; 22 | const ONE: T; 23 | const TEN: T; 24 | 25 | fn trailing_zeros(self) -> u32; 26 | } 27 | 28 | pub trait Unsigned: Integer {} 29 | 30 | pub trait Signed: Integer + Neg {} 31 | 32 | macro_rules! integer { 33 | ($($t:ty)*) => ($( 34 | impl Integer<$t> for $t { 35 | const ZERO: $t = 0; 36 | const ONE: $t = 1; 37 | const TEN: $t = 10; 38 | 39 | #[inline] 40 | fn trailing_zeros(self) -> u32 { 41 | <$t>::trailing_zeros(self) 42 | } 43 | } 44 | )*) 45 | } 46 | 47 | macro_rules! empty_trait { 48 | ($name:ident for $($t:ty)*) => ($( 49 | impl $name<$t> for $t {} 50 | )*) 51 | } 52 | 53 | integer!(u8 u16 u32 u64 u128 usize i16 i32 i64 i128); 54 | empty_trait!(Unsigned for u8 u16 u32 u64 u128 usize); 55 | empty_trait!(Signed for i16 i32 i64 i128); 56 | -------------------------------------------------------------------------------- /src/year2016/day25.rs: -------------------------------------------------------------------------------- 1 | //! # Clock Signal 2 | //! 3 | //! Like [`Day 12`] and [`Day 23`] this problem is all about *reading* code not writing code. 4 | //! 5 | //! Reverse engineering the code shows that it takes the initial value of `a` then adds 6 | //! two constants multiplied by each other to create a seed. 7 | //! 8 | //! This seed is then repeatedly bit shifted right by dividing by 2 using an inefficient linear 9 | //! time loop. The remainder (the bit that drops off) is the output. This means that output 10 | //! sequence is simply the binary digits of `a + offset` in reverse repeated over and over. 11 | //! 12 | //! To obtain the desired pattern we need the next highest binary number that has the 13 | //! pattern `101010..`. 14 | //! 15 | //! [`Day 12`]: crate::year2016::day12 16 | //! [`Day 23`]: crate::year2016::day23 17 | use crate::util::parse::*; 18 | 19 | /// Extract the constant offset from the assembunny code. 20 | pub fn parse(input: &str) -> u32 { 21 | let lines: Vec<_> = input.lines().collect(); 22 | let first: u32 = lines[1].unsigned(); 23 | let second: u32 = lines[2].unsigned(); 24 | first * second 25 | } 26 | 27 | pub fn part1(input: &u32) -> u32 { 28 | let offset = *input; 29 | let mut result = 0; 30 | 31 | // Find the next number with binary pattern `101010..` greater than the input. 32 | while result < offset { 33 | result = (result << 2) | 2; 34 | } 35 | 36 | result - offset 37 | } 38 | 39 | pub fn part2(_input: &u32) -> &'static str { 40 | "n/a" 41 | } 42 | -------------------------------------------------------------------------------- /src/year2017/day08.rs: -------------------------------------------------------------------------------- 1 | //! # I Heard You Like Registers 2 | //! 3 | //! Computes both parts in a single pass. 4 | use crate::util::hash::*; 5 | use crate::util::iter::*; 6 | use crate::util::parse::*; 7 | 8 | type Input = (i32, i32); 9 | 10 | pub fn parse(input: &str) -> Input { 11 | let mut registers = FastMap::new(); 12 | let mut part_two = 0; 13 | 14 | for [a, b, c, _, e, f, g] in input.split_ascii_whitespace().chunk::<7>() { 15 | let first = *registers.entry(e).or_insert(0); 16 | let second: i32 = g.signed(); 17 | 18 | let predicate = match f { 19 | "==" => first == second, 20 | "!=" => first != second, 21 | ">=" => first >= second, 22 | "<=" => first <= second, 23 | ">" => first > second, 24 | "<" => first < second, 25 | _ => unreachable!(), 26 | }; 27 | 28 | if predicate { 29 | let third = registers.entry(a).or_insert(0); 30 | let fourth: i32 = c.signed(); 31 | 32 | match b { 33 | "inc" => *third += fourth, 34 | "dec" => *third -= fourth, 35 | _ => unreachable!(), 36 | } 37 | 38 | part_two = part_two.max(*third); 39 | } 40 | } 41 | 42 | let part_one = *registers.values().max().unwrap(); 43 | (part_one, part_two) 44 | } 45 | 46 | pub fn part1(input: &Input) -> i32 { 47 | input.0 48 | } 49 | 50 | pub fn part2(input: &Input) -> i32 { 51 | input.1 52 | } 53 | -------------------------------------------------------------------------------- /src/year2016/day15.rs: -------------------------------------------------------------------------------- 1 | //! # Timing is Everything 2 | //! 3 | //! Part one is the [Chinese Remainder Theorem](https://en.wikipedia.org/wiki/Chinese_remainder_theorem). 4 | //! The integers n₁, n₂, ... nₖ map to the disc sizes which happen to be prime. This satisfies the 5 | //! requirement that the integers are [pairwise coprime](https://en.wikipedia.org/wiki/Coprime_integers#Coprimality_in_sets). 6 | //! 7 | //! For simplicity we use the "search by sieving" method. We start at zero with a step the size of 8 | //! the first integer. Then we search for each subsequent integer located at the correct offset of 9 | //! minutes and multiply the step by the new integer. This preserves the relative offset at each step 10 | //! in the next search. 11 | use crate::util::iter::*; 12 | use crate::util::parse::*; 13 | 14 | type Disc = [usize; 2]; 15 | 16 | pub fn parse(input: &str) -> Vec { 17 | input.iter_unsigned().skip(1).step_by(2).chunk::<2>().collect() 18 | } 19 | 20 | pub fn part1(input: &[Disc]) -> usize { 21 | solve(input) 22 | } 23 | 24 | pub fn part2(input: &[Disc]) -> usize { 25 | let mut modified = input.to_vec(); 26 | modified.push([11, 0]); 27 | solve(&modified) 28 | } 29 | 30 | fn solve(discs: &[Disc]) -> usize { 31 | let mut time = 0; 32 | let mut step = 1; 33 | 34 | for (offset, &[size, position]) in discs.iter().enumerate() { 35 | while !(time + offset + 1 + position).is_multiple_of(size) { 36 | time += step; 37 | } 38 | 39 | step *= size; 40 | } 41 | 42 | time 43 | } 44 | -------------------------------------------------------------------------------- /src/year2016/day23.rs: -------------------------------------------------------------------------------- 1 | //! # Safe Cracking 2 | //! 3 | //! Like [`Day 12`] this problem is all about *reading* code not writing code. 4 | //! 5 | //! We could implement a brute force virtual machine without understanding the underlying code 6 | //! but it's much more efficient to analyze the code instead. 7 | //! 8 | //! The first thing we notice is that the following idiom is repeated several times: 9 | //! 10 | //! ```none 11 | //! inc x 12 | //! dec y 13 | //! jnz y -2 14 | //! ``` 15 | //! 16 | //! This is equivalent to `x += y` only much less efficient. The `tgl` instruction eventually 17 | //! rewrites a `jnz` to `cpy` to allow the program loop to end. 18 | //! 19 | //! Analysis shows that the code is calculating the [factorial](https://en.wikipedia.org/wiki/Factorial) 20 | //! of `a` plus some constant offset. We can replace the entire code with a single multiplication. 21 | //! If we had emulated the raw instructions directly then it would have taken billions of 22 | //! iterations to get the answer. 23 | //! 24 | //! [`Day 12`]: crate::year2016::day12 25 | use crate::util::parse::*; 26 | 27 | /// Extract the constant offset from the assembunny code. 28 | pub fn parse(input: &str) -> u32 { 29 | let lines: Vec<_> = input.lines().collect(); 30 | let first: u32 = lines[19].unsigned(); 31 | let second: u32 = lines[20].unsigned(); 32 | first * second 33 | } 34 | 35 | /// 7! plus some constant. 36 | pub fn part1(input: &u32) -> u32 { 37 | 5040 + input 38 | } 39 | 40 | /// 12! plus some constant. 41 | pub fn part2(input: &u32) -> u32 { 42 | 479001600 + input 43 | } 44 | -------------------------------------------------------------------------------- /src/year2015/day16.rs: -------------------------------------------------------------------------------- 1 | //! # Aunt Sue 2 | //! 3 | //! Brute force search through each aunt until we find one that matches all the facts. 4 | use crate::util::iter::*; 5 | use crate::util::parse::*; 6 | 7 | pub fn parse(input: &str) -> &str { 8 | input 9 | } 10 | 11 | pub fn part1(input: &str) -> usize { 12 | solve(input, |key, value| match key { 13 | "akitas" | "vizslas" => value == 0, 14 | "perfumes" => value == 1, 15 | "samoyeds" | "cars" => value == 2, 16 | "children" | "pomeranians" | "trees" => value == 3, 17 | "goldfish" => value == 5, 18 | "cats" => value == 7, 19 | _ => unreachable!(), 20 | }) 21 | } 22 | 23 | pub fn part2(input: &str) -> usize { 24 | solve(input, |key, value| match key { 25 | "akitas" | "vizslas" => value == 0, 26 | "perfumes" => value == 1, 27 | "samoyeds" | "cars" => value == 2, 28 | "children" => value == 3, 29 | "pomeranians" => value < 3, 30 | "goldfish" => value < 5, 31 | "trees" => value > 3, 32 | "cats" => value > 7, 33 | _ => unreachable!(), 34 | }) 35 | } 36 | 37 | fn solve(input: &str, predicate: fn(&str, u32) -> bool) -> usize { 38 | for (index, line) in input.lines().enumerate() { 39 | if line 40 | .split([' ', ':', ',']) 41 | .filter(|s| !s.is_empty()) 42 | .chunk::<2>() 43 | .skip(1) 44 | .all(|[key, value]| predicate(key, value.unsigned())) 45 | { 46 | return index + 1; 47 | } 48 | } 49 | 50 | unreachable!() 51 | } 52 | -------------------------------------------------------------------------------- /src/year2025/day04.rs: -------------------------------------------------------------------------------- 1 | //! # Printing Department 2 | use crate::util::grid::*; 3 | use crate::util::point::*; 4 | 5 | type Input = (Vec, Grid); 6 | 7 | pub fn parse(input: &str) -> Input { 8 | let grid = Grid::parse(input); 9 | let offset = Point::new(1, 1); 10 | let mut todo = Vec::new(); 11 | let mut padded = Grid::new(grid.width + 2, grid.height + 2, u8::MAX); 12 | 13 | for y in 0..grid.height { 14 | for x in 0..grid.width { 15 | let point = Point::new(x, y); 16 | 17 | if grid[point] == b'@' { 18 | let count = DIAGONAL 19 | .iter() 20 | .map(|&d| point + d) 21 | .filter(|&next| grid.contains(next) && grid[next] == b'@') 22 | .count(); 23 | 24 | if count < 4 { 25 | todo.push(point + offset); 26 | } 27 | padded[point + offset] = count as u8; 28 | } 29 | } 30 | } 31 | 32 | (todo, padded) 33 | } 34 | 35 | pub fn part1(input: &Input) -> usize { 36 | let (todo, _) = input; 37 | todo.len() 38 | } 39 | 40 | pub fn part2(input: &Input) -> usize { 41 | let (mut todo, mut padded) = input.clone(); 42 | let mut removed = 0; 43 | 44 | while let Some(point) = todo.pop() { 45 | removed += 1; 46 | 47 | for next in DIAGONAL.map(|d| point + d) { 48 | if padded[next] == 4 { 49 | todo.push(next); 50 | } 51 | padded[next] -= 1; 52 | } 53 | } 54 | 55 | removed 56 | } 57 | -------------------------------------------------------------------------------- /src/year2024/day05.rs: -------------------------------------------------------------------------------- 1 | //! # Print Queue 2 | //! 3 | //! The input is constructed so that each possible pair that occurs in a row has a defined 4 | //! ordering that enables sorting with a custom `Ordering` definition. Numbers are always 5 | //! 2 digits so storing ordering in a fixed size 100 x 100 array is faster than using a `HashMap`. 6 | use crate::util::iter::*; 7 | use crate::util::parse::*; 8 | use std::cmp::Ordering::*; 9 | 10 | type Input = (usize, usize); 11 | 12 | pub fn parse(input: &str) -> Input { 13 | let (prefix, suffix) = input.split_once("\n\n").unwrap(); 14 | let mut order = [[Greater; 100]; 100]; 15 | 16 | for [from, to] in prefix.iter_unsigned::().chunk::<2>() { 17 | order[from][to] = Less; 18 | } 19 | 20 | let mut update = Vec::new(); 21 | let mut part_one = 0; 22 | let mut part_two = 0; 23 | 24 | for line in suffix.lines() { 25 | update.clear(); 26 | update.extend(line.iter_unsigned::()); 27 | let middle = update.len() / 2; 28 | 29 | if update.is_sorted_by(|&from, &to| order[from][to] == Less) { 30 | part_one += update[middle]; 31 | } else { 32 | // We only need the middle index so this is slightly faster than "sort_unstable_by" 33 | update.select_nth_unstable_by(middle, |&from, &to| order[from][to]); 34 | part_two += update[middle]; 35 | } 36 | } 37 | 38 | (part_one, part_two) 39 | } 40 | 41 | pub fn part1(input: &Input) -> usize { 42 | input.0 43 | } 44 | 45 | pub fn part2(input: &Input) -> usize { 46 | input.1 47 | } 48 | -------------------------------------------------------------------------------- /src/year2019/day21.rs: -------------------------------------------------------------------------------- 1 | //! # Springdroid Adventure 2 | //! 3 | //! Jumps are always 4 tiles wide landing on `D`. If needed we can jump again immediately 4 | //! landing on `H`. 5 | //! 6 | //! ## Part One 7 | //! 8 | //! We jump if any of `A`, `B` or `C` are holes and there is ground where we will land at `D`. 9 | //! This take 7 instructions: 10 | //! 11 | //! `J = (NOT A OR NOT B OR NOT C) AND D` 12 | //! 13 | //! Using [De Morgan's laws](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) we can simplify 14 | //! to 5 instructions: 15 | //! 16 | //! `J = NOT (A AND B AND C) AND D` 17 | //! 18 | //! ## Part Two 19 | //! 20 | //! We add two rules, either `H` needs to be ground so that we double jump immediately or `E` 21 | //! needs to be ground, so that we can wait and not jump too early. 22 | use super::intcode::*; 23 | use crate::util::parse::*; 24 | 25 | const SLOW: &str = "\ 26 | OR A J 27 | AND B J 28 | AND C J 29 | NOT J J 30 | AND D J"; 31 | 32 | const FAST: &str = "\ 33 | OR E T 34 | OR H T 35 | AND T J"; 36 | 37 | pub fn parse(input: &str) -> Vec { 38 | input.iter_signed().collect() 39 | } 40 | 41 | pub fn part1(input: &[i64]) -> i64 { 42 | survey(input, &format!("{SLOW}\nWALK\n")) 43 | } 44 | 45 | pub fn part2(input: &[i64]) -> i64 { 46 | survey(input, &format!("{SLOW}\n{FAST}\nRUN\n")) 47 | } 48 | 49 | fn survey(input: &[i64], springscript: &str) -> i64 { 50 | let mut computer = Computer::new(input); 51 | computer.input_ascii(springscript); 52 | 53 | let mut result = 0; 54 | while let State::Output(next) = computer.run() { 55 | result = next; 56 | } 57 | result 58 | } 59 | -------------------------------------------------------------------------------- /docs/pie-2015.svg: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 86% 21 | 14% 22 | Year 2015 benchmark time by % of total 23 | 24 | 25 | Day 4 26 | 27 | 28 | 29 | Others 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/year2017/day17.rs: -------------------------------------------------------------------------------- 1 | //! # Spinlock 2 | //! 3 | //! There are two insights that speed up part two. 4 | //! 5 | //! The first is that we don't need a buffer. We only need to preserve the last value inserted 6 | //! whenever the index becomes zero. Once 50 million values have been inserted then this value 7 | //! is the final result. 8 | //! 9 | //! The second trick is realizing that we can insert multiple values at a time before the index 10 | //! wraps around. For example if the index is 1, the current value 10,000 and the step 300, 11 | //! then we can insert 34 values at once. The [`div_ceil`] method is perfect for this computation. 12 | //! 13 | //! This reduces the number of loops needed to approximately √50000000 = 7071. 14 | //! 15 | //! [`div_ceil`]: usize::div_ceil 16 | use crate::util::parse::*; 17 | 18 | pub fn parse(input: &str) -> usize { 19 | input.unsigned() 20 | } 21 | 22 | pub fn part1(input: &usize) -> u16 { 23 | let step = input + 1; 24 | let mut index = 0; 25 | let mut buffer = vec![0]; 26 | 27 | for n in 0..2017 { 28 | index = (index + step) % buffer.len(); 29 | buffer.insert(index, n + 1); 30 | } 31 | 32 | buffer[(index + 1) % buffer.len()] 33 | } 34 | 35 | pub fn part2(input: &usize) -> usize { 36 | let step = input + 1; 37 | let mut n: usize = 1; 38 | let mut index = 0; 39 | let mut result = 0; 40 | 41 | while n <= 50_000_000 { 42 | if index == 0 { 43 | result = n; 44 | } 45 | 46 | let skip = (n - index).div_ceil(step); 47 | n += skip; 48 | index = (index + skip * step) % n; 49 | } 50 | 51 | result 52 | } 53 | -------------------------------------------------------------------------------- /src/year2022/day04.rs: -------------------------------------------------------------------------------- 1 | //! # Camp Cleanup 2 | //! 3 | //! This puzzle asks to compute range intersections. To simplify the 2nd part, we can use a trick. 4 | //! Rather than consider each possible case of intersection (overlapping start, overlapping end, 5 | //! completely enclosed or completely enclosing) it's simpler to check if two ranges *don't* overlap 6 | //! then invert. 7 | //! 8 | //! If `a` and `b` are the ordered start and end of the first range and `c` and `d` the ordered 9 | //! start and end of the second range, then if: 10 | //! 11 | //! `a > d || c > b` 12 | //! 13 | //! the 2 ranges can't overlap. Using [DeMorgan's laws](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) 14 | //! this can be inverted to: 15 | //! 16 | //! `a <= d && c <= b` 17 | //! 18 | //! to check when two ranges do overlap. 19 | use crate::util::iter::*; 20 | use crate::util::parse::*; 21 | 22 | type Pairs = [u32; 4]; 23 | 24 | /// Parse each line into 4 integers. 25 | /// 26 | /// Notes: 27 | /// * Extracting integers from redundant text is a very common theme in Advent of Code that 28 | /// the [`iter_unsigned`] method handles. 29 | /// 30 | /// [`iter_unsigned`]: ParseOps::iter_unsigned 31 | pub fn parse(input: &str) -> Vec { 32 | input.iter_unsigned().chunk::<4>().collect() 33 | } 34 | 35 | /// Count ranges completely enclosed by each other. 36 | pub fn part1(input: &[Pairs]) -> usize { 37 | input.iter().filter(|&&[a, b, c, d]| (a >= c && b <= d) || (c >= a && d <= b)).count() 38 | } 39 | 40 | /// Count ranges with any intersection. 41 | pub fn part2(input: &[Pairs]) -> usize { 42 | input.iter().filter(|&&[a, b, c, d]| a <= d && c <= b).count() 43 | } 44 | --------------------------------------------------------------------------------