From 5587b3c0f4fc38bf4054285563feabc8d519d815 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Sun, 30 Nov 2025 22:48:56 -0800 Subject: [PATCH] repo setup for 2025 --- .gitignore | 7 + Cargo.lock | 725 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 27 ++ src/lib.rs | 5 + src/main.rs | 3 + utils/grid/Cargo.lock | 7 + utils/grid/Cargo.toml | 9 + utils/grid/lib.rs | 512 +++++++++++++++++++++++++++++ utils/misc/Cargo.lock | 25 ++ utils/misc/Cargo.toml | 7 + utils/misc/src/lib.rs | 98 ++++++ 11 files changed, 1425 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 utils/grid/Cargo.lock create mode 100644 utils/grid/Cargo.toml create mode 100644 utils/grid/lib.rs create mode 100644 utils/misc/Cargo.lock create mode 100644 utils/misc/Cargo.toml create mode 100644 utils/misc/src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ad0769 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +**/target +input +flamegraph.svg +perf.data* +guesses +.aoc_tiles/* +!.aoc_tiles/tiles/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e0b5f84 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,725 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "aoc-runner" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d21ef9204ad206a5a3e918e9920da04e1118ad91ce4f23570be964b9d6b9dfcb" + +[[package]] +name = "aoc-runner-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8b944269d3fee645d281b1335e1797044db497bb02d0098cc3fdb8900069cc" +dependencies = [ + "aoc-runner-internal", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "aoc-runner-internal" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "274b0ba7f3669a45ec0aaacf94eb032a749de880ab776091576cca94037c9982" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "aoc2025" +version = "0.1.0" +dependencies = [ + "aoc-runner", + "aoc-runner-derive", + "atoi", + "bitflags", + "cached", + "colored", + "grid", + "indicatif", + "itertools", + "lazy_static", + "misc", + "nom", + "rayon", + "regex", + "rustc-hash", + "thread_local", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[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 2.0.111", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.111", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "grid" +version = "0.1.0" + +[[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 = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "rayon", + "unicode-width", + "web-time", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[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 = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "misc" +version = "0.1.0" +dependencies = [ + "num-traits", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[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 = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[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 2.0.111", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +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 2.0.111", +] + +[[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 = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[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.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.111", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[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 = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..81b2198 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "aoc2025" +edition = "2021" +version = "0.1.0" + +[dependencies] +aoc-runner = "0.3.0" +aoc-runner-derive = "0.3.0" +atoi = "2.0.0" +bitflags = "2.6.0" +cached = "0.54.0" +colored = "2.1.0" +grid = {version = "0.1.0", path = "utils/grid"} +indicatif = { version = "0.17.9", features = ["rayon"] } +itertools = "0.13.0" +lazy_static = "1.5.0" +misc = {path = "utils/misc"} +nom = "7.1.3" +rayon = "1.10.0" +regex = "1.11.1" +rustc-hash = "2.1.0" +thread_local = "1.1.8" + +[profile.release] +lto = true +opt-level = 3 +overflow-checks = false diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5645c2a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +pub mod day1; + +use aoc_runner_derive::aoc_lib; + +aoc_lib! { year = 2025 } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4207064 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +use aoc_runner_derive::aoc_main; + +aoc_main! { lib = aoc2025 } diff --git a/utils/grid/Cargo.lock b/utils/grid/Cargo.lock new file mode 100644 index 0000000..1c1a197 --- /dev/null +++ b/utils/grid/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "grid" +version = "0.1.0" diff --git a/utils/grid/Cargo.toml b/utils/grid/Cargo.toml new file mode 100644 index 0000000..6507dcf --- /dev/null +++ b/utils/grid/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "grid" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[lib] +path = "lib.rs" diff --git a/utils/grid/lib.rs b/utils/grid/lib.rs new file mode 100644 index 0000000..ba73c4f --- /dev/null +++ b/utils/grid/lib.rs @@ -0,0 +1,512 @@ +use std::{ + fmt::{Debug, Display, Formatter, Write}, + io::{BufRead, Cursor}, + iter::repeat_n, + mem::swap, + ops::{Add, AddAssign, Sub}, + str::FromStr, +}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Coord2d { + pub x: i64, + pub y: i64, +} + +pub trait AsCoord2d { + fn to_coord(self) -> Coord2d; + fn x(&self) -> i64; + fn y(&self) -> i64; +} + +impl Sub for &Coord2d { + type Output = Coord2d; + fn sub(self, rhs: T) -> Self::Output { + Coord2d { + x: self.x() - rhs.x(), + y: self.y() - rhs.y(), + } + } +} + +impl Add for &Coord2d { + type Output = Coord2d; + fn add(self, rhs: T) -> Self::Output { + Coord2d { + x: self.x() + rhs.x(), + y: self.y() + rhs.y(), + } + } +} + +impl Add<&T> for Coord2d { + type Output = Coord2d; + fn add(self, rhs: &T) -> Self::Output { + Coord2d { + x: self.x() + rhs.x(), + y: self.y() + rhs.y(), + } + } +} + +impl AsCoord2d for Coord2d { + fn to_coord(self) -> Coord2d { + self + } + fn x(&self) -> i64 { + self.x + } + fn y(&self) -> i64 { + self.y + } +} + +impl AsCoord2d for &Coord2d { + fn to_coord(self) -> Coord2d { + self.to_owned() + } + fn x(&self) -> i64 { + self.x + } + fn y(&self) -> i64 { + self.y + } +} + +impl AsCoord2d for (T, T) +where + T: Copy + TryInto, + >::Error: Debug, +{ + fn to_coord(self) -> Coord2d { + Coord2d { + x: self.0.try_into().unwrap(), + y: self.1.try_into().unwrap(), + } + } + fn x(&self) -> i64 { + self.0.try_into().unwrap() + } + fn y(&self) -> i64 { + self.1.try_into().unwrap() + } +} + +impl AsCoord2d for &(T, T) +where + T: Copy + TryInto, + >::Error: Debug, +{ + fn to_coord(self) -> Coord2d { + Coord2d { + x: self.0.try_into().unwrap(), + y: self.1.try_into().unwrap(), + } + } + fn x(&self) -> i64 { + self.0.try_into().unwrap() + } + fn y(&self) -> i64 { + self.1.try_into().unwrap() + } +} + +impl From for (i64, i64) { + fn from(value: Coord2d) -> Self { + (value.x, value.y) + } +} + +#[derive(Debug)] +pub struct GridRowIter<'a, T> { + iter: std::slice::Iter<'a, T>, +} + +impl<'a, T: Clone + Eq + PartialEq + Debug> GridRowIter<'a, T> { + fn new(grid: &'a Grid, y: i64) -> Self { + let iter = grid.data[y as usize * grid.width()..(y as usize + 1) * grid.width()].iter(); + Self { iter } + } +} + +impl<'a, T> Iterator for GridRowIter<'a, T> { + type Item = &'a T; + fn next(&mut self) -> Option { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[derive(Debug)] +pub struct CoordIter<'a, T> { + pos: usize, + grid: &'a Grid, +} + +impl<'a, T: Clone + Eq + PartialEq + Debug> Iterator for CoordIter<'a, T> { + type Item = Coord2d; + fn next(&mut self) -> Option { + if self.pos < self.grid.data.len() { + self.grid.coord(self.pos as i64).into() + } else { + None + } + } +} + +#[derive(Debug)] +pub struct GridColIter<'a, T> { + grid: &'a Grid, + stride: usize, + cur: usize, +} + +impl<'a, T: Clone + Eq + PartialEq + Debug> GridColIter<'a, T> { + fn new(grid: &'a Grid, x: i64) -> Self { + Self { + grid, + stride: grid.width(), + cur: x as usize, + } + } +} + +impl<'a, T: Clone + Eq + PartialEq + Debug> Iterator for GridColIter<'a, T> { + type Item = &'a T; + fn next(&mut self) -> Option { + let cur = self.cur; + self.cur += self.stride; + if cur < self.grid.data.len() { + Some(&self.grid.data[cur]) + } else { + None + } + } + fn size_hint(&self) -> (usize, Option) { + (self.grid.height() - 1, Some(self.grid.height() - 1)) + } +} + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct Grid { + pub data: Vec, + width: i64, +} + +impl Grid { + /// Returns a new [Grid] with the same shape (width x height) as `self`, filled with `fill` + pub fn same_shape(&self, fill: NT) -> Grid { + Grid::with_shape(self.width(), self.height(), fill) + } + /// Returns a new [Grid] with the given shape (width x height), filled with `fill` + pub fn with_shape(width: usize, height: usize, fill: T) -> Self { + Self { + data: Vec::from_iter(repeat_n(fill, width * height)), + width: width as i64, + } + } + pub fn width(&self) -> usize { + self.width as usize + } + pub fn height(&self) -> usize { + self.data.len() / self.width() + } + pub fn pos(&self, c: &C) -> i64 { + c.y() * self.width + c.x() + } + pub fn coord(&self, pos: i64) -> Option { + if pos < 0 || pos >= self.data.len() as i64 { + None + } else { + Some(Coord2d { + x: pos % self.width, + y: pos / self.width, + }) + } + } + // pub fn coord_iter(&self) -> CoordIter<_> { + // CoordIter { pos: 0, grid: self } + // } + pub fn is_valid(&self, c: &C) -> bool { + if c.x() < 0 || c.x() >= self.width { + return false; + } + if c.y() < 0 || c.y() as usize >= self.height() { + return false; + } + return true; + } + fn valid_pos(&self, c: &C) -> Option { + if c.x() < 0 || c.x() >= self.width { + return None; + } + if c.y() < 0 || c.y() as usize >= self.height() { + return None; + } + let pos = self.pos(c); + if pos < 0 || pos as usize >= self.data.len() { + return None; + } + self.pos(c).try_into().ok() + } + pub fn get(&self, c: &C) -> Option<&T> { + match self.valid_pos(c) { + Some(pos) => Some(&self.data[pos]), + None => None, + } + } + pub fn get_mut(&mut self, c: &C) -> Option<&mut T> { + match self.valid_pos(c) { + Some(pos) => Some(self.data.get_mut(pos).unwrap()), + None => None, + } + } + pub fn set(&mut self, c: &C, mut val: T) -> Option { + match self.valid_pos(c) { + Some(pos) => { + swap(&mut self.data[pos], &mut val); + Some(val) + } + None => None, + } + } + pub fn increment<'a, A, C: AsCoord2d>(&'a mut self, c: &C, i: A) -> Option<&'a T> + where + T: AddAssign, + { + match self.valid_pos(c) { + Some(pos) => { + self.data[pos] += i; + Some(&self.data[pos]) + } + None => None, + } + } + pub fn row(&self, y: i64) -> Option<&[T]> { + if y < self.height() as i64 && y >= 0 { + Some(&self.data[self.pos(&(0, y)) as usize..self.pos(&(self.width, y)) as usize]) + } else { + None + } + } + + pub fn row_iter(&self, y: i64) -> Option> { + if (y as usize) < self.height() { + Some(GridRowIter::new(self, y)) + } else { + None + } + } + + pub fn col(&self, x: i64) -> Option> { + if let Some(iter) = self.col_iter(x) { + Some(iter.collect()) + } else { + None + } + } + + pub fn col_iter(&self, x: i64) -> Option> { + if (x as usize) < self.width() { + Some(GridColIter::new(self, x)) + } else { + None + } + } + + pub fn find(&self, haystack: &T) -> Option { + self.coord( + self.data + .iter() + .enumerate() + .find_map(|(pos, val)| if val == haystack { Some(pos as i64) } else { None }) + .unwrap_or(-1), + ) + } + pub fn count(&self, haystack: &T) -> usize { + self.data.iter().filter(|item| *item == haystack).count() + } + + pub fn forward_slice(&self, start: &C, len: i64) -> Option<&[T]> { + let pos = (self.valid_pos(start), self.valid_pos(&(start.x() + len - 1, start.y()))); + match pos { + (Some(pos1), Some(pos2)) => Some(&self.data[pos1..pos2 + 1]), + _ => None, + } + } + + pub fn swap(&mut self, a: A, b: B) { + if let (Some(a), Some(b)) = (self.valid_pos(&a), self.valid_pos(&b)) { + self.data.swap(a, b) + } + } + + // fn window_compare_impl(&self, needle: &[T]) -> Vec<(i64, i64)> { + // if (self.width as usize) < needle.len() { + // return Vec::new(); + // } + // let mut res = Vec::new(); + // for y in 0..self.height() as i64 { + // let mut windows_tmp = self.row(y).unwrap().windows(needle.len()); + // let windows = if REV { + // windows_tmp.rev() + // } else { + // windows_tmp + // }; + + // res.extend( + // windows + // .enumerate() + // .filter_map(|(x, w)| if w == needle { Some((x as i64, y)) } else { None }), + // ); + // } + // res + // } +} + +impl From for Grid { + fn from(input: T) -> Grid { + let mut data = Vec::new(); + let mut width = 0; + for line in input.split(b'\n').map(|i| i.unwrap()) { + if width == 0 { + width = line.len() as i64 + } else if line.len() as i64 != width { + panic!("Grids must have fixed length rows") + } + data.extend_from_slice(&line); + } + Grid { data, width } + } +} + +// Should be Grid? +impl FromStr for Grid { + type Err = Box; + fn from_str(s: &str) -> Result { + Ok(Cursor::new(s).into()) + } +} + +// impl> Display for Grid { +// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +// for y in 0..self.height() { +// for x in 0..self.width() { +// f.write_fmt(format_args!("{}",self.get(x as i64, y as i64).unwrap() as char))?; +// } +// f.write_char('\n')?; +// } +// f.write_char('\n') +// } +// } + +impl Display for Grid { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + for y in 0..self.height() { + for x in 0..self.width() { + f.write_fmt(format_args!("{}", *self.get(&(x as i64, y as i64)).unwrap() as char))?; + } + f.write_char('\n')?; + } + f.write_char('\n') + } +} + +impl Display for Grid { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + for y in 0..self.height() { + for x in 0..self.width() { + f.write_fmt(format_args!( + "{}", + match *self.get(&(x as i64, y as i64)).unwrap() { + true => '.', + false => '#', + } + ))?; + } + f.write_char('\n')?; + } + f.write_char('\n') + } +} + +#[cfg(test)] +mod tests { + use super::*; + + static TEST_VECTOR: &[u8] = b"ABCD +EFGH +IJKL +FBCG"; + + static TEST_VECTOR_S: &str = "ABCD +EFGH +IJKL +FBCG"; + + fn unchecked_load() -> Grid { + Grid::from(TEST_VECTOR) + } + + #[test] + fn from_string() { + let grid = unchecked_load(); + assert_eq!(grid.data, "ABCDEFGHIJKLFBCG".as_bytes()); + assert_eq!( + TEST_VECTOR_S.parse::>().unwrap().data, + "ABCDEFGHIJKLFBCG".as_bytes() + ); + } + + #[test] + fn indexing() { + let grid = unchecked_load(); + assert_eq!(grid.get(&(0, 0)), Some(b'A').as_ref()); + assert_eq!(grid.get(&(3, 3)), Some(b'G').as_ref()); + assert_eq!(grid.get(&(-1, 0)), None); + assert_eq!(grid.get(&(0, -1)), None); + assert_eq!(grid.get(&(5, 0)), None); + assert_eq!(grid.get(&(0, 5)), None); + } + + #[test] + fn forward_slice() { + let grid = unchecked_load(); + assert_eq!(grid.forward_slice(&(0, 0), 2), Some(b"AB".as_slice())); + assert_eq!(grid.forward_slice(&(2, 0), 2), Some(b"CD".as_slice())); + assert_eq!(grid.forward_slice(&(2, 0), 3), None); + assert_eq!(grid.forward_slice(&(0, 2), 4), Some(b"IJKL".as_slice())); + } + + #[test] + fn row_iter() { + let grid = unchecked_load(); + assert_eq!( + grid.row_iter(2).unwrap().collect::>(), + [&b'I', &b'J', &b'K', &b'L'] + ); + assert!(grid.row_iter(-1).is_none()); + assert!(grid.row_iter(4).is_none()); + } + + #[test] + fn col_iter() { + let grid = unchecked_load(); + assert_eq!( + grid.col_iter(2).unwrap().collect::>(), + [&b'C', &b'G', &b'K', &b'C'] + ); + assert!(grid.col_iter(-1).is_none()); + assert!(grid.col_iter(4).is_none()); + } + + // #[test] + // fn window_compare() { + // let grid = unchecked_load(); + // assert_eq!(grid.window_compare(b"IJKL"), &[(0, 2)]); + // assert_eq!(grid.window_compare(b"BC"), &[(1, 0), (1, 3)]); + // assert_eq!(grid.window_compare(b"LF").len(), 0); + // } +} diff --git a/utils/misc/Cargo.lock b/utils/misc/Cargo.lock new file mode 100644 index 0000000..f6716d7 --- /dev/null +++ b/utils/misc/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "misc" +version = "0.1.0" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] diff --git a/utils/misc/Cargo.toml b/utils/misc/Cargo.toml new file mode 100644 index 0000000..3704ff9 --- /dev/null +++ b/utils/misc/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "misc" +version = "0.1.0" +edition = "2021" + +[dependencies] +num-traits = "0.2.19" diff --git a/utils/misc/src/lib.rs b/utils/misc/src/lib.rs new file mode 100644 index 0000000..b7d4b5c --- /dev/null +++ b/utils/misc/src/lib.rs @@ -0,0 +1,98 @@ +use num_traits::Signed; +use std::fmt::Display; +use std::ops::{Add, AddAssign}; + +/// Wrapped signed integer with custom upper bound with wrapping of 0s to the upper bound +#[derive(Eq, Clone, Copy)] +pub struct CustomWrapped { + pub val: T, + pub bound: T, +} + +impl Add for CustomWrapped { + type Output = CustomWrapped; + fn add(self, rhs: T) -> Self::Output { + Self { + val: ((self.val + rhs % self.bound) + self.bound) % self.bound, + bound: self.bound, + } + } +} + +impl Add for &CustomWrapped { + type Output = CustomWrapped; + fn add(self, rhs: T) -> Self::Output { + CustomWrapped { + val: ((self.val + rhs % self.bound) + self.bound) % self.bound, + bound: self.bound, + } + } +} + +impl AddAssign for CustomWrapped { + fn add_assign(&mut self, rhs: T) { + self.val = ((self.val + rhs % self.bound) + self.bound) % self.bound + } +} + +impl CustomWrapped { + pub fn new(val: T, bound: T) -> Self { + Self { val, bound } + } +} + +impl PartialEq for CustomWrapped { + fn eq(&self, other: &Self) -> bool { + self.val.eq(&other.val) + } +} + +impl PartialOrd for CustomWrapped { + fn partial_cmp(&self, other: &Self) -> Option { + self.val.partial_cmp(&other.val) + } +} + +impl Ord for CustomWrapped { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.val.cmp(&other.val) + } +} + +impl PartialEq for CustomWrapped { + fn eq(&self, other: &T) -> bool { + self.val == *other + } +} + +impl PartialOrd for CustomWrapped { + fn partial_cmp(&self, other: &T) -> Option { + self.val.partial_cmp(other) + } +} + +impl Display for CustomWrapped +where + T: Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.val.fmt(f) + } +} + +// impl Into for CustomWrapped { +// fn into(self) -> T { +// self.val +// } +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +}