diff --git a/Cargo.lock b/Cargo.lock index e40da41..f39ebe1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,11 +26,23 @@ dependencies = [ "dhat", "fmt", "itertools", + "memoize", "pico-args", "regex", "tinyjson", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -226,7 +238,18 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -235,6 +258,15 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -311,12 +343,44 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df4051db13d0816cf23196d3baa216385ae099339f5d0645a8d9ff2305e82b8" +dependencies = [ + "lazy_static", + "lru", + "memoize-inner", +] + +[[package]] +name = "memoize-inner" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bdece7e91f0d1e33df7b46ec187a93ea0d4e642113a1039ac8bfdd4a3273ac" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -424,7 +488,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ - "getrandom", + "getrandom 0.1.16", "redox_syscall 0.1.57", "rust-argon2", ] @@ -511,7 +575,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.90", ] [[package]] @@ -538,6 +602,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.90" @@ -578,12 +653,24 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.97" @@ -606,7 +693,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -628,7 +715,7 @@ checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 1c79ddb..e0e1866 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ clippy = "0.0.302" dhat = { version = "0.3.3", optional = true } fmt = "0.1.0" itertools = "0.13.0" +memoize = "0.4.2" pico-args = "0.5.0" regex = "1.11.1" tinyjson = "2.5.1" diff --git a/src/bin/11.rs b/src/bin/11.rs index 70852e3..545bd85 100644 --- a/src/bin/11.rs +++ b/src/bin/11.rs @@ -1,42 +1,63 @@ advent_of_code::solution!(11); -use std::iter::successors; +use memoize::memoize; -fn update_stones(stones: &Vec) -> Vec { - stones.into_iter().flat_map(|st| - match (st, st.checked_ilog10().unwrap_or(0) + 1) { - (0, _) => vec![1], - (n, digits) if digits % 2 == 0 && digits > 0 => { - let div = 10u64.pow(digits / 2); - vec![ - n / div, - n % div, - ] - }, - _ => vec![st * 2024], +#[memoize] +fn get_child_stones_count(stone: u64, depth: u8) -> usize { + if depth == 0 { + return 1; + } + let digits = stone.checked_ilog10().unwrap_or(0) + 1; + match (stone, digits) { + (0, _) => get_child_stones_count(1, depth - 1), + (n, digits) if digits % 2 == 0 && digits > 0 => { + let div = 10u64.pow(digits / 2); + get_child_stones_count(n / div, depth - 1) + get_child_stones_count(n % div, depth - 1) } - ).collect() + _ => get_child_stones_count(stone * 2024, depth - 1), + } } +// fn update_stones(stones: &Vec) -> Vec { +// stones.into_iter().flat_map(|st| +// match (st, st.checked_ilog10().unwrap_or(0) + 1) { +// (0, _) => vec![1], +// (n, digits) if digits % 2 == 0 && digits > 0 => { +// let div = 10u64.pow(digits / 2); +// vec![ +// n / div, +// n % div, +// ] +// }, +// _ => vec![st * 2024], +// } +// ).collect() +// } + fn parse_input(input: &str) -> Result, std::num::ParseIntError> { input.split_whitespace().map(|c| c.parse::()).collect() } pub fn part_one(input: &str) -> Option { - let stones = parse_input(input).ok()?; - successors(Some(stones), |st| Some(update_stones(st))) - .nth(25) - .unwrap() - .len() + parse_input(input) + .ok()? + .into_iter() + .map(|st| get_child_stones_count(st, 25)) + .sum::() .into() + // successors(Some(stones), |st| Some(update_stones(st))) + // .nth(25) + // .unwrap() + // .len() + // .into() } pub fn part_two(input: &str) -> Option { - let stones = parse_input(input).ok()?; - successors(Some(stones), |st| Some(update_stones(st))) - .nth(75) - .unwrap() - .len() + parse_input(input) + .ok()? + .into_iter() + .map(|st| get_child_stones_count(st, 75)) + .sum::() .into() }