Compare commits
12
Commits
49650c8a28
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e25265af5 | ||
|
|
6d308ac598 | ||
|
|
6643e3c6a8 | ||
|
|
3fd38a2393 | ||
|
|
d84113bf2e | ||
|
|
05e2cdebf2 | ||
|
|
35c7749abf | ||
|
|
bb4e9bbbdd | ||
|
|
60999332dc | ||
|
|
55688a124d | ||
|
|
50dc9543da | ||
|
|
3a9a75558b |
No files matched your search
Generated
+294
@@ -2,6 +2,24 @@
|
||||
# It is not intended for manual editing.
|
||||
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]]
|
||||
name = "anyhow"
|
||||
version = "1.0.93"
|
||||
@@ -13,15 +31,118 @@ name = "aoc2024"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cached",
|
||||
"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]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
@@ -30,3 +151,176 @@ checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"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]
|
||||
anyhow = "1.0.93"
|
||||
cached = "0.54.0"
|
||||
itertools = "0.13.0"
|
||||
+8
-8
@@ -1,14 +1,14 @@
|
||||
pub mod d1;
|
||||
pub mod d2;
|
||||
pub mod d3;
|
||||
// pub mod d4;
|
||||
// pub mod d5;
|
||||
// pub mod d6;
|
||||
// pub mod d7;
|
||||
// pub mod d8;
|
||||
// pub mod d9;
|
||||
// pub mod d10;
|
||||
// pub mod d11;
|
||||
pub mod d4;
|
||||
pub mod d5;
|
||||
pub mod d6;
|
||||
pub mod d7;
|
||||
pub mod d8;
|
||||
pub mod d9;
|
||||
pub mod d10;
|
||||
pub mod d11;
|
||||
// pub mod d12;
|
||||
// pub mod d13;
|
||||
// pub mod d14;
|
||||
|
||||
+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)
|
||||
}
|
||||
}
|
||||
+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,4 +1,5 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(iter_array_chunks)]
|
||||
|
||||
@@ -22,3 +22,9 @@ pub macro n {
|
||||
$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