Compare commits

...

10 Commits

Author SHA1 Message Date
Matej Janezic 0000044041
chore: bump deps 2023-01-24 15:26:45 +01:00
Matej Janezic 000004308b
cleanup: finished all 25 days 2022-12-14 10:44:17 +01:00
Matej Janezic 0000042080
solution: cleanup day25 part1 2022-12-14 10:36:03 +01:00
Matej Janezic 0000041006
solution: day25 part1 2022-12-14 10:35:36 +01:00
Matej Janezic 00000400a9
solution: day24 2022-12-14 10:35:35 +01:00
Matej Janezic 0000039083
solution: cleanup day23 2022-12-14 09:59:43 +01:00
Matej Janezic 00000380c3
solution: day22 2022-12-13 22:54:36 +01:00
Matej Janezic 00000370b3
solution: day21 2022-12-12 21:41:39 +01:00
Matej Janezic 000003606b
solution: day20 2022-12-12 20:34:19 +01:00
Matej Janezic 0000035064
solution: day19 2022-12-11 22:21:04 +01:00
13 changed files with 896 additions and 121 deletions

198
Cargo.lock generated
View File

@ -27,7 +27,7 @@ name = "aoc"
version = "0.1.0"
dependencies = [
"dotenv",
"hashbrown 0.13.1",
"hashbrown 0.13.2",
"hex-literal",
"itertools",
"lazy_static",
@ -46,9 +46,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "bitflags"
@ -67,9 +67,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.11.1"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "bytes"
@ -79,9 +79,9 @@ checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
[[package]]
name = "cc"
version = "1.0.77"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
@ -270,18 +270,18 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.13.1"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
@ -394,9 +394,9 @@ dependencies = [
[[package]]
name = "ipnet"
version = "2.5.1"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
[[package]]
name = "itertools"
@ -409,9 +409,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
@ -430,9 +430,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.138"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
@ -473,7 +473,7 @@ dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.42.0",
"windows-sys",
]
[[package]]
@ -496,9 +496,9 @@ dependencies = [
[[package]]
name = "num_cpus"
version = "1.14.0"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
@ -506,15 +506,15 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.16.0"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "openssl"
version = "0.10.44"
version = "0.10.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29d971fd5722fec23977260f6e81aa67d2f22cadbdc2aa049f1022d9a3be1566"
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
dependencies = [
"bitflags",
"cfg-if",
@ -544,9 +544,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.79"
version = "0.9.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5454462c0eced1e97f2ec09036abc8da362e66802f66fd20f86854d9d8cbcbc4"
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
dependencies = [
"autocfg",
"cc",
@ -587,18 +587,18 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "proc-macro2"
version = "1.0.47"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@ -614,9 +614,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.7.0"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"aho-corasick",
"memchr",
@ -640,9 +640,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.13"
version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9"
dependencies = [
"base64",
"bytes",
@ -677,25 +677,24 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.11"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "schannel"
version = "0.1.20"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
dependencies = [
"lazy_static",
"windows-sys 0.36.1",
"windows-sys",
]
[[package]]
name = "security-framework"
version = "2.7.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
checksum = "645926f31b250a2dca3c232496c2d898d91036e45ca0e97e0e2390c54e11be36"
dependencies = [
"bitflags",
"core-foundation",
@ -706,9 +705,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.6.1"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc",
@ -716,15 +715,15 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.149"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
[[package]]
name = "serde_json"
version = "1.0.89"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
@ -764,9 +763,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.105"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@ -804,9 +803,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.23.0"
version = "1.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb"
dependencies = [
"autocfg",
"bytes",
@ -816,7 +815,7 @@ dependencies = [
"num_cpus",
"pin-project-lite",
"socket2",
"windows-sys 0.42.0",
"windows-sys",
]
[[package]]
@ -871,9 +870,9 @@ dependencies = [
[[package]]
name = "try-lock"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "typenum"
@ -883,15 +882,15 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unicode-bidi"
version = "0.3.8"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-ident"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-normalization"
@ -1039,19 +1038,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -1059,85 +1045,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.0",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "winreg"

72
src/bin/19.rs Normal file
View File

@ -0,0 +1,72 @@
use hashbrown::{HashMap, HashSet};
use itertools::Itertools;
use regex::Regex;
pub fn part_one(input: &str) -> Option<u32> {
let (replacements, molecule) = input.split_once("\n\n")?;
let mappings = replacements
.split('\n')
.map(|x| x.split_once(" => ").unwrap())
.collect_vec();
let mut molecules = HashSet::new();
for (a, b) in mappings.iter() {
let split = molecule.split(a).collect_vec();
for i in 1..split.len() {
let x = split[..i].join(a);
let y = split[i..].join(a);
molecules.insert(format!("{x}{b}{y}"));
}
}
Some(molecules.len() as u32)
}
// https://www.reddit.com/r/adventofcode/comments/3xflz8/comment/cy4etju/
pub fn part_two(input: &str) -> Option<u32> {
let (r, m) = input.split_once("\n\n")?;
let mut molecule: String = m.chars().rev().collect();
let mappings = r
.split('\n')
.map(|x| x.split_once(" => ").unwrap())
.map(|(a, b)| {
(
b.chars().rev().collect::<String>(),
a.chars().rev().collect::<String>(),
)
})
.collect::<HashMap<String, String>>();
let re = Regex::new(&mappings.iter().map(|(k, _)| k.as_str()).join("|")).unwrap();
let mut count = 0;
while molecule != "e" {
let re_range = re.find(&molecule)?.range();
let repl = &molecule[re_range];
molecule = molecule.replacen(repl, mappings.get(repl)?, 1);
count += 1;
}
Some(count)
}
fn main() {
let input = &aoc::read_file("inputs", 19);
aoc::solve!(1, part_one, input);
aoc::solve!(2, part_two, input);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let input = aoc::read_file("test_inputs", 19);
assert_eq!(part_one(input.trim()), Some(4));
}
#[test]
fn test_part_two() {
let input = aoc::read_file("test_inputs", 19);
assert_eq!(part_two(input.trim()), Some(3));
}
}

43
src/bin/20.rs Normal file
View File

@ -0,0 +1,43 @@
pub fn part_one(input: &str) -> Option<u32> {
let limit = input.parse::<usize>().unwrap() / 10;
let elves = 1_000_000;
let mut delivered = vec![0; elves];
for i in 1..elves {
for j in (i..elves).step_by(i) {
delivered[j] += i;
}
}
Some(
delivered
.iter()
.enumerate()
.find(|(_, &x)| x > limit)
.unwrap()
.0 as u32,
)
}
pub fn part_two(input: &str) -> Option<u32> {
let limit = input.parse().unwrap();
let elves = 1_000_000;
let mut delivered = vec![0; elves];
for i in 1..elves {
for j in (i..elves).step_by(i).take(50) {
delivered[j] += i * 11;
}
}
Some(
delivered
.iter()
.enumerate()
.find(|(_, &x)| x > limit)
.unwrap()
.0 as u32,
)
}
fn main() {
let input = &aoc::read_file("inputs", 20);
aoc::solve!(1, part_one, input);
aoc::solve!(2, part_two, input);
}

259
src/bin/21.rs Normal file
View File

@ -0,0 +1,259 @@
use itertools::Itertools;
use ItemType::*;
static STORE: [Item; 16] = [
// weapons
Item {
item_type: Weapon,
cost: 8,
damage: 4,
armor: 0,
},
Item {
item_type: Weapon,
cost: 10,
damage: 5,
armor: 0,
},
Item {
item_type: Weapon,
cost: 25,
damage: 6,
armor: 0,
},
Item {
item_type: Weapon,
cost: 40,
damage: 7,
armor: 0,
},
Item {
item_type: Weapon,
cost: 74,
damage: 8,
armor: 0,
},
// armor
Item {
item_type: Armor,
cost: 13,
damage: 0,
armor: 1,
},
Item {
item_type: Armor,
cost: 31,
damage: 0,
armor: 2,
},
Item {
item_type: Armor,
cost: 53,
damage: 0,
armor: 3,
},
Item {
item_type: Armor,
cost: 75,
damage: 0,
armor: 4,
},
Item {
item_type: Armor,
cost: 102,
damage: 0,
armor: 5,
},
// rings
Item {
item_type: Ring,
cost: 25,
damage: 1,
armor: 0,
},
Item {
item_type: Ring,
cost: 50,
damage: 2,
armor: 0,
},
Item {
item_type: Ring,
cost: 100,
damage: 3,
armor: 0,
},
Item {
item_type: Ring,
cost: 20,
damage: 0,
armor: 1,
},
Item {
item_type: Ring,
cost: 40,
damage: 0,
armor: 2,
},
Item {
item_type: Ring,
cost: 80,
damage: 0,
armor: 3,
},
];
#[derive(Clone, Copy)]
struct Player {
hp: i32,
damage: i32,
armor: i32,
}
impl Player {
fn alive(&self) -> bool {
self.hp > 0
}
}
#[derive(Debug)]
enum ItemType {
Weapon,
Armor,
Ring,
}
#[derive(Debug)]
struct Item {
item_type: ItemType,
cost: i32,
damage: i32,
armor: i32,
}
impl Item {
fn valid_selection(selection: &[&Item]) -> bool {
if selection
.iter()
.filter(|x| matches!(x.item_type, Weapon))
.count()
!= 1
{
return false;
}
if selection
.iter()
.filter(|x| matches!(x.item_type, Armor))
.count()
> 1
{
return false;
}
if selection
.iter()
.filter(|x| matches!(x.item_type, Ring))
.count()
> 2
{
return false;
}
true
}
}
fn simulate(me: Player, items: &[&Item], mut boss: Player) -> bool {
let mut equiped_me = Player {
hp: me.hp,
damage: me.damage + items.iter().map(|x| x.damage).sum::<i32>(),
armor: me.armor + items.iter().map(|x| x.armor).sum::<i32>(),
};
while equiped_me.alive() && boss.alive() {
let mut my_damage = equiped_me.damage - boss.armor;
if my_damage < 1 {
my_damage = 1;
}
let mut boss_damage = boss.damage - equiped_me.armor;
if boss_damage < 1 {
boss_damage = 1;
}
equiped_me.hp -= boss_damage;
boss.hp -= my_damage;
}
!boss.alive()
}
pub fn part_one(input: &str) -> Option<i32> {
let (hp, damage, armor) = input
.split('\n')
.map(|x| x.split(": ").last().unwrap().parse::<i32>().unwrap())
.next_tuple()
.unwrap();
let boss = Player { hp, damage, armor };
let me = Player {
hp: 100,
damage: 0,
armor: 0,
};
(0..STORE.len())
.map(|x| {
STORE
.iter()
.combinations(x)
.filter(|y| Item::valid_selection(y))
.map(|y| {
(
y.iter().map(|z| z.cost).sum::<i32>(),
simulate(me, &y, boss),
)
})
.filter(|(_, y)| *y)
.map(|(y, _)| y)
.collect_vec()
})
.filter_map(|x| x.iter().min().copied())
.min()
}
pub fn part_two(input: &str) -> Option<i32> {
let (hp, damage, armor) = input
.split('\n')
.map(|x| x.split(": ").last().unwrap().parse::<i32>().unwrap())
.next_tuple()
.unwrap();
let boss = Player { hp, damage, armor };
let me = Player {
hp: 100,
damage: 0,
armor: 0,
};
(0..STORE.len())
.map(|x| {
STORE
.iter()
.combinations(x)
.filter(|y| Item::valid_selection(y))
.map(|y| {
(
y.iter().map(|z| z.cost).sum::<i32>(),
!simulate(me, &y, boss),
)
})
.filter(|(_, y)| *y)
.map(|(y, _)| y)
.collect_vec()
})
.filter_map(|x| x.iter().max().copied())
.max()
}
fn main() {
let input = &aoc::read_file("inputs", 21);
aoc::solve!(1, part_one, input);
aoc::solve!(2, part_two, input);
}

211
src/bin/22.rs Normal file
View File

@ -0,0 +1,211 @@
use std::cmp::max;
use itertools::Itertools;
use lazy_static::lazy_static;
#[derive(Clone, Copy)]
struct Player {
hp: i32,
damage: i32,
mana: i32,
}
#[derive(Debug, Clone)]
struct Spell {
name: String,
timer: i32,
damage: i32,
armor: i32,
heal: i32,
mana: i32,
cost: i32,
}
lazy_static! {
static ref SPELLS: [Spell; 5] = [
Spell {
name: "Magic Missile".to_string(),
timer: 1,
damage: 4,
armor: 0,
heal: 0,
mana: 0,
cost: 53,
},
Spell {
name: "Drain".to_string(),
timer: 1,
damage: 2,
armor: 0,
heal: 2,
mana: 0,
cost: 73,
},
Spell {
name: "Shield".to_string(),
timer: 6,
damage: 0,
armor: 7,
heal: 0,
mana: 0,
cost: 113,
},
Spell {
name: "Poison".to_string(),
timer: 6,
damage: 3,
armor: 0,
heal: 0,
mana: 0,
cost: 173,
},
Spell {
name: "Recharge".to_string(),
timer: 5,
damage: 0,
armor: 0,
heal: 0,
mana: 101,
cost: 229,
},
];
}
fn optimize_fight(
mut boss: Player,
mut player: Player,
players_turn: bool,
mut active_spells: Vec<Spell>,
best_cost: &mut i32,
cost: i32,
hardmode: bool,
) {
if cost > *best_cost {
return;
}
let mut remaining = active_spells
.drain(..)
.filter(|x| x.timer > 0)
.collect_vec();
let mut armor = 0;
for spell in remaining.iter_mut() {
spell.timer -= 1;
boss.hp -= spell.damage;
armor += spell.armor;
player.hp += spell.heal;
player.mana += spell.mana;
}
if hardmode && players_turn {
player.hp -= 1;
}
if player.hp <= 0 {
return;
}
if boss.hp <= 0 {
if cost < *best_cost {
*best_cost = cost;
}
return;
}
if players_turn {
let current = remaining
.iter()
.filter(|x| x.timer > 0)
.map(|x| x.name.to_string())
.collect_vec();
for spell in SPELLS
.iter()
.filter(|x| !current.contains(&x.name) && x.cost < player.mana)
.collect_vec()
{
let mut new_spells = remaining.to_vec();
new_spells.push(spell.clone());
let mut c = player;
c.mana -= spell.cost;
optimize_fight(
boss,
c,
!players_turn,
new_spells,
best_cost,
cost + spell.cost,
hardmode,
);
}
} else {
let damage = max(boss.damage - armor, 1);
player.hp -= damage;
optimize_fight(
boss,
player,
!players_turn,
remaining,
best_cost,
cost,
hardmode,
);
}
}
pub fn part_one(input: &str) -> Option<i32> {
let (hp, damage) = input
.split('\n')
.map(|x| x.split(": ").last().unwrap().parse::<i32>().unwrap())
.next_tuple()
.unwrap();
let boss = Player {
hp,
damage,
mana: 0,
};
let me = Player {
hp: 50,
damage: 0,
mana: 500,
};
// this takes 7minutes but iiwii
let mut best_score = i32::max_value();
optimize_fight(boss, me, true, vec![], &mut best_score, 0, false);
Some(best_score)
}
pub fn part_two(input: &str) -> Option<i32> {
let (hp, damage) = input
.split('\n')
.map(|x| x.split(": ").last().unwrap().parse::<i32>().unwrap())
.next_tuple()
.unwrap();
let boss = Player {
hp,
damage,
mana: 0,
};
let me = Player {
hp: 50,
damage: 0,
mana: 500,
};
let mut best_score = i32::max_value();
optimize_fight(boss, me, true, vec![], &mut best_score, 0, true);
Some(best_score)
}
fn main() {
let input = &aoc::read_file("inputs", 22);
aoc::solve!(1, part_one, input);
aoc::solve!(2, part_two, input);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let input = aoc::read_file("test_inputs", 22);
assert_eq!(part_one(input.trim()), Some(212));
}
#[test]
fn test_part_two() {
let input = aoc::read_file("test_inputs", 22);
assert_eq!(part_two(input.trim()), Some(212));
}
}

125
src/bin/23.rs Normal file
View File

@ -0,0 +1,125 @@
use itertools::Itertools;
use Instruction::*;
enum Register {
A,
B,
}
impl From<&str> for Register {
fn from(value: &str) -> Self {
match value {
"a" => Register::A,
"b" => Register::B,
_ => unreachable!(),
}
}
}
enum Instruction {
Half(Register),
Triple(Register),
Increment(Register),
JumpOffset(i32),
JumpEven(Register, i32),
JumpOne(Register, i32),
}
impl From<&str> for Instruction {
fn from(value: &str) -> Self {
match value.split_once(' ').unwrap() {
("hlf", x) => Half(Register::from(x)),
("tpl", x) => Triple(Register::from(x)),
("inc", x) => Increment(Register::from(x)),
("jmp", x) => JumpOffset(x.parse().unwrap()),
("jie", x) => {
let (reg, offset) = x.split_once(", ").unwrap();
JumpEven(Register::from(reg), offset.parse().unwrap())
}
("jio", x) => {
let (reg, offset) = x.split_once(", ").unwrap();
JumpOne(Register::from(reg), offset.parse().unwrap())
}
_ => unreachable!(),
}
}
}
fn run_instructions(input: &str, mut a: u32, mut b: u32) -> Option<u32> {
let instructions = input.split('\n').map(Instruction::from).collect_vec();
let mut index = 0;
while let Some(instruction) = instructions.get(index) {
match instruction {
Half(x) => {
match x {
Register::A => a /= 2,
Register::B => b /= 2,
}
index += 1;
}
Triple(x) => {
match x {
Register::A => a *= 3,
Register::B => b *= 3,
}
index += 1;
}
Increment(x) => {
match x {
Register::A => a += 1,
Register::B => b += 1,
}
index += 1;
}
JumpOffset(x) => index += *x as usize,
JumpEven(r, x) => {
let reg = match r {
Register::A => a,
Register::B => b,
};
if reg % 2 == 0 {
index += *x as usize
} else {
index += 1;
}
}
JumpOne(r, x) => {
let reg = match r {
Register::A => a,
Register::B => b,
};
if reg == 1 {
index += *x as usize
} else {
index += 1;
}
}
}
}
Some(b)
}
pub fn part_one(input: &str) -> Option<u32> {
run_instructions(input, 0, 0)
}
pub fn part_two(input: &str) -> Option<u32> {
run_instructions(input, 1, 0)
}
fn main() {
let input = &aoc::read_file("inputs", 23);
aoc::solve!(1, part_one, input);
aoc::solve!(2, part_two, input);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let input = aoc::read_file("test_inputs", 23);
assert_eq!(part_one(&input.trim()), Some(2));
}
#[test]
fn test_part_two() {
let input = aoc::read_file("test_inputs", 23);
assert_eq!(part_two(&input.trim()), Some(2));
}
}

44
src/bin/24.rs Normal file
View File

@ -0,0 +1,44 @@
use aoc::helpers::to_vec;
use itertools::Itertools;
fn balance(gifts: &[u64], parts: u64) -> Option<u64> {
let part = gifts.iter().sum::<u64>() / parts;
// greedily search for smallest
for i in 1..gifts.len() {
for comb in gifts.iter().combinations(i) {
if comb.iter().copied().sum::<u64>() == part {
return Some(comb.iter().copied().product());
}
}
}
None
}
pub fn part_one(input: &str) -> Option<u64> {
let gifts = to_vec(input, '\n');
balance(&gifts, 3)
}
pub fn part_two(input: &str) -> Option<u64> {
let gifts = to_vec(input, '\n');
balance(&gifts, 4)
}
fn main() {
let input = &aoc::read_file("inputs", 24);
aoc::solve!(1, part_one, input);
aoc::solve!(2, part_two, input);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let input = aoc::read_file("test_inputs", 24);
assert_eq!(part_one(&input.trim()), Some(99));
}
#[test]
fn test_part_two() {
let input = aoc::read_file("test_inputs", 24);
assert_eq!(part_two(&input.trim()), Some(44));
}
}

37
src/bin/25.rs Normal file
View File

@ -0,0 +1,37 @@
const ONE: u64 = 20151125;
const MULTIPLY: u64 = 252533;
const MOD: u64 = 33554393;
pub fn part_one(input: &str) -> Option<u64> {
let l = input.len();
let (row, column): (u32, u32) = input[80..l - 1]
.split_once(", column ")
.map(|(x, y)| (x.parse().unwrap(), y.parse().unwrap()))
.unwrap();
let n = (row + column) * (row + column - 1) / 2 - row + 1;
let mut c = 1;
let mut code = ONE;
while c < n {
code = (code * MULTIPLY) % MOD;
c += 1;
}
Some(code)
}
pub fn part_two(_input: &str) -> Option<u32> {
None
}
fn main() {
let input = &aoc::read_file("inputs", 25);
aoc::solve!(1, part_one, input);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let input = aoc::read_file("test_inputs", 25);
assert_eq!(part_one(&input.trim()), Some(7726640));
}
}

7
src/test_inputs/19.txt Normal file
View File

@ -0,0 +1,7 @@
e => H
e => O
H => HO
H => OH
O => HH
HOH

2
src/test_inputs/22.txt Normal file
View File

@ -0,0 +1,2 @@
Hit Points: 14
Damage: 8

8
src/test_inputs/23.txt Normal file
View File

@ -0,0 +1,8 @@
inc a
jio a, +2
tpl a
inc a
inc b
jio b, +2
tpl b
inc b

10
src/test_inputs/24.txt Normal file
View File

@ -0,0 +1,10 @@
1
2
3
4
5
7
8
9
10
11

1
src/test_inputs/25.txt Normal file
View File

@ -0,0 +1 @@
To continue, please consult the code grid in the manual. Enter the code at row 2, column 4.