Import last years utils
This commit is contained in:
parent
0e6e7d7a10
commit
ad2a33094e
4 changed files with 1031 additions and 0 deletions
458
Cargo.lock
generated
Normal file
458
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aoc_2025"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bstr",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"humantime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||
|
||||
[[package]]
|
||||
name = "color-eyre"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"color-spantrace",
|
||||
"eyre",
|
||||
"indenter",
|
||||
"once_cell",
|
||||
"owo-colors",
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color-spantrace"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"owo-colors",
|
||||
"tracing-core",
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
|
||||
dependencies = [
|
||||
"indenter",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
||||
|
||||
[[package]]
|
||||
name = "indenter"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[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.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-error"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
|
||||
dependencies = [
|
||||
"sharded-slab",
|
||||
"thread_local",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "aoc_2025"
|
||||
version = "0.1.0"
|
||||
authors = ["traxys <quentin@familleboyer.net>"]
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.7.6"
|
||||
bstr = "1.11.0"
|
||||
clap = { version = "4.5.21", features = ["derive"] }
|
||||
color-eyre = "0.6.3"
|
||||
humantime = "2.1.0"
|
||||
128
src/lib.rs
Normal file
128
src/lib.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use bstr::{BString, ByteSlice};
|
||||
use clap::Parser;
|
||||
|
||||
pub mod tinyvec;
|
||||
|
||||
pub fn neighbours<L, C, T>(l: usize, c: usize, map: L) -> ArrayVec<(usize, usize), 4>
|
||||
where
|
||||
L: AsRef<[C]>,
|
||||
C: AsRef<[T]>,
|
||||
{
|
||||
let mut a = ArrayVec::new();
|
||||
|
||||
if l != 0 {
|
||||
a.push((l - 1, c));
|
||||
}
|
||||
if c != 0 {
|
||||
a.push((l, c - 1));
|
||||
}
|
||||
if l + 1 != map.as_ref().len() {
|
||||
a.push((l + 1, c))
|
||||
}
|
||||
if c + 1 != map.as_ref()[0].as_ref().len() {
|
||||
a.push((l, c + 1))
|
||||
}
|
||||
|
||||
a
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Direction {
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Left,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn turn_right(self) -> Self {
|
||||
match self {
|
||||
Self::Up => Self::Right,
|
||||
Self::Right => Self::Down,
|
||||
Self::Down => Self::Left,
|
||||
Self::Left => Self::Up,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn turn_left(self) -> Self {
|
||||
match self {
|
||||
Self::Up => Self::Left,
|
||||
Self::Left => Self::Down,
|
||||
Self::Down => Self::Right,
|
||||
Self::Right => Self::Up,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk(&self, l: usize, c: usize) -> (usize, usize) {
|
||||
match self {
|
||||
Direction::Up => (l - 1, c),
|
||||
Direction::Right => (l, c + 1),
|
||||
Direction::Down => (l + 1, c),
|
||||
Direction::Left => (l, c - 1),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all() -> [Self; 4] {
|
||||
[Self::Up, Self::Right, Self::Down, Self::Left]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
#[arg(short, long)]
|
||||
part: u32,
|
||||
#[arg(short, long)]
|
||||
input: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Context {
|
||||
pub part: u32,
|
||||
pub input: BString,
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print_res {
|
||||
($($tt:tt)*) => {
|
||||
if (!std::env::var("AOC_BENCH").is_ok()) {
|
||||
println!($($tt)*)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print_res_part {
|
||||
($($tt:tt)*) => {
|
||||
if (!std::env::var("AOC_BENCH").is_ok()) {
|
||||
print!($($tt)*)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn parse_u64_bytes(b: &[u8]) -> u64 {
|
||||
b.iter()
|
||||
.map(|d| {
|
||||
if d.is_ascii_digit() {
|
||||
(d - b'0') as u64
|
||||
} else {
|
||||
panic!("Invalid digit in {}", b.as_bstr())
|
||||
}
|
||||
})
|
||||
.fold(0, |acc, d| acc * 10 + d)
|
||||
}
|
||||
|
||||
pub fn load() -> color_eyre::Result<Context> {
|
||||
color_eyre::install()?;
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
let input = std::fs::read(args.input)?.into();
|
||||
|
||||
Ok(Context {
|
||||
part: args.part,
|
||||
input,
|
||||
})
|
||||
}
|
||||
433
src/tinyvec.rs
Normal file
433
src/tinyvec.rs
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
use std::{alloc::Layout, iter::Copied, marker::PhantomData, mem::ManuallyDrop};
|
||||
|
||||
const STACK_LEN: usize = std::mem::size_of::<*mut u8>() * 2 - 1;
|
||||
|
||||
#[repr(C)]
|
||||
struct TinyHeapVec {
|
||||
len: u8,
|
||||
data: *mut u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct TinyStackVec {
|
||||
len: u8,
|
||||
data: [u8; STACK_LEN],
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct TinyVecLen {
|
||||
len: u8,
|
||||
}
|
||||
|
||||
union TinyVecInner {
|
||||
len: TinyVecLen,
|
||||
heap: ManuallyDrop<TinyHeapVec>,
|
||||
stack: TinyStackVec,
|
||||
}
|
||||
|
||||
pub struct TinyVec<T: Copy> {
|
||||
inner: TinyVecInner,
|
||||
_ph: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy> TinyVec<T> {
|
||||
pub fn new() -> Self {
|
||||
const {
|
||||
if std::mem::align_of::<T>() != 1 {
|
||||
panic!("alignof T must be 1")
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
inner: TinyVecInner {
|
||||
stack: TinyStackVec {
|
||||
len: 0,
|
||||
data: [0; STACK_LEN],
|
||||
},
|
||||
},
|
||||
_ph: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { (self.inner.len.len & 127) as usize }
|
||||
}
|
||||
|
||||
fn heap_layout() -> Layout {
|
||||
Layout::from_size_align(127 * size_of::<T>(), 1).unwrap()
|
||||
}
|
||||
|
||||
pub fn insert_at(&mut self, at: usize, v: T) {
|
||||
if at > self.len() {
|
||||
panic!("Out of bound access")
|
||||
}
|
||||
|
||||
if at == self.len() {
|
||||
return self.push(v);
|
||||
}
|
||||
|
||||
let ptr = match self.is_stack() {
|
||||
true => {
|
||||
let new_stack_len = (self.len() + 1) * size_of::<T>();
|
||||
if new_stack_len > STACK_LEN {
|
||||
self.spill();
|
||||
self.insert_at(at, v);
|
||||
return;
|
||||
} else {
|
||||
unsafe { self.inner.stack.data.as_mut_ptr() }
|
||||
}
|
||||
}
|
||||
false => unsafe { self.inner.heap.data },
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let place = ptr.cast::<T>().add(at);
|
||||
place.add(1).copy_from(place, self.len() - at);
|
||||
place.write(v);
|
||||
self.inner.len.len += 1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_from_slice(&mut self, slice: &[T]) {
|
||||
let old_len = self.len();
|
||||
let new_len = old_len + slice.len();
|
||||
if new_len > 127 {
|
||||
panic!("Out of capacity")
|
||||
}
|
||||
|
||||
let ptr = match self.is_stack() {
|
||||
true if new_len * size_of::<T>() <= STACK_LEN => unsafe {
|
||||
self.inner.stack.data.as_mut_ptr()
|
||||
},
|
||||
true => {
|
||||
self.spill();
|
||||
self.extend_from_slice(slice);
|
||||
return;
|
||||
}
|
||||
false => unsafe { self.inner.heap.data },
|
||||
};
|
||||
|
||||
unsafe {
|
||||
ptr.cast::<T>()
|
||||
.add(old_len)
|
||||
.copy_from(slice.as_ptr(), slice.len());
|
||||
self.inner.len.len += slice.len() as u8
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, v: T) {
|
||||
if self.len() == 127 {
|
||||
panic!("Out of capacity");
|
||||
}
|
||||
|
||||
let ptr = match self.is_stack() {
|
||||
true => {
|
||||
let new_stack_len = (self.len() + 1) * size_of::<T>();
|
||||
if new_stack_len > STACK_LEN {
|
||||
self.spill();
|
||||
self.push(v);
|
||||
return;
|
||||
} else {
|
||||
unsafe { self.inner.stack.data.as_mut_ptr() }
|
||||
}
|
||||
}
|
||||
false => unsafe { self.inner.heap.data },
|
||||
};
|
||||
|
||||
unsafe {
|
||||
ptr.cast::<T>().add(self.len()).write(v);
|
||||
self.inner.len.len += 1
|
||||
};
|
||||
}
|
||||
|
||||
fn spill(&mut self) {
|
||||
assert!(self.is_stack());
|
||||
unsafe {
|
||||
let data = self.inner.stack.data;
|
||||
self.inner.len.len |= 128;
|
||||
(*self.inner.heap).data = std::alloc::alloc(Self::heap_layout());
|
||||
(*self.inner.heap)
|
||||
.data
|
||||
.copy_from(&data as *const _, size_of_val(&data));
|
||||
}
|
||||
}
|
||||
|
||||
fn is_stack(&self) -> bool {
|
||||
let len = unsafe { self.inner.len.len } as usize;
|
||||
|
||||
len & 128 == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + std::fmt::Debug> std::fmt::Debug for TinyVec<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_list().entries(self).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> std::ops::Deref for TinyVec<T> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self.is_stack() {
|
||||
true => unsafe {
|
||||
core::slice::from_raw_parts(self.inner.stack.data.as_ptr() as *const _, self.len())
|
||||
},
|
||||
false => unsafe {
|
||||
core::slice::from_raw_parts(self.inner.heap.data as *const _, self.len())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> std::ops::DerefMut for TinyVec<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self.is_stack() {
|
||||
true => unsafe {
|
||||
core::slice::from_raw_parts_mut(
|
||||
self.inner.stack.data.as_ptr() as *mut _,
|
||||
self.len(),
|
||||
)
|
||||
},
|
||||
false => unsafe {
|
||||
core::slice::from_raw_parts_mut(self.inner.heap.data as *mut _, self.len())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> Extend<T> for TinyVec<T> {
|
||||
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||
for v in iter {
|
||||
self.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> FromIterator<T> for TinyVec<T> {
|
||||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
||||
let mut s = Self::new();
|
||||
s.extend(iter);
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntoIter<T: Copy> {
|
||||
index: usize,
|
||||
v: TinyVec<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.v.get(self.index) {
|
||||
None => None,
|
||||
Some(&e) => {
|
||||
self.index += 1;
|
||||
Some(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> IntoIterator for TinyVec<T> {
|
||||
type Item = T;
|
||||
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter { index: 0, v: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Copy> IntoIterator for &'a TinyVec<T> {
|
||||
type Item = T;
|
||||
|
||||
type IntoIter = Copied<std::slice::Iter<'a, T>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter().copied()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> Drop for TinyVec<T> {
|
||||
fn drop(&mut self) {
|
||||
if !self.is_stack() {
|
||||
unsafe {
|
||||
std::alloc::dealloc(self.inner.heap.data, Self::heap_layout());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> Default for TinyVec<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::tinyvec::STACK_LEN;
|
||||
|
||||
use super::TinyVec;
|
||||
|
||||
#[test]
|
||||
pub fn empty() {
|
||||
let a = TinyVec::<u8>::new();
|
||||
assert_eq!(a.len(), 0);
|
||||
assert!(a.is_empty());
|
||||
assert_eq!(&*a, &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn push_stack() {
|
||||
let mut a = TinyVec::new();
|
||||
a.push(42u8);
|
||||
assert_eq!(a.len(), 1);
|
||||
assert!(!a.is_empty());
|
||||
assert_eq!(&*a, &[42]);
|
||||
|
||||
let mut a = TinyVec::new();
|
||||
a.push([42u8, 43]);
|
||||
assert_eq!(a.len(), 1);
|
||||
assert!(!a.is_empty());
|
||||
assert_eq!(&*a, &[[42, 43]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn extend_stack() {
|
||||
let values = (0..STACK_LEN as u8).collect_vec();
|
||||
let mut a = TinyVec::<u8>::new();
|
||||
a.extend_from_slice(&values);
|
||||
assert_eq!(&*a, &values);
|
||||
|
||||
let mut a = TinyVec::new();
|
||||
a.push(values[0]);
|
||||
a.extend_from_slice(&values[1..]);
|
||||
assert_eq!(&*a, &values);
|
||||
|
||||
let values = [[43u8, 45], [46, 47]];
|
||||
let mut a = TinyVec::new();
|
||||
a.extend_from_slice(&values);
|
||||
assert_eq!(&*a, &values);
|
||||
|
||||
let mut a = TinyVec::new();
|
||||
a.push(values[0]);
|
||||
a.extend_from_slice(&values[1..]);
|
||||
assert_eq!(&*a, &values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn extend_spill() {
|
||||
let values = (0..STACK_LEN as u8 + 1).collect_vec();
|
||||
let mut a = TinyVec::<u8>::new();
|
||||
a.extend_from_slice(&values);
|
||||
assert_eq!(&*a, &values);
|
||||
|
||||
let mut a = TinyVec::new();
|
||||
a.push(values[0]);
|
||||
a.extend_from_slice(&values[1..]);
|
||||
assert_eq!(&*a, &values);
|
||||
|
||||
let values = [
|
||||
[43u8, 45, 46, 47],
|
||||
[48, 49, 50, 51],
|
||||
[52, 53, 54, 55],
|
||||
[56, 57, 58, 59],
|
||||
];
|
||||
let mut a = TinyVec::new();
|
||||
a.extend_from_slice(&values);
|
||||
assert_eq!(&*a, &values);
|
||||
|
||||
let mut a = TinyVec::new();
|
||||
a.push(values[0]);
|
||||
a.extend_from_slice(&values[1..]);
|
||||
assert_eq!(&*a, &values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn extend_heap() {
|
||||
let values = (0..127).collect_vec();
|
||||
let mut a = TinyVec::<u8>::new();
|
||||
a.extend_from_slice(&values[0..10]);
|
||||
a.extend_from_slice(&values[10..]);
|
||||
assert_eq!(&*a, values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn insert_stack() {
|
||||
let mut a = TinyVec::<[u8; 2]>::new();
|
||||
a.push([1, 2]);
|
||||
a.push([3, 4]);
|
||||
a.insert_at(1, [5, 6]);
|
||||
assert_eq!(&*a, &[[1, 2], [5, 6], [3, 4]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn insert_heap() {
|
||||
let mut values = vec![[0, 0]; 16];
|
||||
|
||||
let mut a = TinyVec::<[u8; 2]>::new();
|
||||
a.extend_from_slice(&values);
|
||||
|
||||
values.insert(1, [5, 6]);
|
||||
a.insert_at(1, [5, 6]);
|
||||
|
||||
assert_eq!(&*a, &values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn insert_spill() {
|
||||
let mut values = vec![[0, 0]; 7];
|
||||
|
||||
let mut a = TinyVec::<[u8; 2]>::new();
|
||||
a.extend_from_slice(&values);
|
||||
|
||||
values.insert(1, [5, 6]);
|
||||
a.insert_at(1, [5, 6]);
|
||||
|
||||
assert_eq!(&*a, &values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn push_spill() {
|
||||
let values = (0..STACK_LEN as u8 + 1).collect_vec();
|
||||
|
||||
let mut a = TinyVec::new();
|
||||
for &i in &values {
|
||||
a.push(i);
|
||||
}
|
||||
|
||||
assert_eq!(a.len(), values.len());
|
||||
assert!(!a.is_empty());
|
||||
assert_eq!(&*a, &values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn into_iter() {
|
||||
let values = (0..50u8).collect_vec();
|
||||
let mut a = TinyVec::new();
|
||||
a.extend_from_slice(&values);
|
||||
|
||||
assert_eq!(values, a.into_iter().collect_vec());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn into_ref_iter() {
|
||||
let values = (0..50u8).collect_vec();
|
||||
let mut a = TinyVec::new();
|
||||
a.extend_from_slice(&values);
|
||||
|
||||
assert_eq!(values, (&a).into_iter().collect_vec());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue