Compare commits
10 Commits
0000007042
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
0000017053
|
|||
|
00000160b4
|
|||
|
0000015041
|
|||
|
000001406b
|
|||
|
0000013047
|
|||
|
0000012050
|
|||
|
000001107e
|
|||
|
00000100ac
|
|||
|
0000009008
|
|||
|
0000008038
|
@@ -1,6 +0,0 @@
|
|||||||
[alias]
|
|
||||||
scaffold = "run --bin scaffold --quiet --release --"
|
|
||||||
download = "run --bin download --quiet --release --"
|
|
||||||
download_all = "run --bin download_all --quiet --release --"
|
|
||||||
|
|
||||||
solve = "run --bin"
|
|
||||||
4
.cargo/config.toml
Normal file
4
.cargo/config.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[alias]
|
||||||
|
scaffold = "run -p scaffold --release --quiet --"
|
||||||
|
download = "run -p download --release --quiet --"
|
||||||
|
solve = "run --bin"
|
||||||
2
.git-blame-ignore-revs
Normal file
2
.git-blame-ignore-revs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# updated template
|
||||||
|
00000160b401197691cb1ddd77c7cdb7e345d9f4
|
||||||
36
.github/workflows/ci.yml
vendored
36
.github/workflows/ci.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: Check
|
|
||||||
|
|
||||||
on: push
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Check
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: cargo check
|
|
||||||
run: cargo check
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Test
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: cargo test
|
|
||||||
run: cargo test
|
|
||||||
clippy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Lint (clippy)
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: cargo clippy
|
|
||||||
run: cargo clippy -- -D warnings
|
|
||||||
fmt:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Format
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: cargo fmt
|
|
||||||
run: cargo fmt --check
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -11,6 +11,6 @@ target/
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
# downloaded inputs
|
# downloaded inputs
|
||||||
/src/inputs/*
|
/data/inputs/*
|
||||||
!/src/inputs/.keep
|
!/data/inputs/.keep
|
||||||
|
|
||||||
|
|||||||
255
Cargo.lock
generated
255
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
@@ -24,19 +24,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aoc"
|
name = "aoc"
|
||||||
version = "24.0.0"
|
version = "48.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenv",
|
|
||||||
"elves",
|
"elves",
|
||||||
"hashbrown 0.13.1",
|
"hashbrown 0.13.1",
|
||||||
"hex-literal",
|
"hex-literal",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"md-5",
|
"md-5",
|
||||||
"pico-args",
|
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
|
||||||
"tokio",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -47,9 +43,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.13.1"
|
version = "0.21.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
@@ -127,10 +123,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenv"
|
name = "dotenvy"
|
||||||
version = "0.15.0"
|
version = "0.15.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "download"
|
||||||
|
version = "48.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"dotenvy",
|
||||||
|
"pico-args",
|
||||||
|
"reqwest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
@@ -212,6 +217,12 @@ version = "0.3.25"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
|
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.25"
|
version = "0.3.25"
|
||||||
@@ -231,9 +242,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
|
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -280,15 +294,6 @@ dependencies = [
|
|||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex-literal"
|
name = "hex-literal"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
@@ -437,16 +442,6 @@ version = "0.2.139"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.17"
|
||||||
@@ -507,16 +502,6 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
@@ -568,29 +553,6 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.9.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"smallvec",
|
|
||||||
"windows-sys 0.42.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
@@ -676,9 +638,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.13"
|
version = "0.11.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
|
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -698,9 +660,12 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
|
"sync_wrapper",
|
||||||
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@@ -711,12 +676,30 @@ dependencies = [
|
|||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pemfile"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scaffold"
|
||||||
|
version = "48.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"dotenvy",
|
||||||
|
"pico-args",
|
||||||
|
"reqwest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.20"
|
version = "0.1.20"
|
||||||
@@ -727,12 +710,6 @@ dependencies = [
|
|||||||
"windows-sys 0.36.1",
|
"windows-sys 0.36.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.7.0"
|
version = "2.7.0"
|
||||||
@@ -785,15 +762,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-registry"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@@ -803,12 +771,6 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@@ -830,6 +792,33 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sync_wrapper"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"core-foundation",
|
||||||
|
"system-configuration-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
@@ -870,26 +859,11 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"memchr",
|
"memchr",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
|
||||||
"parking_lot",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
|
||||||
"windows-sys 0.42.0",
|
"windows-sys 0.42.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-macros"
|
|
||||||
version = "1.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-native-tls"
|
name = "tokio-native-tls"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -1129,21 +1103,51 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.42.0",
|
||||||
"windows_aarch64_msvc 0.42.0",
|
"windows_aarch64_msvc 0.42.0",
|
||||||
"windows_i686_gnu 0.42.0",
|
"windows_i686_gnu 0.42.0",
|
||||||
"windows_i686_msvc 0.42.0",
|
"windows_i686_msvc 0.42.0",
|
||||||
"windows_x86_64_gnu 0.42.0",
|
"windows_x86_64_gnu 0.42.0",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.42.0",
|
||||||
"windows_x86_64_msvc 0.42.0",
|
"windows_x86_64_msvc 0.42.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
@@ -1156,6 +1160,12 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
@@ -1168,6 +1178,12 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
@@ -1180,6 +1196,12 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
@@ -1192,12 +1214,24 @@ version = "0.42.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
@@ -1211,10 +1245,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.10.1"
|
version = "0.48.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winreg"
|
||||||
|
version = "0.50.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"cfg-if",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|||||||
27
Cargo.toml
27
Cargo.toml
@@ -1,23 +1,30 @@
|
|||||||
[package]
|
[workspace.package]
|
||||||
name = "aoc"
|
description = "Advent of Code 2016"
|
||||||
description = "solutions for advent of code 2016"
|
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
version = "24.0.0"
|
version = "48.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Matej Janežič <janezic.mj@gmail.com>"]
|
authors = ["Matej Janežič <janezic.mj@gmail.com>"]
|
||||||
repository = "https://github.com/janezicmatej/aoc-template.git"
|
repository = "https://git.janezic.dev/janezicmatej/aoc2016.git"
|
||||||
default-run = "aoc"
|
|
||||||
|
[workspace]
|
||||||
|
members = ["utils/download", "utils/scaffold"]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "aoc"
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dotenv = "0.15.0"
|
|
||||||
elves = "0.2.0"
|
elves = "0.2.0"
|
||||||
hashbrown = "0.13.1"
|
hashbrown = "0.13.1"
|
||||||
hex-literal = "0.3.4"
|
hex-literal = "0.3.4"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
md-5 = "0.10.5"
|
md-5 = "0.10.5"
|
||||||
pico-args = "0.5.0"
|
|
||||||
regex = "1.7.0"
|
regex = "1.7.0"
|
||||||
reqwest = "0.11.13"
|
|
||||||
tokio = { version = "1.23.0", features = ["full"] }
|
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -1,27 +1,26 @@
|
|||||||

|
|
||||||
# Advent-of-Code 2016
|
# Advent-of-Code 2016
|
||||||
*This is a dumbed down version of [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust) with some extra features*
|
*This is a dumbed down version of [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust) with some extra features*
|
||||||
|
|
||||||
## Project overview
|
## Project overview
|
||||||
|
|
||||||
### Project structure
|
### Project structure
|
||||||
|
- `data/` :
|
||||||
|
- `examples/`: example files go here; you can push this as test are run in ci
|
||||||
|
- `inputs/`: this directory is gitignored, input files go here
|
||||||
- `src/` :
|
- `src/` :
|
||||||
- `bin/`:
|
- `bin/`:
|
||||||
- `<day>.rs`: solution files
|
- `<day>.rs`: solution files
|
||||||
- `*.rs`: convenience scripts
|
- `lib.rs`: library entrypoint, reusable code goes here
|
||||||
- `inputs/`: this directory is gitignored, input files go here
|
- `template.rs`: contains template code
|
||||||
- `examples/`: example files go here; you can push this as test are run in ci
|
- `utils/`: binary packages with convenience scripts structured using cargo workspaces
|
||||||
- `utils/`: utils files go here
|
|
||||||
- `lib.rs`: contains framework code
|
|
||||||
- `main.rs`: contains framework code
|
|
||||||
- `.env.example`: example dotenv file
|
- `.env.example`: example dotenv file
|
||||||
|
|
||||||
### Cli
|
### Cli
|
||||||
- `cargo scaffold <day>`: prepare solution files for `day`
|
- `cargo scaffold <day>`: prepare solution files for `day`
|
||||||
- `cargo download <day>`: download input file for `day`
|
- `cargo download <day>`: download input file for `day`
|
||||||
- `cargo solve <day>`: run solution against input for `day`
|
- `cargo solve <day>`: run solution against input for `day`
|
||||||
- `cargo all`: alias for run; runs solutions for all days
|
|
||||||
|
|
||||||
|
*Run `cargo build --workspace --release` once so scaffold and download packages get compiled, otherwise they will have to be compiled on first run.*
|
||||||
|
|
||||||
### dotenv
|
### dotenv
|
||||||
|
|
||||||
|
|||||||
8
data/examples/07.txt
Normal file
8
data/examples/07.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
abba[mnop]qrst
|
||||||
|
abcd[bddb]xyyx
|
||||||
|
aaaa[qwer]tyui
|
||||||
|
ioxxoj[asdfgh]zxcvbn
|
||||||
|
aba[bab]xyz
|
||||||
|
xyx[xyx]xyx
|
||||||
|
aaa[kek]eke
|
||||||
|
zazbz[bzb]cdb
|
||||||
4
data/examples/08.txt
Normal file
4
data/examples/08.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
rect 3x2
|
||||||
|
rotate column x=1 by 1
|
||||||
|
rotate row y=0 by 4
|
||||||
|
rotate column x=1 by 1
|
||||||
1
data/examples/09.txt
Normal file
1
data/examples/09.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN
|
||||||
0
src/bin/.keep
Normal file
0
src/bin/.keep
Normal file
@@ -76,22 +76,20 @@ pub fn part_two(input: &str) -> Option<isize> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", 1);
|
aoc::solution!(1);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", 1);
|
let input = aoc::template::read_file("examples", 1);
|
||||||
assert_eq!(part_one(&input), Some(8));
|
assert_eq!(part_one(&input), Some(8));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", 1);
|
let input = aoc::template::read_file("examples", 1);
|
||||||
assert_eq!(part_two(&input), Some(4));
|
assert_eq!(part_two(&input), Some(4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,22 +58,20 @@ pub fn part_two(input: &str) -> Option<String> {
|
|||||||
|
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", 2);
|
aoc::solution!(2);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", 2);
|
let input = aoc::template::read_file("examples", 2);
|
||||||
assert_eq!(part_one(&input), Some(1985));
|
assert_eq!(part_one(&input), Some(1985));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", 2);
|
let input = aoc::template::read_file("examples", 2);
|
||||||
assert_eq!(part_two(&input), Some("5DB3".to_string()));
|
assert_eq!(part_two(&input), Some("5DB3".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,22 +41,20 @@ pub fn part_two(input: &str) -> Option<usize> {
|
|||||||
.count(),
|
.count(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", 3);
|
aoc::solution!(3);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", 3);
|
let input = aoc::template::read_file("examples", 3);
|
||||||
assert_eq!(part_one(&input), Some(2));
|
assert_eq!(part_one(&input), Some(2));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", 3);
|
let input = aoc::template::read_file("examples", 3);
|
||||||
assert_eq!(part_two(&input), Some(1));
|
assert_eq!(part_two(&input), Some(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,22 +77,20 @@ pub fn part_two(input: &str) -> Option<usize> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", 4);
|
aoc::solution!(4);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", 4);
|
let input = aoc::template::read_file("examples", 4);
|
||||||
assert_eq!(part_one(&input), Some(1514));
|
assert_eq!(part_one(&input), Some(1514));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", 4);
|
let input = aoc::template::read_file("examples", 4);
|
||||||
assert_eq!(part_two(&input), None);
|
assert_eq!(part_two(&input), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,22 +57,20 @@ pub fn part_two(input: &str) -> Option<String> {
|
|||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", 5);
|
aoc::solution!(5);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", 5);
|
let input = aoc::template::read_file("examples", 5);
|
||||||
assert_eq!(part_one(&input), Some("18f47a30".to_string()));
|
assert_eq!(part_one(&input), Some("18f47a30".to_string()));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", 5);
|
let input = aoc::template::read_file("examples", 5);
|
||||||
assert_eq!(part_two(&input), Some("05ace8e3".to_string()));
|
assert_eq!(part_two(&input), Some("05ace8e3".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,22 +28,20 @@ pub fn part_one(input: &str) -> Option<String> {
|
|||||||
pub fn part_two(input: &str) -> Option<String> {
|
pub fn part_two(input: &str) -> Option<String> {
|
||||||
Some(solve(input, true))
|
Some(solve(input, true))
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", 6);
|
aoc::solution!(6);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", 6);
|
let input = aoc::template::read_file("examples", 6);
|
||||||
assert_eq!(part_one(&input), Some("easter".to_string()));
|
assert_eq!(part_one(&input), Some("easter".to_string()));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", 6);
|
let input = aoc::template::read_file("examples", 6);
|
||||||
assert_eq!(part_two(&input), Some("advent".to_string()));
|
assert_eq!(part_two(&input), Some("advent".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
81
src/bin/07.rs
Normal file
81
src/bin/07.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
use hashbrown::HashSet;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
fn is_abba(address_part: &str) -> bool {
|
||||||
|
for (a, b, c, d) in address_part.chars().tuple_windows() {
|
||||||
|
if a == d && b == c && a != b {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_abas(address_part: &str) -> Vec<(char, char)> {
|
||||||
|
address_part
|
||||||
|
.chars()
|
||||||
|
.tuple_windows()
|
||||||
|
.map(|(a, b, c)| (a, b, c))
|
||||||
|
.filter(|(a, b, c)| a == c && a != b)
|
||||||
|
.map(|(a, b, _)| (a, b))
|
||||||
|
.collect_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<u32> {
|
||||||
|
let mut count = 0;
|
||||||
|
'lines: for line in input.lines() {
|
||||||
|
let mut found_abba = false;
|
||||||
|
for (idx, address_part) in line.split(['[', ']']).enumerate() {
|
||||||
|
match idx % 2 {
|
||||||
|
0 => found_abba |= is_abba(address_part),
|
||||||
|
1 => {
|
||||||
|
if is_abba(address_part) {
|
||||||
|
continue 'lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found_abba {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(count)
|
||||||
|
}
|
||||||
|
pub fn part_two(input: &str) -> Option<u32> {
|
||||||
|
let mut count = 0;
|
||||||
|
for line in input.lines() {
|
||||||
|
let mut abas = HashSet::new();
|
||||||
|
let mut babs = HashSet::new();
|
||||||
|
for (idx, address_part) in line.split(['[', ']']).enumerate() {
|
||||||
|
match idx % 2 {
|
||||||
|
0 => abas.extend(get_abas(address_part)),
|
||||||
|
1 => babs.extend(get_abas(address_part).into_iter().map(|(a, b)| (b, a))),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !abas.intersection(&babs).collect_vec().is_empty() {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
aoc::solution!(7);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
let input = aoc::template::read_file("examples", 7);
|
||||||
|
assert_eq!(part_one(&input), Some(2));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_part_two() {
|
||||||
|
let input = aoc::template::read_file("examples", 7);
|
||||||
|
assert_eq!(part_two(&input), Some(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
119
src/bin/08.rs
Normal file
119
src/bin/08.rs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
const ROWS: usize = 6;
|
||||||
|
const COLS: usize = 50;
|
||||||
|
|
||||||
|
fn generate_grid<const N: usize, const M: usize>(input: &str) -> [[bool; N]; M] {
|
||||||
|
let mut grid = [[false; N]; M];
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
let (inst, rest) = line.split_once(" ").unwrap();
|
||||||
|
|
||||||
|
match inst {
|
||||||
|
"rect" => {
|
||||||
|
let (a, b) = rest
|
||||||
|
.split('x')
|
||||||
|
.filter_map(|x| x.parse().ok())
|
||||||
|
.next_tuple()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for col in grid.iter_mut().take(a) {
|
||||||
|
for cell in col.iter_mut().take(b) {
|
||||||
|
*cell = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"rotate" => {
|
||||||
|
let (inst, rest) = rest.split_once(" ").unwrap();
|
||||||
|
|
||||||
|
match inst {
|
||||||
|
"row" => {
|
||||||
|
let rest = rest.strip_prefix("y=").unwrap();
|
||||||
|
let (a, b) = rest
|
||||||
|
.split(" by ")
|
||||||
|
.filter_map(|x| x.parse().ok())
|
||||||
|
.next_tuple()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for _ in 0..b {
|
||||||
|
let placeholder = grid[COLS - 1][a];
|
||||||
|
|
||||||
|
for i in (1..COLS).rev() {
|
||||||
|
grid[i][a] = grid[i - 1][a];
|
||||||
|
}
|
||||||
|
|
||||||
|
grid[0][a] = placeholder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"column" => {
|
||||||
|
let rest = rest.strip_prefix("x=").unwrap();
|
||||||
|
let (a, b) = rest
|
||||||
|
.split(" by ")
|
||||||
|
.filter_map(|x| x.parse().ok())
|
||||||
|
.next_tuple()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for _ in 0..b {
|
||||||
|
let placeholder = grid[a][ROWS - 1];
|
||||||
|
|
||||||
|
for i in (1..ROWS).rev() {
|
||||||
|
grid[a][i] = grid[a][i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
grid[a][0] = placeholder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grid
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<u32> {
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
for col in generate_grid::<ROWS, COLS>(input).iter() {
|
||||||
|
for cell in col.iter().copied() {
|
||||||
|
if cell {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_two(input: &str) -> Option<String> {
|
||||||
|
let grid = generate_grid::<ROWS, COLS>(input);
|
||||||
|
|
||||||
|
let mut s = String::with_capacity((ROWS + 1) * COLS);
|
||||||
|
|
||||||
|
for row in 0..ROWS {
|
||||||
|
for col in grid.iter() {
|
||||||
|
if col[row] {
|
||||||
|
s.push('#');
|
||||||
|
} else {
|
||||||
|
s.push('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
aoc::solution!(8);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
let input = aoc::template::read_file("examples", 8);
|
||||||
|
assert_eq!(part_one(&input), Some(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
78
src/bin/09.rs
Normal file
78
src/bin/09.rs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
fn decompress(input: &str, recursive: bool) -> usize {
|
||||||
|
let mut stack = input
|
||||||
|
.chars()
|
||||||
|
.filter(|x| !x.is_whitespace())
|
||||||
|
.rev()
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let mut drained = vec![];
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
while let Some(c) = stack.pop() {
|
||||||
|
if c == '(' {
|
||||||
|
let mut n = 0;
|
||||||
|
let sublen = loop {
|
||||||
|
let l = stack.pop().unwrap();
|
||||||
|
if l == 'x' {
|
||||||
|
break n;
|
||||||
|
}
|
||||||
|
n = n * 10 + l.to_digit(10).unwrap() as usize;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut n = 0;
|
||||||
|
let repeat = loop {
|
||||||
|
let l = stack.pop().unwrap();
|
||||||
|
if l == ')' {
|
||||||
|
break n;
|
||||||
|
}
|
||||||
|
n = n * 10 + l.to_digit(10).unwrap() as usize;
|
||||||
|
};
|
||||||
|
|
||||||
|
drained.clear();
|
||||||
|
|
||||||
|
for _ in 0..sublen {
|
||||||
|
drained.push(stack.pop().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if recursive {
|
||||||
|
for _ in 0..repeat {
|
||||||
|
for d in drained.iter().copied().rev() {
|
||||||
|
stack.push(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count += drained.len() * repeat
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<usize> {
|
||||||
|
Some(decompress(input, false))
|
||||||
|
}
|
||||||
|
pub fn part_two(input: &str) -> Option<usize> {
|
||||||
|
Some(decompress(input, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
aoc::solution!(9);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
let input = aoc::template::read_file("examples", 9);
|
||||||
|
assert_eq!(part_one(&input), Some(238));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_part_two() {
|
||||||
|
let input = aoc::template::read_file("examples", 9);
|
||||||
|
assert_eq!(part_two(&input), Some(445));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
use dotenv::dotenv;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use reqwest::{header, Client};
|
|
||||||
use std::{env, fs::OpenOptions, io::Write, process};
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
dotenv().ok();
|
|
||||||
let token = env::var("TOKEN").expect("$TOKEN is not set");
|
|
||||||
let year = env::var("YEAR")
|
|
||||||
.expect("$YEAR is not set")
|
|
||||||
.parse::<u32>()
|
|
||||||
.expect("$YEAR must be a number");
|
|
||||||
|
|
||||||
let mut headers = header::HeaderMap::new();
|
|
||||||
let mut session_header = header::HeaderValue::from_str(format!("session={token}").as_str())
|
|
||||||
.expect("Error building cookie header");
|
|
||||||
session_header.set_sensitive(true);
|
|
||||||
headers.insert(header::COOKIE, session_header);
|
|
||||||
|
|
||||||
let client = Client::builder().default_headers(headers).build().unwrap();
|
|
||||||
let responses = (1..=25)
|
|
||||||
.map(|d| {
|
|
||||||
let endpoint = format!("https://adventofcode.com/{year}/day/{d}/input");
|
|
||||||
println!("{endpoint}");
|
|
||||||
client.get(endpoint).send()
|
|
||||||
})
|
|
||||||
.collect_vec()
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| async { x.await.unwrap().text().await.unwrap() })
|
|
||||||
.collect_vec();
|
|
||||||
|
|
||||||
for (day, res) in (1..=25).zip(responses) {
|
|
||||||
let input_path = format!("src/inputs/{day:02}.txt");
|
|
||||||
let mut file = match OpenOptions::new()
|
|
||||||
.write(true)
|
|
||||||
.create(true)
|
|
||||||
.open(&input_path)
|
|
||||||
{
|
|
||||||
Ok(file) => file,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to create module file: {e}");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match file.write_all(res.await.as_bytes()) {
|
|
||||||
Ok(_) => {
|
|
||||||
println!("Downloaded input file \"{}\"", &input_path);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to write module contents: {e}");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
128
src/lib.rs
128
src/lib.rs
@@ -1,127 +1 @@
|
|||||||
/*
|
pub mod template;
|
||||||
* This file contains template code.
|
|
||||||
* There is no need to edit this file unless you want to change template functionality.
|
|
||||||
* Prefer `./helpers.rs` if you want to extract code from your solutions.
|
|
||||||
*/
|
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
pub const ANSI_ITALIC: &str = "\x1b[3m";
|
|
||||||
pub const ANSI_BOLD: &str = "\x1b[1m";
|
|
||||||
pub const ANSI_RESET: &str = "\x1b[0m";
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! solve {
|
|
||||||
($part:expr, $solver:ident, $input:expr) => {{
|
|
||||||
use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
fn print_result<T: Display>(func: impl FnOnce(&str) -> Option<T>, input: &str) {
|
|
||||||
let timer = Instant::now();
|
|
||||||
let result = func(input);
|
|
||||||
let elapsed = timer.elapsed();
|
|
||||||
match result {
|
|
||||||
Some(result) => {
|
|
||||||
println!(
|
|
||||||
"{} {}(elapsed: {:.2?}){}",
|
|
||||||
result, ANSI_ITALIC, elapsed, ANSI_RESET
|
|
||||||
);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
println!("not solved.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("🎄 {}Part {}{} 🎄", ANSI_BOLD, $part, ANSI_RESET);
|
|
||||||
print_result($solver, $input);
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_file(folder: &str, day: u8) -> String {
|
|
||||||
let cwd = env::current_dir().unwrap();
|
|
||||||
|
|
||||||
let filepath = cwd.join("src").join(folder).join(format!("{day:02}.txt"));
|
|
||||||
|
|
||||||
let f = fs::read_to_string(filepath);
|
|
||||||
f.expect("could not open input file").trim().to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_time(val: &str, postfix: &str) -> f64 {
|
|
||||||
val.split(postfix).next().unwrap().parse().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_args() -> Result<u8, pico_args::Error> {
|
|
||||||
let mut args = pico_args::Arguments::from_env();
|
|
||||||
args.free_from_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_exec_time(output: &str) -> f64 {
|
|
||||||
output.lines().fold(0_f64, |acc, l| {
|
|
||||||
if !l.contains("elapsed:") {
|
|
||||||
acc
|
|
||||||
} else {
|
|
||||||
let timing = l.split("(elapsed: ").last().unwrap();
|
|
||||||
// use `contains` istd. of `ends_with`: string may contain ANSI escape sequences.
|
|
||||||
// for possible time formats, see: https://github.com/rust-lang/rust/blob/1.64.0/library/core/src/time.rs#L1176-L1200
|
|
||||||
if timing.contains("ns)") {
|
|
||||||
acc // range below rounding precision.
|
|
||||||
} else if timing.contains("µs)") {
|
|
||||||
acc + parse_time(timing, "µs") / 1000_f64
|
|
||||||
} else if timing.contains("ms)") {
|
|
||||||
acc + parse_time(timing, "ms")
|
|
||||||
} else if timing.contains("s)") {
|
|
||||||
acc + parse_time(timing, "s") * 1000_f64
|
|
||||||
} else {
|
|
||||||
acc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// copied from: https://github.com/rust-lang/rust/blob/1.64.0/library/std/src/macros.rs#L328-L333
|
|
||||||
#[cfg(test)]
|
|
||||||
macro_rules! assert_approx_eq {
|
|
||||||
($a:expr, $b:expr) => {{
|
|
||||||
let (a, b) = (&$a, &$b);
|
|
||||||
assert!(
|
|
||||||
(*a - *b).abs() < 1.0e-6,
|
|
||||||
"{} is not approximately equal to {}",
|
|
||||||
*a,
|
|
||||||
*b
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_exec_time() {
|
|
||||||
assert_approx_eq!(
|
|
||||||
parse_exec_time(&format!(
|
|
||||||
"🎄 Part 1 🎄\n0 (elapsed: 74.13ns){ANSI_RESET}\n🎄 Part 2 🎄\n0 (elapsed: 50.00ns){ANSI_RESET}"
|
|
||||||
)),
|
|
||||||
0_f64
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_approx_eq!(
|
|
||||||
parse_exec_time("🎄 Part 1 🎄\n0 (elapsed: 755µs)\n🎄 Part 2 🎄\n0 (elapsed: 700µs)"),
|
|
||||||
1.455_f64
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_approx_eq!(
|
|
||||||
parse_exec_time("🎄 Part 1 🎄\n0 (elapsed: 70µs)\n🎄 Part 2 🎄\n0 (elapsed: 1.45ms)"),
|
|
||||||
1.52_f64
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_approx_eq!(
|
|
||||||
parse_exec_time(
|
|
||||||
"🎄 Part 1 🎄\n0 (elapsed: 10.3s)\n🎄 Part 2 🎄\n0 (elapsed: 100.50ms)"
|
|
||||||
),
|
|
||||||
10400.50_f64
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
43
src/main.rs
43
src/main.rs
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file contains template code.
|
|
||||||
* There is no need to edit this file unless you want to change template functionality.
|
|
||||||
*/
|
|
||||||
use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let total: f64 = (1..=25)
|
|
||||||
.map(|day| {
|
|
||||||
let day = format!("{day:02}");
|
|
||||||
|
|
||||||
let cmd = Command::new("cargo")
|
|
||||||
.args(["run", "--release", "--bin", &day])
|
|
||||||
.output()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("----------");
|
|
||||||
println!("{ANSI_BOLD}| Day {day} |{ANSI_RESET}");
|
|
||||||
println!("----------");
|
|
||||||
|
|
||||||
let output = String::from_utf8(cmd.stdout).unwrap();
|
|
||||||
let is_empty = output.is_empty();
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
if is_empty {
|
|
||||||
"Not solved."
|
|
||||||
} else {
|
|
||||||
output.trim()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if is_empty {
|
|
||||||
0_f64
|
|
||||||
} else {
|
|
||||||
aoc::parse_exec_time(&output)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
println!("{ANSI_BOLD}Total:{ANSI_RESET} {ANSI_ITALIC}{total:.2}ms{ANSI_RESET}");
|
|
||||||
}
|
|
||||||
56
src/template.rs
Normal file
56
src/template.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* This file contains template code.
|
||||||
|
* There is no need to edit this file unless you want to change template functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
pub const ANSI_ITALIC: &str = "\x1b[3m";
|
||||||
|
pub const ANSI_BOLD: &str = "\x1b[1m";
|
||||||
|
pub const ANSI_RESET: &str = "\x1b[0m";
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
fn time_solution<T>(func: impl FnOnce(&str) -> Option<T>, input: &str) -> Option<(T, Duration)> {
|
||||||
|
let timer = Instant::now();
|
||||||
|
let result = func(input);
|
||||||
|
let elapsed = timer.elapsed();
|
||||||
|
|
||||||
|
result.map(|result| (result, elapsed))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_result<T: Display>(func: impl FnOnce(&str) -> Option<T>, input: &str, part: u8) {
|
||||||
|
match time_solution(func, input) {
|
||||||
|
Some((result, elapsed)) => {
|
||||||
|
println!(
|
||||||
|
"{}Part {}{}: {} {}(elapsed: {:.2?}){}",
|
||||||
|
ANSI_BOLD, part, ANSI_RESET, result, ANSI_ITALIC, elapsed, ANSI_RESET
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("{}Part {}{}: not solved.", ANSI_BOLD, part, ANSI_RESET)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! solution {
|
||||||
|
($day:expr) => {
|
||||||
|
fn main() {
|
||||||
|
let input = aoc::template::read_file("inputs", $day);
|
||||||
|
aoc::template::print_result(part_one, &input, 1);
|
||||||
|
aoc::template::print_result(part_two, &input, 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn read_file(folder: &str, day: u8) -> String {
|
||||||
|
let cwd = env::current_dir().unwrap();
|
||||||
|
let filepath = cwd.join("data").join(folder).join(format!("{day:02}.txt"));
|
||||||
|
let f = fs::read_to_string(filepath);
|
||||||
|
f.expect("could not open input file").trim().to_string()
|
||||||
|
}
|
||||||
14
utils/download/Cargo.toml
Normal file
14
utils/download/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "download"
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
reqwest = { version = "0.11.22", features = ["blocking"] }
|
||||||
|
dotenvy = "0.15.6"
|
||||||
|
pico-args = "0.5.0"
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
use dotenv::dotenv;
|
use dotenvy::dotenv;
|
||||||
use reqwest::{header, Client};
|
use reqwest::blocking::Client;
|
||||||
|
use reqwest::header;
|
||||||
use std::{env, fs::OpenOptions, io::Write, process};
|
use std::{env, fs::OpenOptions, io::Write, process};
|
||||||
|
|
||||||
#[tokio::main]
|
pub fn parse_args() -> Result<u8, pico_args::Error> {
|
||||||
async fn main() {
|
let mut args = pico_args::Arguments::from_env();
|
||||||
let day: u8 = match aoc::parse_args() {
|
args.free_from_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let day: u8 = match parse_args() {
|
||||||
Ok(day) => day,
|
Ok(day) => day,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Need to specify a day (as integer). example: `cargo download 7`");
|
eprintln!("Need to specify a day (as integer). example: `cargo download 7`");
|
||||||
@@ -30,13 +35,11 @@ async fn main() {
|
|||||||
let res = client
|
let res = client
|
||||||
.get(format!("https://adventofcode.com/{year}/day/{day}/input"))
|
.get(format!("https://adventofcode.com/{year}/day/{day}/input"))
|
||||||
.send()
|
.send()
|
||||||
.await
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.text()
|
.text()
|
||||||
.await
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let input_path = format!("src/inputs/{day_padded}.txt");
|
let input_path = format!("data/inputs/{day_padded}.txt");
|
||||||
let mut file = match OpenOptions::new()
|
let mut file = match OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
14
utils/scaffold/Cargo.toml
Normal file
14
utils/scaffold/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "scaffold"
|
||||||
|
description.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
reqwest = { version = "0.11.22", features = ["blocking"] }
|
||||||
|
dotenvy = "0.15.6"
|
||||||
|
pico-args = "0.5.0"
|
||||||
@@ -8,32 +8,34 @@ use std::{
|
|||||||
process,
|
process,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MODULE_TEMPLATE: &str = r###"pub fn part_one(input: &str) -> Option<u32> {
|
const MODULE_TEMPLATE: &str = r#"pub fn part_one(input: &str) -> Option<u32> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn part_two(input: &str) -> Option<u32> {
|
pub fn part_two(input: &str) -> Option<u32> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn main() {
|
|
||||||
let input = &aoc::read_file("inputs", DAY);
|
aoc::solution!(DAY);
|
||||||
aoc::solve!(1, part_one, input);
|
|
||||||
aoc::solve!(2, part_two, input);
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one() {
|
fn test_part_one() {
|
||||||
let input = aoc::read_file("examples", DAY);
|
assert_eq!(part_one(&aoc::template::read_file("examples", DAY)), None);
|
||||||
assert_eq!(part_one(&input), None);
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let input = aoc::read_file("examples", DAY);
|
assert_eq!(part_two(&aoc::template::read_file("examples", DAY)), None);
|
||||||
assert_eq!(part_two(&input), None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"###;
|
"#;
|
||||||
|
|
||||||
|
pub fn parse_args() -> Result<u8, pico_args::Error> {
|
||||||
|
let mut args = pico_args::Arguments::from_env();
|
||||||
|
args.free_from_str()
|
||||||
|
}
|
||||||
|
|
||||||
fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
|
fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
|
||||||
OpenOptions::new().write(true).create_new(true).open(path)
|
OpenOptions::new().write(true).create_new(true).open(path)
|
||||||
@@ -44,7 +46,7 @@ fn create_file(path: &str) -> Result<File, std::io::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let day = match aoc::parse_args() {
|
let day = match parse_args() {
|
||||||
Ok(day) => day,
|
Ok(day) => day,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Need to specify a day (as integer). example: `cargo scaffold 7`");
|
eprintln!("Need to specify a day (as integer). example: `cargo scaffold 7`");
|
||||||
@@ -54,8 +56,8 @@ fn main() {
|
|||||||
|
|
||||||
let day_padded = format!("{day:02}");
|
let day_padded = format!("{day:02}");
|
||||||
|
|
||||||
let input_path = format!("src/inputs/{day_padded}.txt");
|
let input_path = format!("data/inputs/{day_padded}.txt");
|
||||||
let example_path = format!("src/examples/{day_padded}.txt");
|
let example_path = format!("data/examples/{day_padded}.txt");
|
||||||
let module_path = format!("src/bin/{day_padded}.rs");
|
let module_path = format!("src/bin/{day_padded}.rs");
|
||||||
|
|
||||||
let mut file = match safe_create_file(&module_path) {
|
let mut file = match safe_create_file(&module_path) {
|
||||||
@@ -97,8 +99,5 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
println!("---");
|
println!("---");
|
||||||
println!(
|
println!("Type `cargo solve {}` to run your solution.", &day_padded);
|
||||||
"🎄 Type `cargo solve {}` to run your solution.",
|
|
||||||
&day_padded
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user