Compare commits
17
Commits
0b2dc35cad
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e25265af5 | ||
|
|
6d308ac598 | ||
|
|
6643e3c6a8 | ||
|
|
3fd38a2393 | ||
|
|
d84113bf2e | ||
|
|
05e2cdebf2 | ||
|
|
35c7749abf | ||
|
|
bb4e9bbbdd | ||
|
|
60999332dc | ||
|
|
55688a124d | ||
|
|
50dc9543da | ||
|
|
3a9a75558b | ||
|
|
49650c8a28 | ||
|
|
93697d8d8d | ||
|
|
39c5eb1897 | ||
|
|
507f88f5d4 | ||
|
|
aefd094548 |
No files matched your search
Generated
+294
@@ -2,6 +2,24 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.93"
|
version = "1.0.93"
|
||||||
@@ -13,15 +31,118 @@ name = "aoc2024"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"cached",
|
||||||
"itertools",
|
"itertools",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cached"
|
||||||
|
version = "0.54.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9718806c4a2fe9e8a56fd736f97b340dd10ed1be8ed733ed50449f351dc33cae"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"cached_proc_macro",
|
||||||
|
"cached_proc_macro_types",
|
||||||
|
"hashbrown",
|
||||||
|
"once_cell",
|
||||||
|
"thiserror",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cached_proc_macro"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cached_proc_macro_types"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@@ -30,3 +151,176 @@ checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.76"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.92"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
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 = "wasm-bindgen"
|
||||||
|
version = "0.2.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-time"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
@@ -5,4 +5,5 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.93"
|
anyhow = "1.0.93"
|
||||||
|
cached = "0.54.0"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
+9
-9
@@ -1,14 +1,14 @@
|
|||||||
pub mod d1;
|
pub mod d1;
|
||||||
pub mod d2;
|
pub mod d2;
|
||||||
// pub mod d3;
|
pub mod d3;
|
||||||
// pub mod d4;
|
pub mod d4;
|
||||||
// pub mod d5;
|
pub mod d5;
|
||||||
// pub mod d6;
|
pub mod d6;
|
||||||
// pub mod d7;
|
pub mod d7;
|
||||||
// pub mod d8;
|
pub mod d8;
|
||||||
// pub mod d9;
|
pub mod d9;
|
||||||
// pub mod d10;
|
pub mod d10;
|
||||||
// pub mod d11;
|
pub mod d11;
|
||||||
// pub mod d12;
|
// pub mod d12;
|
||||||
// pub mod d13;
|
// pub mod d13;
|
||||||
// pub mod d14;
|
// pub mod d14;
|
||||||
|
|||||||
+10
-18
@@ -1,47 +1,39 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub type I = (Vec<u32>, Vec<u32>);
|
pub type I = (B<Rev<u32>>, B<Rev<u32>>);
|
||||||
pub type O = u32;
|
pub type O = u32;
|
||||||
|
|
||||||
fn _parse (data: &str) -> I {
|
fn _parse (data: &str) -> I {
|
||||||
let (mut l, mut r) = (vec![], vec![]);
|
let (mut l, mut r) = (B::new(), B::new());
|
||||||
data.lines().for_each(|line| {
|
data.lines().for_each(|line| {
|
||||||
let mut iter = line.split_whitespace();
|
let mut iter = line.split_whitespace();
|
||||||
|
|
||||||
let left = p!(n!(iter));
|
let left = p!(n!(iter));
|
||||||
let right = p!(n!(iter));
|
let right = p!(n!(iter));
|
||||||
l.push(left);
|
l.push(Rev(left));
|
||||||
r.push(right);
|
r.push(Rev(right));
|
||||||
});
|
});
|
||||||
|
|
||||||
(l, r)
|
(l, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _silver ((mut left, mut right): I) -> O {
|
fn _silver ((left, right): I) -> O {
|
||||||
left.sort();
|
left.into_iter_sorted().zip(right.into_iter_sorted()).fold(0, |acc, (l, r)| acc + l.0.abs_diff(r.0))
|
||||||
right.sort();
|
|
||||||
|
|
||||||
left.into_iter().zip(right.into_iter()).fold(0, |acc, (l, r)| acc + l.abs_diff(r))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _gold ((left, right): I) -> O {
|
fn _gold ((left, right): I) -> O {
|
||||||
let right = right.into_iter().counts();
|
let right = right.into_iter().map(|e| e.0).counts();
|
||||||
|
|
||||||
left.into_iter().fold(0, |acc, cur| acc + cur * *right.get(&cur).unwrap_or(&0) as u32)
|
left.into_iter().fold(0, |acc, cur| acc + cur.0 * *right.get(&cur.0).unwrap_or(&0) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn read () -> I {
|
|
||||||
let data = inc!(1);
|
|
||||||
_parse(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn silver () {
|
fn silver () {
|
||||||
let data = read();
|
let data = _parse(inc!(1));
|
||||||
let ans = _silver(data);
|
let ans = _silver(data);
|
||||||
|
|
||||||
assert_eq!(ans, 2196996)
|
assert_eq!(ans, 2196996)
|
||||||
@@ -49,7 +41,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gold () {
|
fn gold () {
|
||||||
let data = read();
|
let data = _parse(inc!(1));
|
||||||
let ans = _gold(data);
|
let ans = _gold(data);
|
||||||
|
|
||||||
assert_eq!(ans, 23655822)
|
assert_eq!(ans, 23655822)
|
||||||
|
|||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I1 = Vec<Vec<char>>;
|
||||||
|
pub type I2 = Vec<(usize, usize)>;
|
||||||
|
pub type O = usize;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> (I1, I2) {
|
||||||
|
data.trim().lines().enumerate().fold((vec![], vec![]), |(mut map, mut zeroes), (y, line)| {
|
||||||
|
let mut l = vec![];
|
||||||
|
for (x, c) in line.trim().chars().enumerate() {
|
||||||
|
l.push(c);
|
||||||
|
if c == '0' { zeroes.push((y, x)); }
|
||||||
|
}
|
||||||
|
map.push(l);
|
||||||
|
(map, zeroes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _dfs (
|
||||||
|
pos @ (y, x): (usize, usize),
|
||||||
|
map: &[Vec<char>],
|
||||||
|
visited: &mut S<(usize, usize)>,
|
||||||
|
silver: &mut S<(usize, usize)>,
|
||||||
|
gold: &mut O,
|
||||||
|
) {
|
||||||
|
visited.insert(pos);
|
||||||
|
|
||||||
|
let current = map[y][x];
|
||||||
|
if current == '9' {
|
||||||
|
silver.insert(pos);
|
||||||
|
*gold += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let neighbors = [(-1, 0), (0, -1), (0, 1), (1, 0)].into_iter().filter_map(|(dy, dx)| match (y.checked_add_signed(dy), x.checked_add_signed(dx)) {
|
||||||
|
(Some(y), Some(x)) if y < map.len() && x < map[0].len() => Some((y, x)),
|
||||||
|
_ => None
|
||||||
|
}).filter(|&(y, x)| map[y][x] as u8 - current as u8 == 1);
|
||||||
|
|
||||||
|
|
||||||
|
let cloned = visited.clone();
|
||||||
|
|
||||||
|
for n in neighbors {
|
||||||
|
if !visited.contains(&n) {
|
||||||
|
_dfs(n, map, visited, silver, gold);
|
||||||
|
}
|
||||||
|
*visited = cloned.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _solve ((map, zeroes): &(I1, I2)) -> (O, O) {
|
||||||
|
let (mut silver, mut gold) = (0, 0);
|
||||||
|
|
||||||
|
for &z in zeroes {
|
||||||
|
let mut _sm = S::new();
|
||||||
|
_dfs(z, &map, &mut S::new(), &mut _sm, &mut gold);
|
||||||
|
silver += _sm.len();
|
||||||
|
}
|
||||||
|
(silver, gold)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (i: &(I1, I2)) -> O {
|
||||||
|
_solve(i).0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (i: &(I1, I2)) -> O {
|
||||||
|
_solve(i).1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> (I1, I2) {
|
||||||
|
let data = inc!(10);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample () {
|
||||||
|
let data = inc!("10_example");
|
||||||
|
let data = _parse(data);
|
||||||
|
|
||||||
|
assert_eq!(_silver(&data), 36);
|
||||||
|
assert_eq!(_gold(&data), 81);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(&data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 694)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(&data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 1497)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
use cached::proc_macro::cached;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = Vec<u128>;
|
||||||
|
pub type O = u128;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
data.trim().split_ascii_whitespace().map(|e| p!(e)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _solve (data: I, iterations: u32) -> O {
|
||||||
|
data.into_iter().map(|stone| count(stone, iterations)).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_digits (i: u128) -> u32 {
|
||||||
|
i.checked_ilog10().unwrap_or(0) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cached]
|
||||||
|
fn count (stone: u128, blinks: u32) -> u128 {
|
||||||
|
match blinks {
|
||||||
|
0 => 1,
|
||||||
|
_ => next(stone).into_iter().flatten().map(|stone| count(stone, blinks - 1)).sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cached]
|
||||||
|
fn next (i: u128) -> [Option<u128>; 2] {
|
||||||
|
match i {
|
||||||
|
0 => [Some(1), None],
|
||||||
|
i if let a = count_digits(i) && a % 2 == 0 => {
|
||||||
|
let div = 10u128.pow(a / 2);
|
||||||
|
let left = i / div;
|
||||||
|
let right = i % div;
|
||||||
|
|
||||||
|
[Some(left), Some(right)]
|
||||||
|
},
|
||||||
|
i => [Some(i * 2024), None]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (data: I) -> O {
|
||||||
|
_solve(data, 25)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (data: I) -> O {
|
||||||
|
_solve(data, 75)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(11);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample () {
|
||||||
|
let data = "125 17";
|
||||||
|
let data = _parse(data);
|
||||||
|
|
||||||
|
assert_eq!(_silver(data), 55312)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 224529)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 266820198587914)
|
||||||
|
}
|
||||||
|
}
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
#![allow(unused_imports)]
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = &'static str;
|
||||||
|
pub type O = u64;
|
||||||
|
|
||||||
|
fn _silver (data: I) -> O {
|
||||||
|
let mut sum = 0;
|
||||||
|
|
||||||
|
let mut data = data;
|
||||||
|
|
||||||
|
while let Some(f) = data.find("mul(") {
|
||||||
|
data = &data[f..];
|
||||||
|
let start = 4;
|
||||||
|
let Some(fin) = data.find(')') else { break };
|
||||||
|
let inside = &data[start..fin];
|
||||||
|
if let Some((left, right)) = inside.split_once(',') {
|
||||||
|
if let Ok(left) = left.parse::<u64>() && let Ok(right) = right.parse::<u64>() {
|
||||||
|
sum += left * right;
|
||||||
|
} else {
|
||||||
|
data = &data[start..];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = &data[start..];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data = &data[fin+1..];
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (data: I) -> O {
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut enabled = true;
|
||||||
|
let mut data = data;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mul = data.find("mul(").unwrap_or(usize::MAX);
|
||||||
|
let _do = data.find("do()").unwrap_or(usize::MAX);
|
||||||
|
let dont = data.find("don't()").unwrap_or(usize::MAX);
|
||||||
|
|
||||||
|
if [mul, _do, dont].iter().all(|&e| e == usize::MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let next = mul.min(_do).min(dont);
|
||||||
|
|
||||||
|
if next == mul {
|
||||||
|
data = &data[next..];
|
||||||
|
let start = 4;
|
||||||
|
let Some(fin) = data.find(')') else { break };
|
||||||
|
let inside = &data[start..fin];
|
||||||
|
if let Some((left, right)) = inside.split_once(',') {
|
||||||
|
if let Ok(left) = left.parse::<u64>() && let Ok(right) = right.parse::<u64>() {
|
||||||
|
if enabled {
|
||||||
|
sum += left * right;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = &data[start..];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data = &data[start..];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data = &data[fin+1..];
|
||||||
|
} else if next == _do {
|
||||||
|
enabled = true;
|
||||||
|
data = &data[next+4..];
|
||||||
|
} else if next == dont {
|
||||||
|
enabled = false;
|
||||||
|
data = &data[next+7..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> &'static str {
|
||||||
|
inc!(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 181345830)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 98729041)
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = Vec<Vec<char>>;
|
||||||
|
pub type O = usize;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
data.lines().map(|line| line.chars().collect()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _raycast ((y, x): (usize, usize), rows: usize, cols: usize) -> Vec<Vec<(usize, usize)>> {
|
||||||
|
const r: [[(isize, isize); 3]; 8] = [
|
||||||
|
[(-1, -1), (-2, -2), (-3, -3)], // UL
|
||||||
|
[(-1, 0), (-2, 0), (-3, 0)], // U
|
||||||
|
[(-1, 1), (-2, 2), (-3, 3)], // UR
|
||||||
|
|
||||||
|
[(0, -1), (0, -2), (0, -3)], // L
|
||||||
|
[(0, 1), (0, 2), (0, 3)], // R
|
||||||
|
|
||||||
|
|
||||||
|
[(1, -1), (2, -2), (3, -3)], // DL
|
||||||
|
[(1, 0), (2, 0), (3, 0)], // D
|
||||||
|
[(1, 1), (2, 2), (3, 3)], // DR
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
r.into_iter().filter_map(|e| {
|
||||||
|
let new = e.into_iter().filter_map(|(dy, dx)| {
|
||||||
|
let ny = y.checked_add_signed(dy)?;
|
||||||
|
let nx = x.checked_add_signed(dx)?;
|
||||||
|
if ny >= rows || nx >= cols { return None; }
|
||||||
|
Some((ny, nx))
|
||||||
|
}).collect_vec();
|
||||||
|
if new.len() != 3 { return None }
|
||||||
|
Some(new)
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _raycast_2 ((y, x): (usize, usize), rows: usize, cols: usize) -> Vec<(usize, usize)> {
|
||||||
|
const r: [(isize, isize); 4] = [
|
||||||
|
(-1, -1), // UL
|
||||||
|
(-1, 1), // UR
|
||||||
|
(1, -1), // DL
|
||||||
|
(1, 1), // DR
|
||||||
|
];
|
||||||
|
|
||||||
|
let v: Vec<(usize, usize)> = r.into_iter().filter_map(|(dy, dx)| {
|
||||||
|
let ny = y.checked_add_signed(dy)?;
|
||||||
|
let nx = x.checked_add_signed(dx)?;
|
||||||
|
if ny >= rows || nx >= cols { return None; }
|
||||||
|
Some((ny, nx))
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
|
||||||
|
if v.len() != r.len() { vec![] } else { v }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (data: I) -> O {
|
||||||
|
let rows = data.len();
|
||||||
|
let mut count = 0;
|
||||||
|
for (y, row) in data.iter().enumerate() {
|
||||||
|
let cols = row.len();
|
||||||
|
for (x, &cell) in row.iter().enumerate() {
|
||||||
|
if cell == 'X' {
|
||||||
|
count += _raycast((y, x), rows, cols).into_iter().map(|e| format!("X{}", e.iter().map(|&(y, x)| data[y][x]).collect::<String>())).filter(|s| s == "XMAS").count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (data: I) -> O {
|
||||||
|
let rows = data.len();
|
||||||
|
let mut count = 0;
|
||||||
|
for (y, row) in data.iter().enumerate() {
|
||||||
|
let cols = row.len();
|
||||||
|
for (x, &cell) in row.iter().enumerate() {
|
||||||
|
if cell == 'A' {
|
||||||
|
let rays = _raycast_2((y, x), rows, cols).into_iter().map(|(y, x)| (data[y][x], (y, x))).collect_vec();
|
||||||
|
let ms = rays.iter().filter(|(c, _)| *c == 'M').collect_vec();
|
||||||
|
if ms.len() == 2 &&
|
||||||
|
rays.iter().filter(|(c, _)| *c == 'S').count() == 2 &&
|
||||||
|
(ms[0].1.0 == ms[1].1.0 || ms[0].1.1 == ms[1].1.1) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(4);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 2603)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 1965)
|
||||||
|
}
|
||||||
|
}
|
||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = (M<u32, S<u32>>, Vec<Vec<u32>>);
|
||||||
|
pub type O = u32;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
data.trim().split_once("\n\n").map(|(left, right)| {
|
||||||
|
let mut m: M<u32, S<u32>> = M::new();
|
||||||
|
|
||||||
|
left.trim().lines().for_each(|line| {
|
||||||
|
let (x, y) = line.trim().split_once('|').unwrap();
|
||||||
|
let x = p!(x);
|
||||||
|
let y = p!(y);
|
||||||
|
|
||||||
|
m.entry(x).or_default().insert(y);
|
||||||
|
});
|
||||||
|
|
||||||
|
let v = right.trim().lines().map(|e| e.split(',').map(|e| p!(e)).collect()).collect();
|
||||||
|
|
||||||
|
(m, v)
|
||||||
|
}).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn _silver ((rules, list): I) -> O {
|
||||||
|
list.into_iter().filter(|page| {
|
||||||
|
let mut seen = S::new();
|
||||||
|
|
||||||
|
for &n in page {
|
||||||
|
let rules_for_n = rules.get(&n);
|
||||||
|
if let Some(rules) = rules_for_n {
|
||||||
|
if seen.intersection(rules).count() != 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seen.insert(n);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}).map(|page| page[page.len() / 2]).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold ((rules, list): I) -> O {
|
||||||
|
list.into_iter().filter(|page| {
|
||||||
|
let mut seen = S::new();
|
||||||
|
|
||||||
|
for &n in page {
|
||||||
|
let rules_for_n = rules.get(&n);
|
||||||
|
if let Some(rules) = rules_for_n {
|
||||||
|
if seen.intersection(rules).count() != 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seen.insert(n);
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.map(|mut page| {
|
||||||
|
let mut seen = M::new();
|
||||||
|
let mut ptr = 0;
|
||||||
|
|
||||||
|
'outer : while ptr < page.len() {
|
||||||
|
let n = page[ptr];
|
||||||
|
let rules_for_n = rules.get(&n);
|
||||||
|
if let Some(rules) = rules_for_n {
|
||||||
|
for r in rules {
|
||||||
|
if let Some(seen_idx) = seen.get(r) {
|
||||||
|
let removed = page.remove(ptr);
|
||||||
|
page.insert(*seen_idx, removed);
|
||||||
|
ptr = 0;
|
||||||
|
seen.clear();
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seen.insert(n, ptr);
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
page
|
||||||
|
})
|
||||||
|
.map(|page| page[page.len() / 2]).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(5);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 6260)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 5346)
|
||||||
|
}
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = Vec<Vec<char>>;
|
||||||
|
pub type O = usize;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
data.lines().map(|line| line.chars().collect()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _traverse (data: &I) -> S<(usize, usize)> {
|
||||||
|
let (mut sy, mut sx) = data.iter().enumerate().find_map(|(y, row)| row.iter().position(|e| *e == '^').map(|x| (y, x))).unwrap();
|
||||||
|
|
||||||
|
let rows = data.len();
|
||||||
|
let cols = data[0].len();
|
||||||
|
|
||||||
|
let mut s: S<(usize, usize)> = S::new();
|
||||||
|
const dirs: [(isize, isize); 4] = [(-1, 0), (0, 1), (1, 0), (0, -1)];
|
||||||
|
let mut dir = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
|
||||||
|
let (dy, dx) = dirs[dir];
|
||||||
|
let ny = sy.checked_add_signed(dy);
|
||||||
|
let nx = sx.checked_add_signed(dx);
|
||||||
|
|
||||||
|
match (ny, nx) {
|
||||||
|
(Some(ny), Some(nx)) if ny < rows && nx < cols => {
|
||||||
|
if data[ny][nx] == '#' {
|
||||||
|
dir = (dir + 1) % 4;
|
||||||
|
} else {
|
||||||
|
s.insert((ny, nx));
|
||||||
|
sy = ny;
|
||||||
|
sx = nx;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (data: I) -> O {
|
||||||
|
let ans = _traverse(&data);
|
||||||
|
ans.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (mut data: I) -> O {
|
||||||
|
let path = _traverse(&data);
|
||||||
|
let (sy, sx) = data.iter().enumerate().find_map(|(y, row)| row.iter().position(|e| *e == '^').map(|x| (y, x))).unwrap();
|
||||||
|
data[sy][sx] = '.';
|
||||||
|
|
||||||
|
let rows = data.len();
|
||||||
|
let cols = data[0].len();
|
||||||
|
|
||||||
|
const dirs: [(isize, isize); 4] = [(-1, 0), (0, 1), (1, 0), (0, -1)];
|
||||||
|
|
||||||
|
let mut loops = 0;
|
||||||
|
|
||||||
|
'outer : for (cy, cx) in path {
|
||||||
|
if cy == sy && cx == sx { continue; }
|
||||||
|
if data[cy][cx] == '.' {
|
||||||
|
data[cy][cx] = '#';
|
||||||
|
|
||||||
|
let mut y = sy;
|
||||||
|
let mut x = sx;
|
||||||
|
|
||||||
|
let mut s: S<((usize, usize), usize)> = S::new();
|
||||||
|
let mut dir = 0;
|
||||||
|
|
||||||
|
'inner : loop {
|
||||||
|
let (dy, dx) = dirs[dir];
|
||||||
|
|
||||||
|
if s.contains(&((y, x), dir)) {
|
||||||
|
loops += 1;
|
||||||
|
data[cy][cx] = '.';
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
s.insert(((y, x), dir));
|
||||||
|
|
||||||
|
let ny = y.checked_add_signed(dy);
|
||||||
|
let nx = x.checked_add_signed(dx);
|
||||||
|
|
||||||
|
match (ny, nx) {
|
||||||
|
(Some(ny), Some(nx)) if ny < rows && nx < cols => {
|
||||||
|
if data[ny][nx] == '#' {
|
||||||
|
dir = (dir + 1) % 4;
|
||||||
|
} else {
|
||||||
|
y = ny;
|
||||||
|
x = nx;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => break 'inner,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data[cy][cx] = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loops
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(6);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 4967)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 1789)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = Vec<(u64, Vec<u64>)>;
|
||||||
|
pub type O = u64;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
data.trim().lines().map(|e| e.trim().split_once(": ").map(|(left, right)| (p!(left), right.split_ascii_whitespace().map(|e| p!(e)).collect())).unwrap()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _solve (data: I, consider_concats: bool) -> O {
|
||||||
|
data.iter().filter(|(val, list)| {
|
||||||
|
let mut results: S<u64> = S::from([list[0]]);
|
||||||
|
for &i in &list[1..] {
|
||||||
|
for p in results.drain().collect_vec() {
|
||||||
|
let prod = i * p;
|
||||||
|
let sum = i + p;
|
||||||
|
if prod <= *val { results.insert(prod); }
|
||||||
|
if sum <= *val { results.insert(sum); }
|
||||||
|
|
||||||
|
if consider_concats {
|
||||||
|
let concat = p * 10u64.pow(i.ilog10() + 1) + i;
|
||||||
|
if concat <= *val { results.insert(concat); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.contains(val)
|
||||||
|
}).map(|(val, _)| val).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (data: I) -> O {
|
||||||
|
_solve(data, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (data: I) -> O {
|
||||||
|
_solve(data, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(7);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 5837374519342)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 492383931650959)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = (M<char, Vec<(isize, isize)>>, isize, isize);
|
||||||
|
pub type O = usize;
|
||||||
|
|
||||||
|
fn _parse (data: &str) -> I {
|
||||||
|
let data = data.trim();
|
||||||
|
let lines = data.lines();
|
||||||
|
|
||||||
|
let mut w = 0;
|
||||||
|
let mut h = 0;
|
||||||
|
|
||||||
|
let mut m: M<char, Vec<(isize, isize)>> = M::new();
|
||||||
|
|
||||||
|
for l in lines {
|
||||||
|
let l = l.trim();
|
||||||
|
w = l.len();
|
||||||
|
for (i, c) in l.chars().enumerate() {
|
||||||
|
if c == '.' { continue; }
|
||||||
|
m.entry(c).or_default().push((h as isize, i as isize));
|
||||||
|
}
|
||||||
|
h += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(m, w as isize, h as isize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _solve ((map, width, height): I, n: isize) -> O {
|
||||||
|
let is_valid = |(y, x): &(isize, isize)| (0..width).contains(x) && (0..height).contains(y);
|
||||||
|
|
||||||
|
let mut s = S::new();
|
||||||
|
|
||||||
|
for v in map.values() {
|
||||||
|
for (a, b) in v.into_iter().tuple_combinations() {
|
||||||
|
let ydiff = b.0 - a.0;
|
||||||
|
let xdiff = b.1 - a.1;
|
||||||
|
|
||||||
|
if n > 1 {
|
||||||
|
s.insert(*a);
|
||||||
|
s.insert(*b);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 1..=n {
|
||||||
|
let ydiff_mul = ydiff * i;
|
||||||
|
let xdiff_mul = xdiff * i;
|
||||||
|
|
||||||
|
let new = [(b.0 + ydiff_mul, b.1 + xdiff_mul), (a.0 - ydiff_mul, a.1 - xdiff_mul)];
|
||||||
|
|
||||||
|
s.extend(new.into_iter().filter(is_valid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
s.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (i: I) -> O {
|
||||||
|
_solve(i, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (i: I) -> O {
|
||||||
|
_solve(i, 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> I {
|
||||||
|
let data = inc!(8);
|
||||||
|
_parse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _silver(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 299)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let data = read();
|
||||||
|
let ans = _gold(data);
|
||||||
|
|
||||||
|
assert_eq!(ans, 1032)
|
||||||
|
}
|
||||||
|
}
|
||||||
+163
@@ -0,0 +1,163 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub type I = Vec<Block>;
|
||||||
|
pub type O = usize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Block {
|
||||||
|
Empty { size: usize },
|
||||||
|
Taken { id: usize, size: usize }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_silver (i: SS) -> Vec<Block> {
|
||||||
|
let mut switch = true;
|
||||||
|
let mut out = Vec::with_capacity(i.len() * 10);
|
||||||
|
let mut id = 0;
|
||||||
|
for c in i.chars() {
|
||||||
|
let val = (c as u8 - b'0') as usize;
|
||||||
|
if switch {
|
||||||
|
out.push(Block::Taken { id, size: val });
|
||||||
|
id += 1;
|
||||||
|
} else {
|
||||||
|
out.extend((0..val).map(|_| Block::Empty { size: 1 }));
|
||||||
|
}
|
||||||
|
switch = !switch;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_gold (i: SS) -> Vec<Block> {
|
||||||
|
let mut switch = true;
|
||||||
|
let mut out = Vec::with_capacity(i.len() * 10);
|
||||||
|
let mut id = 0;
|
||||||
|
for c in i.chars() {
|
||||||
|
let val = (c as u8 - b'0') as usize;
|
||||||
|
if switch {
|
||||||
|
out.push(Block::Taken { id, size: val });
|
||||||
|
id += 1;
|
||||||
|
} else {
|
||||||
|
out.push(Block::Empty { size: val });
|
||||||
|
}
|
||||||
|
switch = !switch;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _checksum (data: &I) -> usize {
|
||||||
|
let mut position = 0;
|
||||||
|
let mut sum = 0;
|
||||||
|
|
||||||
|
for d in data {
|
||||||
|
match d {
|
||||||
|
Block::Taken { id, size } => {
|
||||||
|
for _ in 0..*size {
|
||||||
|
sum += position * id;
|
||||||
|
position += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Block::Empty { size } => position += size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _silver (mut data: I) -> O {
|
||||||
|
let mut left = 0;
|
||||||
|
let mut right = data.len() - 1;
|
||||||
|
|
||||||
|
while left < right {
|
||||||
|
while di!(data[right], Block::Empty { size: 0 }) {
|
||||||
|
right -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Block::Taken { id, mut size } = data[right] else { break; };
|
||||||
|
data[right] = Block::Empty { size: 0 };
|
||||||
|
|
||||||
|
while size > 0 {
|
||||||
|
while di!(data[left], Block::Taken { id: 0, size: 0 }) {
|
||||||
|
left += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[left] = Block::Taken { id, size: 1 };
|
||||||
|
size -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_checksum(&data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _gold (mut data: I) -> O {
|
||||||
|
let mut left = 0;
|
||||||
|
let mut right = data.len() - 1;
|
||||||
|
|
||||||
|
'outer : while left < right {
|
||||||
|
while di!(data[right], Block::Empty { size: 0 }) {
|
||||||
|
right -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
'mid : loop {
|
||||||
|
if left >= right {
|
||||||
|
right -= 1;
|
||||||
|
left = 0;
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Block::Taken { .. } = data[left] {
|
||||||
|
left += 1;
|
||||||
|
continue 'mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Block::Taken { id, size } = data[right] else { break; };
|
||||||
|
|
||||||
|
if let Block::Empty { size: size_block } = data[left] && size_block >= size {
|
||||||
|
data[left] = Block::Taken { id, size };
|
||||||
|
data[right] = Block::Empty { size };
|
||||||
|
|
||||||
|
if size_block > size {
|
||||||
|
let rest = size_block - size;
|
||||||
|
data.insert(left + 1, Block::Empty { size: rest });
|
||||||
|
right += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
left = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
left += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_checksum(&data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read () -> SS {
|
||||||
|
inc!(9)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample () {
|
||||||
|
let data = "2333133121414131402";
|
||||||
|
assert_eq!(_silver(_parse_silver(data)), 1928);
|
||||||
|
assert_eq!(_gold(_parse_gold(data)), 2858);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn silver () {
|
||||||
|
let ans = _silver(_parse_silver(read()));
|
||||||
|
|
||||||
|
assert_eq!(ans, 6310675819476)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gold () {
|
||||||
|
let ans = _gold(_parse_gold(read()));
|
||||||
|
|
||||||
|
assert_eq!(ans, 6335972980679)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
#![feature(if_let_guard)]
|
||||||
#![feature(array_windows)]
|
#![feature(array_windows)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(iter_array_chunks)]
|
#![feature(iter_array_chunks)]
|
||||||
|
#![feature(binary_heap_into_iter_sorted)]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
pub mod days;
|
pub mod days;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|||||||
+4
-1
@@ -8,7 +8,10 @@ pub use std::{
|
|||||||
VecDeque as D,
|
VecDeque as D,
|
||||||
BinaryHeap as B,
|
BinaryHeap as B,
|
||||||
},
|
},
|
||||||
cmp::Ordering as Or,
|
cmp::{
|
||||||
|
Ordering as Or,
|
||||||
|
Reverse as Rev,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type SS = &'static str;
|
pub type SS = &'static str;
|
||||||
@@ -22,3 +22,9 @@ pub macro n {
|
|||||||
$s.next().unwrap()
|
$s.next().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub macro di {
|
||||||
|
($left: expr, $right: expr) => {
|
||||||
|
std::mem::discriminant(&$left) == std::mem::discriminant(&$right)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user