Compare commits
4 Commits
ff2a983332
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f05ef0e7b6 | |||
| 8f3d66131e | |||
| ea1c26772e | |||
| 19a0956873 |
86
Cargo.lock
generated
86
Cargo.lock
generated
@@ -7,11 +7,13 @@ name = "aoc2022"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec",
|
||||||
|
"derive_more",
|
||||||
"itertools",
|
"itertools",
|
||||||
"nom",
|
"nom",
|
||||||
"num",
|
"num",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"xxcalc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -38,6 +40,12 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "convert_case"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
@@ -81,6 +89,19 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_more"
|
||||||
|
version = "0.99.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||||
|
dependencies = [
|
||||||
|
"convert_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustc_version",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@@ -266,6 +287,24 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.49"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "radium"
|
name = "radium"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -294,18 +333,56 @@ dependencies = [
|
|||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tap"
|
name = "tap"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wyz"
|
name = "wyz"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -314,3 +391,12 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xxcalc"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c2725420f62b8c706cd7f710b45bc30a702de16b092114b84bd0bb6d9cccdbc"
|
||||||
|
dependencies = [
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitvec = "1.0.1"
|
bitvec = "1.0.1"
|
||||||
|
derive_more = "0.99.17"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
nom = "7.1.1"
|
nom = "7.1.1"
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
petgraph = "0.6.2"
|
petgraph = "0.6.2"
|
||||||
rayon = "1.6.1"
|
rayon = "1.6.1"
|
||||||
|
xxcalc = "0.2.1"
|
||||||
|
|||||||
2399
inputs/day21.txt
Normal file
2399
inputs/day21.txt
Normal file
File diff suppressed because it is too large
Load Diff
202
inputs/day22.txt
Normal file
202
inputs/day22.txt
Normal file
File diff suppressed because one or more lines are too long
71
inputs/day23.txt
Normal file
71
inputs/day23.txt
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
...####..#.#.#....###..#....#..#..#...##..###..##.#...######.##....####
|
||||||
|
..#.##..#.#...###..###.##....#..##......#.###..###....#.#.#....#...#.#.
|
||||||
|
.##...#...####..####....#....#####.##.#.....#.#.#.#..#..#...####....###
|
||||||
|
.####..#.##...#.##..#.#...#..#..##.######.#######.###.##.....####.#.##.
|
||||||
|
##.##.#..######.####..##...##.#.##...###.###..#.#..####..##...###.##.#.
|
||||||
|
...###.#.###..####..###.##..#..###..#..##.###.##.##....##...##.#.#..##.
|
||||||
|
###.##...#...#.#..####..##.#..###.##..#..##.#...#...##..##..##.##.###.#
|
||||||
|
..##....###.##.#...#####.#.#.###.#.#.#.##.#...#####.#####.....###.....#
|
||||||
|
#.####.#...#.#...##..#..#.#...###.#.####.#..##..##.#.###...#.####....##
|
||||||
|
#.##...#.#####...##....##..###..#...##.###..#.#.##.##.....#####....#...
|
||||||
|
#...#..#..#.#...##..#####.#.###......##..##.##.##...###..###...#..###..
|
||||||
|
..#.##.#..##.##.####.....#.###..#..#..#...###.###..#.#.##.##..#####..##
|
||||||
|
.##.#...#.....####......#.#..#..#.#....#.#...####...##.#.#.....#.#.....
|
||||||
|
#..#.##..###..#.....#.###..#.#..........##.......##.##.#..######...###.
|
||||||
|
.#...##.#.#...##.####..######.###.#.#.#.####.##.###..#...###.#..#..##.#
|
||||||
|
#.#.##.#.###..##.###.##.....###.#.#...#...###.##.#.#.##.##.#####.....#.
|
||||||
|
.#...###.##...#.##.#.###.###.##......##...##.#.###..#..#.#.##...####.#.
|
||||||
|
.#.#.##..#...#.##..#..##.....#....#....#.###....#########..#.#.########
|
||||||
|
.#.##..###..##..#.......##.##..#..###.#.##.####....#..#.#...##..##.#...
|
||||||
|
#####.##.#.....#.##...#.#...#.#.####..####....#.#...#.....###...##.....
|
||||||
|
..###....#....##...#.#...###....##.###.#.#...##..##.#..#.##....#.#.#.##
|
||||||
|
########..####...#.#..##.###...##.#...#...#.######...#..#..#..#...#..##
|
||||||
|
#.#....##...##..#...#....#.##....#.###.##.#...###.#..#.#.#...###..#.#.#
|
||||||
|
#.##........#..##...#...##.##.###.#.##...##...#####.#.#.....####.#.#..#
|
||||||
|
##.##...####.##.#...#....#...###.#...#....#.#.#.####...#.#....#.####.#.
|
||||||
|
.###....#..#.#..#..####..###.#.#..#.#..#.####..#####..#.#.#..#.....##.#
|
||||||
|
.#####.#.##.###......#..##.#.....#######..##.##.#####....#..#.#..####.#
|
||||||
|
.#....###....#.##..##.#.#.#.....#####..#.#.#.##...#.#....#.##..##....#.
|
||||||
|
####....####...#.#...#..##....#.#.#.###..#.######.##..##..######...#.#.
|
||||||
|
.#..####..#####.###..#..##.#.####.##.##..#.###..#...##.#...#.#.#.#.#.##
|
||||||
|
#.###########.####.....###.#..#...###.#######...#.#...##..###....#....#
|
||||||
|
#..#.####...###..####.#.##.#.#.#.#####.###.####...#...#....########..#.
|
||||||
|
#######.#..#.#..####.##.##..##.#...##..#######..#.#..#...#..##..#.###.#
|
||||||
|
##.#.....###.#..####.##..#.#######.#.#..#.##.#..###.##..##.##.#...#.#.#
|
||||||
|
#.#######.#.##.#.###.##.##...##..#.#....#.#.#..#.#..###..##.#.#.....##.
|
||||||
|
.##.##.#...####.#####.####.####.....#..####..#..##..###...#.#.###.#...#
|
||||||
|
.####...#..#.#.#.#........#..###...#####..####..##..######.###...#####.
|
||||||
|
###....#..##.##..#####....##.#..#...##.#####..#..###.#####..###.#..##.#
|
||||||
|
..#.#...#.##..#.##.####.####..#######....##....#.#....#.#.#..##.#.#..##
|
||||||
|
.#..#.########.........###.#.....###.######..#.######...####..#..#.#.##
|
||||||
|
.#.#...###...#.#.#.#..#...##.###.#.#.##.##.....####......##.#.#....##.#
|
||||||
|
..##..##...#.#######.#.##.####.###.#..#.....#.#..#...#..####..##..#.###
|
||||||
|
.#...####.##....###..#.###...###.##...###..######.#.#.#.#.#.#.#....#.##
|
||||||
|
.###..#.###.###..##.#..##..#.#.#...#..#.#..#...##..#..#...###...#####.#
|
||||||
|
#.#..#.#.#.....##..#.##..##.#.....#..###..#.#.#.#.#.#.##..#.####..##...
|
||||||
|
..#.#.####...#.##..##.##.####..##.#.#..##.#.###.#.######..#.######.#...
|
||||||
|
###.#.#.#.####..##.######.#.#...##......###..###.#..#...#...#.#..######
|
||||||
|
.###.#..#..######..##.####.###..##.#...#.#.#......###..##.#.#....#.#.#.
|
||||||
|
.##..#...#....#..###.##.#..#####.#.#....######..#....#..######.....#...
|
||||||
|
#.#...#..#.##...#..#..###.......####...#.####...#.#.#....#####.##...#.#
|
||||||
|
....#.####.#...#..#####.#..###..######.###.....#..#.#.#.#.#.##.#.##....
|
||||||
|
#.......#####.#.###..##.###..#####..#.###..#.....#.###.###..###..#.##.#
|
||||||
|
##.#.#....##.#.#..#..#...###.#..#.....###...###...#..#.######.#.#...##.
|
||||||
|
#....####.##.###....#....#....#...#..####...#.#.#.###..##.#.#..##.#..##
|
||||||
|
#.....#.##....###..####..##.#.......#..#.#.#.....#....####.#...#....###
|
||||||
|
###.#..####....#.....#..####....######.....#.#....#..###.#.#..#.#..###.
|
||||||
|
#..#.#.#...##....##.##....##.....#..####.###..##.#.#.##..#.##.###...###
|
||||||
|
....###.#.#.#..###.#.##.#.#.#.#####.#####..#..##...##.##.#...####.#.###
|
||||||
|
#####.....#.#.#.#.#.#.###.#####.#...#.##..#.#.##..##..###...#...#..##..
|
||||||
|
##.####.#.#.##..##.##.###....##.#..###.####..#######.#...##....#..##.##
|
||||||
|
##..#.####.##..#..#.#.#####.#.#.....#####..##..#.##.....##..#.#....##.#
|
||||||
|
.#..####...####.#####.##..#.##.....###.###.#.#.######..####.#...#..#.#.
|
||||||
|
##.####..##..#.....##.#.####..#..#....##...#....#####..##########.###.#
|
||||||
|
#...#.#.....#####.......###.#.#.#.###....#.#..#..#.##..#..#..#.####.###
|
||||||
|
##.###..#..##......##########....###..#######..#....#.#..###.##........
|
||||||
|
####.........#.#...##.#.#.#..#.#.####.#####....##...#.#.##.###..#.##.##
|
||||||
|
.####.#...#..#.##.####..##..#..#...##...........##..###.####..##..#.#..
|
||||||
|
.#####.##....##.#..####.##..##.#.###.....##.#..#..#.#.#...#.#...####...
|
||||||
|
#...####........#.##.####..##.....#####.#.#####.#####..#.##.#..##...##.
|
||||||
|
.###..###.####..###..##..##.#..##.###.#...#..#...#..#...#..#######.#.##
|
||||||
|
.#..#..##...##....##....####..#....#.##.....#.##..#.#..#...#..##.#..#.#
|
||||||
8
src/bin/day21_1.rs
Normal file
8
src/bin/day21_1.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day21::process_part_1;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day21.txt").unwrap();
|
||||||
|
println!("{}", process_part_1(&file));
|
||||||
|
}
|
||||||
8
src/bin/day21_2.rs
Normal file
8
src/bin/day21_2.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day21::process_part_2;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day21.txt").unwrap();
|
||||||
|
println!("{}", process_part_2(&file));
|
||||||
|
}
|
||||||
8
src/bin/day22_1.rs
Normal file
8
src/bin/day22_1.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day22::process_part_1;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day22.txt").unwrap();
|
||||||
|
println!("{}", process_part_1(&file));
|
||||||
|
}
|
||||||
8
src/bin/day22_2.rs
Normal file
8
src/bin/day22_2.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day22::process_part_2;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day22.txt").unwrap();
|
||||||
|
println!("{}", process_part_2(&file, 50));
|
||||||
|
}
|
||||||
8
src/bin/day23_1.rs
Normal file
8
src/bin/day23_1.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day23::process_part_1;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day23.txt").unwrap();
|
||||||
|
println!("{}", process_part_1(&file));
|
||||||
|
}
|
||||||
8
src/bin/day23_2.rs
Normal file
8
src/bin/day23_2.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
|
use aoc2022::day23::process_part_2;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let file = fs::read_to_string("./inputs/day23.txt").unwrap();
|
||||||
|
println!("{}", process_part_2(&file));
|
||||||
|
}
|
||||||
128
src/day21.rs
Normal file
128
src/day21.rs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete;
|
||||||
|
use nom::character::complete::{alpha1, newline, one_of, space1};
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::multi::separated_list1;
|
||||||
|
use nom::sequence::separated_pair;
|
||||||
|
use nom::IResult;
|
||||||
|
use xxcalc::calculator::Calculator;
|
||||||
|
|
||||||
|
pub fn process_part_1(input: &str) -> i64 {
|
||||||
|
let (_, monkeys) = parse_input(input).unwrap();
|
||||||
|
monkeys["root"].calc(&monkeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part_2(input: &str) -> i64 {
|
||||||
|
let (_, monkeys) = parse_input(input).unwrap();
|
||||||
|
let expr = match monkeys["root"] {
|
||||||
|
Monkey::Add(a, b) | Monkey::Sub(a, b) | Monkey::Mul(a, b) | Monkey::Div(a, b) => {
|
||||||
|
format!("{}={}", build_expr(&monkeys, a), build_expr(&monkeys, b))
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
// Lazy man, i am
|
||||||
|
xxcalc::linear_solver::LinearSolver
|
||||||
|
.process(&expr)
|
||||||
|
.unwrap()
|
||||||
|
.as_f64()
|
||||||
|
.unwrap()
|
||||||
|
.floor() as i64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_expr(monkeys: &HashMap<&str, Monkey>, name: &str) -> String {
|
||||||
|
if name == "humn" {
|
||||||
|
return "x".to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
match monkeys[name] {
|
||||||
|
Monkey::Number(x) => format!("{x}"),
|
||||||
|
Monkey::Add(a, b) => format!("({}+{})", build_expr(monkeys, a), build_expr(monkeys, b)),
|
||||||
|
Monkey::Sub(a, b) => format!("({}-{})", build_expr(monkeys, a), build_expr(monkeys, b)),
|
||||||
|
Monkey::Mul(a, b) => format!("({}*{})", build_expr(monkeys, a), build_expr(monkeys, b)),
|
||||||
|
Monkey::Div(a, b) => format!("({}/{})", build_expr(monkeys, a), build_expr(monkeys, b)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Monkey<'a> {
|
||||||
|
Number(i64),
|
||||||
|
Add(&'a str, &'a str),
|
||||||
|
Sub(&'a str, &'a str),
|
||||||
|
Mul(&'a str, &'a str),
|
||||||
|
Div(&'a str, &'a str),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Monkey<'a> {
|
||||||
|
fn calc(&self, monkeys: &HashMap<&str, Monkey>) -> i64 {
|
||||||
|
match *self {
|
||||||
|
Monkey::Number(i) => i,
|
||||||
|
Monkey::Add(a, b) => monkeys[a].calc(monkeys) + monkeys[b].calc(monkeys),
|
||||||
|
Monkey::Sub(a, b) => monkeys[a].calc(monkeys) - monkeys[b].calc(monkeys),
|
||||||
|
Monkey::Mul(a, b) => monkeys[a].calc(monkeys) * monkeys[b].calc(monkeys),
|
||||||
|
Monkey::Div(a, b) => monkeys[a].calc(monkeys) / monkeys[b].calc(monkeys),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_operation_monkey(input: &str) -> IResult<&str, Monkey> {
|
||||||
|
let (input, lhs) = alpha1(input)?;
|
||||||
|
let (input, _) = space1(input)?;
|
||||||
|
let (input, op) = one_of("+-*/")(input)?;
|
||||||
|
let (input, _) = space1(input)?;
|
||||||
|
let (input, rhs) = alpha1(input)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
match op {
|
||||||
|
'+' => Monkey::Add(lhs, rhs),
|
||||||
|
'-' => Monkey::Sub(lhs, rhs),
|
||||||
|
'*' => Monkey::Mul(lhs, rhs),
|
||||||
|
'/' => Monkey::Div(lhs, rhs),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_monkey(input: &str) -> IResult<&str, Monkey> {
|
||||||
|
alt((map(complete::i64, Monkey::Number), parse_operation_monkey))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> IResult<&str, HashMap<&str, Monkey>> {
|
||||||
|
let (input, monkeys) =
|
||||||
|
separated_list1(newline, separated_pair(alpha1, tag(": "), parse_monkey))(input)?;
|
||||||
|
Ok((input, HashMap::from_iter(monkeys.into_iter())))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "root: pppw + sjmn
|
||||||
|
dbpl: 5
|
||||||
|
cczh: sllz + lgvd
|
||||||
|
zczc: 2
|
||||||
|
ptdq: humn - dvpt
|
||||||
|
dvpt: 3
|
||||||
|
lfqf: 4
|
||||||
|
humn: 5
|
||||||
|
ljgn: 2
|
||||||
|
sjmn: drzm * dbpl
|
||||||
|
sllz: 4
|
||||||
|
pppw: cczh / lfqf
|
||||||
|
lgvd: ljgn * ptdq
|
||||||
|
drzm: hmdt - zczc
|
||||||
|
hmdt: 32";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day1() {
|
||||||
|
assert_eq!(process_part_1(INPUT), 152);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day2() {
|
||||||
|
assert_eq!(process_part_2(INPUT), 301);
|
||||||
|
}
|
||||||
|
}
|
||||||
434
src/day22.rs
Normal file
434
src/day22.rs
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::{digit1, newline, one_of};
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::multi::{many1, separated_list1};
|
||||||
|
use nom::sequence::separated_pair;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
pub fn process_part_1(input: &str) -> usize {
|
||||||
|
let (grid, instructions) = parse_input(input).unwrap().1;
|
||||||
|
let mut player = Player {
|
||||||
|
x: grid[0]
|
||||||
|
.iter()
|
||||||
|
.position(|t| matches!(t, Tile::Free))
|
||||||
|
.unwrap(),
|
||||||
|
y: 0,
|
||||||
|
dir: Dir::R,
|
||||||
|
};
|
||||||
|
for i in instructions {
|
||||||
|
player.walk1(&i, &grid);
|
||||||
|
}
|
||||||
|
1000 * (player.y + 1) + (4 * (player.x + 1)) + isize::from(&player.dir) as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part_2(input: &str, cube_size: usize) -> usize {
|
||||||
|
let (grid, instructions) = parse_input(input).unwrap().1;
|
||||||
|
let mut player = Player {
|
||||||
|
x: grid[0]
|
||||||
|
.iter()
|
||||||
|
.position(|t| matches!(t, Tile::Free))
|
||||||
|
.unwrap(),
|
||||||
|
y: 0,
|
||||||
|
dir: Dir::R,
|
||||||
|
};
|
||||||
|
for i in instructions {
|
||||||
|
player.walk2(&i, &grid, cube_size);
|
||||||
|
}
|
||||||
|
1000 * (player.y + 1) + (4 * (player.x + 1)) + isize::from(&player.dir) as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Player {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
dir: Dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Player {
|
||||||
|
fn walk1(&mut self, instr: &Instruction, grid: &[Vec<Tile>]) {
|
||||||
|
match instr {
|
||||||
|
Instruction::Left => {
|
||||||
|
self.dir = (isize::from(&self.dir) - 1).rem_euclid(4).into();
|
||||||
|
}
|
||||||
|
Instruction::Right => {
|
||||||
|
self.dir = (isize::from(&self.dir) + 1).rem_euclid(4).into();
|
||||||
|
}
|
||||||
|
Instruction::Walk(dist) => {
|
||||||
|
for _ in 0..*dist {
|
||||||
|
let (next_x, next_y, next_tile) = match &self.dir {
|
||||||
|
Dir::R => {
|
||||||
|
let row = &grid[self.y];
|
||||||
|
let (next_x, next_tile) = row
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.cycle()
|
||||||
|
.skip(self.x + 1)
|
||||||
|
.find(|(_, t)| !matches!(t, Tile::None))
|
||||||
|
.unwrap();
|
||||||
|
(next_x, self.y, next_tile)
|
||||||
|
}
|
||||||
|
Dir::D => {
|
||||||
|
let col = grid.iter().map_while(|row| row.get(self.x));
|
||||||
|
let (next_y, next_tile) = col
|
||||||
|
.enumerate()
|
||||||
|
.cycle()
|
||||||
|
.skip(self.y + 1)
|
||||||
|
.find(|(_, t)| !matches!(t, Tile::None))
|
||||||
|
.unwrap();
|
||||||
|
(self.x, next_y, next_tile)
|
||||||
|
}
|
||||||
|
Dir::L => {
|
||||||
|
let row = &grid[self.y];
|
||||||
|
let (next_x, next_tile) = row
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.rev()
|
||||||
|
.cycle()
|
||||||
|
.skip(row.len() - self.x)
|
||||||
|
.find(|(_, t)| !matches!(t, Tile::None))
|
||||||
|
.unwrap();
|
||||||
|
(next_x, self.y, next_tile)
|
||||||
|
}
|
||||||
|
Dir::U => {
|
||||||
|
let col = grid.iter().map_while(|row| row.get(self.x)).collect_vec();
|
||||||
|
let (next_y, next_tile) = col
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.rev()
|
||||||
|
.cycle()
|
||||||
|
.skip(col.len() - self.y)
|
||||||
|
.find(|(_, t)| !matches!(t, Tile::None))
|
||||||
|
.unwrap();
|
||||||
|
(self.x, next_y, *next_tile)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match next_tile {
|
||||||
|
Tile::Free => (self.x, self.y) = (next_x, next_y),
|
||||||
|
Tile::Wall => break,
|
||||||
|
Tile::None => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk2(&mut self, instr: &Instruction, grid: &[Vec<Tile>], size: usize) {
|
||||||
|
match instr {
|
||||||
|
Instruction::Left => {
|
||||||
|
self.dir = (isize::from(&self.dir) - 1).rem_euclid(4).into();
|
||||||
|
}
|
||||||
|
Instruction::Right => {
|
||||||
|
self.dir = (isize::from(&self.dir) + 1).rem_euclid(4).into();
|
||||||
|
}
|
||||||
|
Instruction::Walk(dist) => {
|
||||||
|
for _ in 0..*dist {
|
||||||
|
let (next_x, next_y, next_dir) = self.next_coord(size);
|
||||||
|
let next_tile = &grid[next_y][next_x];
|
||||||
|
match next_tile {
|
||||||
|
Tile::Free => {
|
||||||
|
self.x = next_x;
|
||||||
|
self.y = next_y;
|
||||||
|
self.dir = next_dir
|
||||||
|
}
|
||||||
|
Tile::Wall => break,
|
||||||
|
Tile::None => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_coord(&self, size: usize) -> (usize, usize, Dir) {
|
||||||
|
let face = get_face(self.x, self.y, size);
|
||||||
|
let (xl, yl) = global_to_local(self.x, self.y, size);
|
||||||
|
match face {
|
||||||
|
1 => match self.dir {
|
||||||
|
Dir::R => (self.x + 1, self.y, Dir::R),
|
||||||
|
Dir::L => {
|
||||||
|
if xl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(xl, size - yl - 1, 4, size);
|
||||||
|
(nx, ny, Dir::R)
|
||||||
|
} else {
|
||||||
|
(self.x - 1, self.y, Dir::L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::U => {
|
||||||
|
if yl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 6, size);
|
||||||
|
(nx, ny, Dir::R)
|
||||||
|
} else {
|
||||||
|
(self.x, self.y - 1, Dir::U)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::D => (self.x, self.y + 1, Dir::D),
|
||||||
|
},
|
||||||
|
2 => match self.dir {
|
||||||
|
Dir::R => {
|
||||||
|
if xl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(xl, size - yl - 1, 5, size);
|
||||||
|
(nx, ny, Dir::L)
|
||||||
|
} else {
|
||||||
|
(self.x + 1, self.y, Dir::R)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::L => (self.x - 1, self.y, Dir::L),
|
||||||
|
Dir::U => {
|
||||||
|
if yl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(xl, size - 1, 6, size);
|
||||||
|
(nx, ny, Dir::U)
|
||||||
|
} else {
|
||||||
|
(self.x, self.y - 1, Dir::U)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::D => {
|
||||||
|
if yl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 3, size);
|
||||||
|
(nx, ny, Dir::L)
|
||||||
|
} else {
|
||||||
|
(self.x, self.y + 1, Dir::D)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
3 => match self.dir {
|
||||||
|
Dir::R => {
|
||||||
|
if xl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 2, size);
|
||||||
|
(nx, ny, Dir::U)
|
||||||
|
} else {
|
||||||
|
(self.x + 1, self.y, Dir::R)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::L => {
|
||||||
|
if xl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 4, size);
|
||||||
|
(nx, ny, Dir::D)
|
||||||
|
} else {
|
||||||
|
(self.x - 1, self.y, Dir::L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::U => (self.x, self.y - 1, Dir::U),
|
||||||
|
Dir::D => (self.x, self.y + 1, Dir::D),
|
||||||
|
},
|
||||||
|
4 => match self.dir {
|
||||||
|
Dir::R => (self.x + 1, self.y, Dir::R),
|
||||||
|
Dir::L => {
|
||||||
|
if xl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(xl, size - yl - 1, 1, size);
|
||||||
|
(nx, ny, Dir::R)
|
||||||
|
} else {
|
||||||
|
(self.x - 1, self.y, Dir::L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::U => {
|
||||||
|
if yl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 3, size);
|
||||||
|
(nx, ny, Dir::R)
|
||||||
|
} else {
|
||||||
|
(self.x, self.y - 1, Dir::U)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::D => (self.x, self.y + 1, Dir::D),
|
||||||
|
},
|
||||||
|
5 => match self.dir {
|
||||||
|
Dir::R => {
|
||||||
|
if xl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(xl, size - yl - 1, 2, size);
|
||||||
|
(nx, ny, Dir::L)
|
||||||
|
} else {
|
||||||
|
(self.x + 1, self.y, Dir::R)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::L => (self.x - 1, self.y, Dir::L),
|
||||||
|
Dir::U => (self.x, self.y - 1, Dir::U),
|
||||||
|
Dir::D => {
|
||||||
|
if yl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 6, size);
|
||||||
|
(nx, ny, Dir::L)
|
||||||
|
} else {
|
||||||
|
(self.x, self.y + 1, Dir::D)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => match self.dir {
|
||||||
|
Dir::R => {
|
||||||
|
if xl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 5, size);
|
||||||
|
(nx, ny, Dir::U)
|
||||||
|
} else {
|
||||||
|
(self.x + 1, self.y, Dir::R)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::L => {
|
||||||
|
if xl == 0 {
|
||||||
|
let (nx, ny) = local_to_global(yl, xl, 1, size);
|
||||||
|
(nx, ny, Dir::D)
|
||||||
|
} else {
|
||||||
|
(self.x - 1, self.y, Dir::L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::U => (self.x, self.y - 1, Dir::U),
|
||||||
|
Dir::D => {
|
||||||
|
if yl == size - 1 {
|
||||||
|
let (nx, ny) = local_to_global(xl, 0, 2, size);
|
||||||
|
(nx, ny, Dir::D)
|
||||||
|
} else {
|
||||||
|
(self.x, self.y + 1, Dir::D)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look, i'm just hardcoding it
|
||||||
|
// _12
|
||||||
|
// _3_
|
||||||
|
// 45_
|
||||||
|
// 6__
|
||||||
|
fn get_face(x: usize, y: usize, size: usize) -> usize {
|
||||||
|
if y < size {
|
||||||
|
if x < 2 * size {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if y < 2 * size {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if y < 3 * size {
|
||||||
|
if x < size {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
6
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global_to_local(x: usize, y: usize, size: usize) -> (usize, usize) {
|
||||||
|
let face = get_face(x, y, size);
|
||||||
|
match face {
|
||||||
|
1 => (x - size, y),
|
||||||
|
2 => (x - 2 * size, y),
|
||||||
|
3 => (x - size, y - size),
|
||||||
|
4 => (x, y - 2 * size),
|
||||||
|
5 => (x - size, y - 2 * size),
|
||||||
|
6 => (x, y - 3 * size),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_to_global(x: usize, y: usize, face: usize, size: usize) -> (usize, usize) {
|
||||||
|
match face {
|
||||||
|
1 => (x + size, y),
|
||||||
|
2 => (x + 2 * size, y),
|
||||||
|
3 => (x + size, y + size),
|
||||||
|
4 => (x, y + 2 * size),
|
||||||
|
5 => (x + size, y + 2 * size),
|
||||||
|
6 => (x, y + 3 * size),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Tile {
|
||||||
|
None,
|
||||||
|
Free,
|
||||||
|
Wall,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Instruction {
|
||||||
|
Walk(usize),
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Dir {
|
||||||
|
R,
|
||||||
|
D,
|
||||||
|
L,
|
||||||
|
U,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Dir> for isize {
|
||||||
|
fn from(value: &Dir) -> Self {
|
||||||
|
match value {
|
||||||
|
Dir::R => 0,
|
||||||
|
Dir::D => 1,
|
||||||
|
Dir::L => 2,
|
||||||
|
Dir::U => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<isize> for Dir {
|
||||||
|
fn from(value: isize) -> Self {
|
||||||
|
match value {
|
||||||
|
0 => Dir::R,
|
||||||
|
1 => Dir::D,
|
||||||
|
2 => Dir::L,
|
||||||
|
3 => Dir::U,
|
||||||
|
_ => panic!("invalid direction"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> IResult<&str, (Vec<Vec<Tile>>, Vec<Instruction>)> {
|
||||||
|
separated_pair(parse_grid, tag("\n\n"), parse_instructions)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_grid(input: &str) -> IResult<&str, Vec<Vec<Tile>>> {
|
||||||
|
separated_list1(
|
||||||
|
newline,
|
||||||
|
many1(map(one_of(" .#"), |c| match c {
|
||||||
|
' ' => Tile::None,
|
||||||
|
'.' => Tile::Free,
|
||||||
|
'#' => Tile::Wall,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instructions(input: &str) -> IResult<&str, Vec<Instruction>> {
|
||||||
|
many1(map(alt((digit1, tag("R"), tag("L"))), |c| match c {
|
||||||
|
"R" => Instruction::Right,
|
||||||
|
"L" => Instruction::Left,
|
||||||
|
dist => Instruction::Walk(dist.parse().unwrap()),
|
||||||
|
}))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = " ...#
|
||||||
|
.#..
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
...#.......#
|
||||||
|
........#...
|
||||||
|
..#....#....
|
||||||
|
..........#.
|
||||||
|
...#....
|
||||||
|
.....#..
|
||||||
|
.#......
|
||||||
|
......#.
|
||||||
|
|
||||||
|
10R5L5R10L4R5L5";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day1() {
|
||||||
|
assert_eq!(process_part_1(INPUT), 6032);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day2() {
|
||||||
|
// no test, because the test folding is different than the input folding
|
||||||
|
// SO FUCK THAT GARBAGE
|
||||||
|
// assert_eq!(process_part_2(INPUT, 4), 5031);
|
||||||
|
assert_eq!(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
180
src/day23.rs
Normal file
180
src/day23.rs
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
use derive_more::{Add, Sub};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use itertools::MinMaxResult::MinMax;
|
||||||
|
use nom::character::complete::{newline, one_of};
|
||||||
|
use nom::multi::{many1, separated_list1};
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, Add, Sub)]
|
||||||
|
struct Vec2 {
|
||||||
|
x: i64,
|
||||||
|
y: i64,
|
||||||
|
}
|
||||||
|
impl Display for Vec2 {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(usize, usize)> for Vec2 {
|
||||||
|
fn from(value: (usize, usize)) -> Self {
|
||||||
|
Self {
|
||||||
|
x: value.0 as i64,
|
||||||
|
y: value.1 as i64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// didn't wanna write them myself
|
||||||
|
macro_rules! vec2 {
|
||||||
|
($x:expr,$y:expr) => {
|
||||||
|
Vec2 { x: $x, y: $y }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const DIRECTIONS: [[Vec2; 3]; 4] = [
|
||||||
|
[vec2!(-1, -1), vec2!(0, -1), vec2!(1, -1)], // North: NW, N, NE
|
||||||
|
[vec2!(-1, 1), vec2!(0, 1), vec2!(1, 1)], // South: SW, S, SE
|
||||||
|
[vec2!(-1, -1), vec2!(-1, 0), vec2!(-1, 1)], // West: NW, W, SW
|
||||||
|
[vec2!(1, -1), vec2!(1, 0), vec2!(1, 1)], // East: NE, E, SE
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn process_part_1(input: &str) -> usize {
|
||||||
|
let mut elves = parse_input(input).unwrap().1;
|
||||||
|
for i in 0..10 {
|
||||||
|
elves.step(i);
|
||||||
|
}
|
||||||
|
elves.bounding_box_area() - elves.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part_2(input: &str) -> usize {
|
||||||
|
let mut elves = parse_input(input).unwrap().1;
|
||||||
|
(0..)
|
||||||
|
.take_while(|i| elves.step(*i))
|
||||||
|
.last()
|
||||||
|
.map(|x| x + 2) // we start counting at 0 while aoc expects 1, and take_while 'noms' the one we need to keep away
|
||||||
|
.unwrap_or(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> IResult<&str, Elves> {
|
||||||
|
let (input, items) = separated_list1(newline, many1(one_of(".#")))(input)?;
|
||||||
|
let result = items
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(y, row)| {
|
||||||
|
row.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(move |(x, &elem)| match elem {
|
||||||
|
'#' => Some(Vec2::from((x, y))),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok((input, Elves(result)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Elves(BTreeSet<Vec2>);
|
||||||
|
|
||||||
|
impl Elves {
|
||||||
|
fn step(&mut self, dir_counter: usize) -> bool {
|
||||||
|
let mut desired_moves = Vec::new();
|
||||||
|
let mut has_moved = false;
|
||||||
|
for elf in self.0.iter() {
|
||||||
|
if !self.has_elf_near(*elf) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
let offsets = DIRECTIONS[(dir_counter + i) % 4];
|
||||||
|
if !self.has_elf(*elf, &offsets) {
|
||||||
|
let next = *elf + offsets[1];
|
||||||
|
desired_moves.push((next, *elf));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let moves = desired_moves
|
||||||
|
.into_iter()
|
||||||
|
.sorted_unstable_by(|a, b| a.0.cmp(&b.0))
|
||||||
|
.dedup_by_with_count(|a, b| a.0 == b.0)
|
||||||
|
.filter(|(count, _)| *count == 1)
|
||||||
|
.map(|(_, m)| m);
|
||||||
|
for (next, elf) in moves {
|
||||||
|
self.0.remove(&elf);
|
||||||
|
self.0.insert(next);
|
||||||
|
has_moved = true;
|
||||||
|
}
|
||||||
|
has_moved
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_elf_near(&self, pos: Vec2) -> bool {
|
||||||
|
DIRECTIONS
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.any(|d| self.0.contains(&(pos + *d)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_elf(&self, pos: Vec2, offsets: &[Vec2]) -> bool {
|
||||||
|
offsets.iter().any(|d| self.0.contains(&(pos + *d)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self) -> (Vec2, Vec2) {
|
||||||
|
let MinMax(min_x, max_x) = self.0.iter().minmax_by_key(|p| p.x) else {
|
||||||
|
panic!("no min/max x?");
|
||||||
|
};
|
||||||
|
let MinMax(min_y, max_y) = self.0.iter().minmax_by_key(|p| p.y) else {
|
||||||
|
panic!("no min/max y?");
|
||||||
|
};
|
||||||
|
(vec2!(min_x.x, min_y.y), vec2!(max_x.x, max_y.y))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box_area(&self) -> usize {
|
||||||
|
let (min, max) = self.bounding_box();
|
||||||
|
((max.x - min.x + 1) * (max.y - min.y + 1)) as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Elves {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let (min, max) = self.bounding_box();
|
||||||
|
for y in min.y..=max.y {
|
||||||
|
for x in min.x..=max.x {
|
||||||
|
let elf = if self.0.contains(&vec2!(x, y)) {
|
||||||
|
'#'
|
||||||
|
} else {
|
||||||
|
'.'
|
||||||
|
};
|
||||||
|
write!(f, "{elf}")?;
|
||||||
|
}
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "....#..
|
||||||
|
..###.#
|
||||||
|
#...#.#
|
||||||
|
.#...##
|
||||||
|
#.###..
|
||||||
|
##.#.##
|
||||||
|
.#..#..";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day1() {
|
||||||
|
assert_eq!(process_part_1(INPUT), 110);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day2() {
|
||||||
|
assert_eq!(process_part_2(INPUT), 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/day25.rs
Normal file
24
src/day25.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
pub fn process_part_1(_input: &str) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_part_2(_input: &str) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const INPUT: &str = "";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day1() {
|
||||||
|
assert_eq!(process_part_1(INPUT), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day2() {
|
||||||
|
assert_eq!(process_part_2(INPUT), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,3 +21,8 @@ pub mod day17;
|
|||||||
pub mod day18;
|
pub mod day18;
|
||||||
pub mod day19;
|
pub mod day19;
|
||||||
pub mod day20;
|
pub mod day20;
|
||||||
|
pub mod day21;
|
||||||
|
pub mod day22;
|
||||||
|
pub mod day23;
|
||||||
|
pub mod day24;
|
||||||
|
pub mod day25;
|
||||||
|
|||||||
Reference in New Issue
Block a user