Compare commits

..
2 Commits
Author SHA1 Message Date
YK b6b7a43fba add array_windows feature 2024-12-02 08:44:56 +03:00
YK bddc0e3ddd add BinaryHeap re-export 2024-12-02 08:44:42 +03:00
16 changed files with 29 additions and 1288 deletions

No files matched your search

Generated
-294
View File
@@ -2,24 +2,6 @@
# 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"
@@ -31,118 +13,15 @@ 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"
@@ -151,176 +30,3 @@ 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",
]
-1
View File
@@ -5,5 +5,4 @@ edition = "2021"
[dependencies]
anyhow = "1.0.93"
cached = "0.54.0"
itertools = "0.13.0"
+10 -10
View File
@@ -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 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 d12;
// pub mod d13;
// pub mod d14;
+18 -10
View File
@@ -1,39 +1,47 @@
use crate::prelude::*;
pub type I = (B<Rev<u32>>, B<Rev<u32>>);
pub type I = (Vec<u32>, Vec<u32>);
pub type O = u32;
fn _parse (data: &str) -> I {
let (mut l, mut r) = (B::new(), B::new());
let (mut l, mut r) = (vec![], vec![]);
data.lines().for_each(|line| {
let mut iter = line.split_whitespace();
let left = p!(n!(iter));
let right = p!(n!(iter));
l.push(Rev(left));
r.push(Rev(right));
l.push(left);
r.push(right);
});
(l, r)
}
fn _silver ((left, right): I) -> O {
left.into_iter_sorted().zip(right.into_iter_sorted()).fold(0, |acc, (l, r)| acc + l.0.abs_diff(r.0))
fn _silver ((mut left, mut right): I) -> O {
left.sort();
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 {
let right = right.into_iter().map(|e| e.0).counts();
let right = right.into_iter().counts();
left.into_iter().fold(0, |acc, cur| acc + cur.0 * *right.get(&cur.0).unwrap_or(&0) as u32)
left.into_iter().fold(0, |acc, cur| acc + cur * *right.get(&cur).unwrap_or(&0) as u32)
}
#[cfg(test)]
mod test {
use super::*;
fn read () -> I {
let data = inc!(1);
_parse(data)
}
#[test]
fn silver () {
let data = _parse(inc!(1));
let data = read();
let ans = _silver(data);
assert_eq!(ans, 2196996)
@@ -41,7 +49,7 @@ mod test {
#[test]
fn gold () {
let data = _parse(inc!(1));
let data = read();
let ans = _gold(data);
assert_eq!(ans, 23655822)
-103
View File
@@ -1,103 +0,0 @@
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)
}
}
-84
View File
@@ -1,84 +0,0 @@
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
View File
@@ -1,102 +0,0 @@
#![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
View File
@@ -1,118 +0,0 @@
#![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
View File
@@ -1,108 +0,0 @@
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
View File
@@ -1,131 +0,0 @@
#![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)
}
}
-62
View File
@@ -1,62 +0,0 @@
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)
}
}
-89
View File
@@ -1,89 +0,0 @@
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
View File
@@ -1,163 +0,0 @@
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)
}
}
-3
View File
@@ -1,10 +1,7 @@
#![feature(let_chains)]
#![feature(if_let_guard)]
#![feature(array_windows)]
#![feature(decl_macro)]
#![feature(iter_array_chunks)]
#![feature(binary_heap_into_iter_sorted)]
#![feature(type_alias_impl_trait)]
pub mod days;
pub mod utils;
+1 -4
View File
@@ -8,10 +8,7 @@ pub use std::{
VecDeque as D,
BinaryHeap as B,
},
cmp::{
Ordering as Or,
Reverse as Rev,
},
cmp::Ordering as Or,
};
pub type SS = &'static str;
-6
View File
@@ -22,9 +22,3 @@ pub macro n {
$s.next().unwrap()
}
}
pub macro di {
($left: expr, $right: expr) => {
std::mem::discriminant(&$left) == std::mem::discriminant(&$right)
}
}