From cf3e8038f09a49423c1adac6e6bcd3623c5a2efe Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 15:59:37 +0100 Subject: [PATCH 001/134] 2021: add .lohr file --- .lohr | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .lohr diff --git a/.lohr b/.lohr new file mode 100644 index 0000000..5e1301b --- /dev/null +++ b/.lohr @@ -0,0 +1,3 @@ +git@github.com:alarsyo/advent-of-code +git@gitlab.com:alarsyo/advent-of-code +git@git.sr.ht:~alarsyo/advent-of-code From fc3f8227c6b1d2439926147a2619c9ac2c22af1c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:04:31 +0100 Subject: [PATCH 002/134] ci: switch branch to main --- .github/workflows/rust.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 42a5e5a..ddeac58 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -2,9 +2,9 @@ name: Rust on: push: - branches: [ master ] + branches: [ main ] pull_request: - branches: [ master ] + branches: [ main ] env: CARGO_TERM_COLOR: always From db0eb16a537c96273f8b55f2fc9d79e82984377e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:14:32 +0100 Subject: [PATCH 003/134] flake: setup dev flake --- .envrc | 1 + flake.lock | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 26 +++++++++++++++ shell.nix | 3 ++ 4 files changed, 124 insertions(+) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 shell.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..051d09d --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +eval "$(lorri direnv)" diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ce50311 --- /dev/null +++ b/flake.lock @@ -0,0 +1,94 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1637593665, + "narHash": "sha256-R7jKS7A+0tZS8qD5pBr1UFcMiTdsw5bfoxgXbYsoWhM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "98747f27ecfee70c8c97b195cbb94df80a074dda", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1637453606, + "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8afc4e543663ca0a6a4f496262cd05233737e732", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1637806606, + "narHash": "sha256-SVecJKEyKAt/+QGTq5mwXpIgdTJwjzYNmqBoUzSkQes=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "aaf6f89ca6a5d22ed822d93835ce438ee338936c", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..fb06686 --- /dev/null +++ b/flake.nix @@ -0,0 +1,26 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + rust-overlay.url = "github:oxalica/rust-overlay"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + myRust = pkgs.rust-bin.stable.latest.default; + in + { + devShell = pkgs.mkShell { + buildInputs = with pkgs; [ + nixpkgs-fmt + rust-analyzer + myRust + ]; + + RUST_SRC_PATH = "${pkgs.rust-bin.stable.latest.rust-src}/lib/rustlib/src/rust/library"; + }; + }); +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..9730ebd --- /dev/null +++ b/shell.nix @@ -0,0 +1,3 @@ +{ system ? builtins.currentSystem }: + +(builtins.getFlake (toString ./.)).devShell.${system} From e01307eb3c30c4bb25f25dc255c648e390896c86 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:18:20 +0100 Subject: [PATCH 004/134] cargo: fix build by bumping dependencies --- Cargo.lock | 292 +++++++++++++++++++++++++++-------------------------- 1 file changed, 147 insertions(+), 145 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6af7b11..1f1b772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,10 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "anyhow" -version = "1.0.35" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4" +checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e" [[package]] name = "aoc" @@ -68,7 +70,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", - "itertools", + "itertools 0.9.0", "nom", ] @@ -105,15 +107,15 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.19.4" +version = "0.19.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" +checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" dependencies = [ "funty", "radium", @@ -144,9 +146,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" dependencies = [ "lazy_static", "memchr", @@ -156,9 +158,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.4.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" [[package]] name = "byte-tools" @@ -168,25 +170,19 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cast" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" dependencies = [ "rustc_version", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -204,24 +200,18 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "const_fn" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" - [[package]] name = "criterion" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", "clap", "criterion-plot", "csv", - "itertools", + "itertools 0.10.1", "lazy_static", "num-traits", "oorandom", @@ -238,43 +228,42 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ "cast", - "itertools", + "itertools 0.10.1", ] [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.1" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ - "cfg-if 1.0.0", - "const_fn", + "cfg-if", "crossbeam-utils", "lazy_static", "memoffset", @@ -283,20 +272,19 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.1" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "autocfg", - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] [[package]] name = "csv" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", @@ -331,30 +319,30 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "funty" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ba62103ce691c2fd80fbae2213dfdda9ce60804973ac6b6e97de818ea7f52c8" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "generic-array" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ "typenum", ] [[package]] name = "half" -version = "1.6.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] @@ -369,16 +357,25 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "0.4.6" +name = "itertools" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "js-sys" -version = "0.3.46" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" dependencies = [ "wasm-bindgen", ] @@ -391,30 +388,30 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lexical-core" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec", "bitflags", - "cfg-if 0.1.10", + "cfg-if", "ryu", "static_assertions", ] [[package]] name = "libc" -version = "0.2.81" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", ] [[package]] @@ -436,20 +433,21 @@ checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" dependencies = [ "autocfg", ] [[package]] name = "nom" -version = "6.0.1" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" +checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" dependencies = [ "bitvec", + "funty", "lexical-core", "memchr", "version_check", @@ -488,30 +486,46 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "plotters" -version = "0.2.15" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" dependencies = [ - "js-sys", "num-traits", + "plotters-backend", + "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] -name = "proc-macro2" -version = "1.0.24" +name = "plotters-backend" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "proc-macro2" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] @@ -524,9 +538,9 @@ checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" [[package]] name = "rayon" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ "autocfg", "crossbeam-deque", @@ -536,9 +550,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -549,33 +563,30 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -dependencies = [ - "byteorder", -] +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.21" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] @@ -603,30 +614,21 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "0.9.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" [[package]] name = "serde" -version = "1.0.118" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" [[package]] name = "serde_cbor" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ "half", "serde", @@ -634,9 +636,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -645,9 +647,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.60" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" +checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" dependencies = [ "itoa", "ryu", @@ -662,9 +664,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "1.0.54" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", @@ -673,9 +675,9 @@ dependencies = [ [[package]] name = "tap" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "textwrap" @@ -688,9 +690,9 @@ dependencies = [ [[package]] name = "tinytemplate" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", @@ -698,33 +700,33 @@ dependencies = [ [[package]] name = "typenum" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "walkdir" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", "winapi", @@ -733,19 +735,19 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.69" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.69" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", @@ -758,9 +760,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.69" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -768,9 +770,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.69" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ "proc-macro2", "quote", @@ -781,15 +783,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.69" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "web-sys" -version = "0.3.46" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" dependencies = [ "js-sys", "wasm-bindgen", From e82df9485236c67400e37c207f046c2a20afda00 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:23:22 +0100 Subject: [PATCH 005/134] clippy: fix lints --- aoc2015/src/day05.rs | 10 +++++----- aoc2018/src/day04.rs | 6 +++--- aoc2019/src/day03.rs | 2 +- aoc2019/src/day06.rs | 2 +- aoc2020/src/day04.rs | 6 +++--- aoc2020/src/day11.rs | 4 ++-- aoc2020/src/day24.rs | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/aoc2015/src/day05.rs b/aoc2015/src/day05.rs index 942a5e5..5efdf56 100644 --- a/aoc2015/src/day05.rs +++ b/aoc2015/src/day05.rs @@ -41,10 +41,10 @@ fn part1(input: &str) -> usize { false }) - .filter(|line| line.find("ab").is_none()) - .filter(|line| line.find("cd").is_none()) - .filter(|line| line.find("pq").is_none()) - .filter(|line| line.find("xy").is_none()) + .filter(|line| !line.contains("ab")) + .filter(|line| !line.contains("cd")) + .filter(|line| !line.contains("pq")) + .filter(|line| !line.contains("xy")) .count() } @@ -56,7 +56,7 @@ fn part2(input: &str) -> usize { for i in 0..(line.chars().count() - 3) { let seq = &line[i..(i + 2)]; let line = &line[(i + 2)..]; - if line.find(seq).is_some() { + if line.contains(seq) { return true; } } diff --git a/aoc2018/src/day04.rs b/aoc2018/src/day04.rs index 879bf67..cab4b8a 100644 --- a/aoc2018/src/day04.rs +++ b/aoc2018/src/day04.rs @@ -31,11 +31,11 @@ impl FromStr for Event { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - if s.find("wakes up").is_some() { + if s.contains("wakes up") { Ok(Event::WakeUp) - } else if s.find("falls asleep").is_some() { + } else if s.contains("falls asleep") { Ok(Event::FallAsleep) - } else if s.find("begins shift").is_some() { + } else if s.contains("begins shift") { let pound = s.find('#').context("`#` not found")?; let s = &s[(pound + 1)..]; let space = s.find(' ').context("` ` not found after `#`")?; diff --git a/aoc2019/src/day03.rs b/aoc2019/src/day03.rs index d77b719..40a1f9a 100644 --- a/aoc2019/src/day03.rs +++ b/aoc2019/src/day03.rs @@ -48,7 +48,7 @@ fn part2(first_wire: &Wire, second_wire: &Wire) -> Result { let mut second_length = 0; for seg2 in &second_wire.0 { - if let Some(inter) = seg1.intersection(&seg2) { + if let Some(inter) = seg1.intersection(seg2) { if inter.x == 0 && inter.y == 0 { continue; } diff --git a/aoc2019/src/day06.rs b/aoc2019/src/day06.rs index 3c7a134..5d2767e 100644 --- a/aoc2019/src/day06.rs +++ b/aoc2019/src/day06.rs @@ -49,7 +49,7 @@ fn part1(input: &str) -> Result { let mut cache = HashMap::new(); Ok(orbits .keys() - .map(|k| count_orbits(&k, &orbits, &mut cache)) + .map(|k| count_orbits(k, &orbits, &mut cache)) .sum()) } diff --git a/aoc2020/src/day04.rs b/aoc2020/src/day04.rs index f79a908..74d021e 100644 --- a/aoc2020/src/day04.rs +++ b/aoc2020/src/day04.rs @@ -154,16 +154,16 @@ impl CompletePassport { fn hgt_valid(&self) -> bool { if let Some(num) = self.hgt.strip_suffix("in") { - is_number_in_range(&num, 59..=76) + is_number_in_range(num, 59..=76) } else if let Some(num) = self.hgt.strip_suffix("cm") { - is_number_in_range(&num, 150..=193) + is_number_in_range(num, 150..=193) } else { false } } fn hcl_valid(&self) -> bool { - if let Some(rest) = self.hcl.strip_prefix("#") { + if let Some(rest) = self.hcl.strip_prefix('#') { rest.chars().filter(|c| !c.is_ascii_hexdigit()).count() == 0 } else { false diff --git a/aoc2020/src/day11.rs b/aoc2020/src/day11.rs index b438df0..8a05a0a 100644 --- a/aoc2020/src/day11.rs +++ b/aoc2020/src/day11.rs @@ -64,13 +64,13 @@ impl Layout { match cell { Cell::EmptySeat => { - if adj_count(&self, i, j, Cell::OccupiedSeat) == 0 { + if adj_count(self, i, j, Cell::OccupiedSeat) == 0 { new[i][j] = Cell::OccupiedSeat; changed = true; } } Cell::OccupiedSeat => { - if adj_count(&self, i, j, Cell::OccupiedSeat) >= occupied_threshold { + if adj_count(self, i, j, Cell::OccupiedSeat) >= occupied_threshold { new[i][j] = Cell::EmptySeat; changed = true; } diff --git a/aoc2020/src/day24.rs b/aoc2020/src/day24.rs index 703c790..9992e86 100644 --- a/aoc2020/src/day24.rs +++ b/aoc2020/src/day24.rs @@ -99,7 +99,7 @@ fn part2(input: &str) -> Result { let count = neighbours .iter() - .filter(|tile| black_tiles.contains(&tile)) + .filter(|tile| black_tiles.contains(tile)) .count(); if black_tiles.contains(&tile) { // Any black tile with zero or more than 2 black tiles immediately adjacent to it is From ebc57d58b6bfa342b9bffb465eebc064c4c227ed Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:34:29 +0100 Subject: [PATCH 006/134] cargo: bump to 2021 edition --- aoc/Cargo.toml | 2 +- aoc2015/Cargo.toml | 2 +- aoc2015/aoc2015_bench/Cargo.toml | 2 +- aoc2018/Cargo.toml | 2 +- aoc2018/aoc2018_bench/Cargo.toml | 2 +- aoc2019/Cargo.toml | 2 +- aoc2019/aoc2019_bench/Cargo.toml | 2 +- aoc2020/Cargo.toml | 2 +- aoc2020/aoc2020_bench/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/aoc/Cargo.toml b/aoc/Cargo.toml index 5387799..db2d7ff 100644 --- a/aoc/Cargo.toml +++ b/aoc/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2015/Cargo.toml b/aoc2015/Cargo.toml index 8b19df4..2d72c07 100644 --- a/aoc2015/Cargo.toml +++ b/aoc2015/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2015" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2015/aoc2015_bench/Cargo.toml b/aoc2015/aoc2015_bench/Cargo.toml index d250c34..a3e62af 100644 --- a/aoc2015/aoc2015_bench/Cargo.toml +++ b/aoc2015/aoc2015_bench/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2015_bench" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2018/Cargo.toml b/aoc2018/Cargo.toml index da6ce2b..f663faa 100644 --- a/aoc2018/Cargo.toml +++ b/aoc2018/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2018" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2018/aoc2018_bench/Cargo.toml b/aoc2018/aoc2018_bench/Cargo.toml index ba77e7a..3eb3e87 100644 --- a/aoc2018/aoc2018_bench/Cargo.toml +++ b/aoc2018/aoc2018_bench/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2018_bench" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2019/Cargo.toml b/aoc2019/Cargo.toml index 088790c..5db168f 100644 --- a/aoc2019/Cargo.toml +++ b/aoc2019/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2019" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2019/aoc2019_bench/Cargo.toml b/aoc2019/aoc2019_bench/Cargo.toml index 226729b..f58cac2 100644 --- a/aoc2019/aoc2019_bench/Cargo.toml +++ b/aoc2019/aoc2019_bench/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2019_bench" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2020/Cargo.toml b/aoc2020/Cargo.toml index d1c3b99..c42c975 100644 --- a/aoc2020/Cargo.toml +++ b/aoc2020/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2020" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/aoc2020/aoc2020_bench/Cargo.toml b/aoc2020/aoc2020_bench/Cargo.toml index 93aba78..47f375f 100644 --- a/aoc2020/aoc2020_bench/Cargo.toml +++ b/aoc2020/aoc2020_bench/Cargo.toml @@ -2,7 +2,7 @@ name = "aoc2020_bench" version = "0.1.0" authors = ["Antoine Martin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From d5c85d4a175448ae8c1815ec357d8d4dfccec3cf Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:49:52 +0100 Subject: [PATCH 007/134] 2021: setup boilerplate --- Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 2 +- aoc2021/Cargo.toml | 18 ++++++++++++++++++ aoc2021/aoc2021_bench/Cargo.toml | 17 +++++++++++++++++ aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 14 ++++++++++++++ aoc2021/input/day00.txt | 1 + aoc2021/src/day00.rs | 17 +++++++++++++++++ aoc2021/src/lib.rs | 3 +++ aoc2021/src/main.rs | 11 +++++++++++ 9 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 aoc2021/Cargo.toml create mode 100644 aoc2021/aoc2021_bench/Cargo.toml create mode 100644 aoc2021/aoc2021_bench/benches/aoc2021_bench.rs create mode 100644 aoc2021/input/day00.txt create mode 100644 aoc2021/src/day00.rs create mode 100644 aoc2021/src/lib.rs create mode 100644 aoc2021/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 1f1b772..acee5e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,22 @@ dependencies = [ "criterion", ] +[[package]] +name = "aoc2021" +version = "0.1.0" +dependencies = [ + "anyhow", + "aoc", +] + +[[package]] +name = "aoc2021_bench" +version = "0.1.0" +dependencies = [ + "aoc2021", + "criterion", +] + [[package]] name = "arrayvec" version = "0.5.2" diff --git a/Cargo.toml b/Cargo.toml index 7ab5e2e..1fddce8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = ["aoc*", "aoc*/aoc*_bench"] -default-members = ["aoc2020"] +default-members = ["aoc2021"] [profile.release] debug = true diff --git a/aoc2021/Cargo.toml b/aoc2021/Cargo.toml new file mode 100644 index 0000000..b336e63 --- /dev/null +++ b/aoc2021/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "aoc2021" +version = "0.1.0" +authors = ["Antoine Martin "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../aoc" } +anyhow = "1.0" + +[lib] +path = "src/lib.rs" + +[[bin]] +name = "aoc2021" +path = "src/main.rs" diff --git a/aoc2021/aoc2021_bench/Cargo.toml b/aoc2021/aoc2021_bench/Cargo.toml new file mode 100644 index 0000000..d8f7503 --- /dev/null +++ b/aoc2021/aoc2021_bench/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "aoc2021_bench" +version = "0.1.0" +authors = ["Antoine Martin "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc2021 = { path = "../" } + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "aoc2021_bench" +harness = false diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs new file mode 100644 index 0000000..bfd8973 --- /dev/null +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -0,0 +1,14 @@ +use criterion::{criterion_group, criterion_main, Criterion}; + +use aoc2021::day00; + +fn aoc2021_all(c: &mut Criterion) { + c.bench_function("day00", |b| b.iter(|| day00::run().unwrap())); +} + +criterion_group! { + name = all_days; + config = Criterion::default().sample_size(200); + targets = aoc2021_all +} +criterion_main!(all_days); diff --git a/aoc2021/input/day00.txt b/aoc2021/input/day00.txt new file mode 100644 index 0000000..cd08755 --- /dev/null +++ b/aoc2021/input/day00.txt @@ -0,0 +1 @@ +Hello world! diff --git a/aoc2021/src/day00.rs b/aoc2021/src/day00.rs new file mode 100644 index 0000000..3e48bd2 --- /dev/null +++ b/aoc2021/src/day00.rs @@ -0,0 +1,17 @@ +use std::fmt::Write; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day00.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result<&str> { + Ok(input) +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs new file mode 100644 index 0000000..7b7f8e8 --- /dev/null +++ b/aoc2021/src/lib.rs @@ -0,0 +1,3 @@ +#![warn(clippy::explicit_iter_loop, clippy::redundant_closure_for_method_calls)] + +pub mod day00; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs new file mode 100644 index 0000000..6bfb61e --- /dev/null +++ b/aoc2021/src/main.rs @@ -0,0 +1,11 @@ +use anyhow::Result; + +use aoc::DayFunc; + +use aoc2021::day00; + +fn main() -> Result<()> { + let days: &[DayFunc] = &[day00::run]; + + aoc::run(days) +} From 0272809c82f4d8fae3165216640f6c4fc371657d Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 25 Nov 2021 16:53:58 +0100 Subject: [PATCH 008/134] ci: fix flags --- .github/workflows/rust.yaml | 4 ++-- Makefile | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index ddeac58..a8b4a92 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -17,8 +17,8 @@ jobs: steps: - uses: actions/checkout@v2 - name: Format - run: cargo fmt -- --check + run: cargo fmt --all -- --check - name: Lint - run: cargo clippy --all --all-targets --all-features -- -D warnings + run: cargo clippy --workspace --all-targets --all-features -- -D warnings - name: Run tests run: make check-all diff --git a/Makefile b/Makefile index 1b23420..007a759 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,9 @@ watch: cargo watch -x clippy check: - cargo test --all --release + cargo test --workspace --release -# run these in release mode because the reason they're ignored is usually that -# they take a long time to run -check-all: check - cargo test --all --release -- --ignored +check-all: + cargo test --workspace --release -- --include-ignored .PHONY: watch check check-all From 3e991d5ac1ff685b806a631b8d0b3cd19c3397cb Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 1 Dec 2021 07:30:10 +0100 Subject: [PATCH 009/134] 2021: day01 part 1 & part 2 --- aoc2021/input/day01.txt | 2000 +++++++++++++++++++++++++++++++++++++++ aoc2021/src/day01.rs | 45 + aoc2021/src/lib.rs | 2 +- aoc2021/src/main.rs | 4 +- 4 files changed, 2048 insertions(+), 3 deletions(-) create mode 100644 aoc2021/input/day01.txt create mode 100644 aoc2021/src/day01.rs diff --git a/aoc2021/input/day01.txt b/aoc2021/input/day01.txt new file mode 100644 index 0000000..c7d277b --- /dev/null +++ b/aoc2021/input/day01.txt @@ -0,0 +1,2000 @@ +150 +152 +155 +156 +157 +141 +124 +138 +143 +145 +144 +146 +148 +149 +148 +149 +124 +122 +123 +124 +117 +118 +119 +132 +159 +152 +175 +183 +194 +222 +226 +237 +242 +248 +229 +225 +227 +235 +229 +230 +227 +229 +252 +253 +251 +269 +270 +266 +268 +269 +270 +256 +257 +258 +261 +258 +251 +242 +245 +270 +275 +287 +309 +310 +330 +337 +344 +347 +353 +350 +355 +356 +353 +354 +372 +371 +370 +365 +368 +370 +374 +370 +332 +329 +340 +343 +347 +348 +349 +350 +351 +366 +358 +370 +369 +370 +367 +368 +369 +371 +382 +380 +385 +379 +394 +395 +393 +406 +389 +400 +389 +396 +386 +387 +390 +399 +406 +408 +413 +415 +416 +417 +416 +417 +416 +424 +425 +426 +427 +434 +435 +434 +436 +433 +430 +431 +434 +435 +436 +437 +452 +456 +459 +462 +463 +475 +477 +479 +500 +497 +498 +501 +507 +522 +517 +509 +519 +541 +542 +540 +551 +558 +551 +552 +553 +564 +569 +575 +581 +587 +589 +591 +596 +610 +617 +621 +618 +614 +615 +620 +640 +654 +669 +670 +686 +685 +686 +690 +691 +700 +706 +722 +721 +720 +725 +726 +736 +738 +754 +761 +759 +757 +765 +773 +790 +797 +798 +797 +798 +796 +789 +794 +798 +797 +804 +806 +807 +831 +823 +833 +836 +857 +852 +856 +863 +896 +898 +893 +904 +908 +931 +933 +948 +966 +967 +957 +961 +969 +971 +985 +988 +989 +996 +1018 +1020 +1025 +1060 +1061 +1060 +1088 +1090 +1096 +1091 +1092 +1091 +1064 +1070 +1087 +1088 +1083 +1085 +1090 +1091 +1094 +1093 +1091 +1093 +1103 +1104 +1105 +1107 +1126 +1127 +1126 +1145 +1151 +1165 +1166 +1171 +1179 +1189 +1190 +1193 +1217 +1218 +1219 +1220 +1222 +1225 +1210 +1221 +1225 +1247 +1249 +1246 +1247 +1228 +1227 +1214 +1224 +1254 +1256 +1276 +1279 +1273 +1268 +1271 +1272 +1269 +1279 +1286 +1290 +1263 +1267 +1270 +1272 +1286 +1276 +1277 +1278 +1280 +1266 +1267 +1266 +1231 +1235 +1260 +1261 +1271 +1280 +1284 +1291 +1299 +1297 +1310 +1322 +1331 +1342 +1336 +1345 +1358 +1361 +1358 +1343 +1334 +1333 +1330 +1346 +1349 +1348 +1353 +1371 +1380 +1388 +1362 +1373 +1378 +1393 +1417 +1407 +1412 +1417 +1419 +1420 +1421 +1436 +1432 +1437 +1442 +1444 +1447 +1448 +1467 +1468 +1472 +1477 +1479 +1513 +1541 +1549 +1566 +1562 +1567 +1571 +1581 +1583 +1578 +1583 +1601 +1588 +1611 +1612 +1614 +1615 +1624 +1618 +1612 +1632 +1633 +1635 +1634 +1646 +1661 +1663 +1656 +1657 +1658 +1657 +1658 +1677 +1679 +1692 +1693 +1692 +1718 +1719 +1720 +1721 +1727 +1732 +1731 +1730 +1722 +1723 +1737 +1743 +1744 +1747 +1753 +1766 +1768 +1765 +1767 +1773 +1768 +1773 +1778 +1776 +1788 +1790 +1799 +1807 +1808 +1805 +1806 +1803 +1804 +1818 +1831 +1832 +1828 +1837 +1840 +1841 +1837 +1840 +1844 +1853 +1854 +1855 +1853 +1856 +1857 +1856 +1862 +1873 +1860 +1862 +1863 +1872 +1888 +1892 +1893 +1906 +1919 +1901 +1910 +1916 +1919 +1921 +1922 +1945 +1942 +1943 +1944 +1947 +1956 +1958 +1964 +1967 +1981 +1988 +1976 +1978 +1999 +2003 +2008 +2039 +2042 +2049 +2075 +2072 +2076 +2082 +2091 +2096 +2120 +2131 +2120 +2116 +2119 +2117 +2139 +2141 +2143 +2144 +2147 +2129 +2140 +2151 +2166 +2167 +2186 +2198 +2199 +2205 +2206 +2207 +2209 +2207 +2228 +2231 +2223 +2231 +2242 +2244 +2232 +2234 +2237 +2242 +2235 +2225 +2227 +2233 +2228 +2229 +2230 +2229 +2221 +2222 +2214 +2216 +2219 +2223 +2229 +2230 +2233 +2241 +2263 +2264 +2259 +2255 +2260 +2277 +2308 +2311 +2312 +2315 +2320 +2322 +2321 +2295 +2297 +2293 +2295 +2296 +2300 +2304 +2298 +2305 +2306 +2305 +2302 +2305 +2306 +2298 +2316 +2335 +2326 +2325 +2291 +2298 +2300 +2305 +2312 +2314 +2316 +2320 +2323 +2321 +2318 +2315 +2318 +2319 +2343 +2341 +2340 +2342 +2341 +2345 +2346 +2347 +2349 +2353 +2327 +2318 +2339 +2342 +2355 +2356 +2357 +2358 +2359 +2386 +2387 +2389 +2403 +2408 +2396 +2394 +2419 +2414 +2419 +2420 +2426 +2425 +2415 +2419 +2420 +2424 +2425 +2436 +2438 +2440 +2435 +2441 +2448 +2456 +2446 +2448 +2447 +2440 +2452 +2451 +2449 +2460 +2452 +2453 +2456 +2473 +2480 +2478 +2486 +2488 +2467 +2469 +2493 +2494 +2493 +2495 +2509 +2511 +2515 +2541 +2554 +2555 +2541 +2535 +2536 +2539 +2535 +2538 +2539 +2548 +2555 +2558 +2557 +2560 +2570 +2571 +2585 +2588 +2599 +2612 +2615 +2623 +2640 +2647 +2648 +2645 +2639 +2637 +2641 +2643 +2678 +2680 +2712 +2721 +2727 +2758 +2753 +2750 +2751 +2758 +2759 +2778 +2789 +2800 +2794 +2799 +2803 +2804 +2810 +2793 +2794 +2792 +2801 +2803 +2804 +2805 +2831 +2851 +2855 +2837 +2848 +2864 +2832 +2822 +2828 +2831 +2823 +2822 +2835 +2821 +2841 +2842 +2845 +2830 +2831 +2837 +2838 +2843 +2845 +2844 +2871 +2874 +2873 +2872 +2873 +2869 +2890 +2893 +2912 +2914 +2908 +2949 +2948 +2961 +2965 +2970 +2971 +2974 +2966 +2968 +2974 +2980 +2948 +2980 +2985 +2999 +3005 +3018 +3022 +3021 +3024 +3025 +3027 +3026 +3025 +3029 +3031 +3024 +2998 +3008 +3016 +3020 +3019 +3016 +3018 +3035 +3062 +3063 +3030 +3021 +3022 +3023 +3017 +3032 +3042 +3043 +3044 +3043 +3041 +3047 +3049 +3055 +3060 +3061 +3033 +3034 +3027 +3032 +3055 +3054 +3059 +3058 +3052 +3074 +3087 +3104 +3106 +3108 +3104 +3113 +3104 +3106 +3102 +3103 +3110 +3116 +3124 +3123 +3116 +3146 +3132 +3140 +3143 +3141 +3145 +3149 +3158 +3154 +3156 +3164 +3173 +3172 +3173 +3179 +3178 +3187 +3188 +3196 +3195 +3198 +3199 +3205 +3206 +3216 +3222 +3223 +3222 +3223 +3211 +3219 +3220 +3221 +3226 +3224 +3225 +3252 +3246 +3257 +3258 +3256 +3274 +3260 +3273 +3277 +3279 +3296 +3297 +3302 +3304 +3306 +3330 +3355 +3360 +3368 +3365 +3371 +3373 +3376 +3389 +3400 +3402 +3426 +3414 +3420 +3433 +3434 +3431 +3440 +3442 +3437 +3427 +3428 +3415 +3427 +3415 +3399 +3400 +3392 +3421 +3428 +3435 +3455 +3456 +3457 +3459 +3470 +3477 +3496 +3497 +3492 +3499 +3500 +3502 +3524 +3510 +3512 +3515 +3525 +3532 +3533 +3534 +3559 +3561 +3551 +3573 +3578 +3579 +3582 +3583 +3578 +3584 +3583 +3594 +3596 +3601 +3602 +3609 +3595 +3601 +3600 +3606 +3607 +3608 +3609 +3611 +3635 +3654 +3673 +3676 +3663 +3669 +3696 +3685 +3687 +3692 +3707 +3711 +3710 +3720 +3723 +3727 +3739 +3761 +3774 +3785 +3811 +3818 +3816 +3821 +3823 +3824 +3825 +3827 +3839 +3841 +3853 +3864 +3861 +3860 +3873 +3868 +3867 +3866 +3867 +3864 +3868 +3869 +3854 +3842 +3845 +3852 +3870 +3871 +3870 +3832 +3838 +3832 +3828 +3827 +3840 +3841 +3840 +3864 +3860 +3861 +3860 +3867 +3835 +3850 +3851 +3864 +3866 +3867 +3876 +3879 +3881 +3884 +3898 +3910 +3916 +3919 +3906 +3875 +3876 +3878 +3880 +3892 +3897 +3901 +3905 +3901 +3909 +3915 +3921 +3920 +3942 +3936 +3945 +3951 +3961 +3950 +3961 +3962 +3966 +3967 +3968 +3979 +3981 +3982 +3976 +3977 +3980 +3983 +3984 +4001 +4020 +4015 +4023 +4025 +4026 +4012 +4017 +4029 +4050 +4037 +4041 +4055 +4062 +4053 +4056 +4055 +4053 +4066 +4064 +4089 +4093 +4110 +4111 +4110 +4112 +4114 +4115 +4126 +4135 +4150 +4151 +4184 +4190 +4195 +4204 +4211 +4220 +4219 +4229 +4225 +4232 +4248 +4269 +4268 +4261 +4257 +4256 +4257 +4269 +4277 +4274 +4277 +4290 +4279 +4314 +4315 +4350 +4374 +4388 +4389 +4386 +4378 +4379 +4409 +4437 +4439 +4441 +4437 +4442 +4448 +4435 +4436 +4413 +4400 +4408 +4409 +4393 +4392 +4395 +4398 +4399 +4400 +4404 +4415 +4416 +4425 +4411 +4412 +4406 +4430 +4431 +4430 +4431 +4429 +4430 +4426 +4435 +4439 +4449 +4460 +4453 +4454 +4488 +4496 +4474 +4480 +4481 +4467 +4469 +4472 +4477 +4474 +4477 +4484 +4489 +4490 +4521 +4522 +4536 +4543 +4544 +4545 +4549 +4556 +4561 +4562 +4588 +4584 +4576 +4577 +4576 +4595 +4608 +4607 +4610 +4611 +4581 +4584 +4591 +4609 +4630 +4631 +4635 +4636 +4635 +4636 +4670 +4683 +4685 +4686 +4687 +4682 +4683 +4680 +4682 +4678 +4682 +4683 +4686 +4697 +4702 +4703 +4702 +4703 +4733 +4772 +4766 +4764 +4771 +4773 +4761 +4760 +4761 +4763 +4776 +4783 +4790 +4789 +4793 +4798 +4797 +4805 +4813 +4804 +4803 +4804 +4808 +4798 +4799 +4811 +4808 +4807 +4810 +4832 +4869 +4870 +4877 +4880 +4879 +4883 +4878 +4875 +4880 +4882 +4884 +4883 +4884 +4921 +4925 +4926 +4921 +4919 +4920 +4922 +4924 +4923 +4914 +4911 +4917 +4925 +4923 +4925 +4937 +4944 +4945 +4949 +4957 +4953 +4923 +4925 +4926 +4925 +4933 +4934 +4940 +4941 +4956 +4944 +4956 +4977 +4987 +4988 +4989 +4992 +4997 +4998 +5016 +5017 +5024 +5033 +5039 +5037 +5042 +5045 +5048 +5066 +5107 +5131 +5145 +5150 +5154 +5153 +5148 +5149 +5150 +5154 +5159 +5161 +5152 +5168 +5170 +5174 +5167 +5191 +5192 +5206 +5208 +5211 +5212 +5249 +5254 +5255 +5252 +5257 +5291 +5302 +5315 +5326 +5327 +5332 +5333 +5328 +5331 +5322 +5327 +5328 +5332 +5338 +5339 +5340 +5351 +5354 +5339 +5340 +5349 +5347 +5355 +5346 +5354 +5352 +5353 +5354 +5353 +5328 +5345 +5346 +5345 +5334 +5338 +5359 +5361 +5369 +5374 +5377 +5378 +5384 +5385 +5389 +5403 +5407 +5399 +5423 +5430 +5429 +5448 +5458 +5485 +5502 +5504 +5506 +5507 +5509 +5515 +5519 +5523 +5526 +5527 +5522 +5520 +5521 +5525 +5528 +5499 +5500 +5504 +5492 +5498 +5499 +5503 +5504 +5503 +5510 +5500 +5524 +5527 +5530 +5532 +5538 +5541 +5520 +5528 +5539 +5540 +5541 +5538 +5545 +5546 +5548 +5553 +5557 +5554 +5562 +5573 +5572 +5573 +5597 +5581 +5577 +5579 +5586 +5578 +5579 +5600 +5601 +5620 +5642 +5634 +5629 +5656 +5640 +5643 +5642 +5629 +5637 +5638 +5639 +5641 +5643 +5649 +5615 +5632 +5623 +5620 +5629 +5630 +5631 +5624 +5639 +5642 +5662 +5671 +5693 +5692 +5694 +5705 +5719 +5727 +5728 +5732 +5717 +5721 +5732 +5733 +5748 +5750 +5755 +5756 +5763 +5780 +5785 +5787 +5781 +5782 +5796 +5797 +5803 +5824 +5830 +5833 +5836 +5835 +5838 +5837 +5854 +5853 +5844 +5843 +5846 +5847 +5856 +5878 +5887 +5890 +5898 +5896 +5898 +5897 +5898 +5899 +5920 +5915 +5925 +5924 +5942 +5939 +5935 +5939 +5941 +5942 +5943 +5951 +5942 +5939 +5940 +5944 +5954 +5955 +5958 +5959 +5960 +5959 +5962 +5986 +6008 +6018 +6011 +6009 +6008 +6012 +6013 +6010 +6015 +6012 +6015 +6024 +6028 +6023 +6027 +6018 +6043 +6059 +6066 +6072 +6074 +6087 +6095 +6096 +6098 +6099 +6096 +6073 +6074 +6072 +6075 +6087 +6088 +6084 +6089 +6097 +6095 +6085 +6083 +6084 +6082 +6093 +6085 +6081 +6082 +6106 +6108 +6124 +6127 +6122 +6103 +6108 +6110 +6109 +6121 +6122 +6132 +6153 +6155 +6160 +6162 +6185 +6193 +6198 +6196 +6187 +6188 +6206 +6207 +6222 +6243 +6244 +6237 +6255 +6251 +6253 +6255 +6257 +6259 +6269 +6273 +6277 +6298 +6301 +6305 +6310 +6312 +6315 +6332 +6333 +6334 +6333 +6335 +6327 +6332 +6330 +6347 +6348 +6344 +6343 +6349 +6355 +6359 +6365 +6370 +6352 +6349 +6375 +6381 +6366 +6398 +6414 +6416 +6417 +6419 +6420 +6419 +6418 +6405 +6414 +6417 +6418 +6419 +6406 +6410 +6409 +6414 +6416 +6403 +6402 +6404 +6406 +6425 +6426 +6427 +6431 +6447 +6432 +6433 +6435 +6440 +6469 +6484 +6489 +6508 +6512 +6514 +6517 +6523 +6505 +6503 +6504 +6512 +6513 +6515 +6516 +6521 +6522 +6525 +6533 +6532 +6535 +6536 +6535 +6539 +6543 +6572 +6576 +6579 +6590 +6600 +6601 +6614 +6616 +6625 +6635 +6636 +6647 +6652 +6659 +6660 +6675 +6691 +6703 +6706 +6719 +6743 +6729 +6756 +6755 +6739 +6740 +6748 +6737 +6738 +6740 +6741 +6746 +6748 +6745 +6744 +6715 +6729 +6743 +6742 +6741 +6744 +6770 +6783 +6793 +6792 +6805 +6788 +6800 +6806 +6793 +6795 +6800 +6801 +6816 +6826 +6822 +6829 +6835 +6847 +6845 +6847 +6845 +6846 +6853 +6860 +6861 +6874 +6866 +6869 +6863 +6866 +6867 +6870 +6849 +6848 +6849 +6853 +6847 +6857 +6898 +6899 +6897 +6888 +6899 +6901 +6896 +6899 +6909 +6912 +6913 +6914 +6915 +6916 +6930 +6931 +6932 +6929 +6930 +6941 +6934 +6954 +6975 +6982 +6988 +7010 +7017 +7021 +7050 +7052 +7029 +7030 +7035 +7036 +7046 +7070 +7071 +7078 +7079 +7078 +7094 +7101 +7113 +7119 +7120 +7121 +7122 +7135 +7139 +7116 +7119 +7129 +7132 +7136 +7133 +7151 +7148 +7136 +7143 +7170 +7183 +7184 +7205 +7207 +7216 +7207 +7232 +7228 +7230 +7256 +7276 +7295 +7320 +7303 +7311 +7313 +7314 +7315 +7325 +7306 +7301 +7291 +7293 +7310 +7318 +7335 +7354 +7374 +7379 +7393 +7396 +7413 +7403 +7387 +7399 +7400 +7399 +7400 +7402 +7412 +7413 +7409 +7410 +7409 +7414 +7415 +7416 +7417 +7421 +7388 +7389 +7388 +7371 +7377 +7378 +7379 +7384 +7396 +7390 +7399 +7401 +7422 +7423 +7421 +7422 +7425 +7444 +7453 +7454 +7455 +7457 +7461 +7456 +7442 +7407 +7408 +7418 +7419 +7427 +7447 +7448 +7449 +7450 +7452 +7462 +7440 +7471 +7492 +7512 +7529 +7530 +7543 +7542 +7543 +7558 +7560 +7566 +7584 +7588 +7589 +7586 +7587 +7586 +7596 +7612 +7616 +7615 +7616 +7605 +7607 +7627 +7648 +7667 +7670 +7679 +7680 +7685 +7695 +7705 +7725 +7751 +7757 +7739 diff --git a/aoc2021/src/day01.rs b/aoc2021/src/day01.rs new file mode 100644 index 0000000..ba6765e --- /dev/null +++ b/aoc2021/src/day01.rs @@ -0,0 +1,45 @@ +use std::fmt::Write; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day01.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let measurements = input + .lines() + .map(|line| line.parse::().map_err(anyhow::Error::new)) + .collect::>>()?; + + Ok(measurements.windows(2).filter(|w| w[0] < w[1]).count()) +} + +fn part2(input: &str) -> Result { + let measurements = input + .lines() + .map(|line| line.parse::().map_err(anyhow::Error::new)) + .collect::>>()?; + + let mut increases = 0; + let mut prev: Option = None; + + for window in measurements.windows(3) { + let sum = window.iter().sum(); + if let Some(prev) = prev { + if prev < sum { + increases += 1; + } + } + prev = Some(sum); + } + + Ok(increases) +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 7b7f8e8..784a117 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -1,3 +1,3 @@ #![warn(clippy::explicit_iter_loop, clippy::redundant_closure_for_method_calls)] -pub mod day00; +pub mod day01; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 6bfb61e..f788a63 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -2,10 +2,10 @@ use anyhow::Result; use aoc::DayFunc; -use aoc2021::day00; +use aoc2021::day01; fn main() -> Result<()> { - let days: &[DayFunc] = &[day00::run]; + let days: &[DayFunc] = &[day01::run]; aoc::run(days) } From 0667ca29ad7c2b6601f08cae4c4ef80156c2200f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 1 Dec 2021 07:34:50 +0100 Subject: [PATCH 010/134] 2021: day01 tests --- aoc2021/input/day01_provided.txt | 10 ++++++++++ aoc2021/src/day01.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 aoc2021/input/day01_provided.txt diff --git a/aoc2021/input/day01_provided.txt b/aoc2021/input/day01_provided.txt new file mode 100644 index 0000000..167e291 --- /dev/null +++ b/aoc2021/input/day01_provided.txt @@ -0,0 +1,10 @@ +199 +200 +208 +210 +200 +207 +240 +269 +260 +263 diff --git a/aoc2021/src/day01.rs b/aoc2021/src/day01.rs index ba6765e..26f40b3 100644 --- a/aoc2021/src/day01.rs +++ b/aoc2021/src/day01.rs @@ -43,3 +43,30 @@ fn part2(input: &str) -> Result { Ok(increases) } + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day01_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 7); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 1502); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 5); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 1538); + } +} From 696c173f930b7ce8549d39042999885a03712f75 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 1 Dec 2021 07:35:34 +0100 Subject: [PATCH 011/134] 2021: rm day00 --- aoc2021/input/day00.txt | 1 - aoc2021/src/day00.rs | 17 ----------------- 2 files changed, 18 deletions(-) delete mode 100644 aoc2021/input/day00.txt delete mode 100644 aoc2021/src/day00.rs diff --git a/aoc2021/input/day00.txt b/aoc2021/input/day00.txt deleted file mode 100644 index cd08755..0000000 --- a/aoc2021/input/day00.txt +++ /dev/null @@ -1 +0,0 @@ -Hello world! diff --git a/aoc2021/src/day00.rs b/aoc2021/src/day00.rs deleted file mode 100644 index 3e48bd2..0000000 --- a/aoc2021/src/day00.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::fmt::Write; - -use anyhow::Result; - -const INPUT: &str = include_str!("../input/day00.txt"); - -pub fn run() -> Result { - let mut res = String::with_capacity(128); - - writeln!(res, "part 1: {}", part1(INPUT)?)?; - - Ok(res) -} - -fn part1(input: &str) -> Result<&str> { - Ok(input) -} From 613b2402114c149468ad20204e7b62c1ac716d31 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 1 Dec 2021 07:39:21 +0100 Subject: [PATCH 012/134] 2021: day01 bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index bfd8973..05cb02e 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -1,9 +1,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use aoc2021::day00; +use aoc2021::day01; fn aoc2021_all(c: &mut Criterion) { - c.bench_function("day00", |b| b.iter(|| day00::run().unwrap())); + c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); } criterion_group! { From 3aa37aff1044ad3c024c6215b8d793c08020ba47 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 1 Dec 2021 10:57:51 +0100 Subject: [PATCH 013/134] 2021: day01: refacto --- aoc2021/src/day01.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/aoc2021/src/day01.rs b/aoc2021/src/day01.rs index 26f40b3..13d369a 100644 --- a/aoc2021/src/day01.rs +++ b/aoc2021/src/day01.rs @@ -19,7 +19,19 @@ fn part1(input: &str) -> Result { .map(|line| line.parse::().map_err(anyhow::Error::new)) .collect::>>()?; - Ok(measurements.windows(2).filter(|w| w[0] < w[1]).count()) + Ok(count_increases(measurements.iter())) +} + +fn count_increases(numbers: I) -> usize +where + C: std::cmp::PartialOrd, + I: Iterator + Clone, +{ + numbers + .clone() + .zip(numbers.skip(1)) + .filter(|(a, b)| a < b) + .count() } fn part2(input: &str) -> Result { @@ -28,20 +40,9 @@ fn part2(input: &str) -> Result { .map(|line| line.parse::().map_err(anyhow::Error::new)) .collect::>>()?; - let mut increases = 0; - let mut prev: Option = None; - - for window in measurements.windows(3) { - let sum = window.iter().sum(); - if let Some(prev) = prev { - if prev < sum { - increases += 1; - } - } - prev = Some(sum); - } - - Ok(increases) + Ok(count_increases( + measurements.windows(3).map(|w| w.iter().sum::()), + )) } #[cfg(test)] From 0eed53749c8c5fa620f2e7fb5de3ce91597549b2 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 2 Dec 2021 10:25:59 +0100 Subject: [PATCH 014/134] 2021: day02: quick solve --- aoc2021/input/day02.txt | 1000 +++++++++++++++++++++++++++++++++++++++ aoc2021/src/day02.rs | 86 ++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 3 +- 4 files changed, 1089 insertions(+), 1 deletion(-) create mode 100644 aoc2021/input/day02.txt create mode 100644 aoc2021/src/day02.rs diff --git a/aoc2021/input/day02.txt b/aoc2021/input/day02.txt new file mode 100644 index 0000000..353ba9a --- /dev/null +++ b/aoc2021/input/day02.txt @@ -0,0 +1,1000 @@ +forward 4 +down 8 +down 1 +forward 6 +forward 7 +down 7 +forward 3 +forward 5 +up 9 +down 1 +forward 5 +down 8 +forward 4 +forward 5 +down 5 +down 1 +forward 1 +down 3 +forward 5 +forward 5 +down 1 +up 2 +down 2 +down 5 +down 5 +forward 3 +forward 7 +forward 5 +forward 9 +forward 8 +down 4 +down 6 +up 5 +down 1 +forward 6 +up 3 +forward 7 +forward 4 +down 7 +up 5 +up 5 +up 1 +up 5 +forward 5 +forward 2 +forward 7 +down 7 +forward 9 +down 9 +up 8 +up 8 +up 2 +forward 5 +forward 8 +up 5 +forward 1 +down 1 +down 6 +forward 1 +forward 2 +forward 4 +forward 6 +up 4 +up 5 +down 4 +down 9 +down 4 +forward 4 +up 8 +up 2 +down 2 +up 9 +forward 9 +forward 4 +forward 1 +forward 6 +up 3 +forward 6 +forward 2 +up 3 +down 3 +forward 6 +down 9 +down 7 +forward 3 +up 7 +up 8 +forward 3 +down 1 +down 8 +forward 7 +forward 3 +down 2 +down 5 +forward 5 +forward 1 +down 1 +down 3 +down 5 +forward 1 +down 1 +down 7 +forward 1 +up 2 +down 5 +up 3 +up 2 +down 7 +up 4 +forward 2 +down 3 +down 1 +up 7 +down 6 +down 1 +forward 7 +down 5 +down 2 +forward 7 +up 9 +forward 6 +forward 6 +forward 2 +forward 6 +down 2 +forward 4 +down 5 +forward 4 +down 8 +forward 3 +down 9 +up 5 +forward 6 +down 5 +forward 5 +down 4 +down 1 +forward 3 +up 9 +up 5 +up 9 +down 3 +forward 7 +forward 7 +up 5 +up 6 +up 3 +down 9 +down 4 +up 8 +down 9 +down 6 +forward 5 +down 6 +forward 7 +down 4 +down 9 +down 9 +forward 6 +down 4 +up 2 +down 8 +up 3 +up 7 +up 1 +forward 9 +down 4 +down 8 +up 2 +forward 7 +forward 5 +down 9 +down 9 +up 5 +down 4 +forward 8 +up 3 +up 4 +up 8 +down 7 +forward 6 +down 8 +down 1 +up 1 +down 7 +down 7 +forward 3 +down 9 +up 2 +forward 2 +up 1 +up 1 +down 2 +down 8 +up 5 +down 3 +down 3 +forward 2 +down 4 +forward 2 +down 2 +forward 3 +down 6 +forward 8 +down 5 +down 6 +forward 9 +forward 2 +down 6 +down 4 +up 9 +forward 2 +forward 1 +up 9 +down 9 +forward 8 +down 4 +up 3 +down 1 +forward 9 +forward 9 +forward 3 +forward 4 +down 2 +down 1 +forward 5 +up 3 +forward 6 +down 8 +down 8 +down 7 +forward 1 +forward 6 +down 9 +down 6 +forward 8 +down 5 +up 6 +down 2 +forward 2 +up 3 +forward 6 +forward 4 +up 4 +down 5 +forward 2 +down 5 +forward 1 +forward 5 +up 7 +up 1 +down 3 +up 8 +forward 4 +forward 8 +forward 8 +up 2 +down 8 +up 2 +up 2 +up 7 +down 9 +down 1 +forward 1 +down 3 +down 1 +down 4 +forward 3 +down 4 +down 5 +forward 7 +forward 6 +forward 7 +forward 8 +up 6 +down 1 +down 9 +up 2 +up 2 +forward 1 +up 9 +forward 6 +down 2 +forward 6 +forward 8 +up 8 +down 6 +forward 2 +up 4 +up 5 +down 3 +down 2 +forward 7 +down 8 +forward 4 +forward 8 +up 4 +down 7 +forward 6 +forward 1 +up 4 +down 4 +down 9 +down 7 +down 6 +down 1 +forward 7 +up 3 +down 1 +down 9 +down 9 +down 1 +down 7 +down 8 +up 9 +down 7 +up 4 +forward 4 +down 2 +up 8 +down 6 +down 6 +forward 4 +up 5 +down 9 +down 8 +up 7 +down 4 +forward 9 +up 3 +down 6 +forward 7 +up 4 +forward 9 +down 6 +forward 6 +down 3 +down 5 +down 4 +up 5 +down 8 +down 8 +forward 5 +forward 1 +down 3 +forward 7 +down 3 +up 6 +forward 5 +up 7 +forward 8 +down 1 +forward 7 +forward 8 +forward 9 +forward 7 +up 5 +forward 9 +up 7 +down 7 +forward 8 +down 8 +up 6 +down 4 +forward 6 +forward 3 +forward 3 +forward 6 +down 3 +up 4 +down 3 +down 8 +forward 2 +down 1 +down 5 +forward 2 +up 3 +up 5 +forward 2 +forward 8 +down 7 +down 9 +forward 8 +forward 5 +forward 2 +down 3 +forward 6 +forward 3 +forward 4 +forward 9 +down 8 +forward 2 +down 6 +down 8 +forward 1 +forward 5 +up 3 +forward 8 +up 3 +forward 2 +down 3 +down 5 +up 4 +down 9 +up 5 +down 2 +forward 7 +forward 8 +forward 2 +forward 4 +forward 6 +down 1 +up 3 +forward 3 +up 6 +forward 1 +down 9 +forward 4 +forward 5 +forward 3 +down 7 +down 9 +forward 1 +forward 5 +up 1 +down 6 +down 7 +up 4 +up 7 +forward 2 +down 7 +forward 5 +up 9 +up 8 +forward 8 +up 1 +up 6 +down 7 +up 8 +forward 2 +down 1 +forward 7 +forward 6 +forward 2 +up 7 +down 5 +down 6 +forward 8 +down 3 +down 2 +forward 5 +down 7 +forward 2 +down 9 +forward 7 +forward 9 +forward 1 +down 7 +down 3 +down 8 +down 4 +up 1 +down 2 +forward 5 +forward 9 +forward 5 +up 6 +up 1 +forward 3 +forward 1 +forward 7 +down 9 +forward 4 +down 7 +up 6 +forward 1 +down 7 +forward 5 +down 4 +down 2 +up 1 +forward 6 +up 6 +down 3 +up 5 +down 8 +down 5 +forward 2 +down 1 +forward 8 +forward 4 +down 3 +forward 3 +forward 6 +forward 2 +forward 9 +forward 2 +down 3 +forward 8 +down 4 +down 1 +forward 4 +down 1 +forward 5 +down 5 +down 6 +forward 6 +down 6 +down 9 +forward 7 +down 6 +forward 6 +forward 7 +forward 1 +forward 4 +forward 2 +forward 3 +up 8 +down 3 +down 7 +forward 6 +forward 4 +up 7 +forward 6 +forward 6 +down 7 +up 8 +down 5 +forward 6 +forward 8 +down 3 +up 2 +down 5 +forward 2 +forward 5 +up 8 +forward 1 +down 3 +forward 3 +forward 2 +down 3 +down 8 +forward 3 +forward 1 +down 5 +down 1 +up 1 +forward 9 +down 7 +up 2 +forward 8 +down 6 +down 5 +up 9 +forward 2 +forward 5 +forward 8 +up 2 +up 5 +forward 2 +down 2 +down 9 +down 3 +forward 7 +up 5 +forward 7 +down 6 +forward 2 +forward 7 +forward 8 +forward 8 +down 7 +forward 3 +forward 6 +down 5 +forward 8 +forward 6 +up 2 +forward 1 +up 9 +forward 1 +up 3 +forward 6 +down 4 +down 5 +down 8 +up 6 +forward 1 +down 8 +forward 3 +forward 2 +forward 9 +down 5 +down 9 +forward 5 +down 7 +up 9 +forward 5 +forward 7 +forward 6 +forward 5 +down 3 +forward 6 +down 9 +up 8 +forward 4 +forward 7 +forward 3 +down 7 +forward 8 +down 5 +forward 3 +up 6 +up 5 +forward 9 +up 4 +up 9 +forward 9 +forward 3 +down 8 +forward 8 +down 3 +forward 2 +down 4 +down 1 +forward 2 +up 9 +down 7 +forward 4 +up 3 +down 9 +down 6 +forward 2 +forward 5 +down 7 +down 2 +forward 8 +down 5 +forward 8 +down 8 +down 4 +down 1 +down 2 +forward 5 +down 8 +down 1 +down 2 +forward 8 +forward 3 +down 8 +up 8 +up 8 +down 3 +forward 3 +forward 6 +down 9 +up 1 +forward 6 +up 1 +down 1 +down 9 +forward 3 +up 1 +forward 7 +forward 6 +forward 1 +up 3 +down 8 +forward 7 +down 3 +down 5 +down 7 +forward 6 +down 9 +forward 9 +forward 8 +down 9 +forward 1 +down 2 +up 7 +down 3 +down 1 +forward 8 +forward 4 +forward 9 +up 9 +down 4 +forward 1 +down 1 +up 1 +up 1 +up 6 +down 7 +down 5 +forward 1 +forward 7 +up 3 +down 7 +up 3 +down 4 +up 9 +up 9 +forward 1 +down 4 +down 6 +forward 2 +forward 6 +up 1 +forward 1 +down 8 +forward 7 +up 6 +forward 6 +forward 3 +up 1 +up 6 +forward 1 +down 2 +forward 8 +forward 4 +forward 2 +down 3 +forward 2 +forward 3 +forward 1 +down 6 +forward 7 +forward 7 +down 4 +forward 6 +up 3 +up 4 +up 6 +down 7 +down 8 +forward 3 +down 2 +forward 5 +down 4 +forward 6 +forward 7 +forward 8 +forward 9 +forward 3 +down 1 +forward 8 +forward 1 +down 8 +up 1 +down 3 +down 6 +down 1 +up 1 +forward 1 +down 6 +down 5 +forward 6 +down 1 +down 5 +forward 7 +up 3 +forward 4 +forward 4 +forward 1 +up 6 +up 2 +up 4 +down 4 +up 4 +forward 8 +up 8 +forward 1 +down 5 +forward 5 +down 7 +up 5 +up 7 +up 5 +forward 9 +down 1 +down 1 +forward 4 +down 2 +down 2 +down 3 +down 1 +forward 1 +up 7 +forward 6 +forward 9 +up 5 +forward 1 +forward 9 +up 2 +forward 5 +down 4 +forward 6 +down 9 +down 3 +forward 1 +down 2 +down 3 +down 1 +down 3 +forward 8 +up 6 +forward 2 +down 5 +down 9 +down 4 +up 2 +up 9 +forward 2 +down 7 +forward 9 +down 5 +down 5 +up 6 +forward 1 +forward 5 +forward 9 +down 4 +forward 2 +forward 7 +down 2 +forward 4 +down 2 +forward 3 +down 3 +down 2 +up 5 +forward 8 +up 8 +down 9 +forward 9 +down 9 +down 4 +down 1 +forward 4 +forward 9 +down 5 +down 9 +down 4 +down 5 +forward 1 +down 3 +down 3 +down 4 +forward 6 +forward 5 +down 3 +up 4 +forward 9 +forward 5 +forward 3 +forward 6 +down 8 +up 9 +forward 2 +up 6 +forward 2 +down 9 +up 9 +down 4 +forward 1 +forward 9 +down 5 +forward 9 +forward 4 +down 6 +forward 7 +forward 4 +down 7 +down 1 +forward 9 +down 6 +down 5 +forward 5 +down 5 +down 1 +forward 3 +down 7 +down 5 +down 9 +down 5 +up 6 +up 5 +down 5 +up 1 +down 9 +forward 5 +forward 9 +forward 3 +forward 4 +down 7 +forward 3 +forward 3 +down 5 +forward 7 +down 9 +forward 8 +forward 4 +forward 8 +forward 9 +forward 1 +forward 6 +up 9 +down 3 +forward 1 +forward 4 +down 2 +down 8 +up 4 +down 4 +forward 1 +down 5 +down 3 +down 9 +up 1 +forward 8 +down 6 +down 4 +forward 3 +down 8 +down 2 +up 6 +down 5 +forward 8 +down 4 +up 1 +forward 5 +down 1 +down 9 +down 1 +down 9 +down 3 +down 3 +forward 2 +forward 6 +down 8 +forward 1 +up 4 +down 3 +forward 9 +up 2 +down 4 +forward 9 +down 3 +down 1 +down 3 +down 4 +up 6 +down 2 +forward 3 +forward 9 +forward 7 +down 2 +down 5 +forward 4 +forward 5 +down 9 +up 3 +forward 5 +forward 9 +up 2 +forward 3 +down 4 +forward 2 +down 5 +down 8 +down 1 +forward 4 +up 4 +forward 7 +down 9 +forward 8 +down 8 +forward 3 +down 6 +up 9 +up 6 +down 2 +forward 6 +up 1 +down 5 +down 5 +down 9 +up 2 +down 2 +forward 1 +forward 8 +down 2 +up 8 +down 3 +forward 2 +down 1 +down 5 +down 5 +up 4 +forward 5 diff --git a/aoc2021/src/day02.rs b/aoc2021/src/day02.rs new file mode 100644 index 0000000..f9e03d2 --- /dev/null +++ b/aoc2021/src/day02.rs @@ -0,0 +1,86 @@ +use std::fmt::Write; + +use anyhow::{bail, Result}; + +const INPUT: &str = include_str!("../input/day02.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let commands = input + .lines() + .map(str::parse::) + .collect::>>()?; + let mut horizontal_pos = 0; + let mut depth = 0; + + for c in commands { + match c { + Command::Forward(dx) => horizontal_pos += dx, + Command::Up(dz) => depth -= dz, + Command::Down(dz) => depth += dz, + } + } + + Ok(depth * horizontal_pos) +} + +fn part2(input: &str) -> Result { + let commands = input + .lines() + .map(str::parse::) + .collect::>>()?; + let mut horizontal_pos = 0; + let mut depth = 0; + let mut aim = 0; + + for c in commands { + match c { + Command::Forward(dx) => { + horizontal_pos += dx; + depth += aim * dx; + } + Command::Up(dz) => { + aim -= dz; + } + Command::Down(dz) => { + aim += dz; + } + } + } + + Ok(depth * horizontal_pos) +} + +enum Command { + Forward(u64), + Up(u64), + Down(u64), +} + +impl std::str::FromStr for Command { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut split = s.split(' '); + + let word = split.next().unwrap(); + let number = split.next().unwrap(); + + let number = number.parse()?; + + Ok(match word { + "forward" => Self::Forward(number), + "up" => Self::Up(number), + "down" => Self::Down(number), + _ => bail!("unkown command"), + }) + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 784a117..c10d8ec 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -1,3 +1,4 @@ #![warn(clippy::explicit_iter_loop, clippy::redundant_closure_for_method_calls)] pub mod day01; +pub mod day02; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index f788a63..316799b 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -3,9 +3,10 @@ use anyhow::Result; use aoc::DayFunc; use aoc2021::day01; +use aoc2021::day02; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run]; + let days: &[DayFunc] = &[day01::run, day02::run]; aoc::run(days) } From 43c89d10bf56ac3931f179f9745c4407c6629419 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 2 Dec 2021 10:30:09 +0100 Subject: [PATCH 015/134] 2021: day02: tests --- aoc2021/input/day02_provided.txt | 6 ++++++ aoc2021/src/day02.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 aoc2021/input/day02_provided.txt diff --git a/aoc2021/input/day02_provided.txt b/aoc2021/input/day02_provided.txt new file mode 100644 index 0000000..b7172ac --- /dev/null +++ b/aoc2021/input/day02_provided.txt @@ -0,0 +1,6 @@ +forward 5 +down 5 +forward 8 +up 3 +down 8 +forward 2 diff --git a/aoc2021/src/day02.rs b/aoc2021/src/day02.rs index f9e03d2..fbc1c2e 100644 --- a/aoc2021/src/day02.rs +++ b/aoc2021/src/day02.rs @@ -84,3 +84,30 @@ impl std::str::FromStr for Command { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day02_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 150); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 1962940); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 900); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 1813664422); + } +} From ee588b7ce76514f5daf16a84bf5871e2a5882dbb Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 14:44:42 +0100 Subject: [PATCH 016/134] 2021: day03 part 1 --- aoc2021/input/day03.txt | 1000 ++++++++++++++++++++++++++++++ aoc2021/input/day03_provided.txt | 12 + aoc2021/src/day03.rs | 79 +++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 3 +- 5 files changed, 1094 insertions(+), 1 deletion(-) create mode 100644 aoc2021/input/day03.txt create mode 100644 aoc2021/input/day03_provided.txt create mode 100644 aoc2021/src/day03.rs diff --git a/aoc2021/input/day03.txt b/aoc2021/input/day03.txt new file mode 100644 index 0000000..0e1771b --- /dev/null +++ b/aoc2021/input/day03.txt @@ -0,0 +1,1000 @@ +000110000001 +011011001101 +001101100111 +001101011001 +110111011101 +110011101010 +111101010001 +010100111101 +011000011000 +001110110011 +001100010110 +110111101100 +110001111100 +001011111100 +000000011010 +110101100111 +011000011111 +011000000111 +011111000110 +100101110111 +010101001110 +111101000011 +010010010110 +100100011111 +101011001110 +001111110000 +110000011111 +110000011000 +011001111100 +010010001101 +000111001110 +110111001110 +110001010101 +100111011001 +000101110000 +110001011100 +111101010010 +101011000001 +001101001111 +110111101010 +101111111000 +110101000110 +011111001001 +001110100001 +010100110111 +110100000110 +101010110010 +100100101110 +101111011110 +000110110101 +011011110101 +111001011110 +110110100111 +000100010001 +001101010110 +100011000110 +001110010010 +010111110111 +011010011101 +110000011100 +010100001001 +000110100000 +101001010000 +000001110000 +101110010011 +010011100111 +010011011000 +110111011111 +000111010010 +101010111010 +111001100100 +101110100011 +111101111110 +010111111000 +010010001111 +110010000011 +001110000010 +100101111110 +000100101001 +101101010000 +111111010000 +101010011000 +011100100001 +011101101000 +001010010100 +010010100011 +110011111111 +110100011001 +111010011110 +011110001101 +011010011100 +100100000001 +111111001010 +110100110011 +110100011111 +100010001110 +101000111100 +100001110010 +110101010011 +101010011101 +011010011010 +101110101101 +001100011010 +101001010101 +101010000100 +000110101010 +100000111100 +000111111100 +000001001011 +010010111100 +011000111001 +111010101100 +010011100010 +010100110001 +001100111011 +101100001111 +111010101111 +010001000011 +000001100010 +000100001011 +100110011011 +101100001110 +000010110100 +011000101011 +010011011100 +110101010000 +101101101100 +101001110000 +010111010011 +110101110001 +011000001000 +011101010010 +111011111110 +010010000110 +110000111000 +101000000110 +011100110000 +111001111010 +110000001100 +101011111110 +100001111100 +011011100110 +101000001101 +001011110011 +111100100011 +101111000111 +101000000001 +001001011010 +010111111010 +101010111001 +011110101001 +101100111101 +011100000010 +000110001111 +111100110101 +100011100010 +000110010100 +011000000011 +010011001011 +000001101111 +101011101101 +100100100101 +011001110110 +010100000000 +100100010001 +001100000100 +100000111010 +101001011001 +010010111001 +110000101010 +001101010101 +110110011100 +010000000011 +111100011000 +000101111110 +100010110101 +101111010000 +000010100010 +101101001010 +011111000000 +011000100100 +110010100110 +010001110011 +010101101101 +001011100000 +001000110110 +001000110111 +110100111110 +110010110100 +101010100111 +000111011001 +111000101101 +110000010110 +010011101010 +110100111011 +100110010100 +100111000011 +011110111111 +010010000111 +111100111110 +001010111101 +000011001110 +000110010101 +111100110011 +101111111001 +101001111011 +111010110000 +000001010101 +100010011001 +111110110010 +110100101100 +100001011110 +100001000011 +101111000011 +101111110100 +111010000010 +001010010110 +010001000110 +100010000101 +111101111010 +000101111111 +010110110100 +110111111110 +011010101011 +100000110011 +000000101001 +010010101111 +010001001010 +000101010100 +101110111010 +101001000000 +001010101111 +011110100110 +110101011001 +100111101101 +110001001001 +110100001010 +100100101001 +110111010011 +011010001011 +011001001101 +110100010001 +010100001100 +011011000001 +110100011100 +001110111111 +111001110010 +001110010000 +011100001110 +001111110001 +001101010111 +111110011100 +111100111010 +010100010100 +000011001010 +011110001010 +111101010011 +100111001010 +010110110011 +000101000000 +000110011010 +100100001111 +000100111111 +010100010101 +001110100011 +100111000100 +100001101110 +011010011110 +001111010101 +111000001100 +100111110110 +101110001100 +101011000111 +001010110010 +100011011100 +110000010000 +101001101011 +111011011000 +000101101001 +011001111011 +101011001111 +001111111111 +110000101011 +111111100011 +101010101111 +001001010001 +011111010001 +001011101110 +011010011011 +011000001011 +100000100000 +001011110110 +011000100011 +001010011010 +000010111111 +001110001111 +111110001100 +010110100011 +110101100010 +100111110000 +010000101011 +011100011111 +001100101010 +101110110100 +100101000111 +111111111010 +000001000001 +110111011001 +010011000000 +101100000101 +110000100100 +110100100101 +101011010010 +101001000101 +110001001111 +010010011010 +000110110111 +011010110001 +001101001001 +010110101000 +101000011000 +110010011010 +100101011111 +001101110011 +110001110001 +011110000110 +111011100101 +001100111001 +001011011011 +001011110001 +010001111101 +011000101001 +100100000110 +011000101111 +001010110100 +000100101010 +111011010110 +100111000000 +001000111010 +101101001111 +000110111010 +001111100001 +011110011001 +100011000101 +001010010011 +110011100110 +010010001011 +110101101110 +111100100101 +101100100010 +111010111101 +000000000011 +011011001110 +101110000001 +000111111000 +100000110001 +101101100111 +001001011001 +101100010010 +001000011100 +111011111100 +010000100011 +111010111100 +011001101111 +100011001111 +011001111010 +110110100101 +010110100110 +011110101101 +011101110001 +111000100101 +000010000000 +100110111001 +000101000001 +000001101100 +011010000100 +111000101001 +111100111111 +100110000110 +100010001010 +011110001000 +100001100100 +101101101010 +101111010001 +010001111100 +001010111001 +001101110111 +010100101100 +100011011101 +010100111000 +000110000000 +110101101010 +010100000101 +101110111100 +001010110000 +000000010101 +000100011000 +011010110100 +010000000010 +111101100011 +000111101001 +011101011100 +101000101101 +110110101011 +011010110011 +011001101010 +100000000011 +101001111111 +111010110100 +010000011100 +011011100000 +110011011000 +111011101111 +100010110110 +010000100111 +110101110101 +100010111001 +011011101000 +011010000001 +001001111110 +100010010001 +010101000110 +111111110010 +101011011110 +010011110110 +000010010100 +100011101111 +001001110110 +000100110100 +100101110110 +011010111001 +010010101110 +110010100011 +011010101010 +000101111000 +111011110011 +100111101110 +101111101001 +010111100010 +111011001011 +111110011110 +110110010110 +010110010111 +011111001100 +110111110010 +110011111000 +001110111101 +111100111000 +000100000010 +110101111110 +010111101101 +111001001010 +000010011100 +110101100100 +111000011110 +010110000000 +011100010011 +011110010100 +101000100111 +111011110101 +000100010000 +000110110011 +100011001011 +111010100000 +010100110101 +001000000101 +010001101100 +010110000101 +100100101111 +011101111110 +000011110000 +000011010011 +101111111110 +101001101010 +000010100011 +010100101010 +001111001110 +011000001001 +010001110100 +010111011110 +100000111111 +101100010101 +111101000110 +110111101111 +011010010010 +011100011100 +001111010010 +111001101000 +110110111010 +101110000111 +011100101100 +011100001010 +110101011101 +011100010010 +010101010010 +000001111101 +110100110111 +011111100111 +111101011110 +110110000110 +100110001011 +111110000001 +010001010011 +101001110110 +011101011101 +010011011110 +000100000000 +100110010001 +000011100110 +101111100001 +101100101010 +001010101110 +001111001101 +110000000111 +110010100001 +011100000111 +100111100111 +101001011111 +110000100011 +111001000111 +010101111010 +110111100100 +001010101100 +001011110100 +001010010111 +110001001000 +110010011001 +110111011100 +001110000011 +010001000010 +100000000101 +110001101001 +000101010111 +101010110101 +100000010000 +000000111100 +011011100100 +110010001110 +110110100000 +101100001100 +110010110111 +010001100010 +101110100010 +001101101101 +010100110000 +010010100000 +011101110100 +100011011001 +010110111101 +010110011011 +011111011111 +001000000000 +001101110101 +010000010101 +000101001000 +011011100101 +001010000101 +110010001101 +000001000011 +001101001110 +000101100010 +010110100001 +010111110011 +011000100111 +100001101011 +100100100011 +111100011001 +010010101000 +101010000010 +010011000001 +100000000010 +010011101011 +101110100111 +111101101011 +011010001111 +001000011000 +011111110111 +101111011100 +011011011111 +110111100010 +010010110001 +111100010111 +111000001111 +101100010011 +010101001101 +110101100001 +010111010110 +110000001111 +000111000000 +110010010001 +001110110101 +101000010010 +010110001100 +001101101010 +110110110110 +000000000111 +011010010000 +011001010111 +001010101011 +001001100011 +001111010110 +000000100111 +000000010100 +001001110011 +010111000010 +010000001100 +101111010111 +101001110100 +100011010111 +000111110100 +011101111010 +000111000010 +011100111100 +011011110100 +101000110011 +010101110111 +111101101000 +010010011011 +000101011111 +010000000110 +011110100101 +111000000100 +010110110101 +010110111001 +101110010000 +010111001111 +001001000110 +010100010000 +101100100111 +101100001000 +110110001001 +011001001010 +011001001110 +110011101001 +010100101111 +111101001000 +100000101100 +111000011000 +011000011100 +111111010001 +111100100100 +011000111110 +010011010000 +100110101100 +110000100001 +001101010011 +011000101110 +000110010000 +011010101100 +001110001010 +010101000001 +101010010101 +100000010111 +000100110101 +110111010110 +101101101011 +100101100101 +101010011110 +111001000100 +011101100111 +010000110101 +100111010110 +010011111110 +111011100100 +100010101101 +010110100101 +100011100000 +110010011101 +011110000011 +111111110011 +100001101100 +000000011000 +000100101101 +000100110000 +000110000010 +011110010011 +111001111111 +000011110101 +111001101100 +111010111010 +000101000101 +111000010110 +111010011000 +101110100110 +111100000100 +101000110001 +000001010110 +101000100000 +110111001010 +001001101000 +010011111010 +100010100100 +110010101001 +111101100101 +010001000101 +011001111101 +110000001110 +100101101100 +110110111100 +010111011101 +111011011100 +011111011100 +100100011001 +111010011011 +110011101011 +100001101000 +010110100010 +101100100110 +010110111010 +111111011001 +101011110011 +011001101001 +110011100111 +010100111110 +001001010011 +010101110000 +010111010101 +100110011100 +110010011011 +001011010111 +000001010100 +001111011100 +000010100100 +010101011011 +010100001011 +000001011110 +011111010111 +010000101100 +111111101111 +100101010110 +100011010101 +100101100100 +010011111101 +010011001111 +011010000101 +110010000111 +101110110110 +000010001001 +111000010010 +111001001111 +111000111010 +010111011100 +011010001101 +111011011111 +001010110001 +011111111101 +001001001011 +100100011000 +001000101010 +101001111010 +011101000010 +111010000111 +001000100000 +100000100010 +111111011000 +110011000110 +111111100010 +100110011101 +101111101000 +001001001100 +100001100001 +100111110011 +001000100010 +011100011000 +000001010010 +100010111110 +101111010010 +100100000011 +000101000010 +101001011100 +000101001101 +000101110010 +111111111011 +110100000100 +000001000010 +101011010101 +000011110011 +000011001000 +010111111001 +111110100111 +100110100111 +001100001111 +000100011110 +001101000101 +011110000000 +000100111100 +011110010111 +011011010011 +010101011110 +100111001100 +011111101010 +011011001000 +100100110100 +011101010101 +100101111001 +100011101001 +101010000001 +101110111001 +110100101111 +010001001100 +100110110000 +100000111001 +010111011011 +111110001000 +101000111101 +000011010110 +100010010010 +010010011111 +011110111110 +000100111000 +111100001101 +000010110101 +010010001110 +101111000100 +100101111100 +010100011111 +110101010010 +000010111110 +100001000100 +001010001010 +110000111100 +010000101000 +111000110110 +001001101010 +001101011100 +001000001100 +110010011100 +011111000011 +111100101101 +110111010101 +000010010110 +111101110111 +000011010010 +111110000000 +001111000101 +100010111100 +001011000011 +010110000010 +001101111101 +101011000011 +100001010010 +100001010100 +111100011101 +010110001101 +011101101101 +101010101110 +110111110100 +001111001010 +100010111101 +011010001001 +111111001000 +100010100001 +111010010110 +001101000011 +000011111011 +110101000100 +110101111101 +010010000011 +110101001111 +001110111110 +101111100011 +011011011100 +001100100100 +010011111000 +101010001111 +111101010101 +001110110001 +101100010100 +100010001000 +101110000110 +001101100001 +111001000110 +101110011110 +100010000110 +101010111011 +001010110101 +001101101110 +100000101111 +011001000001 +010100001110 +100111101000 +011000110000 +110000101111 +010110111111 +001110101000 +111010100010 +100000110100 +100100000010 +101010110011 +010101000100 +100100001011 +000110011011 +110001000010 +111111000111 +010001010010 +001000011011 +110010000101 +111110110111 +001000111001 +101111100010 +101001110010 +001101101111 +101001101101 +001000010011 +111000011111 +111111110101 +101001000001 +010101101111 +110100100100 +001011101011 +001010111100 +000111100011 +010001010100 +110011000011 +100111100000 +001001111001 +111111100001 +001001100110 +001000101001 +111101011011 +111000000010 +100000100111 +101011100100 +001010111110 +100110110100 +110111100111 +000110101000 +011001000111 +010111000001 +101111101101 +000001101101 +000110100111 +110001010100 +111110101111 +111110110101 +111000010001 +101111011010 +101111110110 +000000101100 +010011010010 +000101010101 +100110101000 +000111000011 +001000010110 +000111001010 +000001000111 +000101000110 +000100010100 +001011011101 +001001111101 +000000000101 +000100100101 +101010001101 +001010000111 +110110001110 +000010011010 +011001110101 +111111101011 +001100001100 +100111001000 +011010011000 +000001101001 +010001111001 +001001110100 +111110111000 +000010010001 +111111010011 +100000011011 +010110010100 +010000111000 +100001110110 +111101111001 +110000011010 +100110101111 +010001100111 +100001011100 +110000010011 +010100001111 +110010010110 +110010111000 +001011000110 +101011001101 +010000000100 +010010000000 +010100100101 +110010100101 +010101110110 +101101001101 +110000110011 +110011110110 +111101110110 +001011111001 +110101101000 +101111111100 +110011111101 +100001111110 +011101111000 +101010000111 +101110011111 +101000010101 diff --git a/aoc2021/input/day03_provided.txt b/aoc2021/input/day03_provided.txt new file mode 100644 index 0000000..a6366a8 --- /dev/null +++ b/aoc2021/input/day03_provided.txt @@ -0,0 +1,12 @@ +00100 +11110 +10110 +10111 +10101 +01111 +00111 +11100 +10000 +11001 +00010 +01010 diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs new file mode 100644 index 0000000..bff32b4 --- /dev/null +++ b/aoc2021/src/day03.rs @@ -0,0 +1,79 @@ +use std::fmt::Write; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day03.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let binary_numbers: Vec<&str> = input.lines().collect(); + // all binary numbers should have the same length + let size = binary_numbers[0].len(); + + let gamma = compute_gamma(&binary_numbers, size); + let epsilon = compute_epsilon(gamma, size); + + Ok(gamma * epsilon) +} + +fn compute_gamma(binary_numbers: &[&str], size: usize) -> u64 { + let mut gamma = 0; + + for pos in 0..size { + let digit = if count_ones(binary_numbers, pos) > (binary_numbers.len() / 2) { + // majority of ones + 1 + } else { + // majority of zeroes + 0 + }; + gamma = (gamma << 1) | digit; + } + + gamma +} + +fn count_ones(binary_numbers: &[&str], pos: usize) -> usize { + binary_numbers + .iter() + .filter(|&&num| num.chars().nth(pos).unwrap() == '1') + .count() +} + +fn compute_epsilon(gamma: u64, size: usize) -> u64 { + // mask 0b000000000000000011111111 with `size` 1s. + let shift = u64::BITS - (size as u32); + let mask = (u64::MAX << shift) >> shift; + + (!gamma) & mask +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day03_provided.txt"); + #[test] + fn part1_provided() { + let binary_numbers: Vec<&str> = PROVIDED.lines().collect(); + let size = binary_numbers[0].len(); + + let gamma = compute_gamma(&binary_numbers, size); + let epsilon = compute_epsilon(gamma, size); + + assert_eq!(gamma, 22); + assert_eq!(epsilon, 9); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 3429254); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index c10d8ec..eef213c 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -2,3 +2,4 @@ pub mod day01; pub mod day02; +pub mod day03; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 316799b..2315917 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -4,9 +4,10 @@ use aoc::DayFunc; use aoc2021::day01; use aoc2021::day02; +use aoc2021::day03; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run]; aoc::run(days) } From 03746a1dec176067a32b55ff03cf8ed2b3a28eb6 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 15:28:06 +0100 Subject: [PATCH 017/134] 2021: day03: part 2 --- aoc2021/src/day03.rs | 115 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index bff32b4..2921a0d 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -1,6 +1,6 @@ use std::fmt::Write; -use anyhow::Result; +use anyhow::{Context, Result}; const INPUT: &str = include_str!("../input/day03.txt"); @@ -8,6 +8,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -23,6 +24,8 @@ fn part1(input: &str) -> Result { Ok(gamma * epsilon) } +/// Each bit in the gamma rate can be determined by finding the most common bit in the corresponding +/// position of all numbers in the diagnostic report. fn compute_gamma(binary_numbers: &[&str], size: usize) -> u64 { let mut gamma = 0; @@ -47,6 +50,10 @@ fn count_ones(binary_numbers: &[&str], pos: usize) -> usize { .count() } +/// The epsilon rate is calculated in a similar way; rather than use the most common bit, the least +/// common bit from each position is used. +/// +/// We can just use flip every bit in gamma (respecting the size of the input) fn compute_epsilon(gamma: u64, size: usize) -> u64 { // mask 0b000000000000000011111111 with `size` 1s. let shift = u64::BITS - (size as u32); @@ -55,20 +62,104 @@ fn compute_epsilon(gamma: u64, size: usize) -> u64 { (!gamma) & mask } +fn part2(input: &str) -> Result { + let binary_numbers: Vec<&str> = input.lines().collect(); + // all binary numbers should have the same length + let size = binary_numbers[0].len(); + + let oxygen_generator_rating = compute_oxygen_generator_rating(&binary_numbers, size)?; + let co2_scrubber_rating = compute_co2_scrubber_rating(&binary_numbers, size)?; + + Ok(oxygen_generator_rating * co2_scrubber_rating) +} + +/// To find oxygen generator rating, determine the most common value (0 or 1) in the current bit +/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally common, +/// keep values with a 1 in the position being considered. +fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Result { + let mut numbers = binary_numbers.to_vec(); + + for pos in 0..size { + if numbers.len() == 1 { + // only one number left, we're done! + break; + } + + let most_common = if count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2) { + // majority of ones, or equality + '1' + } else { + // majority of zeroes + '0' + }; + + // TODO: use drain_filter when stable + let mut i = 0; + while i < numbers.len() { + if numbers[i].chars().nth(pos).unwrap() != most_common { + numbers.remove(i); + } else { + i += 1; + } + } + } + + debug_assert_eq!(numbers.len(), 1); + + u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number") +} + +/// To find CO2 scrubber rating, determine the least common value (0 or 1) in the current bit +/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally +/// common, keep values with a 0 in the position being considered. +fn compute_co2_scrubber_rating(binary_numbers: &[&str], size: usize) -> Result { + let mut numbers = binary_numbers.to_vec(); + + for pos in 0..size { + if numbers.len() == 1 { + // only one number left, we're done! + break; + } + + let least_common = if count_ones(&numbers, pos) < ((numbers.len() + 1) / 2) { + // majority of ones + '1' + } else { + // majority of zeroes, or equality + '0' + }; + + // TODO: use drain_filter when stable + let mut i = 0; + while i < numbers.len() { + if numbers[i].chars().nth(pos).unwrap() != least_common { + numbers.remove(i); + } else { + i += 1; + } + } + } + + debug_assert_eq!(numbers.len(), 1); + + u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number") +} + #[cfg(test)] mod tests { use super::*; const PROVIDED: &str = include_str!("../input/day03_provided.txt"); + #[test] fn part1_provided() { let binary_numbers: Vec<&str> = PROVIDED.lines().collect(); let size = binary_numbers[0].len(); let gamma = compute_gamma(&binary_numbers, size); - let epsilon = compute_epsilon(gamma, size); - assert_eq!(gamma, 22); + + let epsilon = compute_epsilon(gamma, size); assert_eq!(epsilon, 9); } @@ -76,4 +167,22 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 3429254); } + + #[test] + fn part2_provided() { + let binary_numbers: Vec<&str> = PROVIDED.lines().collect(); + let size = binary_numbers[0].len(); + + let oxygen_generator_rating = + compute_oxygen_generator_rating(&binary_numbers, size).unwrap(); + assert_eq!(oxygen_generator_rating, 23); + + let co2_scrubber_rating = compute_co2_scrubber_rating(&binary_numbers, size).unwrap(); + assert_eq!(co2_scrubber_rating, 10); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 5410338); + } } From a776f5691587184c1b98c1a1b345e3def61e4c98 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 15:33:47 +0100 Subject: [PATCH 018/134] 2021: day03: factorize --- aoc2021/src/day03.rs | 62 +++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index 2921a0d..dc97d18 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -73,10 +73,12 @@ fn part2(input: &str) -> Result { Ok(oxygen_generator_rating * co2_scrubber_rating) } -/// To find oxygen generator rating, determine the most common value (0 or 1) in the current bit -/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally common, -/// keep values with a 1 in the position being considered. -fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Result { +enum FilterStrategy { + MostCommon, + LeastCommon, +} + +fn filter_by_strat(binary_numbers: &[&str], size: usize, strat: FilterStrategy) -> Result { let mut numbers = binary_numbers.to_vec(); for pos in 0..size { @@ -85,18 +87,24 @@ fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Resu break; } - let most_common = if count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2) { + let digit_of_interest = if count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2) { // majority of ones, or equality - '1' + match strat { + FilterStrategy::MostCommon => '1', + FilterStrategy::LeastCommon => '0', + } } else { // majority of zeroes - '0' + match strat { + FilterStrategy::MostCommon => '0', + FilterStrategy::LeastCommon => '1', + } }; // TODO: use drain_filter when stable let mut i = 0; while i < numbers.len() { - if numbers[i].chars().nth(pos).unwrap() != most_common { + if numbers[i].chars().nth(pos).unwrap() != digit_of_interest { numbers.remove(i); } else { i += 1; @@ -109,40 +117,18 @@ fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Resu u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number") } +/// To find oxygen generator rating, determine the most common value (0 or 1) in the current bit +/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally common, +/// keep values with a 1 in the position being considered. +fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Result { + filter_by_strat(binary_numbers, size, FilterStrategy::MostCommon) +} + /// To find CO2 scrubber rating, determine the least common value (0 or 1) in the current bit /// position, and keep only numbers with that bit in that position. If 0 and 1 are equally /// common, keep values with a 0 in the position being considered. fn compute_co2_scrubber_rating(binary_numbers: &[&str], size: usize) -> Result { - let mut numbers = binary_numbers.to_vec(); - - for pos in 0..size { - if numbers.len() == 1 { - // only one number left, we're done! - break; - } - - let least_common = if count_ones(&numbers, pos) < ((numbers.len() + 1) / 2) { - // majority of ones - '1' - } else { - // majority of zeroes, or equality - '0' - }; - - // TODO: use drain_filter when stable - let mut i = 0; - while i < numbers.len() { - if numbers[i].chars().nth(pos).unwrap() != least_common { - numbers.remove(i); - } else { - i += 1; - } - } - } - - debug_assert_eq!(numbers.len(), 1); - - u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number") + filter_by_strat(binary_numbers, size, FilterStrategy::LeastCommon) } #[cfg(test)] From 7fb284bfe3d1b409e5e6c6f28bdeea4def24ee23 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 15:36:54 +0100 Subject: [PATCH 019/134] 2021: day02: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 05cb02e..965b65a 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -1,9 +1,11 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2021::day01; +use aoc2021::day02; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); + c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); } criterion_group! { From 1968c7894f2416aad27e233ccb0ad42e2fe7aaf9 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 15:37:58 +0100 Subject: [PATCH 020/134] 2021: day03: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 965b65a..f4475d2 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -2,10 +2,12 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2021::day01; use aoc2021::day02; +use aoc2021::day03; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); + c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); } criterion_group! { From 2c0bf85249ae81845aa1f1b5b136404d756b14fd Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 15:44:11 +0100 Subject: [PATCH 021/134] 2021: day03: use lambda for part 2 --- aoc2021/src/day03.rs | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index dc97d18..69989e5 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -73,12 +73,10 @@ fn part2(input: &str) -> Result { Ok(oxygen_generator_rating * co2_scrubber_rating) } -enum FilterStrategy { - MostCommon, - LeastCommon, -} - -fn filter_by_strat(binary_numbers: &[&str], size: usize, strat: FilterStrategy) -> Result { +fn filter_by_strat(binary_numbers: &[&str], size: usize, strat: Strat) -> Result +where + Strat: Fn(bool) -> char, +{ let mut numbers = binary_numbers.to_vec(); for pos in 0..size { @@ -87,19 +85,8 @@ fn filter_by_strat(binary_numbers: &[&str], size: usize, strat: FilterStrategy) break; } - let digit_of_interest = if count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2) { - // majority of ones, or equality - match strat { - FilterStrategy::MostCommon => '1', - FilterStrategy::LeastCommon => '0', - } - } else { - // majority of zeroes - match strat { - FilterStrategy::MostCommon => '0', - FilterStrategy::LeastCommon => '1', - } - }; + let one_is_more_common = count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2); + let digit_of_interest = strat(one_is_more_common); // TODO: use drain_filter when stable let mut i = 0; @@ -121,14 +108,26 @@ fn filter_by_strat(binary_numbers: &[&str], size: usize, strat: FilterStrategy) /// position, and keep only numbers with that bit in that position. If 0 and 1 are equally common, /// keep values with a 1 in the position being considered. fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Result { - filter_by_strat(binary_numbers, size, FilterStrategy::MostCommon) + filter_by_strat(binary_numbers, size, |one_is_more_common| { + if one_is_more_common { + '1' + } else { + '0' + } + }) } /// To find CO2 scrubber rating, determine the least common value (0 or 1) in the current bit /// position, and keep only numbers with that bit in that position. If 0 and 1 are equally /// common, keep values with a 0 in the position being considered. fn compute_co2_scrubber_rating(binary_numbers: &[&str], size: usize) -> Result { - filter_by_strat(binary_numbers, size, FilterStrategy::LeastCommon) + filter_by_strat(binary_numbers, size, |one_is_more_common| { + if one_is_more_common { + '0' + } else { + '1' + } + }) } #[cfg(test)] From b62fa53ed7196c5f63921a16813847af9bad2daa Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 16:09:14 +0100 Subject: [PATCH 022/134] 2021: day02: no dirty unwraps --- aoc2021/src/day02.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aoc2021/src/day02.rs b/aoc2021/src/day02.rs index fbc1c2e..2bfc9c7 100644 --- a/aoc2021/src/day02.rs +++ b/aoc2021/src/day02.rs @@ -1,6 +1,6 @@ use std::fmt::Write; -use anyhow::{bail, Result}; +use anyhow::{bail, Context, Result}; const INPUT: &str = include_str!("../input/day02.txt"); @@ -71,8 +71,8 @@ impl std::str::FromStr for Command { fn from_str(s: &str) -> Result { let mut split = s.split(' '); - let word = split.next().unwrap(); - let number = split.next().unwrap(); + let word = split.next().context("couldn't find word in command")?; + let number = split.next().context("couldn't find number in command")?; let number = number.parse()?; From d54bddde27bf48ae044c055702e44eb917ecefd4 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 16:15:50 +0100 Subject: [PATCH 023/134] 2021: day03: assert that input is safe --- aoc2021/src/day03.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index 69989e5..fababff 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -64,8 +64,13 @@ fn compute_epsilon(gamma: u64, size: usize) -> u64 { fn part2(input: &str) -> Result { let binary_numbers: Vec<&str> = input.lines().collect(); + // all binary numbers should have the same length let size = binary_numbers[0].len(); + #[cfg(debug_assertions)] + binary_numbers.iter().for_each(|num| { + debug_assert_eq!(num.len(), size); + }); let oxygen_generator_rating = compute_oxygen_generator_rating(&binary_numbers, size)?; let co2_scrubber_rating = compute_co2_scrubber_rating(&binary_numbers, size)?; From e8a36de2b493d499894634bf09aa1eabebfa520c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 16:36:25 +0100 Subject: [PATCH 024/134] 2020: day23: remove TODOs std::cmp::Ord::clamp can't really help in this situation, not sure what I had in mind --- aoc2020/src/day23.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/aoc2020/src/day23.rs b/aoc2020/src/day23.rs index cd27a66..5e3c626 100644 --- a/aoc2020/src/day23.rs +++ b/aoc2020/src/day23.rs @@ -71,8 +71,6 @@ impl CupCircle { // keep subtracting one until it finds a cup that wasn't just picked up. If at any point in // this process the value goes below the lowest value on any cup's label, it wraps around to // the highest value on any cup's label instead. - // - // TODO: use std::cmp::Ord::clamp when stabilized (Rust 1.50) let mut destination = if current > 1 { current - 1 } else { self.max() }; while removed_cups.contains(&destination) { destination = if destination > 1 { @@ -193,8 +191,6 @@ impl FastCupCircle { // keep subtracting one until it finds a cup that wasn't just picked up. If at any point in // this process the value goes below the lowest value on any cup's label, it wraps around to // the highest value on any cup's label instead. - // - // TODO: use std::cmp::Ord::clamp when stabilized (Rust 1.50) let mut destination = if self.current > 1 { self.current - 1 } else { From ebc5fe5425bd41bacf5021f38395a7b6db11ba70 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 17:34:28 +0100 Subject: [PATCH 025/134] 2021: day02: use split_once --- aoc2021/src/day02.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/aoc2021/src/day02.rs b/aoc2021/src/day02.rs index 2bfc9c7..a65b4e1 100644 --- a/aoc2021/src/day02.rs +++ b/aoc2021/src/day02.rs @@ -69,10 +69,7 @@ impl std::str::FromStr for Command { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - let mut split = s.split(' '); - - let word = split.next().context("couldn't find word in command")?; - let number = split.next().context("couldn't find number in command")?; + let (word, number) = s.split_once(' ').context("couldn't split command")?; let number = number.parse()?; From 5c3a631dde9b6d36d087d056fd1ce704f79a8e50 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Dec 2021 17:35:41 +0100 Subject: [PATCH 026/134] 2021: day02: formatting --- aoc2021/src/day02.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/aoc2021/src/day02.rs b/aoc2021/src/day02.rs index a65b4e1..f144b45 100644 --- a/aoc2021/src/day02.rs +++ b/aoc2021/src/day02.rs @@ -47,12 +47,8 @@ fn part2(input: &str) -> Result { horizontal_pos += dx; depth += aim * dx; } - Command::Up(dz) => { - aim -= dz; - } - Command::Down(dz) => { - aim += dz; - } + Command::Up(dz) => aim -= dz, + Command::Down(dz) => aim += dz, } } From 1fb5dd9ec4c55401561b89c3228c4d44bd9fd720 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 14:39:22 +0100 Subject: [PATCH 027/134] 2021: day04: part 1 --- aoc2021/input/day04.txt | 601 +++++++++++++++++++++++++++++++ aoc2021/input/day04_provided.txt | 19 + aoc2021/src/day04.rs | 150 ++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 3 +- 5 files changed, 773 insertions(+), 1 deletion(-) create mode 100644 aoc2021/input/day04.txt create mode 100644 aoc2021/input/day04_provided.txt create mode 100644 aoc2021/src/day04.rs diff --git a/aoc2021/input/day04.txt b/aoc2021/input/day04.txt new file mode 100644 index 0000000..d567a2b --- /dev/null +++ b/aoc2021/input/day04.txt @@ -0,0 +1,601 @@ +0,56,39,4,52,7,73,57,65,13,3,72,69,96,18,9,49,83,24,31,12,64,29,21,80,71,66,95,2,62,68,46,11,33,74,88,17,15,5,6,98,30,51,78,76,75,28,53,87,48,20,22,55,86,82,90,47,19,25,1,27,60,94,38,97,58,70,10,43,40,89,26,34,32,23,45,50,91,61,44,35,85,63,16,99,92,8,36,81,84,79,37,93,67,59,54,41,77,42,14 + +63 5 10 69 57 +64 88 27 40 76 +59 20 58 90 6 +74 32 72 16 26 +50 17 7 93 94 + +92 77 33 44 14 +35 25 47 91 7 +99 6 56 82 10 +41 93 70 5 85 +81 97 58 96 29 + +24 53 4 8 23 + 0 13 48 47 83 +55 56 72 50 52 +82 33 58 16 11 +91 7 89 9 81 + +86 70 16 4 34 +49 69 37 78 11 +22 47 59 20 38 +33 82 60 63 56 +18 74 36 7 99 + +64 45 72 86 7 +34 50 94 0 85 +15 69 2 26 32 +62 96 41 17 78 +63 5 99 79 47 + +62 63 24 37 50 +89 80 40 41 13 +32 64 95 93 66 +45 3 23 78 48 +60 26 31 61 99 + + 6 63 66 67 15 +33 43 62 95 89 +72 61 60 2 10 +29 7 9 50 18 +28 36 3 53 30 + +91 4 57 74 66 +49 36 54 7 89 +33 65 59 14 92 +63 42 0 20 11 +64 32 96 18 58 + +85 59 33 18 99 +90 4 1 51 35 + 2 57 9 5 78 +30 53 25 23 80 +74 76 20 19 21 + + 5 42 50 72 90 +58 63 49 17 31 +39 76 8 19 41 + 9 59 61 23 54 +91 57 18 70 69 + +90 6 36 71 78 +73 75 56 43 35 +92 31 21 47 86 +69 10 52 80 55 +68 30 22 45 34 + + 4 15 88 6 38 +46 37 34 23 91 +50 98 89 3 79 +90 93 60 56 20 +40 8 30 69 1 + +13 62 39 56 78 + 6 7 17 94 5 +44 77 76 81 20 +91 64 34 99 45 +63 37 3 2 66 + +57 19 63 59 8 +83 51 58 21 4 +54 61 56 9 95 +92 52 84 67 66 +80 34 1 97 69 + + 0 95 89 40 51 +58 90 97 85 61 +64 47 10 37 26 +19 63 7 71 81 +20 25 57 55 21 + +72 6 39 97 58 +50 63 2 46 86 +73 12 59 37 66 +93 77 47 34 67 + 5 4 98 51 48 + +96 5 17 68 73 +55 13 88 3 52 +95 62 18 83 63 +31 15 99 20 93 +29 50 0 74 22 + +11 84 79 92 67 +36 23 76 14 80 +82 72 53 3 85 +46 71 89 25 40 +51 81 29 0 65 + +68 24 96 87 5 +53 10 95 89 81 +88 80 23 12 50 +65 16 45 29 62 +33 97 91 60 43 + +36 77 68 20 51 +93 71 28 70 97 +10 9 16 15 67 +42 78 62 34 38 +60 74 18 91 53 + +65 35 40 34 71 + 0 84 13 81 95 + 2 31 46 24 76 +67 28 83 63 25 +62 93 10 14 68 + +17 36 72 65 49 +29 9 22 42 58 +76 20 57 3 54 +13 37 88 62 24 +66 78 55 30 48 + +55 18 97 40 30 +76 69 22 86 98 +48 96 20 65 1 +77 45 91 82 25 +56 70 66 34 58 + +15 59 37 69 66 +51 16 25 0 79 +76 72 68 70 20 +95 33 82 27 52 +53 65 40 45 92 + +65 18 54 9 28 +47 11 84 89 71 +52 96 83 57 86 +55 0 56 72 20 +26 19 81 60 64 + +97 28 89 55 11 +33 92 50 86 79 +81 37 0 94 64 +44 76 68 58 26 +57 65 60 78 93 + +62 4 55 50 74 +86 46 89 20 68 + 1 52 78 73 19 +14 10 0 40 28 +69 35 26 22 7 + +29 15 9 27 8 +98 22 69 14 44 +75 24 66 63 90 +62 72 87 32 31 +26 59 85 82 77 + +90 42 40 10 48 +73 8 57 18 29 +67 76 5 72 93 +43 27 28 82 80 +62 41 36 61 21 + +25 64 69 6 65 +40 36 16 81 34 +63 38 80 55 29 +20 50 90 21 72 + 4 17 83 27 92 + +96 89 9 62 78 +18 47 82 80 73 +75 38 51 3 50 +48 19 99 54 6 + 4 28 63 98 43 + +37 68 13 30 23 +82 14 65 60 27 +43 74 62 46 99 +80 26 15 9 20 +58 44 92 76 64 + + 2 80 99 17 43 +37 48 65 52 40 +81 90 83 78 72 +77 21 56 66 68 +92 22 10 61 49 + +72 27 88 7 57 +51 73 31 55 23 +39 48 12 91 2 +92 42 71 93 4 +26 38 36 22 75 + +37 2 9 10 52 +33 45 11 67 25 +31 6 5 79 14 +70 39 99 8 81 +65 87 83 68 77 + +54 89 78 49 63 +39 33 27 98 28 +79 61 20 2 25 +92 12 13 29 30 +51 77 94 38 46 + +28 87 30 75 9 +48 8 23 60 89 +79 2 21 18 6 +25 69 24 15 71 +44 36 59 31 68 + +16 0 69 19 9 +68 15 90 8 87 +75 21 12 97 39 + 5 83 55 23 72 +43 60 58 13 76 + +53 29 98 73 13 +58 30 10 68 21 +32 81 66 6 82 +97 45 15 7 92 +19 75 90 36 67 + +66 14 39 62 89 +94 42 20 46 48 + 0 7 92 4 86 + 3 84 60 37 55 +27 64 1 30 82 + +78 82 57 44 47 +86 11 62 52 99 + 7 70 17 60 15 +45 19 4 91 75 + 3 6 24 94 81 + +38 2 59 51 17 +76 64 19 78 7 +55 42 39 47 56 +79 65 37 57 40 +53 66 73 83 68 + +38 49 65 79 82 +15 63 53 32 21 +48 1 3 81 69 +94 87 20 6 59 + 8 50 96 71 76 + +17 28 41 24 69 +20 96 9 57 85 +70 15 53 38 52 +79 84 37 73 64 +40 30 25 56 1 + +68 11 49 37 46 +24 63 72 35 29 +92 62 89 73 28 +64 58 9 3 39 +13 45 10 19 20 + +54 41 49 33 60 +85 56 0 77 51 +81 12 13 20 27 +36 24 69 39 80 +14 83 57 50 91 + +19 68 61 56 11 + 3 74 6 25 22 +71 10 21 7 29 +92 12 51 84 30 +41 72 85 36 91 + +16 86 37 88 22 +48 18 4 89 55 +58 83 44 7 43 +28 76 15 11 35 +81 52 29 23 64 + +52 42 98 0 31 +92 47 41 87 33 + 6 35 69 44 17 +91 50 89 75 3 +57 61 81 60 21 + +40 86 78 2 58 +76 73 31 19 14 +50 21 53 83 45 +68 9 22 70 69 +54 1 85 90 44 + +13 20 96 89 22 +85 62 19 99 66 +18 46 28 14 39 +12 21 34 1 81 +40 77 25 4 7 + +21 76 60 10 9 +34 29 59 48 40 +30 2 36 82 66 +12 95 80 72 58 +74 3 46 37 49 + + 6 30 25 12 22 +33 65 4 89 59 +86 94 70 49 16 +11 76 66 84 45 +50 31 46 73 36 + +89 4 99 23 84 +72 90 83 44 20 +33 66 91 35 26 +81 85 24 10 55 +45 43 7 78 53 + +55 62 19 44 63 +12 90 77 28 7 +80 92 15 41 11 +58 24 47 66 82 +48 88 37 60 46 + +48 16 86 94 14 +22 43 46 67 1 +91 88 49 79 28 +19 12 35 85 42 +13 26 68 95 97 + +23 67 33 85 82 +21 71 84 8 58 +20 41 53 22 99 +92 89 59 16 19 +79 93 39 83 80 + +98 96 24 47 15 +79 97 19 64 84 +62 91 38 30 65 +74 25 92 16 50 +51 41 34 18 35 + +55 9 27 95 90 +31 11 50 84 71 +37 61 62 60 88 +24 94 29 42 77 +17 83 47 74 91 + +74 19 3 13 29 +48 17 26 42 22 + 9 25 8 55 38 +33 52 90 84 39 +82 50 60 41 35 + +33 7 28 66 21 +98 32 41 81 19 +46 34 10 50 47 +20 68 2 93 25 + 5 85 69 53 39 + +91 83 59 37 8 +51 39 81 48 19 +55 86 73 54 20 + 5 7 18 1 36 +44 75 43 76 23 + + 6 38 71 57 77 +95 75 0 32 5 +64 41 51 91 30 +99 79 8 16 55 +88 97 53 47 85 + +58 23 14 93 59 +67 47 49 2 24 +75 92 31 52 29 +30 7 10 40 55 +20 19 35 72 84 + +75 6 67 76 13 +18 32 27 17 71 +60 4 48 53 84 + 8 23 33 91 68 +24 42 56 50 45 + +52 55 68 62 89 + 9 64 14 58 50 +46 8 94 12 24 +72 47 42 76 61 +97 40 25 7 31 + +13 83 14 29 58 +70 33 28 71 9 +16 90 45 30 99 +84 0 41 79 51 +60 55 35 31 57 + +93 21 42 67 20 +88 73 40 9 1 +92 58 15 83 57 +30 86 36 97 89 +38 22 72 37 24 + +37 38 78 93 50 +44 65 52 54 79 +73 27 6 35 91 + 8 26 63 7 12 +25 17 60 4 14 + + 0 30 70 99 23 + 2 75 51 10 87 +12 91 4 69 8 +81 62 26 72 33 +31 17 46 73 96 + +53 44 78 46 19 +40 85 77 98 50 +71 30 68 0 73 +31 43 83 92 6 +52 45 11 37 1 + +91 67 8 35 36 +23 52 51 83 70 +92 32 27 72 16 +63 54 75 38 97 +45 96 11 13 79 + + 2 62 8 53 3 +63 94 81 61 25 +10 91 9 87 84 +85 59 80 54 0 +43 77 21 89 75 + +12 34 29 68 14 +77 81 67 15 9 +17 85 26 30 86 +33 10 31 23 69 +59 42 24 88 89 + +14 80 84 22 23 +85 93 83 91 6 +57 27 51 95 46 +67 1 24 76 86 +55 19 94 8 61 + +87 42 82 81 98 +43 8 51 92 60 +17 14 96 36 34 + 2 19 70 15 78 +93 35 74 53 3 + +53 34 22 41 59 +58 18 30 71 37 +60 8 74 1 5 +96 52 87 17 85 +57 31 24 72 32 + +58 51 98 28 29 +81 76 49 24 60 + 3 33 22 57 86 + 1 67 46 20 56 + 5 16 2 8 6 + +67 51 43 89 94 + 4 96 50 9 8 +22 87 77 38 35 +39 37 17 59 32 + 5 25 26 83 81 + +15 12 6 27 76 +80 70 87 36 55 +69 35 91 98 18 +89 59 92 5 29 +84 10 86 63 39 + + 3 94 38 93 28 +88 57 42 97 14 +89 36 35 85 9 + 5 29 51 31 69 +46 10 25 0 15 + +87 46 49 60 22 +30 64 93 20 66 +95 86 71 21 11 + 0 58 53 18 97 +62 63 3 1 96 + +56 86 71 30 36 +19 27 16 94 53 +46 81 25 44 55 +75 7 97 76 96 +93 79 22 78 50 + +30 14 68 16 59 +23 60 77 37 4 +22 43 53 34 81 + 7 54 38 39 96 +25 86 64 46 44 + + 2 72 69 90 58 +50 77 16 0 14 +75 1 92 66 29 +71 59 54 67 4 + 3 53 49 9 46 + +21 22 25 42 7 + 4 95 82 91 27 +29 33 30 64 61 +74 80 26 83 70 +31 88 93 52 96 + +51 45 43 70 87 +48 77 27 53 19 +41 83 17 99 49 +94 59 95 58 55 +75 86 44 91 82 + +64 88 91 68 19 +57 60 80 46 98 +20 4 38 32 69 + 8 9 22 70 39 +85 28 97 2 71 + +65 42 46 75 48 +26 66 97 16 74 +51 67 94 89 4 +61 9 54 22 2 +82 8 83 5 90 + +18 51 61 57 11 +41 79 30 78 69 +75 14 81 40 88 +93 76 25 64 47 +24 34 94 46 89 + +74 8 3 64 59 +67 49 26 32 83 +85 0 5 71 90 +16 27 81 98 56 +79 23 76 20 43 + +37 6 24 16 69 +41 82 51 4 35 +79 94 99 42 12 +30 81 60 3 36 + 8 22 11 32 48 + +68 9 1 47 21 +61 55 5 19 73 +29 0 48 4 31 +63 50 93 15 72 +39 98 57 70 65 + +34 55 82 26 10 +62 85 68 69 36 + 5 46 54 50 17 +86 95 72 49 29 +76 91 43 37 97 + +41 76 5 33 59 +81 51 99 86 34 + 0 39 64 27 83 +40 69 37 91 45 +55 49 54 9 61 + +92 34 81 10 80 +64 85 69 28 66 +89 93 22 45 7 + 8 35 90 16 87 + 4 78 44 13 67 + +30 21 24 26 40 +59 17 4 47 73 +10 31 88 12 29 +56 98 69 2 7 +13 58 91 55 36 + +25 28 69 4 19 +45 62 32 16 98 +20 88 6 97 18 +91 71 10 80 31 + 1 66 89 12 21 + +85 34 16 30 71 +47 15 46 24 61 +79 69 23 38 96 + 0 14 80 97 86 +48 92 22 26 98 + +96 94 98 27 56 +64 83 46 30 5 + 3 43 70 67 21 +62 0 92 1 65 +36 26 35 61 76 diff --git a/aoc2021/input/day04_provided.txt b/aoc2021/input/day04_provided.txt new file mode 100644 index 0000000..669a51d --- /dev/null +++ b/aoc2021/input/day04_provided.txt @@ -0,0 +1,19 @@ +7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 + +22 13 17 11 0 + 8 2 23 4 24 +21 9 14 16 7 + 6 10 3 18 5 + 1 12 20 15 19 + + 3 15 0 2 22 + 9 18 13 17 5 +19 8 7 25 23 +20 11 10 24 4 +14 21 16 12 6 + +14 21 17 24 4 +10 16 15 9 19 +18 8 23 26 20 +22 11 13 6 5 + 2 0 12 3 7 diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs new file mode 100644 index 0000000..20aacf2 --- /dev/null +++ b/aoc2021/src/day04.rs @@ -0,0 +1,150 @@ +use std::collections::HashMap; +use std::fmt::Write; + +use anyhow::{anyhow, Context, Result}; + +const INPUT: &str = include_str!("../input/day04.txt"); + +const GRID_WIDTH: usize = 5; +const GRID_HEIGHT: usize = 5; +const GRID_SIZE: usize = GRID_WIDTH * GRID_HEIGHT; + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let (draws, grids) = input + .split_once("\n\n") + .context("couldn't split draws from grids")?; + + let draws = draws + .split(',') + .map(|num| num.parse::().context("couldn't parse drawn number:")) + .collect::>>()?; + let mut grids = grids + .split("\n\n") + .map(str::parse::) + .collect::>>()?; + + let (mut wdraw, mut wgrid) = (None, None); + + 'draw_loop: for draw in draws { + for grid in &mut grids { + if grid.mark(draw) && grid.is_winning() { + wgrid = Some(grid.clone()); + wdraw = Some(draw); + break 'draw_loop; + } + } + } + + match (wdraw, wgrid) { + (Some(draw), Some(grid)) => { + Ok(draw as u64 * grid.unmarked_numbers().map(|n| *n as u64).sum::()) + } + _ => Err(anyhow!("couldn't find a winning grid!")), + } +} + +#[derive(Debug, Clone)] +struct Grid { + number_to_pos: HashMap, + pos_to_number: HashMap<(usize, usize), u8>, + grid: [bool; GRID_SIZE], +} + +impl Grid { + fn mark(&mut self, draw: u8) -> bool { + match self.number_to_pos.get(&draw) { + Some(&(x, y)) => { + *self.access_grid_mut(x, y) = true; + true + } + None => false, + } + } + + fn is_winning(&self) -> bool { + let mut rows = [0u8; GRID_HEIGHT]; + let mut cols = [0u8; GRID_WIDTH]; + + for (y, row) in rows.iter_mut().enumerate() { + for (x, col) in cols.iter_mut().enumerate() { + if self.access_grid(x, y) { + *row += 1; + *col += 1; + + if *row as usize == GRID_WIDTH || *col as usize == GRID_HEIGHT { + return true; + } + } + } + } + + false + } + + fn unmarked_numbers(&self) -> impl Iterator { + self.number_to_pos + .iter() + .filter_map(|(num, &(x, y))| (!self.access_grid(x, y)).then(|| num)) + } + + fn access_grid(&self, x: usize, y: usize) -> bool { + self.grid[y * GRID_HEIGHT + x] + } + + fn access_grid_mut(&mut self, x: usize, y: usize) -> &mut bool { + &mut self.grid[y * GRID_HEIGHT + x] + } +} + +impl std::str::FromStr for Grid { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut numbers = s.split_whitespace().map(str::parse); + let mut number_to_pos = HashMap::new(); + let mut pos_to_number = HashMap::new(); + + for y in 0..GRID_HEIGHT { + for x in 0..GRID_WIDTH { + let pos = (x, y); + let number: u8 = numbers + .next() + .context("not enough numbers for grid")? + .context("couldn't parse number:")?; + number_to_pos.insert(number, pos); + pos_to_number.insert(pos, number); + } + } + + Ok(Grid { + number_to_pos, + pos_to_number, + grid: [false; GRID_SIZE], + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day04_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 4512); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 45031); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index eef213c..93675e3 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -3,3 +3,4 @@ pub mod day01; pub mod day02; pub mod day03; +pub mod day04; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 2315917..e9fe9e3 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -5,9 +5,10 @@ use aoc::DayFunc; use aoc2021::day01; use aoc2021::day02; use aoc2021::day03; +use aoc2021::day04; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run]; aoc::run(days) } From fac1c77bf279b6129f5aee7f2944ae4868f9bffa Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 14:52:26 +0100 Subject: [PATCH 028/134] 2021: day04: part 2 --- aoc2021/src/day04.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs index 20aacf2..c082fdf 100644 --- a/aoc2021/src/day04.rs +++ b/aoc2021/src/day04.rs @@ -13,6 +13,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -51,6 +52,50 @@ fn part1(input: &str) -> Result { } } +fn part2(input: &str) -> Result { + let (draws, grids) = input + .split_once("\n\n") + .context("couldn't split draws from grids")?; + + let draws = draws + .split(',') + .map(|num| num.parse::().context("couldn't parse drawn number:")) + .collect::>>()?; + let mut grids = grids + .split("\n\n") + .map(str::parse::) + .collect::>>()?; + + let mut draws = draws.into_iter(); + + while grids.len() > 1 { + let draw = draws + .next() + .context("no draws available, didn't find last grid")?; + + // TODO: replace with drain_filter when stabilized + let mut i = 0; + while i < grids.len() { + let grid = &mut grids[i]; + if grid.mark(draw) && grid.is_winning() { + grids.remove(i); + } else { + i += 1; + } + } + } + + let last_grid = &mut grids[0]; + + for draw in draws { + if last_grid.mark(draw) && last_grid.is_winning() { + return Ok(draw as u64 * last_grid.unmarked_numbers().map(|n| *n as u64).sum::()); + } + } + + Err(anyhow!("last grid never wins, this is not expected")) +} + #[derive(Debug, Clone)] struct Grid { number_to_pos: HashMap, @@ -147,4 +192,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 45031); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 1924); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2568); + } } From 49e957cff5b73aeed06e562e5be641a3ad725e3c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 14:55:56 +0100 Subject: [PATCH 029/134] 2021: day04: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index f4475d2..d781aac 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -3,11 +3,13 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2021::day01; use aoc2021::day02; use aoc2021::day03; +use aoc2021::day04; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); + c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); } criterion_group! { From 45c3426537bdebdd25025d521a3f274f5e8c298a Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 15:17:54 +0100 Subject: [PATCH 030/134] 2021: day04: do win check when marking number --- aoc2021/src/day04.rs | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs index c082fdf..1f5a4a6 100644 --- a/aoc2021/src/day04.rs +++ b/aoc2021/src/day04.rs @@ -36,7 +36,7 @@ fn part1(input: &str) -> Result { 'draw_loop: for draw in draws { for grid in &mut grids { - if grid.mark(draw) && grid.is_winning() { + if grid.mark(draw) { wgrid = Some(grid.clone()); wdraw = Some(draw); break 'draw_loop; @@ -77,7 +77,7 @@ fn part2(input: &str) -> Result { let mut i = 0; while i < grids.len() { let grid = &mut grids[i]; - if grid.mark(draw) && grid.is_winning() { + if grid.mark(draw) { grids.remove(i); } else { i += 1; @@ -88,7 +88,7 @@ fn part2(input: &str) -> Result { let last_grid = &mut grids[0]; for draw in draws { - if last_grid.mark(draw) && last_grid.is_winning() { + if last_grid.mark(draw) { return Ok(draw as u64 * last_grid.unmarked_numbers().map(|n| *n as u64).sum::()); } } @@ -101,6 +101,8 @@ struct Grid { number_to_pos: HashMap, pos_to_number: HashMap<(usize, usize), u8>, grid: [bool; GRID_SIZE], + rows: [u8; GRID_HEIGHT], + cols: [u8; GRID_WIDTH], } impl Grid { @@ -108,32 +110,16 @@ impl Grid { match self.number_to_pos.get(&draw) { Some(&(x, y)) => { *self.access_grid_mut(x, y) = true; - true + + self.rows[y] += 1; + self.cols[x] += 1; + + self.rows[y] as usize == GRID_WIDTH || self.cols[x] as usize == GRID_HEIGHT } None => false, } } - fn is_winning(&self) -> bool { - let mut rows = [0u8; GRID_HEIGHT]; - let mut cols = [0u8; GRID_WIDTH]; - - for (y, row) in rows.iter_mut().enumerate() { - for (x, col) in cols.iter_mut().enumerate() { - if self.access_grid(x, y) { - *row += 1; - *col += 1; - - if *row as usize == GRID_WIDTH || *col as usize == GRID_HEIGHT { - return true; - } - } - } - } - - false - } - fn unmarked_numbers(&self) -> impl Iterator { self.number_to_pos .iter() @@ -173,6 +159,8 @@ impl std::str::FromStr for Grid { number_to_pos, pos_to_number, grid: [false; GRID_SIZE], + rows: [0; GRID_HEIGHT], + cols: [0; GRID_WIDTH], }) } } From 6dccc14046f8f442f563e2be28b93588aacd102f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 15:18:38 +0100 Subject: [PATCH 031/134] 2021: day04: better Iterator return type --- aoc2021/src/day04.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs index 1f5a4a6..2b0394e 100644 --- a/aoc2021/src/day04.rs +++ b/aoc2021/src/day04.rs @@ -46,7 +46,7 @@ fn part1(input: &str) -> Result { match (wdraw, wgrid) { (Some(draw), Some(grid)) => { - Ok(draw as u64 * grid.unmarked_numbers().map(|n| *n as u64).sum::()) + Ok(draw as u64 * grid.unmarked_numbers().map(|n| n as u64).sum::()) } _ => Err(anyhow!("couldn't find a winning grid!")), } @@ -89,7 +89,7 @@ fn part2(input: &str) -> Result { for draw in draws { if last_grid.mark(draw) { - return Ok(draw as u64 * last_grid.unmarked_numbers().map(|n| *n as u64).sum::()); + return Ok(draw as u64 * last_grid.unmarked_numbers().map(|n| n as u64).sum::()); } } @@ -120,10 +120,10 @@ impl Grid { } } - fn unmarked_numbers(&self) -> impl Iterator { + fn unmarked_numbers(&self) -> impl Iterator + '_ { self.number_to_pos .iter() - .filter_map(|(num, &(x, y))| (!self.access_grid(x, y)).then(|| num)) + .filter_map(|(num, &(x, y))| (!self.access_grid(x, y)).then(|| *num)) } fn access_grid(&self, x: usize, y: usize) -> bool { From 9209659a5a16ba8faab250c42be8e59c71e005fb Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 15:22:35 +0100 Subject: [PATCH 032/134] 2021: day04: remove useless Grid field --- aoc2021/src/day04.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs index 2b0394e..2a39388 100644 --- a/aoc2021/src/day04.rs +++ b/aoc2021/src/day04.rs @@ -99,7 +99,6 @@ fn part2(input: &str) -> Result { #[derive(Debug, Clone)] struct Grid { number_to_pos: HashMap, - pos_to_number: HashMap<(usize, usize), u8>, grid: [bool; GRID_SIZE], rows: [u8; GRID_HEIGHT], cols: [u8; GRID_WIDTH], @@ -141,7 +140,6 @@ impl std::str::FromStr for Grid { fn from_str(s: &str) -> Result { let mut numbers = s.split_whitespace().map(str::parse); let mut number_to_pos = HashMap::new(); - let mut pos_to_number = HashMap::new(); for y in 0..GRID_HEIGHT { for x in 0..GRID_WIDTH { @@ -151,13 +149,11 @@ impl std::str::FromStr for Grid { .context("not enough numbers for grid")? .context("couldn't parse number:")?; number_to_pos.insert(number, pos); - pos_to_number.insert(pos, number); } } Ok(Grid { number_to_pos, - pos_to_number, grid: [false; GRID_SIZE], rows: [0; GRID_HEIGHT], cols: [0; GRID_WIDTH], From 66fa27de0bc548ecb0b3b8febe50ab1ae923cffa Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 15:38:33 +0100 Subject: [PATCH 033/134] 2021: day04: use Vec::retain --- aoc2021/src/day04.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs index 2a39388..15a1250 100644 --- a/aoc2021/src/day04.rs +++ b/aoc2021/src/day04.rs @@ -36,7 +36,8 @@ fn part1(input: &str) -> Result { 'draw_loop: for draw in draws { for grid in &mut grids { - if grid.mark(draw) { + grid.mark(draw); + if grid.is_winning() { wgrid = Some(grid.clone()); wdraw = Some(draw); break 'draw_loop; @@ -74,21 +75,15 @@ fn part2(input: &str) -> Result { .context("no draws available, didn't find last grid")?; // TODO: replace with drain_filter when stabilized - let mut i = 0; - while i < grids.len() { - let grid = &mut grids[i]; - if grid.mark(draw) { - grids.remove(i); - } else { - i += 1; - } - } + grids.iter_mut().for_each(|grid| grid.mark(draw)); + grids.retain(|grid| !grid.is_winning()); } let last_grid = &mut grids[0]; for draw in draws { - if last_grid.mark(draw) { + last_grid.mark(draw); + if last_grid.is_winning() { return Ok(draw as u64 * last_grid.unmarked_numbers().map(|n| n as u64).sum::()); } } @@ -102,23 +97,26 @@ struct Grid { grid: [bool; GRID_SIZE], rows: [u8; GRID_HEIGHT], cols: [u8; GRID_WIDTH], + winning: bool, } impl Grid { - fn mark(&mut self, draw: u8) -> bool { - match self.number_to_pos.get(&draw) { - Some(&(x, y)) => { - *self.access_grid_mut(x, y) = true; + fn mark(&mut self, draw: u8) { + if let Some(&(x, y)) = self.number_to_pos.get(&draw) { + *self.access_grid_mut(x, y) = true; - self.rows[y] += 1; - self.cols[x] += 1; + self.rows[y] += 1; + self.cols[x] += 1; - self.rows[y] as usize == GRID_WIDTH || self.cols[x] as usize == GRID_HEIGHT - } - None => false, + self.winning = + self.rows[y] as usize == GRID_WIDTH || self.cols[x] as usize == GRID_HEIGHT; } } + fn is_winning(&self) -> bool { + self.winning + } + fn unmarked_numbers(&self) -> impl Iterator + '_ { self.number_to_pos .iter() @@ -157,6 +155,7 @@ impl std::str::FromStr for Grid { grid: [false; GRID_SIZE], rows: [0; GRID_HEIGHT], cols: [0; GRID_WIDTH], + winning: false, }) } } From a5adc0185e6cbd8e1de997615104de027f8a4644 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 15:45:57 +0100 Subject: [PATCH 034/134] 2021: day03: use Vec::retain ~30% improvement in benchmark! --- aoc2021/src/day03.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index fababff..919e327 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -93,15 +93,7 @@ where let one_is_more_common = count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2); let digit_of_interest = strat(one_is_more_common); - // TODO: use drain_filter when stable - let mut i = 0; - while i < numbers.len() { - if numbers[i].chars().nth(pos).unwrap() != digit_of_interest { - numbers.remove(i); - } else { - i += 1; - } - } + numbers.retain(|number| number.chars().nth(pos).unwrap() == digit_of_interest); } debug_assert_eq!(numbers.len(), 1); From 691b4041694109b71d1170ccec47e5a721e76be0 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 16:41:00 +0100 Subject: [PATCH 035/134] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file changes: • Updated input 'rust-overlay': 'github:oxalica/rust-overlay/aaf6f89ca6a5d22ed822d93835ce438ee338936c' (2021-11-25) → 'github:oxalica/rust-overlay/4a918c124e43188e8a1d2492a731befe47effa71' (2021-12-04) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index ce50311..7f2e0b6 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1637806606, - "narHash": "sha256-SVecJKEyKAt/+QGTq5mwXpIgdTJwjzYNmqBoUzSkQes=", + "lastModified": 1638584238, + "narHash": "sha256-s9ABdhsYMTz0Qp1EoORN1O8PlJ68390iGv0+KUwaktg=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "aaf6f89ca6a5d22ed822d93835ce438ee338936c", + "rev": "4a918c124e43188e8a1d2492a731befe47effa71", "type": "github" }, "original": { From 239247a8c63e798b2b05e5e0d928eb162f046328 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 16:51:49 +0100 Subject: [PATCH 036/134] 2018: day04: fix new unused warnings --- aoc2018/src/day04.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aoc2018/src/day04.rs b/aoc2018/src/day04.rs index cab4b8a..dc69c45 100644 --- a/aoc2018/src/day04.rs +++ b/aoc2018/src/day04.rs @@ -49,9 +49,9 @@ impl FromStr for Event { #[derive(Debug)] struct Date { - year: u32, - month: u8, - day: u8, + _year: u32, + _month: u8, + _day: u8, hour: u8, minute: u8, @@ -84,9 +84,9 @@ impl FromStr for Date { let minute = s[..r_bracket].parse()?; Ok(Date { - year, - month, - day, + _year: year, + _month: month, + _day: day, hour, minute, }) From d7a77e9283a95dc431ca18f08d2ebff15591b1ba Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 16:55:40 +0100 Subject: [PATCH 037/134] fix various clippy lints from 1.57 --- aoc2015/src/day02.rs | 4 ++-- aoc2019/src/day08.rs | 4 ++-- aoc2020/src/day20.rs | 11 +---------- aoc2020/src/day24.rs | 8 +------- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/aoc2015/src/day02.rs b/aoc2015/src/day02.rs index 79aa3ec..874a109 100644 --- a/aoc2015/src/day02.rs +++ b/aoc2015/src/day02.rs @@ -29,7 +29,7 @@ fn wrapping_paper(present: &Present) -> u64 { } fn part1(presents: &[Present]) -> u64 { - presents.iter().map(|p| wrapping_paper(p)).sum() + presents.iter().map(wrapping_paper).sum() } fn ribbon_bow_length(present: &Present) -> u64 { @@ -49,7 +49,7 @@ fn ribbon_needed(present: &Present) -> u64 { } fn part2(presents: &[Present]) -> u64 { - presents.iter().map(|p| ribbon_needed(p)).sum() + presents.iter().map(ribbon_needed).sum() } struct Present { diff --git a/aoc2019/src/day08.rs b/aoc2019/src/day08.rs index 1d6d6d2..8c493d3 100644 --- a/aoc2019/src/day08.rs +++ b/aoc2019/src/day08.rs @@ -84,12 +84,12 @@ impl FromStr for Image { let lines = digits .chunks(IMG_WIDTH) - .map(|chunk| chunk.to_vec()) + .map(<[_]>::to_vec) .collect::>>(); let layers = lines .chunks(IMG_HEIGHT) - .map(|chunk| chunk.to_vec()) + .map(<[_]>::to_vec) .map(|pixels| Layer { pixels }) .collect::>(); diff --git a/aoc2020/src/day20.rs b/aoc2020/src/day20.rs index 39fbf5f..5961c59 100644 --- a/aoc2020/src/day20.rs +++ b/aoc2020/src/day20.rs @@ -59,7 +59,7 @@ enum Rotation { /// /// Note: we don't need a horizontal and a vertical flip, these result in the same output as a 180 /// degree rotation when combined, so only one is necessary -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Default, Clone, Copy)] struct Transform { flip: bool, rotation: Option, @@ -121,15 +121,6 @@ impl Transform { } } -impl Default for Transform { - fn default() -> Self { - Self { - flip: false, - rotation: None, - } - } -} - #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] enum Position { Down, diff --git a/aoc2020/src/day24.rs b/aoc2020/src/day24.rs index 9992e86..ab6cb28 100644 --- a/aoc2020/src/day24.rs +++ b/aoc2020/src/day24.rs @@ -133,7 +133,7 @@ fn part2(input: &str) -> Result { /// These use the axial coordinates described here: /// /// https://www.redblobgames.com/grids/hexagons/#coordinates-axial -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] struct HexCoordinates { q: i64, r: i64, @@ -188,12 +188,6 @@ impl HexCoordinates { } } -impl Default for HexCoordinates { - fn default() -> Self { - Self { q: 0, r: 0 } - } -} - #[cfg(test)] mod tests { use super::*; From 9c29742b99a7875ce576acf68de267976cb2ff93 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 4 Dec 2021 17:54:29 +0100 Subject: [PATCH 038/134] env: don't version .envrc, switch to nix-direnv --- .envrc | 1 - .gitignore | 2 ++ shell.nix | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 .envrc delete mode 100644 shell.nix diff --git a/.envrc b/.envrc deleted file mode 100644 index 051d09d..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -eval "$(lorri direnv)" diff --git a/.gitignore b/.gitignore index 2f7896d..16a95ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ target/ +/.direnv/ +/.envrc diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 9730ebd..0000000 --- a/shell.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ system ? builtins.currentSystem }: - -(builtins.getFlake (toString ./.)).devShell.${system} From 44afc3bbddadbec7b52eff4f4a52115c4940ac83 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sun, 5 Dec 2021 16:12:37 +0100 Subject: [PATCH 039/134] 2021: day05: part 1 --- aoc2021/input/day05.txt | 500 +++++++++++++++++++++++++++++++ aoc2021/input/day05_provided.txt | 10 + aoc2021/src/day05.rs | 108 +++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 3 +- 5 files changed, 621 insertions(+), 1 deletion(-) create mode 100644 aoc2021/input/day05.txt create mode 100644 aoc2021/input/day05_provided.txt create mode 100644 aoc2021/src/day05.rs diff --git a/aoc2021/input/day05.txt b/aoc2021/input/day05.txt new file mode 100644 index 0000000..afd5d6f --- /dev/null +++ b/aoc2021/input/day05.txt @@ -0,0 +1,500 @@ +964,133 -> 596,133 +920,215 -> 920,976 +123,528 -> 123,661 +613,13 -> 407,13 +373,876 -> 424,876 +616,326 -> 120,326 +486,335 -> 539,388 +104,947 -> 54,947 +319,241 -> 282,204 +453,175 -> 453,438 +485,187 -> 915,617 +863,605 -> 603,605 +870,524 -> 342,524 +967,395 -> 634,62 +405,181 -> 807,181 +961,363 -> 419,905 +89,586 -> 214,461 +545,481 -> 731,295 +407,678 -> 626,678 +421,642 -> 91,312 +11,22 -> 935,946 +770,208 -> 76,902 +668,858 -> 668,890 +568,451 -> 574,451 +233,56 -> 371,56 +233,932 -> 44,932 +404,81 -> 796,81 +520,77 -> 403,194 +296,736 -> 447,887 +210,909 -> 16,909 +692,483 -> 877,668 +777,289 -> 744,289 +22,760 -> 652,130 +96,360 -> 626,360 +101,267 -> 101,783 +47,667 -> 660,667 +805,682 -> 563,440 +112,15 -> 463,366 +406,808 -> 430,808 +793,767 -> 107,81 +560,534 -> 958,534 +722,429 -> 722,459 +646,889 -> 646,195 +433,942 -> 449,958 +716,503 -> 716,99 +266,450 -> 266,780 +316,81 -> 565,81 +760,452 -> 687,452 +976,983 -> 15,22 +499,564 -> 499,909 +839,913 -> 38,112 +707,333 -> 438,333 +47,644 -> 352,644 +807,309 -> 807,706 +434,686 -> 812,308 +559,572 -> 63,76 +493,352 -> 581,352 +94,88 -> 928,88 +898,738 -> 106,738 +201,10 -> 564,10 +976,914 -> 976,472 +836,153 -> 585,153 +178,43 -> 17,204 +784,967 -> 738,967 +370,359 -> 449,359 +13,526 -> 637,526 +399,158 -> 10,158 +572,293 -> 289,293 +627,674 -> 895,674 +921,402 -> 984,402 +907,667 -> 944,704 +574,877 -> 882,569 +977,977 -> 121,121 +550,584 -> 862,584 +396,556 -> 396,289 +391,33 -> 532,174 +12,988 -> 989,11 +48,787 -> 48,637 +476,638 -> 113,638 +985,985 -> 13,13 +838,784 -> 198,784 +567,195 -> 677,305 +174,251 -> 577,654 +296,801 -> 53,558 +983,899 -> 983,380 +507,230 -> 507,929 +264,516 -> 668,920 +865,952 -> 865,768 +522,290 -> 744,512 +936,958 -> 936,115 +527,871 -> 527,519 +944,972 -> 21,49 +880,380 -> 695,565 +471,374 -> 446,349 +503,597 -> 127,221 +471,514 -> 30,73 +890,232 -> 890,511 +14,461 -> 14,853 +167,676 -> 148,676 +987,230 -> 754,230 +797,725 -> 797,847 +347,21 -> 84,21 +839,274 -> 964,274 +607,456 -> 894,456 +335,949 -> 301,949 +167,236 -> 820,889 +87,558 -> 87,917 +318,788 -> 622,484 +699,583 -> 699,321 +971,967 -> 35,31 +420,44 -> 420,36 +29,484 -> 458,484 +768,157 -> 768,30 +690,839 -> 317,839 +870,578 -> 560,578 +697,195 -> 70,822 +689,45 -> 689,223 +790,724 -> 341,724 +694,291 -> 694,507 +43,339 -> 43,987 +590,733 -> 590,179 +751,361 -> 945,361 +99,820 -> 450,469 +460,696 -> 942,696 +783,940 -> 487,644 +630,537 -> 48,537 +643,856 -> 643,396 +558,733 -> 257,432 +16,972 -> 570,418 +636,188 -> 636,610 +868,138 -> 868,407 +85,424 -> 85,919 +710,932 -> 354,576 +356,505 -> 783,505 +606,876 -> 606,62 +577,431 -> 749,431 +108,262 -> 108,145 +615,455 -> 264,104 +205,754 -> 866,754 +189,182 -> 855,848 +10,43 -> 925,958 +293,773 -> 293,534 +746,313 -> 802,369 +607,174 -> 211,570 +860,840 -> 260,240 +879,78 -> 595,78 +11,143 -> 449,143 +190,983 -> 267,983 +912,92 -> 76,928 +744,364 -> 744,258 +436,417 -> 46,807 +629,592 -> 517,592 +113,893 -> 113,959 +714,213 -> 786,285 +868,165 -> 868,731 +349,69 -> 491,69 +278,430 -> 111,263 +593,849 -> 593,203 +156,860 -> 876,860 +169,615 -> 169,984 +983,93 -> 139,937 +94,548 -> 18,548 +623,72 -> 106,589 +530,334 -> 473,334 +384,746 -> 925,205 +711,74 -> 28,757 +850,728 -> 629,949 +378,801 -> 228,651 +347,968 -> 201,822 +82,578 -> 82,555 +149,405 -> 707,963 +254,169 -> 793,169 +443,454 -> 331,454 +460,659 -> 608,807 +838,807 -> 31,807 +561,952 -> 290,952 +755,626 -> 204,75 +550,424 -> 550,81 +772,115 -> 772,600 +40,517 -> 40,232 +277,841 -> 317,841 +899,150 -> 128,921 +735,332 -> 465,332 +839,254 -> 915,330 +959,616 -> 182,616 +729,723 -> 487,965 +64,838 -> 953,838 +689,830 -> 689,982 +191,83 -> 191,879 +522,833 -> 942,833 +877,785 -> 877,346 +255,95 -> 556,95 +782,491 -> 475,798 +268,815 -> 812,271 +119,181 -> 905,181 +445,457 -> 742,160 +973,30 -> 27,976 +356,681 -> 356,289 +882,279 -> 914,279 +672,162 -> 672,153 +180,729 -> 357,729 +985,716 -> 985,313 +191,618 -> 191,963 +949,749 -> 636,749 +289,902 -> 142,902 +923,615 -> 123,615 +710,929 -> 541,760 +211,402 -> 211,433 +515,178 -> 533,178 +525,869 -> 525,578 +201,569 -> 17,569 +629,848 -> 882,848 +152,512 -> 152,189 +914,723 -> 764,723 +218,231 -> 721,734 +438,382 -> 846,382 +582,475 -> 582,559 +529,943 -> 529,683 +330,312 -> 59,312 +242,900 -> 862,900 +271,220 -> 271,118 +182,459 -> 182,673 +513,265 -> 513,420 +918,942 -> 378,942 +277,765 -> 812,230 +625,874 -> 219,874 +737,533 -> 644,626 +647,975 -> 152,480 +638,284 -> 785,284 +549,680 -> 549,877 +886,278 -> 372,792 +130,560 -> 516,174 +186,741 -> 186,555 +208,536 -> 469,536 +674,906 -> 312,906 +934,156 -> 934,322 +568,412 -> 214,412 +243,19 -> 243,814 +861,230 -> 104,987 +683,891 -> 683,533 +545,740 -> 545,980 +343,320 -> 796,320 +821,220 -> 821,302 +578,741 -> 578,141 +633,405 -> 27,405 +645,975 -> 225,555 +25,527 -> 412,527 +378,817 -> 378,913 +352,741 -> 352,293 +48,986 -> 925,109 +506,231 -> 491,231 +854,883 -> 48,77 +261,221 -> 895,855 +902,240 -> 902,943 +145,338 -> 770,963 +832,216 -> 832,869 +480,385 -> 324,385 +644,202 -> 433,202 +202,176 -> 190,176 +668,693 -> 668,349 +95,230 -> 143,230 +873,144 -> 67,950 +232,509 -> 238,509 +963,43 -> 133,873 +527,631 -> 641,517 +363,61 -> 849,61 +72,326 -> 72,861 +542,801 -> 233,492 +247,48 -> 247,785 +972,563 -> 480,71 +362,870 -> 932,300 +263,811 -> 263,584 +556,157 -> 417,157 +946,900 -> 175,129 +790,542 -> 530,542 +777,195 -> 154,818 +71,764 -> 71,193 +197,13 -> 453,13 +664,714 -> 158,714 +257,819 -> 257,730 +796,927 -> 688,927 +124,53 -> 954,883 +30,16 -> 980,966 +84,151 -> 597,151 +840,776 -> 684,776 +548,460 -> 718,630 +291,635 -> 291,151 +948,43 -> 58,933 +373,483 -> 373,591 +309,81 -> 259,81 +692,808 -> 692,835 +737,112 -> 215,634 +808,595 -> 808,115 +160,912 -> 973,99 +494,191 -> 494,475 +713,925 -> 43,255 +736,580 -> 290,134 +257,679 -> 725,211 +464,81 -> 712,81 +35,147 -> 35,420 +372,159 -> 372,548 +508,228 -> 682,402 +120,491 -> 518,889 +139,948 -> 272,815 +398,523 -> 398,818 +935,50 -> 40,945 +415,959 -> 195,739 +250,868 -> 250,930 +77,60 -> 917,900 +584,389 -> 493,298 +362,163 -> 362,704 +670,740 -> 670,703 +689,297 -> 689,388 +988,572 -> 988,340 +238,248 -> 238,916 +748,753 -> 29,34 +184,565 -> 184,486 +812,217 -> 812,34 +60,140 -> 96,104 +826,673 -> 230,673 +221,221 -> 207,235 +449,483 -> 270,304 +805,810 -> 805,564 +952,52 -> 139,865 +428,967 -> 312,851 +854,673 -> 661,673 +985,209 -> 853,209 +523,365 -> 54,365 +492,171 -> 646,171 +908,853 -> 69,14 +38,698 -> 724,12 +400,479 -> 167,479 +948,313 -> 948,976 +280,145 -> 37,145 +206,858 -> 683,381 +203,413 -> 545,413 +726,173 -> 673,173 +30,954 -> 150,954 +319,592 -> 870,41 +808,91 -> 180,719 +845,612 -> 972,485 +160,430 -> 160,780 +19,339 -> 379,339 +476,550 -> 476,291 +341,785 -> 229,673 +371,476 -> 371,663 +509,836 -> 412,933 +980,20 -> 31,969 +822,526 -> 328,32 +859,314 -> 425,314 +963,961 -> 963,100 +984,978 -> 31,25 +659,251 -> 619,211 +649,477 -> 846,477 +32,259 -> 724,951 +468,753 -> 468,91 +690,301 -> 690,652 +436,912 -> 845,503 +32,123 -> 576,667 +142,79 -> 741,678 +610,228 -> 468,370 +172,667 -> 172,736 +961,700 -> 132,700 +804,875 -> 804,213 +71,970 -> 340,970 +171,52 -> 149,30 +754,604 -> 226,604 +485,941 -> 27,941 +126,383 -> 328,181 +41,39 -> 987,985 +128,62 -> 896,830 +414,278 -> 923,787 +712,15 -> 712,859 +794,35 -> 200,629 +516,147 -> 402,261 +526,862 -> 905,862 +721,407 -> 721,887 +728,920 -> 339,920 +117,417 -> 203,417 +291,561 -> 17,835 +171,359 -> 837,359 +93,125 -> 136,125 +220,226 -> 220,177 +75,434 -> 75,407 +235,664 -> 141,664 +553,490 -> 566,477 +487,651 -> 487,877 +699,150 -> 933,384 +73,556 -> 453,556 +363,371 -> 363,984 +905,106 -> 668,106 +139,271 -> 139,125 +466,379 -> 466,420 +12,935 -> 625,935 +89,892 -> 779,892 +119,701 -> 270,852 +354,886 -> 80,886 +917,376 -> 440,376 +23,182 -> 794,953 +451,718 -> 121,718 +62,251 -> 62,451 +642,74 -> 642,698 +425,200 -> 442,200 +828,175 -> 828,405 +751,743 -> 591,743 +569,681 -> 574,681 +329,187 -> 329,837 +302,592 -> 302,230 +359,135 -> 386,108 +44,234 -> 44,731 +836,305 -> 836,574 +170,512 -> 367,512 +576,699 -> 576,44 +398,185 -> 821,185 +733,78 -> 733,747 +141,183 -> 141,787 +65,360 -> 65,691 +828,780 -> 828,98 +776,744 -> 776,751 +881,74 -> 481,474 +438,642 -> 438,399 +676,972 -> 175,972 +60,318 -> 56,314 +312,169 -> 341,169 +736,472 -> 392,128 +225,281 -> 164,281 +407,799 -> 341,799 +458,826 -> 983,301 +12,988 -> 987,13 +23,854 -> 662,215 +82,863 -> 82,416 +542,708 -> 542,44 +659,51 -> 520,51 +353,246 -> 353,90 +985,976 -> 77,68 +628,493 -> 628,510 +51,48 -> 635,48 +97,814 -> 828,83 +14,44 -> 773,44 +603,178 -> 597,178 +11,220 -> 783,220 +613,39 -> 613,719 +68,303 -> 690,925 +121,974 -> 896,199 +343,54 -> 343,837 +744,303 -> 744,942 +678,370 -> 246,370 +937,134 -> 84,987 +357,333 -> 357,516 +848,212 -> 429,631 +909,244 -> 138,244 +122,794 -> 786,130 +274,611 -> 57,611 +66,337 -> 385,18 +847,356 -> 831,356 +740,480 -> 740,359 +194,443 -> 194,301 +50,564 -> 572,42 +86,587 -> 774,587 +708,258 -> 49,917 +420,530 -> 277,387 +509,580 -> 509,71 +237,196 -> 479,196 +442,287 -> 850,287 +830,393 -> 532,393 +274,720 -> 501,493 +610,565 -> 218,957 +380,393 -> 380,800 +237,847 -> 155,847 +267,791 -> 52,791 +275,772 -> 275,794 +239,238 -> 419,418 +200,785 -> 884,101 +185,980 -> 185,284 +47,46 -> 750,749 +724,661 -> 724,337 +630,349 -> 666,349 +21,911 -> 21,569 +661,562 -> 661,925 +41,898 -> 41,104 +988,67 -> 105,67 +739,65 -> 868,65 +187,973 -> 809,973 +730,211 -> 255,686 +254,445 -> 254,872 +622,364 -> 235,751 +402,980 -> 761,621 +46,488 -> 960,488 +799,708 -> 799,862 +909,181 -> 909,189 +450,266 -> 450,304 +631,584 -> 631,455 +164,830 -> 744,250 +679,755 -> 690,744 +949,26 -> 190,785 +695,783 -> 218,783 +269,151 -> 40,151 +166,152 -> 22,152 +281,819 -> 922,178 +956,649 -> 956,593 diff --git a/aoc2021/input/day05_provided.txt b/aoc2021/input/day05_provided.txt new file mode 100644 index 0000000..b258f68 --- /dev/null +++ b/aoc2021/input/day05_provided.txt @@ -0,0 +1,10 @@ +0,9 -> 5,9 +8,0 -> 0,8 +9,4 -> 3,4 +2,2 -> 2,1 +7,0 -> 7,4 +6,4 -> 2,0 +0,9 -> 2,9 +3,4 -> 1,4 +0,0 -> 8,8 +5,5 -> 8,2 diff --git a/aoc2021/src/day05.rs b/aoc2021/src/day05.rs new file mode 100644 index 0000000..17ca76f --- /dev/null +++ b/aoc2021/src/day05.rs @@ -0,0 +1,108 @@ +use std::collections::HashMap; +use std::fmt::Write; +use std::iter; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day05.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let lines = input + .lines() + .map(str::parse::) + .collect::>>()?; + + let mut grid = HashMap::new(); + + lines + .iter() + .filter(|l| l.is_horizontal() || l.is_vertical()) + .for_each(|l| { + for cell in l.cells() { + *grid.entry(cell).or_insert(0) += 1; + } + }); + + Ok(grid.into_values().filter(|c| *c > 1).count()) +} + +#[derive(Debug)] +struct Line { + from: (usize, usize), + to: (usize, usize), +} + +impl Line { + fn is_horizontal(&self) -> bool { + self.to.1 == self.from.1 + } + + fn is_vertical(&self) -> bool { + self.to.0 == self.from.0 + } + + fn cells(&self) -> Box> { + if self.is_horizontal() { + let min = self.from.0.min(self.to.0); + let max = self.from.0.max(self.to.0); + Box::new((min..=max).zip(iter::repeat(self.from.1))) + as Box> + } else { + let min = self.from.1.min(self.to.1); + let max = self.from.1.max(self.to.1); + Box::new(iter::repeat(self.from.0).zip(min..=max)) + as Box> + } + } +} + +impl std::str::FromStr for Line { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (from, to) = s + .split_once(" -> ") + .context("couldn't parse line: missing ` -> `")?; + + let from = { + let (x, y) = from + .split_once(',') + .context("couldn't parse line origin: missing `,`")?; + (x.parse()?, y.parse()?) + }; + + let to = { + let (x, y) = to + .split_once(',') + .context("couldn't parse line origin: missing `,`")?; + (x.parse()?, y.parse()?) + }; + + Ok(Line { from, to }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day05_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 5); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 4745); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 93675e3..e0126f6 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -4,3 +4,4 @@ pub mod day01; pub mod day02; pub mod day03; pub mod day04; +pub mod day05; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index e9fe9e3..20a1ce0 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -6,9 +6,10 @@ use aoc2021::day01; use aoc2021::day02; use aoc2021::day03; use aoc2021::day04; +use aoc2021::day05; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run, day05::run]; aoc::run(days) } From 1890268bd51f546985249a26167ccea9c92da0e6 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sun, 5 Dec 2021 16:53:46 +0100 Subject: [PATCH 040/134] 2021: day05: part 2 --- aoc2021/src/day05.rs | 62 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/aoc2021/src/day05.rs b/aoc2021/src/day05.rs index 17ca76f..c768b82 100644 --- a/aoc2021/src/day05.rs +++ b/aoc2021/src/day05.rs @@ -10,6 +10,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -34,6 +35,23 @@ fn part1(input: &str) -> Result { Ok(grid.into_values().filter(|c| *c > 1).count()) } +fn part2(input: &str) -> Result { + let lines = input + .lines() + .map(str::parse::) + .collect::>>()?; + + let mut grid = HashMap::new(); + + lines.iter().for_each(|l| { + for cell in l.cells() { + *grid.entry(cell).or_insert(0) += 1; + } + }); + + Ok(grid.into_values().filter(|c| *c > 1).count()) +} + #[derive(Debug)] struct Line { from: (usize, usize), @@ -50,16 +68,32 @@ impl Line { } fn cells(&self) -> Box> { + let min_x = self.from.0.min(self.to.0); + let max_x = self.from.0.max(self.to.0); + + let min_y = self.from.1.min(self.to.1); + let max_y = self.from.1.max(self.to.1); + if self.is_horizontal() { - let min = self.from.0.min(self.to.0); - let max = self.from.0.max(self.to.0); - Box::new((min..=max).zip(iter::repeat(self.from.1))) - as Box> + Box::new((min_x..=max_x).zip(iter::repeat(self.from.1))) as Box> + } else if self.is_vertical() { + Box::new(iter::repeat(self.from.0).zip(min_y..=max_y)) } else { - let min = self.from.1.min(self.to.1); - let max = self.from.1.max(self.to.1); - Box::new(iter::repeat(self.from.0).zip(min..=max)) - as Box> + let x_range = min_x..=max_x; + let x_range = if self.from.0 < self.to.0 { + Box::new(x_range) as Box> + } else { + Box::new(x_range.rev()) + }; + + let y_range = min_y..=max_y; + let y_range = if self.from.1 < self.to.1 { + Box::new(y_range) as Box> + } else { + Box::new(y_range.rev()) + }; + + Box::new(x_range.zip(y_range)) } } } @@ -82,7 +116,7 @@ impl std::str::FromStr for Line { let to = { let (x, y) = to .split_once(',') - .context("couldn't parse line origin: missing `,`")?; + .context("couldn't parse line end: missing `,`")?; (x.parse()?, y.parse()?) }; @@ -105,4 +139,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 4745); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 12); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 18442); + } } From 15796e43709f686b0c2c2b0a6a8d68fe0a7221d2 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sun, 5 Dec 2021 17:05:48 +0100 Subject: [PATCH 041/134] 2021: day05: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index d781aac..49066d1 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -4,12 +4,14 @@ use aoc2021::day01; use aoc2021::day02; use aoc2021::day03; use aoc2021::day04; +use aoc2021::day05; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); + c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); } criterion_group! { From 22c25916998fe7f56e5d594f955e6a26dd022161 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sun, 5 Dec 2021 17:25:28 +0100 Subject: [PATCH 042/134] 2021: day05: refacto --- aoc2021/src/day05.rs | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/aoc2021/src/day05.rs b/aoc2021/src/day05.rs index c768b82..c6bd2e3 100644 --- a/aoc2021/src/day05.rs +++ b/aoc2021/src/day05.rs @@ -68,31 +68,25 @@ impl Line { } fn cells(&self) -> Box> { - let min_x = self.from.0.min(self.to.0); - let max_x = self.from.0.max(self.to.0); - - let min_y = self.from.1.min(self.to.1); - let max_y = self.from.1.max(self.to.1); + fn inclusive_range_any_order(a: usize, b: usize) -> Box> { + if a < b { + Box::new(a..=b) as Box> + } else { + Box::new((b..=a).rev()) + } + } if self.is_horizontal() { - Box::new((min_x..=max_x).zip(iter::repeat(self.from.1))) as Box> + Box::new( + inclusive_range_any_order(self.from.0, self.to.0).zip(iter::repeat(self.from.1)), + ) as Box> } else if self.is_vertical() { - Box::new(iter::repeat(self.from.0).zip(min_y..=max_y)) + Box::new( + iter::repeat(self.from.0).zip(inclusive_range_any_order(self.from.1, self.to.1)), + ) } else { - let x_range = min_x..=max_x; - let x_range = if self.from.0 < self.to.0 { - Box::new(x_range) as Box> - } else { - Box::new(x_range.rev()) - }; - - let y_range = min_y..=max_y; - let y_range = if self.from.1 < self.to.1 { - Box::new(y_range) as Box> - } else { - Box::new(y_range.rev()) - }; - + let x_range = inclusive_range_any_order(self.from.0, self.to.0); + let y_range = inclusive_range_any_order(self.from.1, self.to.1); Box::new(x_range.zip(y_range)) } } From bdc5a25d431678f25fc1906a3dc5018176a0c837 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 11:05:34 +0100 Subject: [PATCH 043/134] 2021: day06: part 1 & 2 --- aoc2021/input/day06.txt | 1 + aoc2021/src/day06.rs | 126 ++++++++++++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 10 +++- 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 aoc2021/input/day06.txt create mode 100644 aoc2021/src/day06.rs diff --git a/aoc2021/input/day06.txt b/aoc2021/input/day06.txt new file mode 100644 index 0000000..156bc49 --- /dev/null +++ b/aoc2021/input/day06.txt @@ -0,0 +1 @@ +4,1,4,1,3,3,1,4,3,3,2,1,1,3,5,1,3,5,2,5,1,5,5,1,3,2,5,3,1,3,4,2,3,2,3,3,2,1,5,4,1,1,1,2,1,4,4,4,2,1,2,1,5,1,5,1,2,1,4,4,5,3,3,4,1,4,4,2,1,4,4,3,5,2,5,4,1,5,1,1,1,4,5,3,4,3,4,2,2,2,2,4,5,3,5,2,4,2,3,4,1,4,4,1,4,5,3,4,2,2,2,4,3,3,3,3,4,2,1,2,5,5,3,2,3,5,5,5,4,4,5,5,4,3,4,1,5,1,3,4,4,1,3,1,3,1,1,2,4,5,3,1,2,4,3,3,5,4,4,5,4,1,3,1,1,4,4,4,4,3,4,3,1,4,5,1,2,4,3,5,1,1,2,1,1,5,4,2,1,5,4,5,2,4,4,1,5,2,2,5,3,3,2,3,1,5,5,5,4,3,1,1,5,1,4,5,2,1,3,1,2,4,4,1,1,2,5,3,1,5,2,4,5,1,2,3,1,2,2,1,2,2,1,4,1,3,4,2,1,1,5,4,1,5,4,4,3,1,3,3,1,1,3,3,4,2,3,4,2,3,1,4,1,5,3,1,1,5,3,2,3,5,1,3,1,1,3,5,1,5,1,1,3,1,1,1,1,3,3,1 diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs new file mode 100644 index 0000000..876252c --- /dev/null +++ b/aoc2021/src/day06.rs @@ -0,0 +1,126 @@ +use std::fmt::Write; +use std::str; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day06.txt"); + +const SPAWNING_DELAY: u8 = 7; +const TURNS_PART_1: usize = 80; +const TURNS_PART_2: usize = 256; + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut school = input + .trim() + .split(',') + .map(str::parse::) + .collect::>>()?; + + for _ in 0..TURNS_PART_1 { + let mut newly_spawned = 0; + + for fish in &mut school { + if fish.next_turn() { + newly_spawned += 1; + } + } + + school.resize_with(school.len() + newly_spawned, LanternFish::default) + } + + Ok(school.len()) +} + +fn part2(input: &str) -> Result { + let mut school = input.trim().parse::()?; + + for _ in 0..TURNS_PART_2 { + school.next_turn(); + } + + Ok(school.size()) +} + +struct LanternFish { + timer: u8, +} + +impl LanternFish { + fn spawn() -> Self { + LanternFish { + timer: SPAWNING_DELAY + 1, + } + } + + fn next_turn(&mut self) -> bool { + if self.timer == 0 { + self.timer = SPAWNING_DELAY - 1; + true + } else { + self.timer -= 1; + false + } + } +} + +impl Default for LanternFish { + fn default() -> Self { + Self::spawn() + } +} + +struct School { + fish_timers: [usize; SPAWNING_DELAY as usize + 2], +} + +impl School { + fn next_turn(&mut self) { + let newly_spawned = self.fish_timers[0]; + + for i in 1..self.fish_timers.len() { + self.fish_timers[i - 1] = self.fish_timers[i]; + } + + self.fish_timers[SPAWNING_DELAY as usize - 1] += newly_spawned; + *self.fish_timers.last_mut().unwrap() = newly_spawned; + } + + fn size(&self) -> usize { + self.fish_timers.iter().sum() + } +} + +impl std::str::FromStr for School { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut fish_timers = [0usize; SPAWNING_DELAY as usize + 2]; + + for fish in s.split(',').map(str::parse::) { + let fish = fish?; + fish_timers[fish] += 1; + } + + Ok(School { fish_timers }) + } +} + +impl std::str::FromStr for LanternFish { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(LanternFish { timer: s.parse()? }) + } +} + +#[cfg(test)] +mod tests {} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index e0126f6..f236974 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -5,3 +5,4 @@ pub mod day02; pub mod day03; pub mod day04; pub mod day05; +pub mod day06; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 20a1ce0..c712420 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -7,9 +7,17 @@ use aoc2021::day02; use aoc2021::day03; use aoc2021::day04; use aoc2021::day05; +use aoc2021::day06; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run, day05::run]; + let days: &[DayFunc] = &[ + day01::run, + day02::run, + day03::run, + day04::run, + day05::run, + day06::run, + ]; aoc::run(days) } From 0e4c121ebdb3f6687148a550587c54ad61287d1f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 11:24:54 +0100 Subject: [PATCH 044/134] 2021: day06: tests --- aoc2021/input/day06_provided.txt | 1 + aoc2021/src/day06.rs | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 aoc2021/input/day06_provided.txt diff --git a/aoc2021/input/day06_provided.txt b/aoc2021/input/day06_provided.txt new file mode 100644 index 0000000..55129f1 --- /dev/null +++ b/aoc2021/input/day06_provided.txt @@ -0,0 +1 @@ +3,4,3,1,2 diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs index 876252c..f0b6ec4 100644 --- a/aoc2021/src/day06.rs +++ b/aoc2021/src/day06.rs @@ -123,4 +123,28 @@ impl std::str::FromStr for LanternFish { } #[cfg(test)] -mod tests {} +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day06_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 5934); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 350149); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 26984457539); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 1590327954513); + } +} From 7cffb7cdc6315954a8394083129ea3e7d44b0a9c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 11:25:08 +0100 Subject: [PATCH 045/134] 2021: day06: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 49066d1..6de70e6 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -5,6 +5,7 @@ use aoc2021::day02; use aoc2021::day03; use aoc2021::day04; use aoc2021::day05; +use aoc2021::day06; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -12,6 +13,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); + c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); } criterion_group! { From bb9265657bcce9b8b9afc1f484861a18f9b35c4e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 11:34:54 +0100 Subject: [PATCH 046/134] 2021: day06: refacto --- aoc2021/src/day06.rs | 79 +++++++++----------------------------------- 1 file changed, 15 insertions(+), 64 deletions(-) diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs index f0b6ec4..3fae107 100644 --- a/aoc2021/src/day06.rs +++ b/aoc2021/src/day06.rs @@ -5,7 +5,7 @@ use anyhow::Result; const INPUT: &str = include_str!("../input/day06.txt"); -const SPAWNING_DELAY: u8 = 7; +const SPAWNING_DELAY: usize = 7; const TURNS_PART_1: usize = 80; const TURNS_PART_2: usize = 256; @@ -19,63 +19,15 @@ pub fn run() -> Result { } fn part1(input: &str) -> Result { - let mut school = input - .trim() - .split(',') - .map(str::parse::) - .collect::>>()?; + let mut school = input.trim().parse::()?; - for _ in 0..TURNS_PART_1 { - let mut newly_spawned = 0; - - for fish in &mut school { - if fish.next_turn() { - newly_spawned += 1; - } - } - - school.resize_with(school.len() + newly_spawned, LanternFish::default) - } - - Ok(school.len()) + Ok(school.grow_for(TURNS_PART_1)) } fn part2(input: &str) -> Result { let mut school = input.trim().parse::()?; - for _ in 0..TURNS_PART_2 { - school.next_turn(); - } - - Ok(school.size()) -} - -struct LanternFish { - timer: u8, -} - -impl LanternFish { - fn spawn() -> Self { - LanternFish { - timer: SPAWNING_DELAY + 1, - } - } - - fn next_turn(&mut self) -> bool { - if self.timer == 0 { - self.timer = SPAWNING_DELAY - 1; - true - } else { - self.timer -= 1; - false - } - } -} - -impl Default for LanternFish { - fn default() -> Self { - Self::spawn() - } + Ok(school.grow_for(TURNS_PART_2)) } struct School { @@ -90,38 +42,37 @@ impl School { self.fish_timers[i - 1] = self.fish_timers[i]; } - self.fish_timers[SPAWNING_DELAY as usize - 1] += newly_spawned; + self.fish_timers[SPAWNING_DELAY - 1] += newly_spawned; *self.fish_timers.last_mut().unwrap() = newly_spawned; } fn size(&self) -> usize { self.fish_timers.iter().sum() } + + fn grow_for(&mut self, turns: usize) -> usize { + for _ in 0..turns { + self.next_turn(); + } + + self.size() + } } impl std::str::FromStr for School { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - let mut fish_timers = [0usize; SPAWNING_DELAY as usize + 2]; + let mut fish_timers = [0usize; SPAWNING_DELAY + 2]; for fish in s.split(',').map(str::parse::) { - let fish = fish?; - fish_timers[fish] += 1; + fish_timers[fish?] += 1; } Ok(School { fish_timers }) } } -impl std::str::FromStr for LanternFish { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { - Ok(LanternFish { timer: s.parse()? }) - } -} - #[cfg(test)] mod tests { use super::*; From fceda8ac1b6b00727b1b1b8e4cdc5078e59c73a2 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 11:53:34 +0100 Subject: [PATCH 047/134] 2021: day06: use rotate_left --- aoc2021/src/day06.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs index 3fae107..499531b 100644 --- a/aoc2021/src/day06.rs +++ b/aoc2021/src/day06.rs @@ -38,12 +38,9 @@ impl School { fn next_turn(&mut self) { let newly_spawned = self.fish_timers[0]; - for i in 1..self.fish_timers.len() { - self.fish_timers[i - 1] = self.fish_timers[i]; - } + self.fish_timers.rotate_left(1); self.fish_timers[SPAWNING_DELAY - 1] += newly_spawned; - *self.fish_timers.last_mut().unwrap() = newly_spawned; } fn size(&self) -> usize { From 7077559b3a6d5e258c2656125a9624166a9f1c98 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 12:15:25 +0100 Subject: [PATCH 048/134] 2021: day06: use a VecDeque for faster rotating --- aoc2021/src/day06.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs index 499531b..e52d172 100644 --- a/aoc2021/src/day06.rs +++ b/aoc2021/src/day06.rs @@ -1,3 +1,4 @@ +use std::collections::VecDeque; use std::fmt::Write; use std::str; @@ -31,7 +32,7 @@ fn part2(input: &str) -> Result { } struct School { - fish_timers: [usize; SPAWNING_DELAY as usize + 2], + fish_timers: VecDeque, } impl School { @@ -66,7 +67,9 @@ impl std::str::FromStr for School { fish_timers[fish?] += 1; } - Ok(School { fish_timers }) + Ok(School { + fish_timers: fish_timers.into(), + }) } } From 6bb234ee6a36f6492b28a1e49c528f859a7c87b1 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 15:05:29 +0100 Subject: [PATCH 049/134] aoc-get: init helper script --- aoc-get/aoc-get | 39 +++++++++++++++++++++++++++++++++++++++ aoc-get/default.nix | 32 ++++++++++++++++++++++++++++++++ flake.nix | 6 ++++++ 3 files changed, 77 insertions(+) create mode 100755 aoc-get/aoc-get create mode 100644 aoc-get/default.nix diff --git a/aoc-get/aoc-get b/aoc-get/aoc-get new file mode 100755 index 0000000..a6248f0 --- /dev/null +++ b/aoc-get/aoc-get @@ -0,0 +1,39 @@ +#!/usr/bin/env fish + +function usage + printf "Usage: %s [OPTIONS]\n\n" (status -f) + printf "Options:\n" + printf " -h/--help Prints help and exits\n" + printf " -d/--day=NUM Day (minimum 1, maximum 25)\n" + printf " -y/--year=NUM Year (minimum 2015, default current year)\n" +end + +set --local options +set --append options (fish_opt --short h --long help) +set --append options (fish_opt --short d --long day --required-val)"!_validate_int --min 1 --max 25" +set --append options (fish_opt --short y --long year --required-val)"!_validate_int --min 2015" + +argparse $options -- $argv + +set --query _flag_year; or set --local _flag_year (date +%Y) + +if set --query _flag_help + usage + exit 0 +end + +if not set --query _flag_day + echo "Please provide a day to fetch" + exit 1 +end + +if not set --query AOC_SESSION + echo "Please provide a session cookie via the AOC_SESSION environment variable" + exit 1 +end + +set --local padded_day (string pad --width 2 --char 0 $_flag_day) + +curl https://adventofcode.com/{$_flag_year}/day/{$_flag_day}/input \ + --cookie "session="{$AOC_SESSION} \ + --output aoc{$_flag_year}/input/day{$padded_day}.txt diff --git a/aoc-get/default.nix b/aoc-get/default.nix new file mode 100644 index 0000000..eef4f45 --- /dev/null +++ b/aoc-get/default.nix @@ -0,0 +1,32 @@ +{ lib +, curl +, makeWrapper +, stdenvNoCC }: +stdenvNoCC.mkDerivation rec { + pname = "aoc-get"; + version = "0.1.0"; + + src = ./aoc-get; + + buildInputs = [ + makeWrapper + ]; + + dontUnpack = true; + dontBuild = true; + + wrapperPath = lib.makeBinPath [ + curl + ]; + + fixupPhase = '' + patchShebangs $out/bin/${pname} + wrapProgram $out/bin/${pname} --prefix PATH : "${wrapperPath}" + ''; + + installPhase = '' + mkdir -p $out/bin + cp $src $out/bin/${pname} + chmod a+x $out/bin/${pname} + ''; +} diff --git a/flake.nix b/flake.nix index fb06686..31a64b2 100644 --- a/flake.nix +++ b/flake.nix @@ -18,9 +18,15 @@ nixpkgs-fmt rust-analyzer myRust + + self.packages.${system}.aoc-get ]; RUST_SRC_PATH = "${pkgs.rust-bin.stable.latest.rust-src}/lib/rustlib/src/rust/library"; }; + + packages = { + aoc-get = pkgs.callPackage ./aoc-get {}; + }; }); } From 21ebbbfcc440a713dbf59c61c46538b086f9c987 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 15:08:23 +0100 Subject: [PATCH 050/134] cargo: adapt workspace wildcards --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1fddce8..6604557 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["aoc*", "aoc*/aoc*_bench"] +members = ["aoc20*", "aoc20*/aoc20*_bench"] default-members = ["aoc2021"] From 246d34cc1fab4284f36d2c20fa182be6292a4fa5 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 15:16:07 +0100 Subject: [PATCH 051/134] aoc-get: include fish in build --- aoc-get/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc-get/default.nix b/aoc-get/default.nix index eef4f45..14cf5f0 100644 --- a/aoc-get/default.nix +++ b/aoc-get/default.nix @@ -1,5 +1,6 @@ { lib , curl +, fish , makeWrapper , stdenvNoCC }: stdenvNoCC.mkDerivation rec { @@ -10,6 +11,7 @@ stdenvNoCC.mkDerivation rec { buildInputs = [ makeWrapper + fish ]; dontUnpack = true; From 48f78825b87c54070a5e277f035463634ed8e74b Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 15:39:40 +0100 Subject: [PATCH 052/134] aoc-get: default to current day in december --- aoc-get/aoc-get | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/aoc-get/aoc-get b/aoc-get/aoc-get index a6248f0..dbe975b 100755 --- a/aoc-get/aoc-get +++ b/aoc-get/aoc-get @@ -15,25 +15,37 @@ set --append options (fish_opt --short y --long year --required-val)"!_validate_ argparse $options -- $argv -set --query _flag_year; or set --local _flag_year (date +%Y) - if set --query _flag_help usage exit 0 end -if not set --query _flag_day - echo "Please provide a day to fetch" - exit 1 +# automatically set day if we're in December, otherwise require a value +set --local flag_day +if set --query _flag_day + set flag_day _flag_day +else + set --local month (date +%-m) + if [ $month -eq 12 ] + set flag_day (date +%-d) + else + echo "Please provide a day to fetch" + exit 1 + end end +set --query _flag_year; or set --local _flag_year (date +%Y) + if not set --query AOC_SESSION echo "Please provide a session cookie via the AOC_SESSION environment variable" exit 1 end -set --local padded_day (string pad --width 2 --char 0 $_flag_day) +set --local padded_day (string pad --width 2 --char 0 {$flag_day}) +set --local outpath aoc{$_flag_year}/input/day{$padded_day}.txt -curl https://adventofcode.com/{$_flag_year}/day/{$_flag_day}/input \ +echo "Saving input to" {$outpath} "..." + +curl https://adventofcode.com/{$_flag_year}/day/{$flag_day}/input \ --cookie "session="{$AOC_SESSION} \ - --output aoc{$_flag_year}/input/day{$padded_day}.txt + --output {$outpath} From 1973fead31ca8b8e0d09a1e0fb331001bac605ff Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 16:01:16 +0100 Subject: [PATCH 053/134] aoc-get: exit if arguments aren't valid --- aoc-get/aoc-get | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aoc-get/aoc-get b/aoc-get/aoc-get index dbe975b..8acbbaa 100755 --- a/aoc-get/aoc-get +++ b/aoc-get/aoc-get @@ -13,7 +13,9 @@ set --append options (fish_opt --short h --long help) set --append options (fish_opt --short d --long day --required-val)"!_validate_int --min 1 --max 25" set --append options (fish_opt --short y --long year --required-val)"!_validate_int --min 2015" -argparse $options -- $argv +if not argparse $options -- $argv + exit 1 +end if set --query _flag_help usage From 48f1a4ffeb7bdb13b1d2caac88934fff7bf56a22 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 16:02:45 +0100 Subject: [PATCH 054/134] aoc-get: fix variable setting bug --- aoc-get/aoc-get | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aoc-get/aoc-get b/aoc-get/aoc-get index 8acbbaa..007569a 100755 --- a/aoc-get/aoc-get +++ b/aoc-get/aoc-get @@ -25,7 +25,7 @@ end # automatically set day if we're in December, otherwise require a value set --local flag_day if set --query _flag_day - set flag_day _flag_day + set flag_day $_flag_day else set --local month (date +%-m) if [ $month -eq 12 ] From 56a5379a1bae2a22b88d31102e19e32bc990f744 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 6 Dec 2021 16:49:39 +0100 Subject: [PATCH 055/134] 2021: day05: use custom iterator --- aoc2021/src/day05.rs | 77 +++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/aoc2021/src/day05.rs b/aoc2021/src/day05.rs index c6bd2e3..c076deb 100644 --- a/aoc2021/src/day05.rs +++ b/aoc2021/src/day05.rs @@ -1,6 +1,6 @@ +use std::cmp::Ordering; use std::collections::HashMap; use std::fmt::Write; -use std::iter; use anyhow::{Context, Result}; @@ -52,6 +52,57 @@ fn part2(input: &str) -> Result { Ok(grid.into_values().filter(|c| *c > 1).count()) } +struct PointIterator { + current: (usize, usize), + to: (usize, usize), + dx: Ordering, + dy: Ordering, + done: bool, +} + +impl PointIterator { + fn new(from: (usize, usize), to: (usize, usize)) -> Self { + Self { + current: from, + to, + dx: from.0.cmp(&to.0), + dy: from.1.cmp(&to.1), + done: false, + } + } +} + +impl Iterator for PointIterator { + type Item = (usize, usize); + + fn next(&mut self) -> Option { + if self.done { + return None; + } + + let (x, y) = self.current; + + if x == self.to.0 && y == self.to.1 { + self.done = true; + return Some((x, y)); + } + + match self.dx { + Ordering::Less => self.current.0 += 1, + Ordering::Greater => self.current.0 -= 1, + Ordering::Equal => {} + } + + match self.dy { + Ordering::Less => self.current.1 += 1, + Ordering::Greater => self.current.1 -= 1, + Ordering::Equal => {} + } + + Some((x, y)) + } +} + #[derive(Debug)] struct Line { from: (usize, usize), @@ -67,28 +118,8 @@ impl Line { self.to.0 == self.from.0 } - fn cells(&self) -> Box> { - fn inclusive_range_any_order(a: usize, b: usize) -> Box> { - if a < b { - Box::new(a..=b) as Box> - } else { - Box::new((b..=a).rev()) - } - } - - if self.is_horizontal() { - Box::new( - inclusive_range_any_order(self.from.0, self.to.0).zip(iter::repeat(self.from.1)), - ) as Box> - } else if self.is_vertical() { - Box::new( - iter::repeat(self.from.0).zip(inclusive_range_any_order(self.from.1, self.to.1)), - ) - } else { - let x_range = inclusive_range_any_order(self.from.0, self.to.0); - let y_range = inclusive_range_any_order(self.from.1, self.to.1); - Box::new(x_range.zip(y_range)) - } + fn cells(&self) -> impl Iterator { + PointIterator::new(self.from, self.to) } } From fa9827852d87821652360267c0596368b203dfbf Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 7 Dec 2021 10:31:07 +0100 Subject: [PATCH 056/134] 2021: day07: part 1 --- aoc2021/input/day07.txt | 1 + aoc2021/input/day07_provided.txt | 1 + aoc2021/src/day07.rs | 48 ++++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 ++ 5 files changed, 53 insertions(+) create mode 100644 aoc2021/input/day07.txt create mode 100644 aoc2021/input/day07_provided.txt create mode 100644 aoc2021/src/day07.rs diff --git a/aoc2021/input/day07.txt b/aoc2021/input/day07.txt new file mode 100644 index 0000000..706de5d --- /dev/null +++ b/aoc2021/input/day07.txt @@ -0,0 +1 @@ +1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,848,1174,380,1195,277,353,425,292,225,1521,631,76,692,329,1530,445,1625,561,161,1760,88,129,89,866,133,353,372,1456,888,115,347,291,246,8,57,17,869,1230,1224,681,586,1553,183,508,760,1200,812,634,578,126,147,684,1037,822,217,521,136,438,456,26,258,9,395,1,1398,34,13,40,493,871,154,606,716,649,491,416,293,1,107,21,317,1156,194,179,693,1591,894,845,10,18,1314,11,730,408,365,0,516,192,96,1438,1521,787,503,454,84,478,19,26,109,287,657,216,148,155,816,384,288,1121,39,263,488,348,110,1219,321,1101,51,5,95,147,806,17,207,81,139,686,23,231,1154,36,410,1025,2,327,172,307,232,420,88,129,1507,1028,852,467,46,81,16,64,989,558,919,1301,612,278,306,1500,95,507,1034,272,526,68,41,870,37,78,434,459,268,375,1427,1039,1039,1077,1068,445,482,106,1823,218,76,33,131,934,112,72,404,118,848,99,10,816,527,125,279,200,10,248,243,416,242,639,401,66,110,364,243,550,1289,55,30,1246,72,46,251,1225,264,765,137,94,626,252,18,481,250,55,10,284,247,90,277,34,176,118,1178,554,761,3,938,140,890,109,811,760,179,1084,998,16,338,550,120,190,220,74,846,212,30,1098,455,1110,1662,71,1275,609,47,1239,1050,93,169,383,564,323,134,310,208,685,255,219,369,556,272,1604,562,600,493,178,337,33,949,775,588,288,498,40,1056,483,796,8,1588,463,122,120,26,215,786,525,129,259,346,21,35,247,1564,1094,1013,85,54,193,889,590,908,122,158,363,646,1301,533,73,767,405,89,358,936,737,78,982,163,867,373,1460,492,151,560,371,647,110,1779,802,374,147,1279,252,299,244,568,1014,685,912,942,767,3,76,207,296,40,181,312,192,684,988,490,31,410,928,47,1345,943,1013,705,675,543,446,84,869,1173,393,348,99,25,21,20,132,295,4,1273,800,182,140,593,964,55,167,15,219,269,35,848,324,474,189,4,305,62,7,1145,13,975,55,880,43,368,82,1083,6,969,844,1388,185,818,114,641,151,1006,220,599,143,170,36,631,891,531,871,13,77,1261,340,911,159,258,213,1245,222,200,946,875,301,9,381,69,1152,901,490,207,38,104,103,423,311,1532,536,314,73,314,29,844,141,1191,169,136,42,143,163,277,22,1655,1063,45,774,103,83,1253,121,1473,834,245,143,211,1252,1368,97,4,1188,1102,359,134,298,225,292,101,832,426,1204,652,468,110,529,34,384,663,534,80,1,68,117,419,1321,1729,38,1609,416,554,1047,130,145,267,1382,0,237,32,17,237,803,21,888,185,108,79,1,192,286,1167,86,71,464,122,375,0,186,927,525,1127,442,675,373,53,404,624,65,1157,107,687,98,165,891,1186,513,727,46,148,275,516,1412,17,684,113,246,137,1246,1357,143,307,307,656,1030,198,33,955,1765,314,79,5,385,248,402,75,12,76,325,175,1198,258,38,912,795,296,1931,111,72,1619,1563,8,327,867,293,515,1647,1266,128,44,9,431,300,72,501,1181,147,1330,1446,490,297,436,274,512,107,185,57,112,2,121,472,505,860,1650,411,23,328,119,64,0,1684,249,106,167,55,225,501,36,81,1225,270,186,10,477,783,39,319,1151,264,788,42,521,282,257,721,442,250,642,255,63,1015,241,939,86,997,569,330,189,129,547,1424,446,285,8,288,599,372,56,274,245,3,41,943,353,67,294,32,656,879,918,94,314,767,957,1554,854,610,590,403,139,377,129,930,341,678,577,375,809,490,39,153,3,48,133,54,225,1261,677,267,30,28,115,642,1733,12,297,428,155,812,635,16,634,223,823,261,662,652,71,138,103,220,544,211,313,1298,512,559,1243,1319,427,78,765,343,212,557,275,1,551,234,697,1815,1005,275,179,595,1,1658,204,345,794,36,102,912,657,194,8,2,526,350,399,390,1166,469,324,1497,371,759,621,800,895,235,314,579,863,278,54,239,1275,79,1728,934,1145,1008,748,196,1056,339,569,629,47,1437,416,758,1000,287,592,1057,921,170,273,144,133,0,320,216,216,118,229,4,681,410,1801,34,485,769,839,47,950,1694,1222,1199,411,598,1210,7,1644,245,44,428,49,653,7,1037,310,754,32,476,253,124,809,66,539,434,1142,136,4,344,306,628,1332,15,1523,149,191,498,1480,498,385,562,457,199,201,487,608,172,20,584,7,17,342,167,93,60,589,445,926 diff --git a/aoc2021/input/day07_provided.txt b/aoc2021/input/day07_provided.txt new file mode 100644 index 0000000..18bd32a --- /dev/null +++ b/aoc2021/input/day07_provided.txt @@ -0,0 +1 @@ +16,1,2,0,4,2,7,1,2,14 diff --git a/aoc2021/src/day07.rs b/aoc2021/src/day07.rs new file mode 100644 index 0000000..861208e --- /dev/null +++ b/aoc2021/src/day07.rs @@ -0,0 +1,48 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day07.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut horizontal_positions = input + .trim() + .split(',') + .map(|n| n.parse::().context("couldn't parse position")) + .collect::>>()?; + + // TODO: try linear selection algorithm + horizontal_positions.sort_unstable(); + let median = horizontal_positions[horizontal_positions.len() / 2]; + + Ok(horizontal_positions + .iter() + // TODO: use abs_diff when stabilized + .map(|n| n.max(&median) - n.min(&median)) + .sum()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day07_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 37); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 340056); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index f236974..5fb1402 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -6,3 +6,4 @@ pub mod day03; pub mod day04; pub mod day05; pub mod day06; +pub mod day07; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index c712420..2bc1b96 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -8,6 +8,7 @@ use aoc2021::day03; use aoc2021::day04; use aoc2021::day05; use aoc2021::day06; +use aoc2021::day07; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -17,6 +18,7 @@ fn main() -> Result<()> { day04::run, day05::run, day06::run, + day07::run, ]; aoc::run(days) From e56e70a6a36284c5b0d8962231954c8a5da3d110 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 7 Dec 2021 11:04:20 +0100 Subject: [PATCH 057/134] 2021: day07: part 2 --- aoc2021/src/day07.rs | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/aoc2021/src/day07.rs b/aoc2021/src/day07.rs index 861208e..764df93 100644 --- a/aoc2021/src/day07.rs +++ b/aoc2021/src/day07.rs @@ -8,6 +8,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -26,10 +27,44 @@ fn part1(input: &str) -> Result { Ok(horizontal_positions .iter() // TODO: use abs_diff when stabilized - .map(|n| n.max(&median) - n.min(&median)) + .map(|n| abs_diff(*n, median)) .sum()) } +fn part2(input: &str) -> Result { + let horizontal_positions = input + .trim() + .split(',') + .map(|n| n.parse::().context("couldn't parse position")) + .collect::>>()?; + + let min = *horizontal_positions.iter().min().unwrap(); + let max = *horizontal_positions.iter().max().unwrap(); + + let minimum_fuel = (min..=max) + .map(|pos| { + horizontal_positions + .iter() + .map(|n| part2_distance(*n, pos)) + .sum::() + .floor() as u64 + }) + .min() + .unwrap(); + + Ok(minimum_fuel) +} + +fn abs_diff(a: u64, b: u64) -> u64 { + a.max(b) - a.min(b) +} + +fn part2_distance(a: u64, b: u64) -> f64 { + let distance = abs_diff(a, b) as f64; + + distance * (distance + 1.0) / 2.0 +} + #[cfg(test)] mod tests { use super::*; @@ -45,4 +80,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 340056); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 168); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 96592275); + } } From f7bbbf5cce00aa9892f7202a81699362ac1aa5d6 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 7 Dec 2021 11:06:16 +0100 Subject: [PATCH 058/134] 2021: day07: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 6de70e6..8263066 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -6,6 +6,7 @@ use aoc2021::day03; use aoc2021::day04; use aoc2021::day05; use aoc2021::day06; +use aoc2021::day07; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -14,6 +15,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); + c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); } criterion_group! { From f621e603f33fab527d686bc110be8f212f3d8109 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 7 Dec 2021 15:22:30 +0100 Subject: [PATCH 059/134] 2021: day07: QuickSelect for median computation --- Cargo.lock | 64 ++++++++++++++++++++++++++++++++++++++++++++ aoc2021/Cargo.toml | 1 + aoc2021/src/day07.rs | 63 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 125 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acee5e3..82780e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", + "rand", ] [[package]] @@ -348,6 +349,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "half" version = "1.8.2" @@ -528,6 +540,12 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + [[package]] name = "proc-macro2" version = "1.0.32" @@ -552,6 +570,46 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + [[package]] name = "rayon" version = "1.5.1" @@ -749,6 +807,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "wasm-bindgen" version = "0.2.78" diff --git a/aoc2021/Cargo.toml b/aoc2021/Cargo.toml index b336e63..4d8f362 100644 --- a/aoc2021/Cargo.toml +++ b/aoc2021/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" [dependencies] aoc = { path = "../aoc" } anyhow = "1.0" +rand = "0.8" [lib] path = "src/lib.rs" diff --git a/aoc2021/src/day07.rs b/aoc2021/src/day07.rs index 764df93..34151b8 100644 --- a/aoc2021/src/day07.rs +++ b/aoc2021/src/day07.rs @@ -1,6 +1,7 @@ use std::fmt::Write; use anyhow::{Context, Result}; +use rand::Rng; const INPUT: &str = include_str!("../input/day07.txt"); @@ -20,9 +21,8 @@ fn part1(input: &str) -> Result { .map(|n| n.parse::().context("couldn't parse position")) .collect::>>()?; - // TODO: try linear selection algorithm - horizontal_positions.sort_unstable(); - let median = horizontal_positions[horizontal_positions.len() / 2]; + let median_rank = horizontal_positions.len() / 2; + let median = selection(&mut horizontal_positions, median_rank); Ok(horizontal_positions .iter() @@ -31,6 +31,52 @@ fn part1(input: &str) -> Result { .sum()) } +fn selection(data: &mut [T], i: usize) -> T +where + T: Copy + Ord, +{ + if data.len() == 1 { + return data[0]; + } + + let mid = random_partition(data); + + if i < mid { + selection(&mut data[..mid], i) + } else { + selection(&mut data[mid..], i - mid) + } +} + +fn random_partition(data: &mut [T]) -> usize +where + T: Copy + Ord, +{ + let pivot_index = rand::thread_rng().gen_range(0..data.len()); + let pivot = data[pivot_index]; + + let mut i = 0; + let mut j = data.len() - 1; + + loop { + while data[i] < pivot { + i += 1; + } + + while data[j] > pivot { + j -= 1; + } + + if i >= j { + return usize::max(i, 1); + } + + data.swap(i, j); + i += 1; + j -= 1; + } +} + fn part2(input: &str) -> Result { let horizontal_positions = input .trim() @@ -90,4 +136,15 @@ mod tests { fn part2_real() { assert_eq!(part2(INPUT).unwrap(), 96592275); } + + #[test] + fn test_selection() { + for _ in 0..4200 { + for i in 0..=9 { + let mut data = vec![9, 2, 7, 3, 5, 4, 6, 1, 8, 0]; + let res = selection(&mut data, i); + assert_eq!(res, i); + } + } + } } From 64ee9796ba5a20d82fda05220f9ec9127bb3de32 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 7 Dec 2021 15:45:55 +0100 Subject: [PATCH 060/134] 2021: day07: use binary search for part 2 --- aoc2021/src/day07.rs | 45 +++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/aoc2021/src/day07.rs b/aoc2021/src/day07.rs index 34151b8..ce5a56b 100644 --- a/aoc2021/src/day07.rs +++ b/aoc2021/src/day07.rs @@ -87,28 +87,47 @@ fn part2(input: &str) -> Result { let min = *horizontal_positions.iter().min().unwrap(); let max = *horizontal_positions.iter().max().unwrap(); - let minimum_fuel = (min..=max) - .map(|pos| { - horizontal_positions - .iter() - .map(|n| part2_distance(*n, pos)) - .sum::() - .floor() as u64 - }) - .min() - .unwrap(); + let optimal_distance = minimize_binary_search(&horizontal_positions, min, max, part2_distance); + let minimum_fuel = horizontal_positions + .iter() + .map(|n| part2_distance(*n, optimal_distance)) + .sum::(); Ok(minimum_fuel) } +fn minimize_binary_search(positions: &[u64], min: u64, max: u64, distance: F) -> u64 +where + F: Fn(u64, u64) -> u64, +{ + if min == max { + return min; + } + + let mid1 = min + (max - min) / 2; + let mid2 = mid1 + 1; + + let (cost1, cost2) = positions + .iter() + .map(|n| (distance(*n, mid1), distance(*n, mid2))) + .reduce(|(sum1, sum2), (x1, x2)| (sum1 + x1, sum2 + x2)) + .unwrap(); + + if cost1 < cost2 { + minimize_binary_search(positions, min, mid1, distance) + } else { + minimize_binary_search(positions, mid2, max, distance) + } +} + fn abs_diff(a: u64, b: u64) -> u64 { a.max(b) - a.min(b) } -fn part2_distance(a: u64, b: u64) -> f64 { - let distance = abs_diff(a, b) as f64; +fn part2_distance(a: u64, b: u64) -> u64 { + let distance = abs_diff(a, b); - distance * (distance + 1.0) / 2.0 + distance * (distance + 1) / 2 } #[cfg(test)] From fe5ce3b1a6878382c3fb4d7660540ea5840de4b1 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 8 Dec 2021 18:38:06 +0100 Subject: [PATCH 061/134] 2021: day08: part 1 --- aoc2021/input/day08.txt | 200 +++++++++++++++++++++++++++++++ aoc2021/input/day08_provided.txt | 10 ++ aoc2021/src/day08.rs | 68 +++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 281 insertions(+) create mode 100644 aoc2021/input/day08.txt create mode 100644 aoc2021/input/day08_provided.txt create mode 100644 aoc2021/src/day08.rs diff --git a/aoc2021/input/day08.txt b/aoc2021/input/day08.txt new file mode 100644 index 0000000..4aa4902 --- /dev/null +++ b/aoc2021/input/day08.txt @@ -0,0 +1,200 @@ +beacf afbd bcead cgefa ecdbga efb gbfdeac ecgfbd acbdfe fb | bf efb bgecdfa egcfa +cbdgef cdfageb cegbd fecba edgf dcfbe dbcafg df fcd dbegca | bgcdef dgbec bfeac fdeg +bgdcfa dgabf bfdec baefd abeg eda afcdge ea bfceadg dfegba | efbad fbdea dae fagbd +cfdabe fcgbe gcdeb ecdfgb bdc cdgf cd cfageb bgdae daebfcg | decbaf cdfg deabg cd +eacgdfb fdbeca agedc cbedf dcfgab bgef gdf fdgec fbcged gf | gf acegd fdeabgc gfd +egcd aebdcf gbeca eg edfcbga gbe cfbag bdeca gadbec bdgefa | caegfbd dgcebfa eg bgdfae +fcgab egafb gedbca gfc cf ceagdf cafbdeg gcafbd dbagc cfdb | dbecga dbgcefa cfg fcg +geacd bg cbfead efgabcd fbace ceabg efbadg gfbc gab geabcf | cfbg fabce bg fdgeacb +bfceg ca baefc caedfb acfedgb cfad edacbg eac debaf bdfage | geadbc bfgeacd efagcdb cefbg +fd dcfbge fcad dfg bgaefc fdcgab fgdceab afdbg cbagf gdaeb | aecdgfb dbcfag cdaf gfecba +dabce gceab fegcab fbdca adeg gcabdfe gedbac ed egdfbc deb | fdegcb acbdf ed gdae +bgcea cbfdage egad ecadb beg befdcg fcgba aecbdf ge abedcg | geb gbe deag eg +bfecag egbdfac abecg gcebf efdagc ca acbf cfbegd eac bgaed | bdcegfa gbfce dbgecaf ac +fcbed dbfegca cdafbe edfgc abfde ebc egcfab dbca fdgbea cb | cb fgedc cb cdfeb +fb fdeacb bfe bfdc ebcgda afdeb acbfge agedf ecbad fdagcbe | gfcdbae fb abcefgd bef +egbca cfe eadbfg baedgfc cf bcfd afbde acebf fecdag edafbc | cfe caedfgb fc eadfgc +gfabc fbcaeg bagd cgbfaed dfecb gfdcb fcedga dg dafbgc dgf | abgd bdgcf ebcdfga fcedbga +cdb abce ebgfdc bfagdec abdcef dbfea gfdca facbd dfaebg cb | cdb cb dbc cdafbeg +afdbe dcfegb gedca adcbe ecfgbad fcadge cb acgdeb cbe agcb | dcage bec cb cb +gafdec cbdg fdgbce dce dfegb fceab becagdf dc dfbce agdefb | dgebf dc bfgde cde +bagfc bdef cgeafd eagfbcd afceb fe cfabde agcdeb cef eabdc | fbdgaec ef ef cafbe +fbage cgfba bdcage edagbf fe agcfdeb gfe adfe dgabe egbfdc | fe gfe geabf dgecab +gdfec bgfc dbgafe gfdebc dbfeg fc fabdcge fcd gedac dcbfea | egadc cfd efbdg gcbf +dacgf dfabc ebgcad daegfcb aedfbc dbgf agd aegfc cbfdag gd | agd gbdf bdafcge bcfegad +gdbea ebacdf adebfgc dfb df fbdea gcfebd fceab bfcgea fdac | gfabecd efdgbc fcebgd fbd +fba gbdcf cbae ebfgca fbcegda ab gbedfa gbacf gface gecdfa | ba bacgfde edfgac ab +fgebda bfgae cfdgba agcbe dbaegcf gbfda ef bfe gcbdfe dfea | ebgfdc eagcb eafd bef +agfecb cabef dafgec adfeb fbc gacb cb afbegdc cfaeg cbdefg | aegbfc fcb cgfdbe fcaged +agf eadfc cegabfd eagdf efdgb cgfbde agbfed gfbcae ag abdg | abdegf gbad baecgf afdbeg +gfbdac bd gcaefd bdcegfa gadbce dgb badf gbfdc fgecb cgadf | bgd fcbgd gdb dbfa +cbgf efcgbd aefdcbg feabd dcf cdebf ebcgda cf egcbd fadceg | dcf cf gcedaf bgfc +bacgfe fbc cgfe bcdagf gebfa cafeb bdcafge afdegb caedb cf | befga cbf gcfe bcf +bgdf geacf acedgb gb aecbfd bdcfa abgcf bgc acgefdb cdgabf | cdbgea gcb fdbg adgefcb +bdacgef fadeb abcg gfcebd gbf afbge egacf dgceaf bg aefgcb | gfb fbg dbgecfa bacg +dcegf bg cdafegb cfdebg fagced bge ecfab dbgace cgbef bdgf | gb gbfd adgefc ebg +gbf fbcdega egdafc bg aefgd gbecfd agbe abcdf edgafb fbdag | cgaefbd dfaeg dafgb dfeagc +beaf aed aecdf aebcgd eafdcb cgfabd ea gfcde cbdfa ceagdfb | fabe bafecd fecgdab ae +bdcfe gbdae bcgafd daegfb aecg cdagbe gfbadec gbc gc edcgb | cdbge efbgcda dagcbe agebdf +ec fdcag aegcbf bagfcd cgfade adecg fdaebcg fecd degba egc | deagc ec ebagd cafgeb +dcgaeb egadc agcfde efac beagdfc fcdagb dgcef gbfde dfc cf | cdf cf febadgc ecgfd +afd df gdafecb bdcf fecba acged edcabf egdbfa egfabc acdfe | cgebaf dacge fdbc decga +ga beafc cgbea dceagf feabdc bfagec abgf cga fdeagbc cebdg | cagbe bgfa gbced gabf +edag cdafb ae efacd eacgbf cedgbf afe fbceadg cdgaef egcdf | eaf cdafb efa ae +eagdbfc cagdf badcge fgec cg cdg bdfca feadg fecdga dfbega | abcfd dgc cgd gdc +beadg ca cdeba gcda acfebg dfbce fcbadge dbafge gdabec cae | gcad eca agbced gdbace +agfcde gdceab dbeaf agfed dg acfegb gaedbfc adg aegcf fgcd | bdefa cgebfad gdfc gd +gafcdb bfgaec daecf bcfgdea bged be dcgfb cfebd fbe dfebgc | fcabge dbfagec gebdfca gbfcd +dcaef agfbec gea ge bged cbdfag fgbade gbdefca abfgd faged | bfdcega aeg bdgaf bedg +dcbfa ag fcaegb fcdaegb gebdf adeg bdfga dgfeba ebcdgf gaf | cbgedfa ag egda ga +bcgdaef fcabde dbfage cfdgb daegf bfe dgefb gfadce egab eb | bfe gfeabd gdbef dagfbec +be egb fgcbde agdbcf gcdfb edbf bagecf ecadg bdefgca bdegc | efcdgab edgbcf efabcg dgecb +bcegfd ceafd gbefca eba dacebfg gebfd baegdf dabg dbfae ab | bae abcgef gbdcefa dbga +dceagfb edac ecfba cbgadf dfbge bcdefa fdc cd fcaegb edcbf | bdface cgfabde cdf cdafeb +cgaedbf acd afbdge afdcg bdcaeg gadfb ac gcbdfa abcf cdgef | gdfac cgdef cgfad cfbedga +gaefdcb debga cd aebcd gceafb afdceb cfabe dfcb dca agdcef | dbcafeg dfecag dbfc efgdacb +abdeg eaf cedfba aefdg gcadfe af gdfaecb gcfa gdfec cbgdef | fea cebfda dfceag fadcebg +bcgdfe fbdce fcdbea bcead adc ca bdgcaf edcgbaf baged feac | ecbad bfdec acd ac +bd aecfgb bfad gdb dgbace fbaegdc egbaf ecdgf egbdf fgadeb | fcageb dgb dgfeb bfad +bfcea dfbcea badge bfegdca gac cafdgb gc aecbgf caebg gefc | fegc bcaeg beafc feadbc +cagef fadgebc fd daf dcfbga ebdgfa cbeadg afdeg abegd ebdf | gbafedc daefg fd gbadec +dfaebc bcgaf bcaeg abecgf eagf dgecb cae ae dcgbafe gbadcf | ea gdecb bfacge gbace +dfbec gcbade fadb df badefcg dbeac cfgeb ebafcd fecdga edf | febcg cfadeg ebcgda dbfa +cadgfe bdfea dgbfeca dab dgbaec afdegb fdgb gaefd db cbfae | dgbf edabf bd dfgb +decbga ebfcgd gcebf cabfe aec cbfad ea eafg adbgcef cebfag | efga ea cgafbed acfdb +dcgefb gafc bagfce ca fcaeb aec dfbae ebgcf bcfdega deacgb | begcdfa ace fdegbac ac +gafc dgafecb cdgeba dbgafc fa bacdg fceabd fbgde afb fadgb | cafgdbe fbedagc adefbc gacefdb +dgfe dfa fd agcfbd bedac gfaec bdfcgae ebgcaf edfac acegfd | adf degf fad fedacgb +efgacdb gedfc eadbfg efd dcagf cfdage gdbacf gcbed fe fcae | eafdgb fdcge cafe dfe +aebg gbfdac dcebfga bdcef ebcfag abcfg acfeb dfcaeg ea eca | bega ace bacfg bgadcf +ceag caefgb agb fbgdc ag cafbg becfa cfeabd deafgb eafcgbd | cgadbef gba ag bag +bdge agbec dgcfae agbedcf gdc gbecad dabgc gd fbadc abefcg | gfcbaed dbge dg acfbd +dcef efb dbcfgae gbecfa fe ebcdag cafedb cadbe afdbe badfg | edcf ef fe fe +cdagfeb fgabc cafd fcb bdagc dfcgeb gbfacd cf baefg bdegac | cf acgbd fdac cdbfega +cefbdg debgca abfeg cebgf fdbgac adcgefb fcde cbe ce cdbgf | bgfae bec cfdebga cfegbd +fcbag gcfbed adgbefc afbdeg adbgf dbea ad cefagd daf debfg | da afd baegdfc afd +ba gbcda degcb bad adbegc fgcad eacb adgefb gdfaecb gcbedf | dgbaec gdbcfe dba ba +cdabf cbdgae facgb fadg acg gfbce ag cgdafb edcfab dbcegfa | dafg bdafec cbfeg facbg +edbaf cfebad aec cdaf ca gfabce cbeda afgebd fbdacge bcgde | ac afgbce dacf fcda +egdba bafeg bd gdfeba bcedfa agcde bad fgdb fceabg gabdefc | fbgae efgacb cadfeb bgdf +fdcgae dcefb cdb fecgabd afecb dbcfeg bgceda bd gfdb cdegf | dgabec cbdgae bcd aedcbgf +beg eg bfcea cdfgeb baefg abgdf fgeabd gcfdba agde dgbaefc | cdabgf dbefgc bdgfa facgebd +dbgef bfecgad egfcd agfbce agbde bf gcebdf dagfce cbdf feb | fbe ebfcdg bcfd fgcdabe +abgdec fgd fcgeb gedabf gfbdc dgaecbf afdc dgcafb fd bgcad | fgd adcf bgfcd fdegba +cafdb acdbge acedb dfbcg af ceadfbg adf adfgec faeb dcfeab | gdabfec bdgfc dcfba feab +dbcgae bcdfeg bfceadg bafgcd dacgb dfac cfgba bfc aefgb cf | dcegbf fc becagd fc +geacb gebfda gbcdafe efgc ge ecabd bcefag gfbcda age gafbc | adbfecg acbge cabedfg gea +gabce feagdb dgb fceadb deagb edbfa gd cbfgde agdbfec afdg | gbd begdcf aegbd bgd +afecbg fgeda dfeabgc cdafe adgb dg dbcegf fabged faebg egd | ged abfgced gd afcde +ec badfec cfe befgd gdacfe bace fgedbac gbcadf fdcba cfedb | ecf ec ce efcdb +dacfgb fd gfdbae ecbdgfa ecbdag cbfeg faed gdf aegbd egdfb | eacdbg gbfdea begfd becfdag +faegbd fgdace acbfeg dfgecba ed dabge fdbe dae badcg eagbf | dfeb dfgabe adcgb de +dbe gbcef acdebf defa geabdc de dfcbag dbgaecf cabfd becdf | eadf adcegb efcbg cfabdg +gcaed adgbce abfeg cb egcba cdba cgadef cgbefda fdbegc ebc | gbeaf cb bcad fadcge +cef fbacd gafedc ec gaecbdf bfedg gdcfeb bfdce cegb bfadeg | ec fbceagd fce fec +gfdae adgb cabfde fgdceb dea gafec bdgafec agdebf ad degfb | bcedgf bedacgf cegfa bcfgead +ec cge dagef eacgbf cdafegb cfgadb gbedca ecagd cdeb agcbd | cfagbd dcega gaecdb bgfaecd +ebgac cegbad dfcegb abegdf gbdec bae dcae efabgdc ea cgfba | ea eba deca bea +dcgfba adgbef feac afedgc dcegf egabfdc fc fdaeg bdceg dcf | beagcfd gdbcafe efac cf +cadfg gb cedagf gbd abgcfd fdcebga acgb febgda fdbec bdgcf | cagb cfagd gbd fegcbad +fgdca afcdeg bcdeagf gc fcaed defabc aedcbg bgfad cdg cfge | gc gdeacf agdbce fbacdge +fea adgeb bgfe fe dcfeag bafegd badcf aedbfgc adefb bcdeag | eafbd abfged begf egfb +gace dagcf fedac fbceagd defab cfe gdcfeb cdfgae ec gbfadc | ecf cagefbd befgdac acge +afc gaedf dfecga bafcdge cf bgdac dafcg eacbfd gbdafe gcef | adbcg fca agdbfce acf +cdfebg dcbe fgbdac bfegd be beagfc gfdea gacfbed fbe cgfbd | gedabfc eb eb aegcbfd +afg dfgec gcfeab ebcfagd fa adfe bagcd gdcfa gfbedc gecdfa | fa eacgdbf fa defa +bfdag gbecd cefg efcbdga fbc cf gbcfd badfec bedfcg egcbda | gadefcb bfc bacfde bgedc +cafde dce dcbfa dgcefb cgea dgafceb fgcdae dagfe gfebad ec | fcdae dbgfec gfdea dfcgeba +gcebad cfgdb cfgeab cdb cd egcdbf gbdaf fcde fgdbcae gfbec | cbd geacdb adbcge dc +afegb adbfg becafdg dg bgd gaebfc fdge cdfba gbcead abfdeg | gd gbd dabfc defg +fabeg gd dfebcg dgfae bfgeca fecad adgb efabgd ecfdbag deg | gd cfead dcfea cbefgda +bfceag dafgb fdce fc cfg gcdebf becgfda dgbec aedcgb cbgdf | fc adfgb dgfab cgbedf +bfeg decaf cegfa ecfgab gcf dbfeacg caedgb aegbc dbcafg fg | bgdcfea fg bfdaegc afgcdbe +eac ae cbdfe cbaedf abcfedg bade aefcbg bdcgef cedaf gdfca | efcdbg ae bdfce cdefa +gdebfca bfgca fda bcafd ad gcda cfgdab fadbeg edfcb gcbfae | cgafdb fad fda acdg +gfbdcae afed gedac facegd bgeac de fgbecd cagfd ged bdgfca | bacge egbacfd adgfc deg +gdafbe dbacgf cbefag cbfdg bfdag fcedg cdbgfae adbc cgb cb | bc gadefb bc acbd +fa egcad acfed ebdcfa dgcbef daf bdecf fgadbc fbae gabdecf | cedfa egdcbfa fa afd +cfd fd gbafc dcagf daecg dbfa cbfage egfdbc bfdgcae cbdfga | ecbdgf df dabf fd +eafbdgc baegd fe bagfed aebfg cabedg efg facgb bdgfec fade | defa ef ef fdae +cfdeagb bdeacf eac gcdbfa egab egacfb cdgfe ea ecfga cgfba | aecfg dfbacge cae ea +aefcdgb bacfg cdg afecd gedbcf afgcbe abgd adbfcg fgdac dg | bagfc gbfcdea gfdac bgda +becf baefgd dcafg cb cdbage dcgfb bcg gdbef edbfcg egbcafd | fbce cbg gcbfde gefabd +gb bgedca fedga cfdeag fegb dcbfa gab afgdb acbgefd bdgaef | bga gb gb ebfg +dca cedbf dcfebga ca egbcad cdaefb fedag efdac acbf cfgdbe | fbcade cebfdag adc acd +bgdeafc gaefd fbeagc cdfa fgc degcf dgbafe gcedaf dgcbe fc | gfc egafd cf bcdeg +dfaeb fae ebacfd egadb fe gadbfc febc gbfeacd fagcde dcabf | beadg adefb fcbe dagfcb +fgaed gd dacgfb egcd gdf acfed adbfceg edbfca dcafeg baefg | decaf bacdgf fgd ebgaf +bcfeadg dfagce fdcgba dfcab gabec gcf gf abgfc bacedf bdgf | bcgfeda bdgf fg gf +ceab gafec cef fcdgba cbfeadg bcagf ce ceagbf agdfe degcbf | efgca efgca cef ebac +abgef abf gbeac gabfcde degcfb efdbga aefd bgdcfa af befdg | afbcdg fa bdfgec dfbgae +gdafce cfb agfbc ebaf fcebdg aegfc cbgfea egbfdca dbgac bf | fb abfe aebf dgecbf +ceadf fecag dcgaeb dgbfcea edc bcafd cdabef ed befd gfcdab | badecf ed egfca edfb +gecdbaf dbag bfade gabfed cedfba gfade cfaebg fgdce ag fga | bafgdce gacbef ga dagb +defbcg gbfce beag gacdf cfbaeg dbcfea ea cefga ceafbgd ace | aefcg ae aegcbf ebga +egbdac fgadb cefdbg aceg gc cedba dcbag ecafdb fgeacdb gcd | cg ecbad egdafbc cgd +bdac ac fcdaebg afbdeg dbagf fbcge acf cadgbf afedgc bgfca | cdab fgceb ac fgbac +ba eacfg cab aefcb cdeabgf ecgdbf dcbfe dbfeac acdbeg dfab | bacef adbf bfda cab +gbfca ceafbd geda gcdfae efbcdg fgced da degbcfa adf cdagf | aegd ad da geabcfd +fgdacb dg efagc gcd cgefab edcgfa cbedf gfdce eabgcfd daeg | dgc gdc cfedga cdg +bcadeg fbgaec ecdag gbafced ba bca edab bgadc fdcgae gdbcf | bcadfge edgacf bac dabgce +aedfb dbfcae caefbdg aefcdg gafcb dfcba bgfeda dc fdc edcb | bdfae cd eafdb cdf +cga afdebc gc adcgefb adbgf acgfde gcabd gbedac ecgb acdeb | gbce ecadb daebcg gc +cdf dcafg df cgade cebgad dcgfea fdacbeg dgbfec afbgc fade | bgeafdc feda edaf fbgac +fagbc dbag feadgc gfa dcebfg gbdcf ag gecafbd ceafb bagcfd | fadegcb gacfed defcbg dgcbaef +cadbfeg dbgace fcagd bedfca cfegd afgb bgdfca ga adg fdabc | dfcag gcedf cefabd fbadc +fgeabd egbca dfage fdagec fb dacbfe badgecf baf gfaeb bdgf | bfdg fdbg ebagc beafg +gbdaefc fa dgafb feda fegbdc dfbeg gaf cegfba gacdb badgfe | bagdf fa afg ebgcdf +bedc fbagd bdage cgdeab eba gcabef afcdge edgca be cfbgeda | geadb be dceb ebdgca +fe fceb acegdfb efg fdgce fagbed bedgc fedbgc dagbce agdfc | febcdg egdcfab dcebgf gef +fagdc ebacgd ecgdb decafgb cefbda geba bagcd bad fbdgce ba | ecdbg abeg dfbeac fgdaceb +decgaf cgab aedbc cbaegd ca bdegc fcegdab efabd cda cdbfeg | aedbf ebdaf cda dca +gafbde ecfda afdegc ecdgb ba cbfa cfadeb edabc bea ecbdfga | eab ecdgb bea ab +gbecaf dbgf facbgde cegabd gebdfa fdaec dfage egf adebg fg | gfe egf becafg abfgedc +gfceabd adgcb bcdf afb gafbd becafg bf dagef agbdec fgcdba | cbagfd fdbga dcbega dfgecba +ba afegdb cdab cfgeb facebdg fcabg cdagf fdgcab gab decgfa | cfbdega dacb agdcfb gabfdc +adebgc bdefcga afegdb bcedf bfg fedbg fg efga dbgea facdbg | gf gf debafg fgb +cegfda gfa ecgf gf ebgdac afcbd ecagd afebgd fcdag begcafd | fcabd dfacgbe fcabedg ceadfg +febgcd fcbda cdgab fcgbad bf fdcea dfb egbadfc bgcdae fbag | cedfa fb fb gabf +ebfag fcbade ad adec bgecdfa afd gebfcd bfdec fbade bgcdfa | adf ecad ebadf bdcgafe +cafbgde bdace cefadg gefcbd ag egdcf gae bcfaeg gcdae adfg | egabcdf cedga cedag adgf +agcef egcab fc dfeagb fce gbaefdc ebcadf aefdg adefcg gcfd | dfgc aebcg egdcfba agbec +db fdbcge dgb gfaced bfacgde dfba egdfba cabge edgfa gebda | eafbgdc db db gdafcbe +cad cdfgea caegbf agbd cbdef gbcdaf gadecbf ad bcafg dacbf | fgecba cgbfeda da dbecafg +bdegaf gfde gf bcadeg dafgcb afg bgaef eagdb cfbeadg fbeac | ebgad gfed debfcag fdge +bgac edgacbf dfbea cgebda gea cfedga agedb ag dcgeb fcedgb | dbage bdgacef cfagdeb deabg +caebd edf edgfbc fe abfegdc cdfea gfdac eacfgd gfacbd gaef | fega fgae gafe cabde +bfadegc dafec dbgaec abdcef fdaegc dag cagf ga aedgf fbedg | bcafedg ag ga adg +dcgfa dgcafeb cfb bf cegafb begcda fdgbce dcebg bfed fcgdb | dgcebaf bedf fb bcged +cbegd edfa fdc gadcfb gbcefad bgacef acfbe ebacfd bfecd fd | fdc dbgafc cefbd cdf +fgd dgbfe gf gcef bdecf dgcfba acfbde gdefbc badge facbdeg | dcfaebg fg fgd fbgced +abdeg adebcg ebafdc bgcadfe gedc ega bgdaf cabed efacbg ge | ge gae age afebgdc +debfa dfbga fagdc fbg cadgfe acgfbd efgcab cgfeabd dbcg bg | fgdba bg gfacbed ecabgf +bc egdba ebdacg cgba dabfec bec defcg cdbefga gbfead becdg | bcefagd bec cebfgda cb +deagbfc agebdc fbedca fa edgafc bfac adcbe gfedb afd efdab | fad dbaef cbfdae af +afgdeb beagd daecbfg gbfedc ecd becad egac agecbd ce fbcda | fbadge eacdbg cde ce +fgabec gefb cdagefb fbacgd dgecba adecf eg cefga egc gcfba | dafgbc gec bfeg gefb +gbcf fceag gb bag bdafge gbeac fdegca cfegdab egfacb daceb | bg cagfeb aedbc cbaeg +gbac fedagb gaf adcbf ceabfd abecgfd bfcdga ga edgcf gfcda | badcf fcedg adbcfg agebfd +gdbfc fbaecd gaef ef efb agebc gabdefc ebcgad facegb bgcfe | cfgdbae faeg efga cdegab +fbacge decgba bcafd fedgab fageb ed efgd ebafd gedbcfa bed | de ed bdafe de +bcgdf badgec de fecgd cfeag dfbe dcgafeb gdacfb ced fdbgce | de de edc gafbdc +gebfa fd dgacb dfgba bfdeca daf becfga edfg afgebcd gfadbe | bdcfea bafecgd acdegfb fgbdea +fgdcb efdcg gcfabd gcdbafe gbf acfb aegcdb edfabg fb gbcda | bgafde gfcbd fb cedbfga +de fadcg befcdg fbeac adcef efd ebgfca cbefadg edba dbaecf | eagbfcd beagfc bcefgd beda +ebcfad fbecgd edgba df adgfcbe dfe bcfaeg bedgf bcefg dgfc | df bcagef df aecfgb +acgdb gdc gcebdaf abcge ecgdfa egbd cbaegf gdacbe fcdba dg | egcfda aebgfc aegcbdf cgd +gc cge cgdb deafbgc dageb cbega agbcde cedgfa gbefad cefab | dabfeg gc eabcgdf gabde +abegc agecf adfcbge bcdaeg fbadec bca cb bcgd egdba gbafde | gbdc begad bfecda cb +daecgb abegd bagedf begfcd fe feag abefd bfe fbgceda fbdac | fbdac gcebdaf egfa fe +eafcbdg abcdg acegf dfcga fgaebc defcbg aefd dfc dfgace df | df adef fd dfea +fdecabg ba agebdc adb gcdea befdg gabc egdba badefc ecagdf | bda gcabde gdaec fgdcae +cdfg dbecf dg caebdf gbd beafg cbegfd ebcgdfa gdfeb agdecb | cedfb gd cbgeafd debgacf +bca cadbfeg gabfcd bcgafe caebg adgfec bc bcfe gefac beadg | cgefab cgfae befc acbegf +cabgdef cgabde efcab degcf gcfdeb da fgda cda feagcd aedcf | adc da cgaedf cgdfbe +dagfbe gaefb efcgadb fbcae fg gbf edbag cbgdae gadfbc gfde | bgf gf acgdfb cfgdba +cbedag edgca bfcagde gfbae gfdea df adfc dafceg fedbcg gdf | adecg gbafe acdbfeg df +ebfc ef gecfad gfdcb egbad gfabcd ecgdafb feg bfgdce dbefg | aegdb bfged ef bafdgc +ce cefd cafdg cdgefa geacbd eca gcbfad gebfa afecg bfedcga | ecgfa cea defc ce +ceb edbgafc fabec cb dfagec fgbea daefcb efdca cebgda bfdc | bec eadfgbc degabc adgfce +cgf aefbdgc gf bagf gedacf ecgfb cdfeb acgbe ebcfga cedbga | gf fbgcade cbegfda acbdfeg diff --git a/aoc2021/input/day08_provided.txt b/aoc2021/input/day08_provided.txt new file mode 100644 index 0000000..c9f629b --- /dev/null +++ b/aoc2021/input/day08_provided.txt @@ -0,0 +1,10 @@ +be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe +edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc +fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg +fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb +aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea +fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb +dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe +bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef +egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb +gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce diff --git a/aoc2021/src/day08.rs b/aoc2021/src/day08.rs new file mode 100644 index 0000000..7ec0260 --- /dev/null +++ b/aoc2021/src/day08.rs @@ -0,0 +1,68 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day08.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let entries = input + .lines() + .map(TryInto::try_into) + .collect::>>()?; + + Ok(entries.iter().map(Entry::count_easy_digits_in_output).sum()) +} + +struct Entry<'a> { + four_digits_output: Vec<&'a str>, +} + +impl<'a> Entry<'a> { + fn count_easy_digits_in_output(&self) -> usize { + self.four_digits_output + .iter() + .filter(|digit| Self::is_easy_digit(digit)) + .count() + } + + fn is_easy_digit(digit: &str) -> bool { + matches!(digit.len(), 2 | 3 | 4 | 7) + } +} + +impl<'a> TryFrom<&'a str> for Entry<'a> { + type Error = anyhow::Error; + + fn try_from(s: &'a str) -> Result { + let (_, output) = s.split_once(" | ").context("couldn't split on ` | `")?; + + Ok(Self { + four_digits_output: output.trim().split(' ').collect(), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day08_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 26); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 488); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 5fb1402..31b0d7e 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -7,3 +7,4 @@ pub mod day04; pub mod day05; pub mod day06; pub mod day07; +pub mod day08; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 2bc1b96..7d1b154 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -9,6 +9,7 @@ use aoc2021::day04; use aoc2021::day05; use aoc2021::day06; use aoc2021::day07; +use aoc2021::day08; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -19,6 +20,7 @@ fn main() -> Result<()> { day05::run, day06::run, day07::run, + day08::run, ]; aoc::run(days) From 65ddabcf0085884fe93a1aec789506dcb2a6bb6f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 8 Dec 2021 19:36:00 +0100 Subject: [PATCH 062/134] 2021: day08: part 2 --- aoc2021/src/day08.rs | 148 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 4 deletions(-) diff --git a/aoc2021/src/day08.rs b/aoc2021/src/day08.rs index 7ec0260..a61474b 100644 --- a/aoc2021/src/day08.rs +++ b/aoc2021/src/day08.rs @@ -8,6 +8,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -21,20 +22,148 @@ fn part1(input: &str) -> Result { Ok(entries.iter().map(Entry::count_easy_digits_in_output).sum()) } +fn part2(input: &str) -> Result { + let entries = input + .lines() + .map(TryInto::try_into) + .collect::>>()?; + + let mut sum = 0; + + for entry in entries { + let mapping = entry.compute_mapping()?; + sum += entry.decode_output(&mapping)?; + } + + Ok(sum) +} + struct Entry<'a> { four_digits_output: Vec<&'a str>, + unique_signals: Vec<&'a str>, } impl<'a> Entry<'a> { fn count_easy_digits_in_output(&self) -> usize { self.four_digits_output .iter() - .filter(|digit| Self::is_easy_digit(digit)) + .filter_map(|digit| Self::translate_easy_digit(digit)) .count() } - fn is_easy_digit(digit: &str) -> bool { - matches!(digit.len(), 2 | 3 | 4 | 7) + fn translate_easy_digit(digit: &str) -> Option { + match digit.len() { + 2 => Some(1), + 3 => Some(7), + 4 => Some(4), + 7 => Some(8), + _ => None, + } + } + + fn compute_mapping(&self) -> Result> { + let mut mapping = Vec::new(); + + // first, let's get the easy digits + self.unique_signals + .iter() + .filter_map(|signal| Self::translate_easy_digit(signal).zip(Some(signal))) + .for_each(|(translation, &signal)| { + mapping.push((signal, translation)); + }); + + // now we can get `9` for free: it's the signal that uses 6 segments and has 4 in common + // with the digit `4` (`6` and `0` also use 6 segments, but only have 3 segments in common + // with `4`). + let (four, _) = *mapping + .iter() + .find(|(_, translation)| *translation == 4) + .context("no signal found for the digit 4!")?; + let nine = self + .unique_signals + .iter() + .filter(|signal| signal.len() == 6) + .find(|signal| four.chars().all(|c| signal.contains(c))) + .context("couldn't identify any signal corresponding to the digit 9!")?; + mapping.push((nine, 9)); + + // `0` has 2 segments in common with `1`, while `6` only has 1. + let (one, _) = *mapping + .iter() + .find(|(_, translation)| *translation == 1) + .context("no signal found for the digit 1!")?; + let zero = self + .unique_signals + .iter() + .filter(|signal| signal.len() == 6) + .filter(|signal| *signal != nine) + .find(|signal| one.chars().all(|c| signal.contains(c))) + .context("couldn't identify any signal corresponding to the digit 0!")?; + mapping.push((zero, 0)); + + // `6` is an easy one now, the only other signal with 6 segments, that isn't nine or zero. + let six = self + .unique_signals + .iter() + .filter(|signal| signal.len() == 6) + .find(|signal| *signal != nine && *signal != zero) + .context("couldn't identify any signal corresponding to the digit 6!")?; + mapping.push((six, 6)); + + // `2`, `3` and `5` have 5 segments each. + // + // `3` has 2 segments in common with `1`. + let three = self + .unique_signals + .iter() + .filter(|signal| signal.len() == 5) + .find(|signal| one.chars().all(|c| signal.contains(c))) + .context("couldn't identify any signal corresponding to the digit 3!")?; + mapping.push((three, 3)); + + // `5` has all its segments used in `6`, `2` doesn't. + let five = self + .unique_signals + .iter() + .filter(|signal| signal.len() == 5) + .find(|signal| signal.chars().all(|c| six.contains(c))) + .context("couldn't identify any signal corresponding to the digit 5!")?; + mapping.push((five, 5)); + + // `2` is the last one! + let two = self + .unique_signals + .iter() + .filter(|signal| signal.len() == 5) + .find(|signal| *signal != five && *signal != three) + .context("couldn't identify any signal corresponding to the digit 2!")?; + mapping.push((two, 2)); + + debug_assert_eq!(mapping.len(), 10); + + Ok(mapping) + } + + fn decode_output(&self, digit_mapping: &[(&str, u64)]) -> Result { + let mut res = 0; + for digit in &self.four_digits_output { + // search is kind of ugly, but having to sort everything is probably time consuming as + // well. + let digit = digit_mapping + .iter() + .find_map(|(signal, translation)| { + if digit.len() == signal.len() && digit.chars().all(|c| signal.contains(c)) { + Some(translation) + } else { + None + } + }) + .with_context(|| format!("couldn't translate digit `{}`", digit))?; + + res = (res * 10) + digit; + } + + Ok(res) } } @@ -42,10 +171,11 @@ impl<'a> TryFrom<&'a str> for Entry<'a> { type Error = anyhow::Error; fn try_from(s: &'a str) -> Result { - let (_, output) = s.split_once(" | ").context("couldn't split on ` | `")?; + let (signals, output) = s.split_once(" | ").context("couldn't split on ` | `")?; Ok(Self { four_digits_output: output.trim().split(' ').collect(), + unique_signals: signals.trim().split(' ').collect(), }) } } @@ -65,4 +195,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 488); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 61229); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 1040429); + } } From b5c79e9b1c84408de75ef9622670d9294680a43b Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 8 Dec 2021 19:45:40 +0100 Subject: [PATCH 063/134] 2021: day08: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 8263066..26dd631 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -7,6 +7,7 @@ use aoc2021::day04; use aoc2021::day05; use aoc2021::day06; use aoc2021::day07; +use aoc2021::day08; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -16,6 +17,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); + c.bench_function("day08", |b| b.iter(|| day08::run().unwrap())); } criterion_group! { From b5c4b72864e458dc3e549d72b4e86ec8a9e03cd3 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 8 Dec 2021 20:04:45 +0100 Subject: [PATCH 064/134] 2021: day08: only store "hard" digits in mapping --- aoc2021/src/day08.rs | 58 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/aoc2021/src/day08.rs b/aoc2021/src/day08.rs index a61474b..f358720 100644 --- a/aoc2021/src/day08.rs +++ b/aoc2021/src/day08.rs @@ -65,21 +65,20 @@ impl<'a> Entry<'a> { let mut mapping = Vec::new(); // first, let's get the easy digits - self.unique_signals + let easy_digits: Vec<(&str, u64)> = self + .unique_signals .iter() - .filter_map(|signal| Self::translate_easy_digit(signal).zip(Some(signal))) - .for_each(|(translation, &signal)| { - mapping.push((signal, translation)); - }); + .filter_map(|signal| Some(*signal).zip(Self::translate_easy_digit(signal))) + .collect(); // now we can get `9` for free: it's the signal that uses 6 segments and has 4 in common // with the digit `4` (`6` and `0` also use 6 segments, but only have 3 segments in common // with `4`). - let (four, _) = *mapping + let (four, _) = *easy_digits .iter() .find(|(_, translation)| *translation == 4) .context("no signal found for the digit 4!")?; - let nine = self + let nine = *self .unique_signals .iter() .filter(|signal| signal.len() == 6) @@ -88,32 +87,32 @@ impl<'a> Entry<'a> { mapping.push((nine, 9)); // `0` has 2 segments in common with `1`, while `6` only has 1. - let (one, _) = *mapping + let (one, _) = *easy_digits .iter() .find(|(_, translation)| *translation == 1) .context("no signal found for the digit 1!")?; - let zero = self + let zero = *self .unique_signals .iter() - .filter(|signal| signal.len() == 6) - .filter(|signal| *signal != nine) + .filter(|&signal| signal.len() == 6) + .filter(|&signal| *signal != nine) .find(|signal| one.chars().all(|c| signal.contains(c))) .context("couldn't identify any signal corresponding to the digit 0!")?; mapping.push((zero, 0)); // `6` is an easy one now, the only other signal with 6 segments, that isn't nine or zero. - let six = self + let six = *self .unique_signals .iter() .filter(|signal| signal.len() == 6) - .find(|signal| *signal != nine && *signal != zero) + .find(|&signal| *signal != nine && *signal != zero) .context("couldn't identify any signal corresponding to the digit 6!")?; mapping.push((six, 6)); // `2`, `3` and `5` have 5 segments each. // // `3` has 2 segments in common with `1`. - let three = self + let three = *self .unique_signals .iter() .filter(|signal| signal.len() == 5) @@ -122,7 +121,7 @@ impl<'a> Entry<'a> { mapping.push((three, 3)); // `5` has all its segments used in `6`, `2` doesn't. - let five = self + let five = *self .unique_signals .iter() .filter(|signal| signal.len() == 5) @@ -135,11 +134,11 @@ impl<'a> Entry<'a> { .unique_signals .iter() .filter(|signal| signal.len() == 5) - .find(|signal| *signal != five && *signal != three) + .find(|&signal| *signal != five && *signal != three) .context("couldn't identify any signal corresponding to the digit 2!")?; mapping.push((two, 2)); - debug_assert_eq!(mapping.len(), 10); + debug_assert_eq!(mapping.len(), 6); Ok(mapping) } @@ -149,16 +148,21 @@ impl<'a> Entry<'a> { for digit in &self.four_digits_output { // search is kind of ugly, but having to sort everything is probably time consuming as // well. - let digit = digit_mapping - .iter() - .find_map(|(signal, translation)| { - if digit.len() == signal.len() && digit.chars().all(|c| signal.contains(c)) { - Some(translation) - } else { - None - } - }) - .with_context(|| format!("couldn't translate digit `{}`", digit))?; + let digit = if let Some(translation) = Self::translate_easy_digit(digit) { + translation + } else { + *digit_mapping + .iter() + .find_map(|(signal, translation)| { + if digit.len() == signal.len() && digit.chars().all(|c| signal.contains(c)) + { + Some(translation) + } else { + None + } + }) + .with_context(|| format!("couldn't translate digit `{}`", digit))? + }; res = (res * 10) + digit; } From 6eb80413625f3830f89768b39bc70da0f8db8f5d Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 9 Dec 2021 19:39:35 +0100 Subject: [PATCH 065/134] 2021: day09: part 1 --- aoc2021/input/day09.txt | 100 +++++++++++++++++++++++ aoc2021/input/day09_provided.txt | 5 ++ aoc2021/src/day09.rs | 133 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 241 insertions(+) create mode 100644 aoc2021/input/day09.txt create mode 100644 aoc2021/input/day09_provided.txt create mode 100644 aoc2021/src/day09.rs diff --git a/aoc2021/input/day09.txt b/aoc2021/input/day09.txt new file mode 100644 index 0000000..3084053 --- /dev/null +++ b/aoc2021/input/day09.txt @@ -0,0 +1,100 @@ +8969799987646798965432975435334567987976999867976794468999979759865767896545699865678952123899325456 +7658678998434597654321984320123458976765789998965432367998968998754556789434987654489543535698912349 +6243457899325679997620195431934569765654667999993101246796856997643245679759865443356954656987894498 +4102345678912998789531297659895978954213456899874512659965239876432134578998754321267899877976789987 +3212466989109887678942989797659799542102345798765423867894103987543026799989866532345678999765469896 +4323487893299795489899978987947689654243496789876864988943212498654135999967987765466789987654398754 +5694698999987654398788967895434589879359989999987879999994467598795276789756798876567895699873219865 +6788799998998975976567456899598678985498879898798989865879978939876987993145899987879954598765102987 +7899899897989989875432345678998789897987968799659197654756899857989899921034999898989433459854213698 +8913998766779999964321234569999897789876754678943296543434998769997797892129898789995321298765434569 +9101987655767989875732345679987946689654343469764987542127899898765656789298797678976510159977675678 +3212396543256878986893478999876434596543212378965698321016789999854245991987664599987621245698789789 +5433495432145767897954567896985423689954301299986986432125899998762127892976553469998753457789899892 +6567989543023456798966878994597434567896212989897998764234678987654679999897432348999864567997999953 +7699978932124569899987989789986545678997329878798969976656789998785793599789645667898965989456789867 +8988767993237678998998995678998698789865498765689654399787898999887975987689956788977899992398999879 +9976458789398899687899234567999899899978987654569543219899956789998989896579899899866458943989109989 +9854345679479976556954346788998999999989876543468965323987548999969498765466788956954367969878998797 +8765456796567895434699459899996878998694987742556896439876439999854329654354567899875167898657897656 +9896577897679966724978998943985456896513498651345689546989998898765439843212456789984356789346789843 +5998678998789653219866987899876368954323489710556898768998787789876898756533568899995679891245898932 +4299789349898742109654346798765458976535679921237999879867546678987989987654679978976789910234567891 +5989894234969876298743234569878567899796798545346899998653434569399876599785789567987898929345688932 +9878943123459865459652127999989678978998987655456789129742129679210997679897995456798987898957899543 +4965431012567986798764335679598789469899998767767891019843298999429698789998932348899876767899999654 +3986949143479997899865466789409892346789979879878992123969976578998539997899321467999765646978998765 +2399898954567898999876567893219921235798766990999789235698895457997623456921932346998654334567899978 +1299767895789999999987678999398633896899954321235695476987789598998735797899894459876543212456899899 +2988956799899998989998989798976545789999896532346789569986679679439987898986789667987654201268999798 +9876545788987887679899897657987656798998789987656799698785458994321299999575678978998764312349987677 +8787434867976544556797623546698767987887678999767978988654356789490123985434567899799876543456997536 +9643323456895433545679510134599879876765567899878969876543234899989349876423468976567998954567895215 +7432102568954321234595431235678998765634345678989456998754345987879956994312469965456899996789954324 +6543212349975410123489545676789769874321234789790365679976576896567898984203457896597946987898766534 +7695323457897521236679686787896656965454345689621234567987687932498959876412679989989532498939878745 +8986445569998934345689899998955549877965678796542347678999798940989942986567897678978901359012999987 +9997556978969765456897998899643435988876789898753456789999899759878891987879976564568992459223989999 +9998967889349876577896767789532123999998898999897598999988959898767790298989985323456789998939878998 +9879878993212987698965656679921039876439967899999979899876545987656689349896546012367899876899767987 +8867989854623999999873245567892134965323456789998765789987632496545459998765432123456998765698959876 +7656799769539897895482133456954379854212597993987653999898521569632367899979643236567898754987939984 +9545678998998765989321012567895459763102379932199654569765437698743458932398654387989987543656898765 +8936567897899874578932123456976598765213467891034987698996548899654567891019767898999876521246789897 +7623468976799765799543438967898679984324579932123498997989679998765678942423989999978988430134899998 +5434578985679878997654567898939789995445698965349569876678989899876789759994596598769877321475678999 +6559689643456989298775678999029895987576987896467978965457899782989899998789789429898765432386799989 +7798789432345690129976789998939974599999896889878999784346998651296989876598993219989876743457898878 +8989895431258789245987899987898953459878784978989989653245696542345679999457894398879987857567947566 +9877987646779898659998999876567994979967643467899878964126789655456989998379965976569898967679434345 +9965499867895989798999598765476789398756532456798967893235899766967998987567899879456799298989321234 +9876789978954878987995459654345891296543101236987656789345678979899896798679998768345692129695433545 +1988899989763567896889698743236892989754752345698545678956799998789765698789876753238789234569546656 +3499949999874878945779987632123999768969643467899234589999899876578954329999875432124679945698756767 +9989237999996989234567976431019888943498955989998545678989906987689965410199764321012989896799999879 +8978956789997892146678986542239767832487996792987656789679215698896894321989875754123456797899989992 +7867897899989921012349597953398756721276789891098767896598924599965789939878996543254597898998978991 +5658998979876432124692398965986543210345996999239878965487895987654597898965987654765678949987959889 +4234789767987543235789459896798765321267894878945989874356789998783456987954599875676989657995349778 +2123679854987674347896569789999876543458943467956999995245894987632969876843456996787899969986234567 +3012568966998989498987998677899987754567892458969899874348943986549898765652345987998999898942123679 +6123456799879996579999899576789999869678943467899789965457921098798789854321234598949998677991014589 +5434767959767987898998765435699987998789765598923679876767892349987698765210349899659986566789323899 +8545679943854598986987654324589996689896986679013459989888999959876579894321235789898975345678946789 +7676899892123999875698763215679965456965498793223598794999998799975467965452347999987654234599659899 +8989986799019887654679974323467896568942349954334987653234987678894359879643458969876542123689898988 +9798865678998765712578985454598987979321257895455798852109895467789234998754569653999892012567987877 +7697654367897654323456798579689898989910969999579999743219654347689945679967679999549764123456896556 +3598765456998768974567987689795679099899898997678987654498653201567896989898798878934965236587974449 +2359987767999899765978998999964589298787656789989398765789765443489989899789897767949874347678953237 +1491299879999999987889459329899999987654745894590249876899899865679876784699976456899985678789654126 +0989901989789989998991399439777899898543435789931399987934999876898765633987895367899876799896543235 +9877899995678978989532578998656998797632124567893989998923498989999874012346789246987989898987655345 +8766798989789469878943789879546899654321012978999878999212997796799982178968992134976591997899796656 +9954547878992399967899899865434678998732129899998769899929876565689875357899843239899432395698989768 +7653235669991987856798999876215789987654239789987657789899765373499876567898765498798954986987878979 +8762124456789996543467894989104589998768998678986545678789876212345987688959876569657995999876567999 +9989012347899865432356993298913478999879876548995434345678968101356799799545987898745789865985456789 +6598924456895996421245689987897567892989998756789621257989543212456893987634598999658999654986687899 +7987899568934987840234567896789978921399899987898530968999964566567892396723679998767898953199789989 +9876798979924987656495888934567899210198789898987649899999898788689910975435678979878997899019899975 +7675356899899898767686789123679954391297698769999789799898789898799921296586789567989876798923989764 +6543245698798789879899899019789995989987569543935998689765679909899892397697994345698765867894578953 +8432136987657678999910998998998789778943468999899019789954234912998789998998943234989544556895678942 +7543239876543457989422997867997643567892979679678929899892123893989689789989432109875432347989989431 +8664345975442345678999876656789432456789895434569439998789234679876597678976543499964321235679894320 +8798459864321256899987655346896563567898789212497598687679345798765326567897654989984310199998789491 +9897568995438767898998643238987678689987679101789987543568996987654215458998775979996532987877578989 +9987679986549878987976543129998989799986568932679876542356789099873101299439989868987543976966457577 +8998790197678989756797643256899999899865457894569867421867992198764323489321098756597654965452323456 +7679891998789691234598765345678923989954366789697654320378943579885654678999987643469869876321012345 +4567939879896542456999975457789019878942134898789865621247894567986965699678996532398979876432123456 +3459329765998653567895986568993139765899012979899876732456789678987876896599989421297989998673234568 +5678909984329764678993497679954397654678923567943987654567997999799987897987678932986794569984545778 +8799998965679889889989598989795986543567994578992399876799236789654398999896568943975523679995656789 +9989767899789997993978999895689997562456789989989976987890145899876789998768456999854302368987789894 +9879356789899876432767898764789775431634578899879765698991236799987896999654397789763213459998993912 +8656244678998765321545987653459654320123456789767954019789445678998945898743235678954424668999542103 +7542133569899878510126976432398797431835668892456892124689556889329236789655656789765634569987543765 +6531012456789996431239954321239986545646799986587893776789678993210127898767787899879745678998955897 +6542123568899987544398765510123497656656789987678954567898799654431338999978898910989656789209876789 diff --git a/aoc2021/input/day09_provided.txt b/aoc2021/input/day09_provided.txt new file mode 100644 index 0000000..6dee4a4 --- /dev/null +++ b/aoc2021/input/day09_provided.txt @@ -0,0 +1,5 @@ +2199943210 +3987894921 +9856789892 +8767896789 +9899965678 diff --git a/aoc2021/src/day09.rs b/aoc2021/src/day09.rs new file mode 100644 index 0000000..3dd7c4c --- /dev/null +++ b/aoc2021/src/day09.rs @@ -0,0 +1,133 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day09.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let height_map: HeightMap = input.parse()?; + + Ok(height_map + .low_points() + .map(|(x, y)| height_map.risk_level(x, y)) + .sum()) +} + +#[derive(Clone, Copy)] +enum Neighbour { + Up, + Down, + Left, + Right, +} + +impl Neighbour { + fn apply(&self, x: usize, y: usize, width: usize, height: usize) -> Option<(usize, usize)> { + match self { + Neighbour::Left if x > 0 => Some((x - 1, y)), + Neighbour::Right if x < width - 1 => Some((x + 1, y)), + Neighbour::Up if y > 0 => Some((x, y - 1)), + Neighbour::Down if y < height - 1 => Some((x, y + 1)), + _ => None, + } + } + + const ALL: &'static [Self] = &[ + Neighbour::Left, + Neighbour::Right, + Neighbour::Up, + Neighbour::Down, + ]; +} + +#[derive(Debug)] +struct HeightMap { + heights: Vec, + width: usize, + height: usize, +} + +impl HeightMap { + fn low_points(&self) -> impl Iterator + '_ { + (0..self.height) + .flat_map(|y| (0..self.width).map(move |x| (x, y))) + .filter(|&(x, y)| { + self.neighbours(x, y) + .all(|(nx, ny)| self.get(x, y) < self.get(nx, ny)) + }) + } + + fn neighbours(&self, x: usize, y: usize) -> impl Iterator + '_ { + Neighbour::ALL + .iter() + .copied() + .filter_map(move |neighbour| neighbour.apply(x, y, self.width, self.height)) + } + + fn risk_level(&self, x: usize, y: usize) -> u64 { + self.get(x, y) as u64 + 1 + } + + fn get(&self, x: usize, y: usize) -> u8 { + self.heights[y * self.width + x] + } +} + +impl std::str::FromStr for HeightMap { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut heights = Vec::new(); + + let mut height = 0; + let mut width = None; + for line in s.lines().map(str::trim) { + let line = line + .chars() + .map(|chr| { + chr.to_digit(10) + .map(|digit| digit as u8) + .with_context(|| format!("cannot parse char {} to digit", chr)) + }) + .collect::>>()?; + + if width.is_none() { + width = Some(line.len()); + } + + height += 1; + heights.extend_from_slice(&line); + } + + Ok(HeightMap { + heights, + width: width.context("0 lines parsed, width never computed")?, + height, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day09_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 15); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 522); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 31b0d7e..98f8aa8 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -8,3 +8,4 @@ pub mod day05; pub mod day06; pub mod day07; pub mod day08; +pub mod day09; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 7d1b154..b94515f 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -10,6 +10,7 @@ use aoc2021::day05; use aoc2021::day06; use aoc2021::day07; use aoc2021::day08; +use aoc2021::day09; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -21,6 +22,7 @@ fn main() -> Result<()> { day06::run, day07::run, day08::run, + day09::run, ]; aoc::run(days) From a30bbaa4e19f87ef145309e9eec8890f68b932ab Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 9 Dec 2021 20:03:48 +0100 Subject: [PATCH 066/134] 2021: day09: part 2 --- aoc2021/src/day09.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/aoc2021/src/day09.rs b/aoc2021/src/day09.rs index 3dd7c4c..9d21357 100644 --- a/aoc2021/src/day09.rs +++ b/aoc2021/src/day09.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::fmt::Write; use anyhow::{Context, Result}; @@ -8,6 +9,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -21,6 +23,25 @@ fn part1(input: &str) -> Result { .sum()) } +fn part2(input: &str) -> Result { + let mut height_map: HeightMap = input.parse()?; + + let low_points: Vec<_> = height_map.low_points().collect(); + + let mut bassin_sizes: Vec<_> = low_points + .iter() + .map(|&(x, y)| height_map.fill_basin(x, y)) + .collect(); + bassin_sizes.sort_unstable(); + + bassin_sizes + .iter() + .copied() + .skip(bassin_sizes.len() - 3) + .reduce(|acc, elem| acc * elem) + .context("couldn't find 3 bassins") +} + #[derive(Clone, Copy)] enum Neighbour { Up, @@ -53,9 +74,28 @@ struct HeightMap { heights: Vec, width: usize, height: usize, + filled_points: HashSet<(usize, usize)>, } impl HeightMap { + fn fill_basin(&mut self, x: usize, y: usize) -> u64 { + if self.get(x, y) == 9 { + return 0; + } + + if self.filled_points.contains(&(x, y)) { + return 0; + } + self.filled_points.insert((x, y)); + + let neighbours: Vec<_> = self.neighbours(x, y).collect(); + neighbours + .iter() + .map(|&(nx, ny)| self.fill_basin(nx, ny)) + .sum::() + + 1 + } + fn low_points(&self) -> impl Iterator + '_ { (0..self.height) .flat_map(|y| (0..self.width).map(move |x| (x, y))) @@ -111,6 +151,7 @@ impl std::str::FromStr for HeightMap { heights, width: width.context("0 lines parsed, width never computed")?, height, + filled_points: HashSet::new(), }) } } @@ -130,4 +171,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 522); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 1134); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 916688); + } } From 4cf5c2c6b0a8df9429edfa701db756be13eab441 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 9 Dec 2021 20:03:56 +0100 Subject: [PATCH 067/134] 2021: day09: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 26dd631..eeb312e 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -8,6 +8,7 @@ use aoc2021::day05; use aoc2021::day06; use aoc2021::day07; use aoc2021::day08; +use aoc2021::day09; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -18,6 +19,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); c.bench_function("day08", |b| b.iter(|| day08::run().unwrap())); + c.bench_function("day09", |b| b.iter(|| day09::run().unwrap())); } criterion_group! { From 6c7b3d9cc6ad1007e2ef3d92aa7f66bf6af06e77 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 10 Dec 2021 14:13:20 +0100 Subject: [PATCH 068/134] 2021: day10: part 1 --- aoc2021/input/day10.txt | 110 +++++++++++++++++++++++++++ aoc2021/input/day10_provided.txt | 10 +++ aoc2021/src/day10.rs | 125 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 248 insertions(+) create mode 100644 aoc2021/input/day10.txt create mode 100644 aoc2021/input/day10_provided.txt create mode 100644 aoc2021/src/day10.rs diff --git a/aoc2021/input/day10.txt b/aoc2021/input/day10.txt new file mode 100644 index 0000000..3a3d7bd --- /dev/null +++ b/aoc2021/input/day10.txt @@ -0,0 +1,110 @@ +<{[[({([{<[[([()<>]<<><>>)<[[]()]{<>()}>][<(()[])<()<>>>]]<(<(<><>)(())>)[<([]()){<><>}>{{()<>}<{}>}]>>[({ +<<({<{{{[(<{([{}{}]{{}[]}){({}())}}<<[[][]](()<>)>[{<><>}<{}<>>]>>(<[[()]([]{})]((()<>)[()() +({<<({[<[[<[([()])]<<<{}<>><()[]>>[[()<>]<[]()>]>>([((()[])[()])]{[[()()]<<><>>][{<>[]}(()<>)]}) +(([[<<[{(({{{(()<>)[()()]}[({}<>)[[][]]]}([{{}<>}<[]()}]{[[][]][()<>]})})(([({[]{}}{[][]}) +({{<[[<<{{[{[<{}{}>{[]{}}]<([]{}){()[]}>}]<{([<><>]([]<>)){({}())({}<>)}}[[<{}<>>([]{})][[()[]]]]>}}>>]] +[(<<<{([[[<{(<()<>>{<><>})(<[]<>>([][]))}[<[{}[]]>{<[]>(<><>)}]>([{{[]()}{[]()}}([<>[]][{}<> +<[{[{{([<(<{{[{}<>]({}{})}{{<>[]}(()())}}(<<<>{}>(<><>)>(<<>{}>[[]<>]))>)>[{[<[[()<>]{{}<> +{(<<[([<{<<<({()()}(<><>)}{((){})([]())}>>[<{<[]<>>{[]{}}}([()()])>]>}>]{{([{<{{[]<>}(<>)}<({}( +((<[{(({([<{(<[][]>)[<<>{}><()<>>]}<{<{}{}>}[{()[]}<{}[]>]>>])})<[{[{([{[]()}((){})][<<>()><()()>])>]}][[({{[ +[[{([[<<[({[<<[]{}>{[][]}>(<()<>>[{}()])][([{}[]}[<><>]){[{}()]}]}[<<<{}<>>{()<>}>(<{}()>([]()))>{[[<><>][ +{{{<[([[{<[<{([]{}>{<>()}}{<(){}><()()>}>[{[[][]](<>())}[{[]<>}[<>[]]]]]{<{{{}[]}{<><>}}[[()()](< +(([{(({[[[[{(<<>[]>((){})){<()<>><[]{}>}}{[{{}()}(()[])]((()){()<>})}]]]<[<<{(()[])<{}[]>}{ +{<<([(<([{{(<(()<>)[[][]]>{[[]{}]{(){}}})[{<(){}>[[]<>]}]}}])[[[([[{()()}{<>[]}]{[()]{[][]}}]<[(( +[{<<{<([(<[<{<{}[]>{{}[]}}(([]()))>{([(){}]<()[]>)(<[][]>{[]<>})}]>[{<<{<>()}[{}[]]>{(<><>)}>{[<[]<>>{()[]}]< +<{{<{[[{{([({<()>{(){}}}((<>[])(<><>)))[(<[]<>>[()[]])<<()()>{<>{}}>]])<[{[{[]<>}{()()}][[{}{}]<[]>]}<{{{ +[(<[{([{({<<[<<>()>[[]()]]{<<>{}><{}<>>}><{<()()>{{}{}}}(({}<>)<()<>>)>>})({(([<{}<>>{[][] +{(([{[<{{[({{[{}<>][()]}<{{}<>}>}(({<>[]})))]{((<[<>{}][<>[])>[[<>()]{[][]}]))<<<({}<>){{}<>}>( +{[<{({((([[{[(<>{}){<>()}][([]{}}]}]{[<(()()){[]()}>((<>[])<(){}>)]}]){<(<<{{}<>}>>)([[{<><>}< +{<{[(<{<[({<<[<><>]{()()}>[{()<>}<{}>]>[[<[]>][{()[]}{()}]]}(<(({}()){<><>})<(()())[<>()]>>{ +<[({[[{<([[{<{{}}>(<<><>>{[]()}}}[{{<>{}}<()<>>}{[[][]]{[]<>}}]]<((([][])<<>{}>)<((){})[{}() +{{[{<[{<<{<<(<{}[]><(){}>)<{<>[]}[{}()]>>[{{[]<>}<()<>>}[{{}<>}(<>())]]><[(({}<>)({}<>))<<{}<>><< +{<<({(<[(<[[{{[][]}{{}}}<[[]()]<<>())>]](<{{{}<>}{()<>}}>)>)]<(({{[[[][]]]}<[[(){}]<[]{}>]>}))> +({{([<<{[(<<{{<>()}<[]()>}<{(){}}{{}{}}>><(<{}[]>{<>{}})<([]<>)([]())>>>)]}>>[[{<{[<<(<>{}) +<{({{({<<[{<<{<>}{{}[]}>>[[{[]<>}{()()}]<<[][]>(()())>]}]{<<{[(){}><<><>>}{{<>[]}(()<>)}>[<<(){}>[[] +<({<([[[([({<{(){}}([][])>}<[{[][]}{<>()}]<[(){}][{}<>]>>){<({{}()}{[]{}})>{[{[]{})[()[]]]<[ +{([({[(([<{((({}()){{}<>})(<()[]>{()()})){[({}{})<<>[]>]([{}][()])}}>]{<<[<[[][]]{[][]}>({[]{}}<{}()>) +<<{[<({[(<[({<{}{}><()()>})]{<<[<><>]>>}>){{[((<<><>><{}[]>)){<{[]()}(<>())>}]{{{({}<>){[]<>}}{{ +<<({<[{(([{({({}())(<>{})}{((){})})[<[[][]]([][])>]}<<[[<>{}][[]<>]]<([]<>)[()()]>><<<{}[]>(()())>>]])[[[ +[{<({<(({([([{[]}]<{[]()}[()<>]>]{{(()())<{}()>}{{[]()}<()<>>}}][{(<[]<>>[<>{}])[<[]<>><<><>>]}<(<< +<{{((<<(<{({<{<>{}}[[]{}]>})[[{{[][]}{{}<>}}]]}[(([(()[])<()<>>]((<>[])<<>{}>))<[[<>()][<> +{[([<<<({[{<<[<>{}]<[]<>>>>({<<>{}>((){})}<{[][]}{[]{}}>)}<{(([]{})<<>>><{{}()}(<><>)>}<{<[] +<({[[{{{([(({[{}<>]{[]<>}}[{()<>}<(){}>])<[<{}()>[[]<>]]>)]{{[<{<>()}[{}()]><<<><>>{[][]}>]([[[][]](<>()) +[<<{{<[[{[<(<{()[]}[(){}]><[()[]]<<>{}>>)>[[[[[]{}]{[][]}]{<[]{}><(){}>}]({{<>()}<<>{}>}({()<> +[<[[(<[[[[<<<{()<>}[[]()]>>{[[<>[]]{[]{}}]{[<>[]][[]<>]}}>]]({[({[<><>]<{}<>>}<<(){}>[{}()]>)[[<<> +<{{({<([{({({{{}()}((){})})([([][])[[]<>]](([])[{}<>]))}<(([()<>][()[]])[<[]><{}{}>])<{({}<>)<<>()>} +{<[[[([{[<<(({{}<>})(<{}()](<>{}))){[[<>[]]({}<>)]}><[((<>()){[][]})[({}())<{}<>>]]<({<>[]}{{}<> +{<[<[({<({(<(({}[])<{}>)((<>[])({}<>))><(([][])(()()))>)})({{({{<>())}<{<>()}([]{})>)[[(()<>)<<>[]>](<< +{(<(<<{{({{<{(<>[])[[]]}{(<>{})>>{<(()())[{}{}]>{{[]{}}{{}<>}}}}(<{[{}[]]<(){}>}[[{}{}]{()<>}]>([{<>{}}[<>]] +[{[{{[[[{([<(({}{})<[][]>)<([]{})<<>{}>>>[{[[]{}]([]<>)}{(()())[<>[]]}}]((<([]<>)[()<>]>(<{}()>)){<[<>[]]( +{<<<<{(({<<({(()())(<>{})}<([][])[[]()]>)[{{[]()}(<>)}]><{[<<>()>]{<[]()>[[]<>]}}>>}>[(<<<[{()<>}{{}<> +[{[(<[<{<[({[{[]<>}<[][]>]{{<>()}}}[({<>[]}{{}{}}){[[]<>](<><>)}])({({{}<>}<{}<>>)}<[((){})[{ +{<[[{[(((<({([[]<>](()<>))}[{{()<>}({}())}(<[]{}>{[]{}})])<<(({})[{}{}])[(<>{})<()>]>>>))<[{{<[{{}<>}[[][] +[[<<([{<{((([<{}{}>(<><>)][({}[])])[[(<>{}){{}<>}](<()[]>[[]()])])[{({()}{{}{}})(({}())([]{}))}({[{}[]]{ +<<((<[<(([<{[<{}<>>][<{}{}>{{}[]}]}[{<<>()>[[]{}]}{[()[]]([]{})}]><{({()()}{[]})<{[]()}[{}{}]>}{((<>( +({<<{[(({{<<{[[]()]{{}()}}{[<>{}]<[][]>}>{(([]())[<>[]]){<[]{}>{<><>}}}>{{{{<>[]}{{}()]}{{<>{}}[{}{} +{((<<{<<<((<(({}{})(()))[[()()]{{}<>}]>{(<()[]][{}[]])[[<>[]]<<>>]}))>([[{({()[]}{()[]})(<[][]><{}{}>)}[[[[][ +[(<<{<[(<([<(<[]()><()()>)>]{({[<><>]{[][]}})}}<[([(()())[{}]]<<(){}>[<><>]>)][<<((){})>>[[{<><>}[{}()]][([] +[<{[<[[(({{{[<{}[]><<>{}}][[{}<>]<<>()>]}{[{[]}[{}[]]]{[()[]]<{}<>>}}}[({<(){}>{{}{}}}<(()[])( +<{([{(<[<<<<[[{}{}]([])](<{}{}>[[][]])>{{(()[]){<>[]}}<[<><>][(){}]>}>(([[{}{}]{{}<>}](<()()>))<<(<>{})<< +[(<[[[[(({[<<<<>{}><<><>>>>]<{[{{}<>}<()>]{{[]{}}[<>[]]}}<<<()[]>([]<>)><(<>{}){[]()}>>>}))[[([{< +[([(({<{([<[({{}{}}<{}{}>)[[[]{}]({}<>)]]<[([]<>)({}[])]{(()[]){[]<>}}>>{[<{[]<>}>{[()[]]<()<>>}][<([ +{<[<[[<[{({{<[[]()][{}()]>({()[]}(()[]))}([[<>()]])})}{{<{{[<>]<[]()>}{<{}[]]}}<{{()[]}<[]<>>}([()()]<{}()>)> +[{{(<(([([((<{{}{}}({}())>{{<>[]}<[]{}>})([{<>()}{{}<>}]{<()<>>[{}{}]})>]{{[<(<>){[]{}}>{<<>[]>[()[]]}] +[<<(({[[({({[{[]{}}<<>[]]]{[()()]<<>()>}}{[{<>[]}<()>]}){{<<()[]>{[]{}}><<<>>[[]()]>}}})<[{{[< +<([{{{(<{{{<<({}()){(){})>{<{}{}>{<>()}}>{(<()[]>({}()))<({}())<()()>>}}[(({[]{}}[<>{}])([{}<>])){{{{}}(< +<<{[{[[<([[<(<{}<>><()[]>)<{<>()>[<>()]>>]][{{{{()<>}<{}[]>}[<[]()>[()[]]]}<{[{}](<>{})}>}[<[[<><>]< +[{[([{<<[([[{<<>[]>(<>())}((()())({}{}))>{[({}())<<>()>]<(<><>){()<>}>}]({([(){}]<[]<>>){<[ +[{<<[[<((({[<[[]()]>(<<>>(<>{}))]<<([]<>)[<>{}]>{<[][]>(<>())}>}(([{{}<>}{{}[]}]{[()[]]{{}{}}})< +([<<{[([[<{<{({}())}{(()<>)}>[<[{}<>][[]()]><[<>{}]({}[])>]}<[([<>()]){[()<>]([]{})}][[[{}[]]][ +<{[[{({<{(<[[(()[])<<>[]>]<<<>()>{[]<>}>]>{[<(<>()){<>[]}>(([][]))]([<[]<>><{}{}>]([<>{}](()() +{[([{{(([[<{<[{}<>]([]{})>[((){})<()[]>]}[[{{}<>}<[][]>]<{[]<>}([]())>]>{<{{{}<>}{(){}}]{{[] +[{{<[([<{[[({[{}[]][(){}]}<{<>()}<[]{}>>)]<<({()<>}[[]()]){[<>[]]<()()>}>>]{[<<(<>[])<[]<>> +<[{<[<((<({[{[{}[])(<>{})}(({}[])[<>])]})>[[([{((){})<<>>}])[<((()<>)[{}{}])[[(){}]]>{<<{}()>{ +({[[[[[[[<((<[<><>][()[]]><(<><>)>))>{{<(<<>[]>{{}})[[[]<>]({}())]><{{()<>>[[]<>]}[<{}{}>{<>{}}]>}[{<(< +([([(<[{<[[{<{<>[]}>{{{}()]<{}()>}}<([{}()]{{}<>})[([][]){{}<>}]>]{<{{[]{}}{{}<>}}<[[]()]>>[[{()[]}{(){}}]{[ +{<{([([{<<<<{[<>()]<[]>}[[()<>]<()>]>>(([[<>[]][{}{}]])((([][]){<><>})([[]{}]<()<>})))><{<<[()()]<[]()> +[{({[{[(([([{{{}<>}{()<>}}(([]<>){{}{}})][<{()}{{}{}}>(<<>()>[<>()])])]))<<<({((<>()){[]{}})[{ +([([(<(({<(<<<{}[]>){{<><>}[[]{}]}>[{{[][]}<<><>>}])<{<<[]>(()[])>[[{}()]<[]<>>]}{({[]()}[<><>]){{{}[]}[{ +{{[{<{((<((<<<(){}>>{([]{})[[]()]}>([({}{})]{<()>{[]{}}}))[[(<<><>>)]<<<{}{}><(){}>>[({}[])({} +<{[({{<<((([[[(){}][{}<>]]<(<>[])<[]()>>]<[[{}()]({}())]>)({<[(){}]>{(<><>){[]{}}}})){{{<<[]()>[()<>]>[< +(<[[(<((<[[<{[[]()][()<>]}<[[][]]<[][]>>>((({}())((){}))(<{}<>]{()()}))]]>[[{<{[{}<>]}>([[{}<>](() +<<<{<(<[<{[[([<>()][()<>])(<<>()>[{}()])][<{<>()}>]]}<<<({<>[]}([]{}))<<(){}>>>[[({}())(())]]>{({({}[ +([<<<{<{({<[{(()<>)<()()>}]<[({}<>)]>>{[[{<>{}}(()[])](<<>>[[]<>])]}}{<<{<<>()>}><{{<>()}<<><>>}{<(){}>[(){ +{{(<<[{{({({({[]()}<{}()>)(([][])[()<>])}<{(<>())[()<>]}>)[[(([]<>)[[]<>])]]}[({[({}()){{}>]}) +<((((<{{{{{[{[(){}]([][])}[{<>{}}([]<>)]]([((){})]<[[][]][<><>]>)}}<(<{(()<>)([]{})}><([()<>]{<>() +<{<{<(<(<<<(<[[][]]<<>()>><[<>[]][[]]>)[<[<>{}][<>()]>]>{<{(()){{}()}}[<{}<>><<><>>]>[{<{}[]><<><>>}]}>{( +{[{<<(<([({{<<[]<>>[<>{}]>{<{}<>>([]<>)}}([<<>{}>((){})}<{<>[]}>)}<<({{}()})<(<>[])[[]]>>[[<<>[]>{()[]}][[[] +<<<<[<{<[{{(<[<>]<[]{}>><(<>{}){{}()}>)[[{<>{}}{{}[]}](<[]>[<>{}])]}{{[{{}[]}(()<>)]<([]())( +[([({[[{<{{<<{()()}<{}{}>>({{}{}}[{}{}]>>[{(<>{})<()()>}[[<>[]]<{}()>]]}[<<{<><>}(()[])>(<{}[]> +[<<[[(({<[[([(<>[]){()[]}][(<><>)[<>[]]])]<({<{}{}>(()[])}[<{}<>>({}())])((({}{})<{}[]>)[{{}<>}{{}{}}]) +(({({[<<[<[([<<><>){[]{}}][<()<>><[]<>>])({[{}<>]<[]<>>}<({}{})[{}[]]>)][{((<><>)(()[]))}[<<{}()>{<> +<((<[(<(<[[([{(){}}<<>()>]({(){}}{(){}}))]][{{[{[][]]{<>{}}]{[{}<>]([]{})}}}[<{[[]{}][<>()]}[(()[])< +{((<<{({<[([(([]())([]()))(<[][]>{()})])<<[<<>[]>[<>())](<()<>><()()>)>>]>{{[{<[<>{}]<[]<>>>}<{{<><>}< +{<<<<[((<{({<{<>[]}{<>()}><{<><>){<>()}>}([[[]()][(){}]]<<()<>>{<><>}>)){[{{<>[]}{[]()}}{(<>()) +({<<<<[{<{<{(<{}{}><()[]>)[{<>{}}]}>(<[([]{}){<><>}]{<<><>>[()[]]}}<[{()[]}{()[]}][{{}[]}{[][]}]>)}>}] +({({{<{{{[<{{(<><>)}({[]()}{<><>})}{<[{}[]]<[]<>>>[(<>[]){()()}]}><[[<<>()><[][]>]]>]<<[{[[]()]( +<{[<([<[({([{(<>{}){()}}<([]<>)[{}{}]>)[[<()[]><{}<>>][(<>{})[()()]]]){<{({}){{}{}}}<{<>()}[[ +{((({[{<{[<({[{}()]({}{})}<(<>)(()())>)({[[]{}](<><>)}[<<>[]>[<>[]]])><<[{[]<>}][([][])<[]()>]>( +({[((([<[(<{[(<>[])(()[])]}<[([][])([]<>)]<(()())>>>((([(){}])<(<>())<<><>>>)<[[()<>>{{}{} +[{{((<{[(<{[{{[][]}{<><>}}[[()[]]<[][]>]]<<({}[])((){})>>}>[(<([[]()]<{}[]>)([{}<>])>({<<>[]>(<>[])}[( +((<((<[<(<[{(<[]()>[()[]])((())(()[]))}{[[{}<>]([]{})]<[[]()]>}]>)><([<[<{[]<>}<{}[]>>[[(){}]]]({[[][]]{ +[(([([(([<<(<{<>}{[][]}>)[{[()<>]{{}{}}}({{}{}}<[]()>)]>>{([({<><>}<[]>){<{}{}>[()<>]}]<<[[]{}]{{ +[(<{<[[{[<<{<[[]<>]<[]()>>{{[]<>}}}><[[{{}()}([]<>)]][({{}<>}{{}{}})<[[][]](()())>]>><<({([]{})<<>{}>}){ +<{[<[(<<[[[[{<{}[]><[]<>>](<{}[]>{()[]})](<[<>()][[][]]>([()()]<<>()>))]]({([<()[]>[{}()]])<{[[]()]}{<[][ +<{{{([[([{{{<({}[])>}}<<({<>{}}{{}()))<({}{}){[]{}}>>[[(<>())[{}[]]]<<[]{}>{<>[]}>]>}([{[<< +[{<(({{<[{[[([<>{}]{<>{}})(((){})[{}[]])][{<{}<>>}[([]{})<{}>]]]}{<<([<>{}][()[]})[{{}}<{}()>]>( +[((<[{<<[<[{[{{}()}[{}[]]]<[<>[]][{}<>]>}]>]{[([([[]<>]{{}[]})[<(){}>[()[]]]]<<({}[])<[]()>>[( +[{([<{([(({(<[[]<>]>{({}()){<><>}})([([]())[[]<>]])}(<[({}())(<>())]<{()<>}[[]<>]>>)){{([[<><>][()[]>](<[][]> +<<(<<<{{{<<(<<[]<>>{<>()}>[<[]>])<{<{}<>>}{[{}{}]<<>[]>}>><{<<<>{}>({}<>)>}{([()[]]<<>()>)(<<><>><[]{}>)}>>< +{[<<[{{(<<[((({}{})[{}{}])(({}<>)[{}()]))]>{([[[(){}]<{}<>>][[{}[]]{()[]}]](<{[]{}}(<>[]>>))}>)}[(< +<{{[[<[[[(((({<><>}{{}{}})<[<>()]([]())>)[<{{}<>}>{((){})[[][]]}]))<{<{[[]()]<[][]>}{<[]<>>(<> +{<[<<([[[[{{<({}<>)<{}()>>[(<>())({}[])]}<{([][])({}<>)}>}(({[<>{}]{[]{}}}<(<>{})>)[<{[][]}{[][]}>{({}()){ +[[({{[(((({<{{<><>]}{(<><>){<><>}}>(<[()<>]<{}{}>>((<><>){<>[]}))}{<[[{}[]]([][])][{{}[]}[ +[{{<([((<<{(((<><>)<(){}>))((({}[]){<>()})(<{}()}({}{})))}><[<<{<>[]}[()<>]>{[<>{}]{[]()}}>{{ +[<{<{{({{<<<{[<><>]<[][]>}<<(){}>(<>)>>>([<{[]()}{{}[]}>{<{}()><[]<>>}]([([]())[[]]]([[]()]<<>{}>)))> +<[{<[(<{{([[<[{}{}]><([]<>)(()())>][<((){})[[]()]>[([]<>){<><>}]]]{<{<[]<>><<>>}{<{}<>><[]{} +{[((((((({([([(){}]([]<>)){[{}](<>[])}]{[<<>()>([]<>)]<<[][]>{[]<>}>})<<[{{}[]}(<><>)]<[()<>] +([({(([[[([[((<>{}){{}{}}]{[()<>]((){})}]((({})(<>[])){[{}{}]<<>()>})]{({(())[<>{}]}((<>{}) +{<[<{(<[{<[{(<{}()>)[<<>[]>(()<>)]}([{()[]}<{}<>>])}(({<[]{}><{}{}>}([[]<>]{{}()})){[[{}<>] +<<({[[<<[([(<[<><>]{<>{}}>{<(){}>(()())})<{[<>{}]<()[]>}>]<{[{<>{}}<<>()>]<{{}()}[()<>]>}<[[{}<>][{ diff --git a/aoc2021/input/day10_provided.txt b/aoc2021/input/day10_provided.txt new file mode 100644 index 0000000..b1518d9 --- /dev/null +++ b/aoc2021/input/day10_provided.txt @@ -0,0 +1,10 @@ +[({(<(())[]>[[{[]{<()<>> +[(()[<>])]({[<{<<[]>>( +{([(<{}[<>[]}>{[]{[(<()> +(((({<>}<{<{<>}{[]{[]{} +[[<[([]))<([[{}[[()]]] +[{[{({}]{}}([{[{{{}}([] +{<[[]]>}<{[{[{[]{()[[[] +[<(<(<(<{}))><([]([]() +<{([([[(<>()){}]>(<<{{ +<{([{{}}[<[[[<>{}]]]>[]] diff --git a/aoc2021/src/day10.rs b/aoc2021/src/day10.rs new file mode 100644 index 0000000..49d35de --- /dev/null +++ b/aoc2021/src/day10.rs @@ -0,0 +1,125 @@ +use std::fmt::Write; + +use anyhow::{bail, Result}; + +const INPUT: &str = include_str!("../input/day10.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let lines = input + .lines() + .map(str::parse::) + .collect::>>()?; + + Ok(lines.iter().map(Line::corrupt_score).sum()) +} + +enum SymbolState { + Open(Symbol), + Close(Symbol), +} + +impl TryFrom for SymbolState { + type Error = anyhow::Error; + + fn try_from(value: char) -> Result { + match value { + '(' | '[' | '{' | '<' => Ok(SymbolState::Open(value.try_into().unwrap())), + ')' | ']' | '}' | '>' => Ok(SymbolState::Close(value.try_into().unwrap())), + _ => bail!("invalid char for symbol"), + } + } +} + +#[derive(PartialEq, Eq)] +enum Symbol { + Parenthesis, // () + Bracket, // [] + Brace, // {} + AngleBracket, // <> +} + +impl Symbol { + fn score(&self) -> u64 { + match self { + Symbol::Parenthesis => 3, + Symbol::Bracket => 57, + Symbol::Brace => 1197, + Symbol::AngleBracket => 25137, + } + } +} + +impl TryFrom for Symbol { + type Error = anyhow::Error; + + fn try_from(value: char) -> Result { + match value { + '(' | ')' => Ok(Symbol::Parenthesis), + '[' | ']' => Ok(Symbol::Bracket), + '{' | '}' => Ok(Symbol::Brace), + '<' | '>' => Ok(Symbol::AngleBracket), + _ => bail!("invalid char for symbol"), + } + } +} + +struct Line { + symbols: Vec, +} + +impl Line { + fn corrupt_score(&self) -> u64 { + let mut stack = Vec::new(); + + for state in &self.symbols { + match state { + SymbolState::Open(symbol) => stack.push(symbol), + SymbolState::Close(symbol) => match stack.pop() { + Some(other_symbol) if symbol == other_symbol => continue, + _ => return symbol.score(), + }, + } + } + + 0 + } +} + +impl std::str::FromStr for Line { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(Line { + symbols: s + .trim() + .chars() + .map(TryFrom::try_from) + .collect::>>()?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day10_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 26397); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 394647); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 98f8aa8..cff51ba 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -9,3 +9,4 @@ pub mod day06; pub mod day07; pub mod day08; pub mod day09; +pub mod day10; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index b94515f..e45aa5c 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -11,6 +11,7 @@ use aoc2021::day06; use aoc2021::day07; use aoc2021::day08; use aoc2021::day09; +use aoc2021::day10; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -23,6 +24,7 @@ fn main() -> Result<()> { day07::run, day08::run, day09::run, + day10::run, ]; aoc::run(days) From 7ec783fc16f3e346fef82ae59d08035a45cb9e6e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 10 Dec 2021 14:26:31 +0100 Subject: [PATCH 069/134] 2021: day10: part 2 --- aoc2021/src/day10.rs | 66 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/aoc2021/src/day10.rs b/aoc2021/src/day10.rs index 49d35de..8ccacfb 100644 --- a/aoc2021/src/day10.rs +++ b/aoc2021/src/day10.rs @@ -8,6 +8,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -18,7 +19,21 @@ fn part1(input: &str) -> Result { .map(str::parse::) .collect::>>()?; - Ok(lines.iter().map(Line::corrupt_score).sum()) + Ok(lines.iter().filter_map(Line::syntax_checking_score).sum()) +} + +fn part2(input: &str) -> Result { + let lines = input + .lines() + .map(str::parse::) + .collect::>>()?; + + let mut scores: Vec = lines.iter().filter_map(Line::completion_score).collect(); + scores.sort_unstable(); + + debug_assert!(scores.len() % 2 == 1); + + Ok(scores[scores.len() / 2]) } enum SymbolState { @@ -47,7 +62,7 @@ enum Symbol { } impl Symbol { - fn score(&self) -> u64 { + fn syntax_checking_score(&self) -> u64 { match self { Symbol::Parenthesis => 3, Symbol::Bracket => 57, @@ -55,6 +70,15 @@ impl Symbol { Symbol::AngleBracket => 25137, } } + + fn completion_score(&self) -> u64 { + match self { + Symbol::Parenthesis => 1, + Symbol::Bracket => 2, + Symbol::Brace => 3, + Symbol::AngleBracket => 4, + } + } } impl TryFrom for Symbol { @@ -76,7 +100,7 @@ struct Line { } impl Line { - fn corrupt_score(&self) -> u64 { + fn syntax_checking_score(&self) -> Option { let mut stack = Vec::new(); for state in &self.symbols { @@ -84,12 +108,34 @@ impl Line { SymbolState::Open(symbol) => stack.push(symbol), SymbolState::Close(symbol) => match stack.pop() { Some(other_symbol) if symbol == other_symbol => continue, - _ => return symbol.score(), + _ => return Some(symbol.syntax_checking_score()), }, } } - 0 + None + } + + fn completion_score(&self) -> Option { + let mut stack = Vec::new(); + + for state in &self.symbols { + match state { + SymbolState::Open(symbol) => stack.push(symbol), + SymbolState::Close(symbol) => match stack.pop() { + Some(other_symbol) if symbol == other_symbol => continue, + _ => return None, // ignore corrupt line + }, + } + } + + let mut score = 0; + + for symbol in stack.into_iter().rev() { + score = score * 5 + symbol.completion_score(); + } + + Some(score) } } @@ -122,4 +168,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 394647); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 288957); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2380061249); + } } From 8ddde41f0ce3bc53dbf7fa787f4fde5d85712af7 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 10 Dec 2021 14:27:01 +0100 Subject: [PATCH 070/134] 2021: day10: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index eeb312e..5444068 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -9,6 +9,7 @@ use aoc2021::day06; use aoc2021::day07; use aoc2021::day08; use aoc2021::day09; +use aoc2021::day10; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -20,6 +21,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); c.bench_function("day08", |b| b.iter(|| day08::run().unwrap())); c.bench_function("day09", |b| b.iter(|| day09::run().unwrap())); + c.bench_function("day10", |b| b.iter(|| day10::run().unwrap())); } criterion_group! { From 1d6ed92b36a956f66fa7ed372dc541fdcb5f436c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 11 Dec 2021 15:38:34 +0100 Subject: [PATCH 071/134] 2021: day11: part 1 & 2 --- aoc2021/input/day11.txt | 10 ++ aoc2021/input/day11_provided.txt | 10 ++ aoc2021/src/day11.rs | 236 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 259 insertions(+) create mode 100644 aoc2021/input/day11.txt create mode 100644 aoc2021/input/day11_provided.txt create mode 100644 aoc2021/src/day11.rs diff --git a/aoc2021/input/day11.txt b/aoc2021/input/day11.txt new file mode 100644 index 0000000..3f9a2ec --- /dev/null +++ b/aoc2021/input/day11.txt @@ -0,0 +1,10 @@ +4764745784 +4643457176 +8322628477 +7617152546 +6137518165 +1556723176 +2187861886 +2553422625 +4817584638 +3754285662 diff --git a/aoc2021/input/day11_provided.txt b/aoc2021/input/day11_provided.txt new file mode 100644 index 0000000..03743f6 --- /dev/null +++ b/aoc2021/input/day11_provided.txt @@ -0,0 +1,10 @@ +5483143223 +2745854711 +5264556173 +6141336146 +6357385478 +4167524645 +2176841721 +6882881134 +4846848554 +5283751526 diff --git a/aoc2021/src/day11.rs b/aoc2021/src/day11.rs new file mode 100644 index 0000000..189032f --- /dev/null +++ b/aoc2021/src/day11.rs @@ -0,0 +1,236 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day11.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut grid: OctopusGrid = input.parse()?; + + Ok((0..100).map(|_| grid.step()).sum()) +} + +fn part2(input: &str) -> Result { + let mut grid: OctopusGrid = input.parse()?; + + let (_, step) = (0..) + .map(|step| (grid.step(), step)) + .find(|(flashes, _)| *flashes == 100) + .context("never reached step where octopuses all flashed simultaneously")?; + + Ok(step + 1) +} + +#[derive(Clone, Copy, Debug)] +struct Octopus { + energy_level: u8, + has_flashed: bool, +} + +impl Octopus { + fn increment_energy_level(&mut self) { + self.energy_level += 1; + } + + fn reset_energy_level(&mut self) { + if self.has_flashed { + self.energy_level = 0; + self.has_flashed = false; + } + } + + fn flashes(&mut self) -> bool { + if self.energy_level > 9 && !self.has_flashed { + self.has_flashed = true; + return true; + } + + false + } +} + +impl TryFrom for Octopus { + type Error = anyhow::Error; + + fn try_from(value: char) -> Result { + Ok(Octopus { + energy_level: value + .to_digit(10) + .with_context(|| format!("couldn't convert char `{}` to digit", value))? + as u8, + has_flashed: false, + }) + } +} + +#[derive(Clone, Copy)] +enum Neighbour { + Up, + Down, + Left, + Right, + UpperLeft, + UpperRight, + LowerLeft, + LowerRight, +} + +impl Neighbour { + fn apply(&self, x: usize, y: usize, width: usize, height: usize) -> Option<(usize, usize)> { + match self { + Neighbour::Left if x > 0 => Some((x - 1, y)), + Neighbour::Right if x < width - 1 => Some((x + 1, y)), + Neighbour::Up if y > 0 => Some((x, y - 1)), + Neighbour::Down if y < height - 1 => Some((x, y + 1)), + Neighbour::UpperLeft => Neighbour::Left + .apply(x, y, width, height) + .and_then(|(x, y)| Neighbour::Up.apply(x, y, width, height)), + Neighbour::UpperRight => Neighbour::Right + .apply(x, y, width, height) + .and_then(|(x, y)| Neighbour::Up.apply(x, y, width, height)), + Neighbour::LowerLeft => Neighbour::Left + .apply(x, y, width, height) + .and_then(|(x, y)| Neighbour::Down.apply(x, y, width, height)), + Neighbour::LowerRight => Neighbour::Right + .apply(x, y, width, height) + .and_then(|(x, y)| Neighbour::Down.apply(x, y, width, height)), + _ => None, + } + } + + const ALL: &'static [Self] = &[ + Neighbour::Left, + Neighbour::Right, + Neighbour::Up, + Neighbour::Down, + Neighbour::UpperLeft, + Neighbour::UpperRight, + Neighbour::LowerLeft, + Neighbour::LowerRight, + ]; +} + +#[derive(Debug)] +struct OctopusGrid { + octopuses: Vec, + width: usize, + height: usize, +} + +impl OctopusGrid { + fn neighbours(&self, x: usize, y: usize) -> impl Iterator + 'static { + let width = self.width; + let height = self.height; + Neighbour::ALL + .iter() + .copied() + .filter_map(move |neighbour| neighbour.apply(x, y, width, height)) + } + + fn get_mut(&mut self, x: usize, y: usize) -> &mut Octopus { + &mut self.octopuses[y * self.width + x] + } + + fn step(&mut self) -> usize { + // First, the energy level of each octopus increases by 1. + self.octopuses + .iter_mut() + .for_each(Octopus::increment_energy_level); + + // Then, any octopus with an energy level greater than 9 flashes. This increases the energy + // level of all adjacent octopuses by 1, including octopuses that are diagonally adjacent. + // If this causes an octopus to have an energy level greater than 9, it also flashes. This + // process continues as long as new octopuses keep having their energy level increased + // beyond 9. (An octopus can only flash at most once per step.) + let mut flashed = true; + let mut flashes = 0; + while flashed { + flashed = false; + for index in 0..self.octopuses.len() { + if self.octopuses[index].flashes() { + let (x, y) = (index % self.width, index / self.width); + for (x, y) in self.neighbours(x, y) { + self.get_mut(x, y).increment_energy_level(); + } + + flashed = true; + flashes += 1; + } + } + } + + // Finally, any octopus that flashed during this step has its energy level set to 0, as it + // used all of its energy to flash. + self.octopuses + .iter_mut() + .for_each(Octopus::reset_energy_level); + + flashes + } +} + +impl std::str::FromStr for OctopusGrid { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut octopuses = Vec::new(); + + let mut height = 0; + let mut width = None; + for line in s.lines().map(str::trim) { + let octopus_line = line + .chars() + .map(TryFrom::try_from) + .collect::>>()?; + + if width.is_none() { + width = Some(octopus_line.len()); + } + + height += 1; + octopuses.extend_from_slice(&octopus_line); + } + + Ok(OctopusGrid { + octopuses, + width: width.context("0 lines parsed, width never computed")?, + height, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day11_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 1656); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 1588); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 195); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 517); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index cff51ba..6cbe7cd 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -10,3 +10,4 @@ pub mod day07; pub mod day08; pub mod day09; pub mod day10; +pub mod day11; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index e45aa5c..e5145c4 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -12,6 +12,7 @@ use aoc2021::day07; use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; +use aoc2021::day11; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -25,6 +26,7 @@ fn main() -> Result<()> { day08::run, day09::run, day10::run, + day11::run, ]; aoc::run(days) From fc3d23397b02d310bb23d47cc96038dab80b2ddd Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 11 Dec 2021 15:39:11 +0100 Subject: [PATCH 072/134] 2021: day11: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 5444068..7b41e76 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -10,6 +10,7 @@ use aoc2021::day07; use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; +use aoc2021::day11; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -22,6 +23,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day08", |b| b.iter(|| day08::run().unwrap())); c.bench_function("day09", |b| b.iter(|| day09::run().unwrap())); c.bench_function("day10", |b| b.iter(|| day10::run().unwrap())); + c.bench_function("day11", |b| b.iter(|| day11::run().unwrap())); } criterion_group! { From d515ced9a01e22205d9ef5740f51d39b0f74590d Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 11 Dec 2021 16:08:22 +0100 Subject: [PATCH 073/134] 2021: day09: fix neighbour iterator lifetime --- aoc2021/src/day09.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aoc2021/src/day09.rs b/aoc2021/src/day09.rs index 9d21357..8b0d09a 100644 --- a/aoc2021/src/day09.rs +++ b/aoc2021/src/day09.rs @@ -88,10 +88,8 @@ impl HeightMap { } self.filled_points.insert((x, y)); - let neighbours: Vec<_> = self.neighbours(x, y).collect(); - neighbours - .iter() - .map(|&(nx, ny)| self.fill_basin(nx, ny)) + self.neighbours(x, y) + .map(|(nx, ny)| self.fill_basin(nx, ny)) .sum::() + 1 } @@ -105,11 +103,13 @@ impl HeightMap { }) } - fn neighbours(&self, x: usize, y: usize) -> impl Iterator + '_ { + fn neighbours(&self, x: usize, y: usize) -> impl Iterator + 'static { + let width = self.width; + let height = self.height; Neighbour::ALL .iter() .copied() - .filter_map(move |neighbour| neighbour.apply(x, y, self.width, self.height)) + .filter_map(move |neighbour| neighbour.apply(x, y, width, height)) } fn risk_level(&self, x: usize, y: usize) -> u64 { From b8e2bbf2f3eaf0a7061048ee9baf12043948a289 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 13 Dec 2021 11:58:29 +0100 Subject: [PATCH 074/134] 2021: day13: part 1 & 2 --- aoc2021/input/day13.txt | 916 +++++++++++++++++++++++++++++++ aoc2021/input/day13_provided.txt | 21 + aoc2021/src/day13.rs | 210 +++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 1150 insertions(+) create mode 100644 aoc2021/input/day13.txt create mode 100644 aoc2021/input/day13_provided.txt create mode 100644 aoc2021/src/day13.rs diff --git a/aoc2021/input/day13.txt b/aoc2021/input/day13.txt new file mode 100644 index 0000000..aef0a4a --- /dev/null +++ b/aoc2021/input/day13.txt @@ -0,0 +1,916 @@ +1213,736 +1158,890 +626,303 +98,10 +878,268 +1208,143 +112,400 +865,894 +1218,179 +1089,418 +535,886 +726,515 +1263,786 +589,270 +80,518 +288,322 +1101,483 +989,308 +1002,707 +467,18 +1036,364 +552,591 +445,280 +912,40 +1268,761 +984,47 +883,574 +815,784 +719,236 +865,166 +836,581 +656,735 +228,264 +23,466 +1099,515 +1284,665 +432,268 +195,493 +1001,308 +430,222 +1294,537 +427,646 +574,381 +1116,829 +1143,808 +950,578 +293,579 +28,751 +169,341 +326,159 +257,721 +773,670 +1231,556 +306,436 +454,520 +1267,522 +85,309 +1273,358 +1019,208 +870,504 +647,175 +408,544 +1310,386 +912,854 +512,10 +674,770 +273,742 +626,584 +112,10 +736,420 +1198,884 +214,620 +139,751 +448,782 +771,646 +709,796 +755,460 +179,838 +360,578 +274,364 +656,401 +810,61 +194,310 +584,515 +773,238 +184,241 +932,661 +105,333 +1096,838 +959,838 +252,341 +1237,338 +112,884 +746,812 +735,556 +45,75 +815,838 +654,719 +1225,309 +1226,892 +453,465 +783,520 +987,446 +348,458 +976,175 +487,392 +1307,558 +1279,882 +145,509 +909,444 +1310,389 +626,527 +356,527 +363,774 +142,130 +246,581 +1064,581 +925,837 +166,842 +529,877 +124,341 +709,546 +651,490 +372,16 +537,614 +1004,213 +1198,661 +1240,40 +701,504 +1103,120 +638,462 +857,351 +269,794 +1099,122 +624,360 +1284,217 +902,26 +102,672 +691,208 +850,287 +1083,698 +636,770 +475,539 +1280,735 +495,712 +1273,655 +217,854 +1109,687 +345,565 +939,43 +902,203 +803,241 +35,838 +169,624 +206,236 +413,718 +617,599 +729,786 +372,430 +467,242 +771,324 +924,268 +574,854 +167,502 +141,738 +166,52 +659,336 +1240,123 +672,462 +902,581 +883,320 +37,655 +209,0 +897,875 +823,630 +1074,264 +385,794 +1131,838 +1151,504 +1294,357 +1260,396 +1228,768 +209,57 +1225,360 +1111,710 +333,586 +996,371 +954,140 +790,367 +843,348 +1058,877 +252,509 +181,385 +1218,267 +1123,428 +191,98 +1039,372 +214,504 +274,260 +359,751 +1109,753 +659,359 +10,674 +835,56 +730,490 +378,1 +0,539 +35,182 +276,661 +469,626 +1061,533 +783,432 +656,847 +281,707 +187,428 +1275,568 +716,143 +938,878 +663,117 +738,254 +954,86 +467,796 +966,761 +405,311 +209,651 +38,98 +1233,824 +430,837 +1290,841 +865,280 +1123,18 +985,170 +182,859 +1164,245 +656,607 +979,784 +634,10 +460,829 +768,172 +1126,317 +1000,805 +1198,830 +629,536 +208,542 +1193,747 +328,60 +1123,751 +1004,10 +1056,571 +254,571 +1086,57 +192,815 +1287,204 +1012,754 +838,411 +1225,361 +380,310 +616,117 +621,243 +1165,509 +706,781 +564,530 +905,311 +162,763 +354,889 +975,103 +10,226 +326,847 +184,317 +1261,143 +1310,65 +310,462 +1208,672 +402,17 +85,361 +129,847 +1020,486 +16,462 +618,856 +440,102 +686,381 +925,794 +453,65 +1287,639 +180,656 +507,91 +460,65 +893,271 +344,581 +609,208 +246,432 +781,246 +185,268 +311,696 +736,488 +346,707 +875,708 +38,565 +420,267 +433,18 +1101,651 +159,222 +420,627 +1245,446 +905,361 +954,527 +909,450 +495,392 +755,434 +179,429 +1230,868 +1129,621 +932,681 +211,122 +344,313 +52,530 +602,288 +947,326 +433,113 +634,557 +529,17 +647,117 +1253,324 +331,502 +580,205 +1111,184 +359,143 +52,36 +32,409 +1280,584 +112,661 +1143,392 +1228,126 +32,485 +28,310 +768,436 +1000,761 +281,502 +753,214 +443,646 +1213,680 +97,515 +939,820 +112,172 +1068,674 +371,43 +1089,642 +1064,82 +1131,429 +947,840 +684,751 +420,264 +1082,660 +965,553 +52,82 +795,751 +351,98 +1143,726 +815,224 +80,656 +900,605 +897,360 +706,333 +880,57 +676,841 +119,877 +938,16 +393,176 +1001,586 +507,388 +31,194 +405,182 +35,470 +185,716 +1310,57 +733,70 +391,658 +815,182 +31,65 +868,866 +356,140 +628,229 +841,492 +691,712 +1195,696 +634,287 +523,65 +345,138 +310,49 +663,623 +474,581 +520,639 +224,57 +1287,428 +328,579 +323,392 +351,504 +1287,255 +815,360 +194,136 +207,269 +542,436 +432,178 +110,634 +878,716 +201,829 +897,718 +52,726 +328,159 +1258,502 +1307,87 +1129,733 +979,315 +323,427 +1002,187 +351,639 +938,430 +527,520 +870,176 +1069,639 +1307,467 +36,856 +23,31 +413,534 +402,341 +687,65 +619,120 +634,884 +1258,858 +18,203 +542,885 +604,781 +1282,758 +5,553 +1294,385 +378,437 +1096,56 +835,838 +23,876 +1111,278 +1011,33 +308,707 +117,798 +331,763 +470,241 +830,732 +1265,691 +982,287 +950,709 +755,196 +691,694 +776,12 +1290,765 +619,40 +738,640 +1121,88 +938,464 +951,143 +537,208 +736,518 +405,126 +453,543 +365,694 +157,329 +385,57 +37,358 +482,341 +442,28 +870,457 +984,336 +693,239 +917,176 +45,158 +892,264 +1258,812 +1113,534 +303,7 +1004,661 +569,869 +281,158 +378,681 +569,534 +16,509 +435,708 +373,840 +1192,542 +721,606 +1041,794 +1151,392 +343,646 +684,143 +1064,740 +552,751 +1151,182 +1143,616 +698,313 +1064,812 +446,800 +564,812 +1191,717 +452,105 +85,360 +947,504 +380,82 +937,483 +319,551 +922,815 +1213,515 +984,607 +73,556 +309,852 +50,661 +1181,847 +1300,535 +448,560 +291,854 +447,8 +0,91 +1191,625 +932,233 +371,689 +361,131 +865,798 +1169,738 +446,94 +966,581 +110,309 +74,404 +1000,49 +1,842 +798,354 +20,884 +1233,406 +1230,243 +492,267 +867,248 +346,187 +1245,472 +736,406 +656,287 +962,590 +572,640 +544,260 +927,522 +841,786 +1029,392 +169,278 +378,445 +420,630 +488,52 +626,751 +927,372 +691,854 +803,355 +3,87 +1230,26 +154,341 +612,313 +823,560 +802,245 +216,137 +987,427 +207,120 +775,877 +897,176 +1266,654 +541,191 +159,110 +1275,182 +678,268 +1153,565 +1274,856 +991,656 +15,696 +172,341 +691,504 +310,705 +1275,470 +574,243 +448,637 +1111,262 +951,751 +619,390 +539,324 +626,143 +733,809 +656,281 +0,837 +529,429 +862,180 +1279,194 +947,568 +227,574 +378,400 +418,364 +556,182 +969,481 +500,61 +947,774 +761,333 +1012,136 +1258,530 +574,518 +666,311 +326,558 +512,130 +870,718 +689,682 +1104,658 +1101,614 +187,876 +1237,556 +313,861 +222,716 +676,884 +201,375 +336,28 +1058,509 +469,492 +1081,232 +361,763 +42,761 +1183,462 +1148,110 +1273,239 +905,712 +863,438 +905,518 +736,474 +1034,445 +1088,716 +1022,677 +117,224 +1265,686 +1171,751 +862,112 +0,165 +1123,546 +1310,508 +49,143 +880,837 +976,719 +684,361 +1233,70 +28,478 +82,126 +1053,721 +131,625 +900,289 +1193,278 +373,65 +1272,796 +490,617 +1016,633 +413,176 +82,96 +1116,584 +469,786 +867,646 +843,652 +1118,815 +775,886 +624,829 +166,500 +555,574 +385,837 +455,278 +487,840 +65,446 +1139,819 +1211,460 +1169,114 +1101,894 +624,381 +227,250 +119,269 +1029,56 +616,98 +905,126 +937,449 +1096,504 +1141,624 +1099,772 +201,687 +1116,65 +217,40 +708,136 +787,65 +1273,648 +1155,338 +659,87 +201,207 +402,161 +1091,708 +440,722 +447,269 +1022,572 +939,205 +497,329 +1058,553 +542,661 +863,886 +155,338 +622,857 +92,715 +612,133 +962,458 +634,159 +28,30 +288,677 +1028,878 +1183,520 +169,176 +23,428 +1292,203 +754,182 +555,320 +35,208 +701,75 +1022,322 +684,533 +320,623 +857,95 +18,770 +214,50 +7,777 +398,406 +261,176 +783,462 +709,98 +1123,815 +440,457 +708,168 +447,625 +359,418 +1278,485 +1012,143 +159,504 +38,796 +1230,332 +418,530 +877,255 +654,505 +28,136 +912,406 +1193,320 +485,46 +351,838 +1265,75 +758,143 +1300,226 +1282,527 +612,761 +575,556 +979,763 +77,70 +654,607 +688,261 +766,585 +145,385 +363,504 +676,287 +788,607 +857,465 +1128,35 +574,513 +1200,309 +10,668 +169,553 +654,57 +1064,868 +191,796 +45,686 +982,159 +795,79 +413,361 +761,863 +473,273 +0,401 +1017,579 +840,808 +99,434 +79,556 +162,784 +459,418 +798,10 +195,418 +651,404 +520,527 +959,887 +965,565 +288,217 +730,404 +1282,478 +602,364 +803,315 +962,304 +820,617 +741,534 +549,333 +862,714 +363,326 +102,222 +348,436 +1156,553 +1064,463 +97,214 +609,691 +214,722 +827,208 +372,688 +453,519 +385,401 +622,633 +70,40 +455,616 +949,763 +693,599 +194,758 +512,541 +1169,786 +617,536 +1086,837 +112,494 +910,161 +984,495 +959,56 +977,586 +454,262 +1141,341 +609,203 +748,19 +1143,560 +656,508 +541,703 +1181,495 +1183,246 +542,102 +736,189 +433,866 +661,756 +659,490 +331,446 +236,630 +610,688 +3,467 +446,268 +694,117 +308,35 +537,350 +1101,243 +951,418 +127,432 +979,110 +802,705 +741,86 +787,829 +1198,233 +808,890 +1279,12 +50,396 +1183,14 +23,255 +636,124 +448,714 +1236,205 +1193,798 +1103,625 +945,694 +1139,108 +522,287 +624,513 +997,33 +1190,658 +35,56 +1275,406 +773,208 +1125,716 +69,621 +1093,518 +1310,837 +1125,268 +865,448 +1102,94 +306,10 +373,483 +442,866 +858,105 +602,168 +624,159 +334,719 +480,162 +870,172 +602,736 +0,508 +1064,154 +1056,712 +582,161 +1261,591 +661,308 +35,200 +92,19 +214,390 + +fold along x=655 +fold along y=447 +fold along x=327 +fold along y=223 +fold along x=163 +fold along y=111 +fold along x=81 +fold along y=55 +fold along x=40 +fold along y=27 +fold along y=13 +fold along y=6 diff --git a/aoc2021/input/day13_provided.txt b/aoc2021/input/day13_provided.txt new file mode 100644 index 0000000..282114c --- /dev/null +++ b/aoc2021/input/day13_provided.txt @@ -0,0 +1,21 @@ +6,10 +0,14 +9,10 +0,3 +10,4 +4,11 +6,0 +6,12 +4,1 +0,13 +10,12 +3,4 +3,0 +8,4 +1,10 +2,14 +8,10 +9,0 + +fold along y=7 +fold along x=5 diff --git a/aoc2021/src/day13.rs b/aoc2021/src/day13.rs new file mode 100644 index 0000000..37f39f4 --- /dev/null +++ b/aoc2021/src/day13.rs @@ -0,0 +1,210 @@ +use std::collections::HashSet; +use std::fmt::Write; + +use anyhow::{anyhow, Context, Result}; + +const INPUT: &str = include_str!("../input/day13.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let (sheet, fold_instructions) = input.split_once("\n\n").context("couldn't split input")?; + let mut sheet: PaperSheet = sheet.parse()?; + let fold_instructions: Vec = fold_instructions + .lines() + .map(|l| l.trim().parse()) + .collect::>()?; + + sheet.apply( + *fold_instructions + .first() + .context("had 0 fold instructions")?, + ); + + Ok(sheet.num_points()) +} + +fn part2(input: &str) -> Result { + let (sheet, fold_instructions) = input.split_once("\n\n").context("couldn't split input")?; + let mut sheet: PaperSheet = sheet.parse()?; + let fold_instructions: Vec = fold_instructions + .lines() + .map(|l| l.trim().parse()) + .collect::>()?; + + for instr in fold_instructions { + sheet.apply(instr); + } + + Ok(format!("{}", sheet)) +} + +struct PaperSheet { + points: HashSet<(usize, usize)>, +} + +impl PaperSheet { + fn apply(&mut self, instr: FoldInstruction) { + let mut to_insert = Vec::new(); + let mut to_remove = Vec::new(); + + for point in &self.points { + match instr { + FoldInstruction::AlongX(x) => { + if point.0 <= x { + continue; + } + + let new_point = (x - (point.0 - x), point.1); + to_insert.push(new_point); + to_remove.push(*point); + } + FoldInstruction::AlongY(y) => { + if point.1 <= y { + continue; + } + + let new_point = (point.0, y - (point.1 - y)); + to_insert.push(new_point); + to_remove.push(*point); + } + } + } + + to_remove.iter().for_each(|point| { + self.points.remove(point); + }); + + to_insert.into_iter().for_each(|point| { + self.points.insert(point); + }); + } + + fn num_points(&self) -> usize { + self.points.len() + } +} + +impl std::fmt::Display for PaperSheet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // make sure first row appears on its own line + writeln!(f)?; + + if self.points.is_empty() { + return writeln!(f, "`empty paper sheet`"); + } + + let (width, _) = self.points.iter().max_by_key(|point| point.0).unwrap(); + let (_, height) = self.points.iter().max_by_key(|point| point.1).unwrap(); + + for y in 0..=*height { + for x in 0..=*width { + let chr = if self.points.contains(&(x, y)) { + '#' + } else { + '.' + }; + f.write_char(chr)?; + } + writeln!(f)?; + } + + Ok(()) + } +} + +impl std::str::FromStr for PaperSheet { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut points = HashSet::new(); + + for l in s.lines() { + let (x, y) = l + .trim() + .split_once(',') + .context("couldn't parse paper sheet point coordinate")?; + let (x, y) = (x.parse()?, y.parse()?); + + points.insert((x, y)); + } + + Ok(PaperSheet { points }) + } +} + +#[derive(Clone, Copy)] +enum FoldInstruction { + AlongX(usize), + AlongY(usize), +} + +impl std::str::FromStr for FoldInstruction { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (axis, coord) = s + .split_once('=') + .context("couldn't parse folding instruction")?; + let coord = coord.parse()?; + + match axis { + "fold along x" => Ok(FoldInstruction::AlongX(coord)), + "fold along y" => Ok(FoldInstruction::AlongY(coord)), + _ => Err(anyhow!("couldn't parse folding instruction")), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day13_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 17); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 753); + } + + #[test] + fn part2_provided() { + assert_eq!( + part2(PROVIDED).unwrap(), + " +##### +#...# +#...# +#...# +##### +" + ); + } + + #[test] + fn part2_real() { + assert_eq!( + part2(INPUT).unwrap(), + " +#..#.####.#....####.#..#...##.###..#..# +#..#....#.#....#....#..#....#.#..#.#.#. +####...#..#....###..####....#.#..#.##.. +#..#..#...#....#....#..#....#.###..#.#. +#..#.#....#....#....#..#.#..#.#.#..#.#. +#..#.####.####.####.#..#..##..#..#.#..# +" + ); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 6cbe7cd..5d8eeba 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -11,3 +11,4 @@ pub mod day08; pub mod day09; pub mod day10; pub mod day11; +pub mod day13; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index e5145c4..c21a96f 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -13,6 +13,7 @@ use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; use aoc2021::day11; +use aoc2021::day13; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -27,6 +28,7 @@ fn main() -> Result<()> { day09::run, day10::run, day11::run, + day13::run, ]; aoc::run(days) From d0f3b941ce3183b8139e1e4992d8fc8d07f3154f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 13 Dec 2021 11:59:08 +0100 Subject: [PATCH 075/134] 2021: day13: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 7b41e76..4e13654 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -11,6 +11,7 @@ use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; use aoc2021::day11; +use aoc2021::day13; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -24,6 +25,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day09", |b| b.iter(|| day09::run().unwrap())); c.bench_function("day10", |b| b.iter(|| day10::run().unwrap())); c.bench_function("day11", |b| b.iter(|| day11::run().unwrap())); + c.bench_function("day13", |b| b.iter(|| day13::run().unwrap())); } criterion_group! { From c439b3a2650fbc4df52f4ffd94795978e84811ed Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 13 Dec 2021 14:16:03 +0100 Subject: [PATCH 076/134] 2021: day12: part 1 --- aoc2021/input/day12.txt | 22 +++++ aoc2021/input/day12_provided1.txt | 7 ++ aoc2021/input/day12_provided2.txt | 10 +++ aoc2021/input/day12_provided3.txt | 18 ++++ aoc2021/src/day12.rs | 140 ++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 7 files changed, 200 insertions(+) create mode 100644 aoc2021/input/day12.txt create mode 100644 aoc2021/input/day12_provided1.txt create mode 100644 aoc2021/input/day12_provided2.txt create mode 100644 aoc2021/input/day12_provided3.txt create mode 100644 aoc2021/src/day12.rs diff --git a/aoc2021/input/day12.txt b/aoc2021/input/day12.txt new file mode 100644 index 0000000..731cd4b --- /dev/null +++ b/aoc2021/input/day12.txt @@ -0,0 +1,22 @@ +GC-zi +end-zv +lk-ca +lk-zi +GC-ky +zi-ca +end-FU +iv-FU +lk-iv +lk-FU +GC-end +ca-zv +lk-GC +GC-zv +start-iv +zv-QQ +ca-GC +ca-FU +iv-ca +start-lk +zv-FU +start-zi diff --git a/aoc2021/input/day12_provided1.txt b/aoc2021/input/day12_provided1.txt new file mode 100644 index 0000000..6fd8c41 --- /dev/null +++ b/aoc2021/input/day12_provided1.txt @@ -0,0 +1,7 @@ +start-A +start-b +A-c +A-b +b-d +A-end +b-end diff --git a/aoc2021/input/day12_provided2.txt b/aoc2021/input/day12_provided2.txt new file mode 100644 index 0000000..62cc714 --- /dev/null +++ b/aoc2021/input/day12_provided2.txt @@ -0,0 +1,10 @@ +dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc diff --git a/aoc2021/input/day12_provided3.txt b/aoc2021/input/day12_provided3.txt new file mode 100644 index 0000000..65f3833 --- /dev/null +++ b/aoc2021/input/day12_provided3.txt @@ -0,0 +1,18 @@ +fs-end +he-DX +fs-he +start-DX +pj-DX +end-zg +zg-sl +zg-pj +pj-he +RW-he +fs-DX +pj-RW +zg-RW +start-pj +he-WI +zg-he +pj-fs +start-RW diff --git a/aoc2021/src/day12.rs b/aoc2021/src/day12.rs new file mode 100644 index 0000000..c92b979 --- /dev/null +++ b/aoc2021/src/day12.rs @@ -0,0 +1,140 @@ +use std::collections::{HashMap, HashSet}; +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day12.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let cave_map: CaveMap = input.try_into()?; + + cave_map.count_paths() +} + +#[derive(Clone, Copy)] +struct Cave<'a> { + name: &'a str, + small: bool, +} + +impl<'a> Cave<'a> { + fn is_end(&self) -> bool { + self.name == "end" + } + + fn is_start(&self) -> bool { + self.name == "start" + } + + fn is_small(&self) -> bool { + self.small + } +} + +impl<'a> From<&'a str> for Cave<'a> { + fn from(s: &'a str) -> Self { + Cave { + name: s, + small: s.chars().all(char::is_lowercase), + } + } +} + +impl<'a> std::hash::Hash for Cave<'a> { + fn hash(&self, state: &mut H) { + self.name.hash(state); + } +} + +impl<'a> std::cmp::PartialEq for Cave<'a> { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} +impl<'a> std::cmp::Eq for Cave<'a> {} + +struct CaveMap<'a> { + connections: HashMap, Vec>>, +} + +impl<'a> CaveMap<'a> { + fn count_paths(&self) -> Result { + let start = *self + .connections + .keys() + .find(|cave| cave.is_start()) + .context("couldn't find starting cave")?; + Ok(self.count_paths_rec(start, HashSet::new())) + } + + fn count_paths_rec(&self, from: Cave<'a>, mut small_seen: HashSet>) -> usize { + if from.is_end() { + return 1; + } + + if from.is_small() { + if small_seen.contains(&from) { + return 0; + } + small_seen.insert(from); + } + + let mut paths = 0; + for dst in &self.connections[&from] { + paths += self.count_paths_rec(*dst, small_seen.clone()); + } + + paths + } +} + +impl<'a> TryFrom<&'a str> for CaveMap<'a> { + type Error = anyhow::Error; + + fn try_from(s: &'a str) -> Result { + let mut map = HashMap::new(); + + for line in s.lines().map(str::trim) { + let (src, dst) = line + .split_once('-') + .context("couldn't parse cave connection")?; + map.entry(src.into()) + .or_insert_with(Vec::new) + .push(dst.into()); + map.entry(dst.into()) + .or_insert_with(Vec::new) + .push(src.into()); + } + + Ok(CaveMap { connections: map }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED1: &str = include_str!("../input/day12_provided1.txt"); + const PROVIDED2: &str = include_str!("../input/day12_provided2.txt"); + const PROVIDED3: &str = include_str!("../input/day12_provided3.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED1).unwrap(), 10); + assert_eq!(part1(PROVIDED2).unwrap(), 19); + assert_eq!(part1(PROVIDED3).unwrap(), 226); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 5252); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 5d8eeba..cc37626 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -11,4 +11,5 @@ pub mod day08; pub mod day09; pub mod day10; pub mod day11; +pub mod day12; pub mod day13; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index c21a96f..1fa15e3 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -13,6 +13,7 @@ use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; use aoc2021::day11; +use aoc2021::day12; use aoc2021::day13; fn main() -> Result<()> { @@ -28,6 +29,7 @@ fn main() -> Result<()> { day09::run, day10::run, day11::run, + day12::run, day13::run, ]; From 28b84ae86546d8e1013737425b42d5de6c15b60b Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 13 Dec 2021 14:37:32 +0100 Subject: [PATCH 077/134] 2021: day12: part 2 --- aoc2021/src/day12.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/aoc2021/src/day12.rs b/aoc2021/src/day12.rs index c92b979..4628a85 100644 --- a/aoc2021/src/day12.rs +++ b/aoc2021/src/day12.rs @@ -9,6 +9,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -19,6 +20,12 @@ fn part1(input: &str) -> Result { cave_map.count_paths() } +fn part2(input: &str) -> Result { + let cave_map: CaveMap = input.try_into()?; + + cave_map.count_paths_twice() +} + #[derive(Clone, Copy)] struct Cave<'a> { name: &'a str, @@ -94,6 +101,46 @@ impl<'a> CaveMap<'a> { paths } + + fn count_paths_twice(&self) -> Result { + let start = *self + .connections + .keys() + .find(|cave| cave.is_start()) + .context("couldn't find starting cave")?; + Ok(self.count_paths_twice_rec(start, HashSet::new(), false)) + } + + fn count_paths_twice_rec( + &self, + from: Cave<'a>, + mut small_seen: HashSet>, + visited_twice: bool, + ) -> usize { + if from.is_end() { + return 1; + } + + if from.is_small() { + small_seen.insert(from); + } + + let mut paths = 0; + for dst in &self.connections[&from] { + let will_visit_twice = small_seen.contains(dst) && dst.is_small(); + if will_visit_twice && (visited_twice || dst.is_start()) { + continue; + } + + paths += self.count_paths_twice_rec( + *dst, + small_seen.clone(), + visited_twice || will_visit_twice, + ); + } + + paths + } } impl<'a> TryFrom<&'a str> for CaveMap<'a> { @@ -137,4 +184,16 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 5252); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED1).unwrap(), 36); + assert_eq!(part2(PROVIDED2).unwrap(), 103); + assert_eq!(part2(PROVIDED3).unwrap(), 3509); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 147784); + } } From 441e41c30c234d05ed2606449564a78e66325022 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 13 Dec 2021 14:56:05 +0100 Subject: [PATCH 078/134] 2021: day12: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 4e13654..5ac530a 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -11,6 +11,7 @@ use aoc2021::day08; use aoc2021::day09; use aoc2021::day10; use aoc2021::day11; +use aoc2021::day12; use aoc2021::day13; fn aoc2021_all(c: &mut Criterion) { @@ -25,6 +26,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day09", |b| b.iter(|| day09::run().unwrap())); c.bench_function("day10", |b| b.iter(|| day10::run().unwrap())); c.bench_function("day11", |b| b.iter(|| day11::run().unwrap())); + c.bench_function("day12", |b| b.iter(|| day12::run().unwrap())); c.bench_function("day13", |b| b.iter(|| day13::run().unwrap())); } From 218d9d5298a7b44887e560ddb03a46d18961af6a Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 14 Dec 2021 13:35:35 +0100 Subject: [PATCH 079/134] 2021: day14: part 1 --- aoc2021/input/day14.txt | 102 ++++++++++++++++++++ aoc2021/input/day14_provided.txt | 18 ++++ aoc2021/src/day14.rs | 160 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 283 insertions(+) create mode 100644 aoc2021/input/day14.txt create mode 100644 aoc2021/input/day14_provided.txt create mode 100644 aoc2021/src/day14.rs diff --git a/aoc2021/input/day14.txt b/aoc2021/input/day14.txt new file mode 100644 index 0000000..eed6b77 --- /dev/null +++ b/aoc2021/input/day14.txt @@ -0,0 +1,102 @@ +CKFFSCFSCBCKBPBCSPKP + +NS -> P +KV -> B +FV -> S +BB -> V +CF -> O +CK -> N +BC -> B +PV -> N +KO -> C +CO -> O +HP -> P +HO -> P +OV -> O +VO -> C +SP -> P +BV -> H +CB -> F +SF -> H +ON -> O +KK -> V +HC -> N +FH -> P +OO -> P +VC -> F +VP -> N +FO -> F +CP -> C +SV -> S +PF -> O +OF -> H +BN -> V +SC -> V +SB -> O +NC -> P +CN -> K +BP -> O +PC -> H +PS -> C +NB -> K +VB -> P +HS -> V +BO -> K +NV -> B +PK -> K +SN -> H +OB -> C +BK -> S +KH -> P +BS -> S +HV -> O +FN -> F +FS -> N +FP -> F +PO -> B +NP -> O +FF -> H +PN -> K +HF -> H +VK -> K +NF -> K +PP -> H +PH -> B +SK -> P +HN -> B +VS -> V +VN -> N +KB -> O +KC -> O +KP -> C +OS -> O +SO -> O +VH -> C +OK -> B +HH -> B +OC -> P +CV -> N +SH -> O +HK -> N +NO -> F +VF -> S +NN -> O +FK -> V +HB -> O +SS -> O +FB -> B +KS -> O +CC -> S +KF -> V +VV -> S +OP -> H +KN -> F +CS -> H +CH -> P +BF -> F +NH -> O +NK -> C +OH -> C +BH -> O +FC -> V +PB -> B diff --git a/aoc2021/input/day14_provided.txt b/aoc2021/input/day14_provided.txt new file mode 100644 index 0000000..b5594dd --- /dev/null +++ b/aoc2021/input/day14_provided.txt @@ -0,0 +1,18 @@ +NNCB + +CH -> B +HH -> N +CB -> H +NH -> C +HB -> C +HC -> B +HN -> C +NN -> C +BH -> H +NC -> B +NB -> B +BN -> B +BB -> N +BC -> B +CC -> N +CN -> C diff --git a/aoc2021/src/day14.rs b/aoc2021/src/day14.rs new file mode 100644 index 0000000..b94d370 --- /dev/null +++ b/aoc2021/src/day14.rs @@ -0,0 +1,160 @@ +use std::collections::{HashMap, HashSet, LinkedList}; +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day14.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let (polymer, rules) = input.split_once("\n\n").context("couldn't split input")?; + let mut polymer: Polymer = polymer.parse()?; + let rules: Rules = rules.parse()?; + + let mut molecule_set = polymer.molecule_set(); + rules.0.values().for_each(|v| { + molecule_set.insert(*v); + }); + + for _ in 0..10 { + polymer.insert_pairs(&rules.0)?; + } + + let occurrences = polymer.compute_occurrences(&molecule_set); + + let (_, least_common_occurrences) = occurrences + .iter() + .min_by_key(|(_, occurrences)| occurrences) + .unwrap(); + let (_, most_common_occurrences) = occurrences + .iter() + .max_by_key(|(_, occurrences)| occurrences) + .unwrap(); + + Ok(most_common_occurrences - least_common_occurrences) +} + +struct Rules(HashMap<(char, char), char>); + +impl std::str::FromStr for Rules { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(Self( + s.lines() + .map(str::trim) + .map(|l| { + let (pair, res) = l.split_once(" -> ").context("couldn't parse rule")?; + Ok(( + ( + pair.chars().next().context("")?, + pair.chars().nth(1).context("")?, + ), + res.chars().next().context("couldn't parse rule")?, + )) + }) + .collect::>()?, + )) + } +} + +#[derive(Debug)] +struct Polymer { + molecules: Option>, +} + +impl Polymer { + fn insert_pairs(&mut self, rules: &HashMap<(char, char), char>) -> Result<()> { + debug_assert!(self.molecules.is_some()); + + self.molecules = Some(insert_pairs( + std::mem::replace(&mut self.molecules, None).unwrap(), + rules, + )?); + Ok(()) + } + + fn compute_occurrences(&self, molecule_set: &HashSet) -> Vec<(char, usize)> { + debug_assert!(self.molecules.is_some()); + + let mut res = Vec::new(); + for molecule in molecule_set { + let count = self + .molecules + .as_ref() + .unwrap() // we always have a Some, Option only used for std::mem::replace + .iter() + .filter(|&m| m == molecule) + .count(); + res.push((*molecule, count)); + } + + res + } + + fn molecule_set(&self) -> HashSet { + debug_assert!(self.molecules.is_some()); + + self.molecules.as_ref().unwrap().iter().copied().collect() + } +} + +impl std::str::FromStr for Polymer { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let molecules = s.trim().chars().collect(); + + Ok(Polymer { + molecules: Some(molecules), + }) + } +} + +fn insert_pairs( + mut molecules: LinkedList, + rules: &HashMap<(char, char), char>, +) -> Result> { + if molecules.len() <= 1 { + return Ok(molecules); + } + + // List length is at least 2 + let mut iter = molecules.iter(); + let (left, right) = (*iter.next().unwrap(), *iter.next().unwrap()); + + let to_insert = *rules + .get(&(left, right)) + .with_context(|| format!("couldn't find rule for pair ({}, {})", left, right))?; + + let mut tail = insert_pairs(molecules.split_off(1), rules)?; + + molecules.push_back(to_insert); + molecules.append(&mut tail); + + Ok(molecules) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day14_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 1588); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 3247); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index cc37626..4b6855a 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -13,3 +13,4 @@ pub mod day10; pub mod day11; pub mod day12; pub mod day13; +pub mod day14; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 1fa15e3..0c06f85 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -15,6 +15,7 @@ use aoc2021::day10; use aoc2021::day11; use aoc2021::day12; use aoc2021::day13; +use aoc2021::day14; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -31,6 +32,7 @@ fn main() -> Result<()> { day11::run, day12::run, day13::run, + day14::run, ]; aoc::run(days) From 9d81739f2b726d4b3b2cc321427b47a3f9ea92a1 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 14 Dec 2021 13:39:48 +0100 Subject: [PATCH 080/134] 2021: day14: fix stack overflow in part 1 --- aoc2021/src/day14.rs | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/aoc2021/src/day14.rs b/aoc2021/src/day14.rs index b94d370..c1ef925 100644 --- a/aoc2021/src/day14.rs +++ b/aoc2021/src/day14.rs @@ -119,27 +119,41 @@ impl std::str::FromStr for Polymer { } fn insert_pairs( - mut molecules: LinkedList, + molecules: LinkedList, rules: &HashMap<(char, char), char>, ) -> Result> { if molecules.len() <= 1 { return Ok(molecules); } - // List length is at least 2 - let mut iter = molecules.iter(); - let (left, right) = (*iter.next().unwrap(), *iter.next().unwrap()); + let mut head = molecules; + let mut tail = head.split_off(0); - let to_insert = *rules - .get(&(left, right)) - .with_context(|| format!("couldn't find rule for pair ({}, {})", left, right))?; + while tail.len() > 1 { + // List length is at least 2 + let mut iter = tail.iter(); + let (left, right) = (*iter.next().unwrap(), *iter.next().unwrap()); - let mut tail = insert_pairs(molecules.split_off(1), rules)?; + let to_insert = *rules + .get(&(left, right)) + .with_context(|| format!("couldn't find rule for pair ({}, {})", left, right))?; - molecules.push_back(to_insert); - molecules.append(&mut tail); + // tail = left + // new_tail = right -> rest + let new_tail = tail.split_off(1); - Ok(molecules) + // head = head -> left + head.append(&mut tail); + // head = head -> left -> to_insert + head.push_back(to_insert); + + // tail = right -> rest + tail = new_tail; + } + + head.append(&mut tail); + + Ok(head) } #[cfg(test)] From 822707939e85bcffe26951fad6a77b1aff22f80d Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 14 Dec 2021 15:47:40 +0100 Subject: [PATCH 081/134] 2021: day14: part 2 --- aoc2021/src/day14.rs | 155 +++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 78 deletions(-) diff --git a/aoc2021/src/day14.rs b/aoc2021/src/day14.rs index c1ef925..a91b2a6 100644 --- a/aoc2021/src/day14.rs +++ b/aoc2021/src/day14.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet, LinkedList}; +use std::collections::HashMap; use std::fmt::Write; use anyhow::{Context, Result}; @@ -9,6 +9,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -18,30 +19,48 @@ fn part1(input: &str) -> Result { let mut polymer: Polymer = polymer.parse()?; let rules: Rules = rules.parse()?; - let mut molecule_set = polymer.molecule_set(); - rules.0.values().for_each(|v| { - molecule_set.insert(*v); - }); - for _ in 0..10 { polymer.insert_pairs(&rules.0)?; } - let occurrences = polymer.compute_occurrences(&molecule_set); + let occurrences = polymer.compute_occurrences(); let (_, least_common_occurrences) = occurrences .iter() - .min_by_key(|(_, occurrences)| occurrences) + .min_by_key(|&(_, occurrences)| occurrences) .unwrap(); let (_, most_common_occurrences) = occurrences .iter() - .max_by_key(|(_, occurrences)| occurrences) + .max_by_key(|&(_, occurrences)| occurrences) .unwrap(); Ok(most_common_occurrences - least_common_occurrences) } -struct Rules(HashMap<(char, char), char>); +fn part2(input: &str) -> Result { + let (polymer, rules) = input.split_once("\n\n").context("couldn't split input")?; + let mut polymer: Polymer = polymer.parse()?; + let rules: Rules = rules.parse()?; + + for _ in 0..40 { + polymer.insert_pairs(&rules.0)?; + } + + let occurrences = polymer.compute_occurrences(); + + let (_, least_common_occurrences) = occurrences + .iter() + .min_by_key(|&(_, occurrences)| occurrences) + .unwrap(); + let (_, most_common_occurrences) = occurrences + .iter() + .max_by_key(|&(_, occurrences)| occurrences) + .unwrap(); + + Ok(most_common_occurrences - least_common_occurrences) +} + +struct Rules(HashMap<(u8, u8), u8>); impl std::str::FromStr for Rules { type Err = anyhow::Error; @@ -54,10 +73,10 @@ impl std::str::FromStr for Rules { let (pair, res) = l.split_once(" -> ").context("couldn't parse rule")?; Ok(( ( - pair.chars().next().context("")?, - pair.chars().nth(1).context("")?, + *pair.as_bytes().get(0).context("couldn't parse rule")?, + *pair.as_bytes().get(1).context("couldn't parse rule")?, ), - res.chars().next().context("couldn't parse rule")?, + res.bytes().next().context("couldn't parse rule")?, )) }) .collect::>()?, @@ -67,42 +86,45 @@ impl std::str::FromStr for Rules { #[derive(Debug)] struct Polymer { - molecules: Option>, + molecules: HashMap<(u8, u8), usize>, + first: u8, + last: u8, } impl Polymer { - fn insert_pairs(&mut self, rules: &HashMap<(char, char), char>) -> Result<()> { - debug_assert!(self.molecules.is_some()); + fn insert_pairs(&mut self, rules: &HashMap<(u8, u8), u8>) -> Result<()> { + let mut new_molecules = HashMap::new(); + + for (&(a, b), &count) in &self.molecules { + let middle = *rules + .get(&(a, b)) + .with_context(|| format!("couldn't find rule for pair ({}, {})", a, b))?; + + *new_molecules.entry((a, middle)).or_insert(0) += count; + *new_molecules.entry((middle, b)).or_insert(0) += count; + } + + self.molecules = new_molecules; - self.molecules = Some(insert_pairs( - std::mem::replace(&mut self.molecules, None).unwrap(), - rules, - )?); Ok(()) } - fn compute_occurrences(&self, molecule_set: &HashSet) -> Vec<(char, usize)> { - debug_assert!(self.molecules.is_some()); + fn compute_occurrences(&self) -> Vec<(u8, usize)> { + let mut counts = HashMap::new(); - let mut res = Vec::new(); - for molecule in molecule_set { - let count = self - .molecules - .as_ref() - .unwrap() // we always have a Some, Option only used for std::mem::replace - .iter() - .filter(|&m| m == molecule) - .count(); - res.push((*molecule, count)); + for (&(a, b), &count) in &self.molecules { + *counts.entry(a).or_insert(0) += count; + *counts.entry(b).or_insert(0) += count; } - res - } + // the first and last molecule are only counted once, all other molecules are counted twice + *counts.entry(self.first).or_insert(0) += 1; + *counts.entry(self.last).or_insert(0) += 1; - fn molecule_set(&self) -> HashSet { - debug_assert!(self.molecules.is_some()); - - self.molecules.as_ref().unwrap().iter().copied().collect() + counts + .into_iter() + .map(|(m, count)| (m, count / 2)) + .collect() } } @@ -110,52 +132,19 @@ impl std::str::FromStr for Polymer { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - let molecules = s.trim().chars().collect(); + let mut molecules = HashMap::new(); + s.as_bytes() + .windows(2) + .for_each(|w| *molecules.entry((w[0], w[1])).or_insert(0) += 1); Ok(Polymer { - molecules: Some(molecules), + molecules, + first: *s.as_bytes().first().context("polymer was empty")?, + last: *s.as_bytes().last().context("polymer was empty")?, }) } } -fn insert_pairs( - molecules: LinkedList, - rules: &HashMap<(char, char), char>, -) -> Result> { - if molecules.len() <= 1 { - return Ok(molecules); - } - - let mut head = molecules; - let mut tail = head.split_off(0); - - while tail.len() > 1 { - // List length is at least 2 - let mut iter = tail.iter(); - let (left, right) = (*iter.next().unwrap(), *iter.next().unwrap()); - - let to_insert = *rules - .get(&(left, right)) - .with_context(|| format!("couldn't find rule for pair ({}, {})", left, right))?; - - // tail = left - // new_tail = right -> rest - let new_tail = tail.split_off(1); - - // head = head -> left - head.append(&mut tail); - // head = head -> left -> to_insert - head.push_back(to_insert); - - // tail = right -> rest - tail = new_tail; - } - - head.append(&mut tail); - - Ok(head) -} - #[cfg(test)] mod tests { use super::*; @@ -171,4 +160,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 3247); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 2188189693529); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 4110568157153); + } } From 1fb0be9e89491f899f5481ebe06c0217f737ba12 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 14 Dec 2021 15:48:12 +0100 Subject: [PATCH 082/134] 2021: day14: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 5ac530a..cfa9869 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -13,6 +13,7 @@ use aoc2021::day10; use aoc2021::day11; use aoc2021::day12; use aoc2021::day13; +use aoc2021::day14; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -28,6 +29,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day11", |b| b.iter(|| day11::run().unwrap())); c.bench_function("day12", |b| b.iter(|| day12::run().unwrap())); c.bench_function("day13", |b| b.iter(|| day13::run().unwrap())); + c.bench_function("day14", |b| b.iter(|| day14::run().unwrap())); } criterion_group! { From d204e46890f3af902e006c666c7fb4ae74ceb63d Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 01:31:44 +0100 Subject: [PATCH 083/134] 2021: day15: part 1 --- aoc2021/input/day15.txt | 100 +++++++++++++++++++ aoc2021/input/day15_provided.txt | 10 ++ aoc2021/src/day15.rs | 165 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 278 insertions(+) create mode 100644 aoc2021/input/day15.txt create mode 100644 aoc2021/input/day15_provided.txt create mode 100644 aoc2021/src/day15.rs diff --git a/aoc2021/input/day15.txt b/aoc2021/input/day15.txt new file mode 100644 index 0000000..1ec5758 --- /dev/null +++ b/aoc2021/input/day15.txt @@ -0,0 +1,100 @@ +8656175343119439947311919179279377257689197682985752287249881788527977345924133329967132199899199876 +4281288396984115627338957853913949146812568775798196289991176529889498798259196976277683981565984526 +8169838335918963371547591999342191683995972519179929683978126291855319511168245582651697938949414963 +9911589184911198759466719191189995157885898771177913669999436998997781742478168921196176418888127932 +2332856729917591158935782911513226531793881992469468248251991718456991551657621249229316797949388969 +6488738222981127824819626661531168733698299313631126969162927725778914183239351484699921454131481322 +3456499223985116399353928681116846939429849384129296119943791119497551946593566977823982927391143399 +9297612841849646148511299569971197927971682598351883892842936977227795411959211782251399118676896328 +1685688918999598249622886442487951289969917848948815999749154287969297396481891239821819247914959943 +2855192597719945162116189119381795158862162959133647579913886639586438893695967226719685616432291318 +3893139873964939791913261811173979825213968972939996181992593113695976322782892995939891783998623789 +5964671772545917912328949994999514157618987654288269789931394913375316999489275494179994919117119365 +3216339828898396212733674969295762442389789119366989996931919596282992864471192938639162947919972647 +7879826444123912118829914949989194219763533694839431198212319893181151696157671388992581982743988967 +7876122492176935838133394839673532581399474449569117478121989273123412313151952891988698552384251637 +8786999269197821985731819155537259938991261919979365751539876866146174376911518943778479997131942722 +7239919942299391891898171771589178983916281118889294494829292752139999754571391999826947791975394972 +2727617215141959982544247383138498917281833932371546394891963994434638187617528821379728933335772342 +6712949984729176138535147942577311588399869767114795759883948915177671474313191789814718292236422124 +8689792116597916131779139899373471282726812338914773516383771158691551851991689929199689197212298649 +6228175894997691471313338136819712699979449476188196729899628851391971728199959981585798691881191415 +9491157288112631922166642933446197292729817888649185515198768537925149995158353829229269894798938589 +5199389142294542461535132814487861987422485947698739199748986652229272998164982399192268248929567161 +6881119581991538187539159493621999896486112182779617795198955921614753699796171837819179999654231813 +6996595113784151975521879415898217119639999975184518599369743127684295298268259495226623211591871888 +1779949977648145993713949919359399998812143513534984334127763318649997689919849157137418761137512977 +9223292971993981422528813498119387921238194638215641911218326517839287886478991147999899894724396962 +7451983891767995938972123465939918261682281929689989464297789895588752221375859586787938391672994381 +1579954176878141996516584483611183926131694919877929897576151469657864935819598781814826881644187861 +8934595321937914584995177237653199951582515953621782173159453287575529819242531191989113518599339361 +3214791137819868237121897913928328682928239268681975567994149694512799167598489194267554981611157817 +3161289322443822496458312797912957538349962328948955764669152944278622928929944477635195993465821714 +3769985892295265479971729196428585411214871889139731131516448815999122871374996159138497416978598848 +4926877381218811127939655759733739111889455359949289979523168797571871445191441719179859376969393872 +7159871151274214979637977982939997337182139971896511115912187982698278842961545125121242636339621282 +8423118867997391616931374681582965659184916625321536161483641999294114251928796446618889979683993218 +6824788915976897879897933391998341399228914119912289149511515799142181679965255395897688149876629889 +4794395837416911945432167619882718499181629123717219977896911277339851349162195299228963994667691947 +1465122112768881153591399679274839985297692314947884169719151181986711822112796246416415955915718319 +7114797833579933611249299912348294873921288555119486979959982462111791467394161781467316779796883775 +9767795467854144194712742294766968549329117618283754959873952489784997597669593796889571883816748771 +1759974879458746414925558868197241214751687661841649999221178613679929261984417289292556869111324941 +9557955429999672993612951916598187741611893112948813816999484953994151249931191942493691497559992158 +1469791219499218437828194894539893191199115998162227659757698173867329816328599398544492677817272998 +6696472832532492295279572315976884291727999732161858916985514872395367168971969865959582923387918951 +9722652752119479169481198119314728131429449798379179119171791999189878174319864498112912224658495939 +9581794449119116165418178711351481129242636919987948291451161695541253977174231393582734959682898495 +4757727865924728111221629983989222587789999361791192917315287219922119718827676188689966872358484669 +1982319969915242121935864989286462118395187369193933592791414764965279817872197863615512262358899223 +1811379712999278717898361849316989959114612857179582117839285399618929182259624916911439331479239488 +1377519658968884779897799292198595917148591218821239614925192183128211371959295299959221257811239131 +2627929612263297913663198357736594275199769318118546371628241929618769991214845296132728799271417791 +7576972138942696587693261199467749912936563131454674591315468112333812659454789393699615918167338715 +1778985995949591574849625759667137792111923771976687288498928179271746938986792658149697999719931492 +1497174992519427759719169714342998311421419197412331399469329847692794191181111339933357161599799597 +7158163932199423259572847121198873491117119999919996985599149129919588579223518511588378639685891315 +6219361855573892912131718991998196749251949481814844299182119621344738991784149679694476483378729929 +1398599388779918861183115593522489331874978727922373471991219247115944295163699192776967648639268659 +8246143812623927544154898631717811662213981175534335932638718171969421398421692892399791789186618487 +4457134139841167885881924949364884427839314973843366971997383189398399657998961185159781215111619878 +2889934549617841969369167119338852267887359654637229634658717722728239549585928482358431813296859898 +9968328746979669249145999585143117898196251944175462877716129989773292878848966999379983436559934934 +6493994193996595991299891992438695916166928199197254269991979292986895799985938128881229638182945947 +7266928918675112795879219714929968471352931229592623394713393869269941181318972192169271548316892574 +2174196776119149368951321419512925818641848291921584561885586189445194773817792112569311611884895234 +5617593683181229369984148191819568774125471789395181874847932736429929334265516997661987796259692831 +7882228973393795938729341656949619511272988446634311621871394678132831899299832311614174939261965429 +1131881592984545192978449637151892697525357924197922698921549791127287595929496515499876251183628176 +9922954913893559597663824459627321943979599969474976998899879429185892995511392872381956558981867119 +5166385448694129439797196837181355547743133114829285275149516986685925813416161972979872853196155916 +3292899922794159291851551956738911971988929383861879921354871787791695284999126375594873179426338749 +3971894752927483651131869717199971871964396958991799413921821198121691265888799954912311963139425236 +5778565318498395151591219315499879273943817921588123199611531989674238272218198865913747444419629892 +1148956123134785152496887782841669964225944272953163717879528194631986997718971481186872943816456591 +5982998155291779554662769986899318991622943125199743569463317913185991442772122148595119965486877247 +1592622221626611159996955945922614981222438358385913259412688295754161193293194979914999974739594393 +1735995389872189896282749844299933869588931688619645726996959149185997128397635694766944945458588326 +8969839951998899979864239155832982419271118982882915197745124695321464198748765361499779978719441246 +6625484228731161195646227911299498172947526327866775111148173468799729895761595437743769876911891521 +6742199381937628999297557371399872217983581247138899399239252389649491949578491998528132446741686888 +9212328164223895178547771855976415127193137191217188318191949238429129518281919843229126971963111111 +8589368771155989697277997492471969978917117589192916193887975787949771588121551699971132275182798898 +1321997349438946615383211392181979153964221243634922639112684529286794272849757186396714797832698913 +5499455959999492339698359789213323519479768626457859213487938838995348379392231623595879353861382977 +4612129999347379911982695394862437936254989311441326295994617191963497895691479282499959828989987571 +3953949985681978999897341375236798381973326952579319464522624134872231113676167279146985521828793431 +2547232255918288952326674861524529119719429148626615319818611241832868529862499874951986568635799957 +2181959929952711246913363617991144311613441799129546223661433628933579819732979148127949974997119951 +1369158892917379123998253242599392893199998853969933983592129813969821127281951849151627687114757833 +9629699176294886577773394197932998769278865351155516385519239971147785457838922269188195227329168368 +1788912961677399663173822433232514884848179868666798987368382881226468481869127998236137881926332779 +4811241997249159619241887142461943467819366815858371379792287198271563986876852729186927761281942192 +2121993996798639492562961751217922319969898368461919218459919713413366292171628639922554153774327219 +3489591127775295131639799492971117993637992434115331278511281997587996291111198123428588991837368589 +1283798883941983912985615991541417994114453747887836936186431822993881123911799962749981389292178586 +8392631553657936578372199916912973193995216848776811924799769959318889717919172521769363698292447429 +9587697134368994212916856845984875416273418561198913859115983139967143891991617853289936814265113512 +9111571922348271733199797953979536915998195916688317991255916216419817129423728913622269119972958686 +9959599568987335314713638999897919449512991684446347789183915679567141547281548619496728636288445972 +8391247911139217869276338998734496391173478717461631572924754792241695917352991662734191814376765142 diff --git a/aoc2021/input/day15_provided.txt b/aoc2021/input/day15_provided.txt new file mode 100644 index 0000000..ab80887 --- /dev/null +++ b/aoc2021/input/day15_provided.txt @@ -0,0 +1,10 @@ +1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581 diff --git a/aoc2021/src/day15.rs b/aoc2021/src/day15.rs new file mode 100644 index 0000000..44fd45a --- /dev/null +++ b/aoc2021/src/day15.rs @@ -0,0 +1,165 @@ +use std::cmp::Reverse; +use std::collections::BinaryHeap; +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day15.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let cavern: CavernMap = input.parse()?; + + let lowest_risk = cavern.lowest_risk_path(); + + Ok(lowest_risk) +} + +struct CavernMap { + height: usize, + width: usize, + risk: Vec, +} + +impl CavernMap { + // typical Dijkstra implementation, using a binary heap as a priority queue + fn lowest_risk_path(&self) -> u64 { + let mut visited = Vec::new(); + visited.resize(self.height * self.width, false); + let mut total_risk = Vec::new(); + total_risk.resize(self.height * self.width, u64::MAX); + total_risk[self.index(0, 0)] = 0; + + let mut queue = BinaryHeap::new(); + queue.push(Reverse((0, (0, 0)))); + + while !queue.is_empty() { + let Reverse((curr_risk, (x, y))) = queue.pop().unwrap(); + debug_assert_eq!(curr_risk, total_risk[self.index(x, y)]); + + if (x, y) == (self.width - 1, self.height - 1) { + // reached destination, we're done! + break; + } + + if visited[self.index(x, y)] { + // duplicate entry in queue, discard + continue; + } + visited[self.index(x, y)] = true; + + for (nx, ny) in self.neighbours(x, y) { + let neighbour_index = self.index(nx, ny); + let old_risk = total_risk[neighbour_index]; + let new_risk = curr_risk + self.risk[neighbour_index]; + + if new_risk < old_risk { + total_risk[neighbour_index] = new_risk; + // we don't delete older queue entries for the same cell, if we find them later + // on we can just skip them because they're marked as visited already + queue.push(Reverse((new_risk, (nx, ny)))); + } + } + } + + *total_risk.last().unwrap() + } + + fn neighbours(&self, x: usize, y: usize) -> impl Iterator + 'static { + let width = self.width; + let height = self.height; + Neighbour::ALL + .iter() + .copied() + .filter_map(move |neighbour| neighbour.apply(x, y, width, height)) + } + + fn index(&self, x: usize, y: usize) -> usize { + y * self.width + x + } +} + +impl std::str::FromStr for CavernMap { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut risk = Vec::new(); + + let mut height = 0; + let mut width = None; + for line in s.lines().map(str::trim) { + let line = line + .chars() + .map(|chr| { + chr.to_digit(10) + .map(|digit| digit as u64) + .with_context(|| format!("cannot parse char {} to digit", chr)) + }) + .collect::>>()?; + + if width.is_none() { + width = Some(line.len()); + } + + height += 1; + risk.extend_from_slice(&line); + } + + Ok(CavernMap { + height, + width: width.context("0 lines parsed, width never computed")?, + risk, + }) + } +} + +#[derive(Clone, Copy)] +enum Neighbour { + Up, + Down, + Left, + Right, +} + +impl Neighbour { + fn apply(&self, x: usize, y: usize, width: usize, height: usize) -> Option<(usize, usize)> { + match self { + Neighbour::Left if x > 0 => Some((x - 1, y)), + Neighbour::Right if x < width - 1 => Some((x + 1, y)), + Neighbour::Up if y > 0 => Some((x, y - 1)), + Neighbour::Down if y < height - 1 => Some((x, y + 1)), + _ => None, + } + } + + const ALL: &'static [Self] = &[ + Neighbour::Left, + Neighbour::Right, + Neighbour::Up, + Neighbour::Down, + ]; +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day15_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 40); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 562); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 4b6855a..3427e05 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -14,3 +14,4 @@ pub mod day11; pub mod day12; pub mod day13; pub mod day14; +pub mod day15; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 0c06f85..4dcd949 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -16,6 +16,7 @@ use aoc2021::day11; use aoc2021::day12; use aoc2021::day13; use aoc2021::day14; +use aoc2021::day15; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -33,6 +34,7 @@ fn main() -> Result<()> { day12::run, day13::run, day14::run, + day15::run, ]; aoc::run(days) From 0acae295daf4997400684c66d44a7fe2c951853f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 01:52:47 +0100 Subject: [PATCH 084/134] 2021: day15: part 2 --- aoc2021/src/day15.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/aoc2021/src/day15.rs b/aoc2021/src/day15.rs index 44fd45a..e8a3a18 100644 --- a/aoc2021/src/day15.rs +++ b/aoc2021/src/day15.rs @@ -10,6 +10,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -22,6 +23,16 @@ fn part1(input: &str) -> Result { Ok(lowest_risk) } +fn part2(input: &str) -> Result { + let cavern: CavernMap = input.parse()?; + let cavern = cavern.bigger(); + + let lowest_risk = cavern.lowest_risk_path(); + + Ok(lowest_risk) +} + +#[derive(Debug)] struct CavernMap { height: usize, width: usize, @@ -84,6 +95,38 @@ impl CavernMap { fn index(&self, x: usize, y: usize) -> usize { y * self.width + x } + + fn bigger(self) -> Self { + let width = self.width * 5; + let height = self.height * 5; + let mut risk = self.risk.clone(); + risk.resize(width * height, 0); + + for shift_y in 0..5 { + for shift_x in 0..5 { + for y in 0..self.height { + for x in 0..self.width { + let new_y = shift_y * self.height + y; + let new_x = shift_x * self.width + x; + let new_index = new_y * width + new_x; + + let old_risk = self.risk[self.index(x, y)]; + let mut new_risk = old_risk + shift_x as u64 + shift_y as u64; + if new_risk > 9 { + new_risk -= 9; + } + risk[new_index] = new_risk; + } + } + } + } + + Self { + height, + width, + risk, + } + } } impl std::str::FromStr for CavernMap { @@ -162,4 +205,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 562); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 315); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2874); + } } From 95d955f5067cd89223ba13d42968b524b62a4575 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 01:53:58 +0100 Subject: [PATCH 085/134] 2021: day15: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index cfa9869..1c4a956 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -14,6 +14,7 @@ use aoc2021::day11; use aoc2021::day12; use aoc2021::day13; use aoc2021::day14; +use aoc2021::day15; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -30,6 +31,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day12", |b| b.iter(|| day12::run().unwrap())); c.bench_function("day13", |b| b.iter(|| day13::run().unwrap())); c.bench_function("day14", |b| b.iter(|| day14::run().unwrap())); + c.bench_function("day15", |b| b.iter(|| day15::run().unwrap())); } criterion_group! { From 025374e68544ba785e6d3c60d1b9641b9a04458b Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 15:50:19 +0100 Subject: [PATCH 086/134] 2021: day16: part 1: parse litterals --- Cargo.lock | 47 +++++++++++---- aoc2021/Cargo.toml | 1 + aoc2021/input/day16.txt | 1 + aoc2021/src/day16.rs | 129 ++++++++++++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 6 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 aoc2021/input/day16.txt create mode 100644 aoc2021/src/day16.rs diff --git a/Cargo.lock b/Cargo.lock index 82780e0..b620f0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", + "bitvec 0.22.3", "rand", ] @@ -130,14 +131,26 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.19.6" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" +checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" dependencies = [ "funty", - "radium", + "radium 0.5.3", "tap", - "wyz", + "wyz 0.2.0", +] + +[[package]] +name = "bitvec" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" +dependencies = [ + "funty", + "radium 0.6.2", + "tap", + "wyz 0.4.0", ] [[package]] @@ -336,9 +349,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "funty" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" [[package]] name = "generic-array" @@ -470,12 +483,11 @@ dependencies = [ [[package]] name = "nom" -version = "6.2.1" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" +checksum = "3d521ee2250f619dd5e06515ba405858d249edc8fae9ddee2dba0695e57db01b" dependencies = [ - "bitvec", - "funty", + "bitvec 0.19.4", "lexical-core", "memchr", "version_check", @@ -570,6 +582,12 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" +[[package]] +name = "radium" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" + [[package]] name = "rand" version = "0.8.4" @@ -913,3 +931,12 @@ name = "wyz" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "wyz" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" +dependencies = [ + "tap", +] diff --git a/aoc2021/Cargo.toml b/aoc2021/Cargo.toml index 4d8f362..e31557d 100644 --- a/aoc2021/Cargo.toml +++ b/aoc2021/Cargo.toml @@ -10,6 +10,7 @@ edition = "2021" aoc = { path = "../aoc" } anyhow = "1.0" rand = "0.8" +bitvec = "0.22" [lib] path = "src/lib.rs" diff --git a/aoc2021/input/day16.txt b/aoc2021/input/day16.txt new file mode 100644 index 0000000..dbbec6c --- /dev/null +++ b/aoc2021/input/day16.txt @@ -0,0 +1 @@ +E20D4100AA9C0199CA6A3D9D6352294D47B3AC6A4335FBE3FDD251003873657600B46F8DC600AE80273CCD2D5028B6600AF802B2959524B727D8A8CC3CCEEF3497188C017A005466DAA6FDB3A96D5944C014C006865D5A7255D79926F5E69200A164C1A65E26C867DDE7D7E4794FE72F3100C0159A42952A7008A6A5C189BCD456442E4A0A46008580273ADB3AD1224E600ACD37E802200084C1083F1540010E8D105A371802D3B845A0090E4BD59DE0E52FFC659A5EBE99AC2B7004A3ECC7E58814492C4E2918023379DA96006EC0008545B84B1B00010F8E915E1E20087D3D0E577B1C9A4C93DD233E2ECF65265D800031D97C8ACCCDDE74A64BD4CC284E401444B05F802B3711695C65BCC010A004067D2E7C4208A803F23B139B9470D7333B71240050A20042236C6A834600C4568F5048801098B90B626B00155271573008A4C7A71662848821001093CB4A009C77874200FCE6E7391049EB509FE3E910421924D3006C40198BB11E2A8803B1AE2A4431007A15C6E8F26009E002A725A5292D294FED5500C7170038C00E602A8CC00D60259D008B140201DC00C401B05400E201608804D45003C00393600B94400970020C00F6002127128C0129CDC7B4F46C91A0084E7C6648DC000DC89D341B23B8D95C802D09453A0069263D8219DF680E339003032A6F30F126780002CC333005E8035400042635C578A8200DC198890AA46F394B29C4016A4960C70017D99D7E8AF309CC014FCFDFB0FE0DA490A6F9D490010567A3780549539ED49167BA47338FAAC1F3005255AEC01200043A3E46C84E200CC4E895114C011C0054A522592912C9C8FDE10005D8164026C70066C200C4618BD074401E8C90E23ACDFE5642700A6672D73F285644B237E8CCCCB77738A0801A3CFED364B823334C46303496C940 diff --git a/aoc2021/src/day16.rs b/aoc2021/src/day16.rs new file mode 100644 index 0000000..53dec9e --- /dev/null +++ b/aoc2021/src/day16.rs @@ -0,0 +1,129 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; +use bitvec::prelude::*; + +const INPUT: &str = include_str!("../input/day16.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let packet: Packet = input.parse()?; + + Ok(packet.version_sum()) +} + +#[derive(PartialEq, Eq, Debug)] +enum PacketType { + Litteral(LitteralPacket), + Operator(OperatorPacket), +} + +#[derive(PartialEq, Eq, Debug)] +struct Packet { + version: u8, + type_id: u8, + packet: PacketType, +} + +impl Packet { + fn version_sum(&self) -> u64 { + match &self.packet { + PacketType::Litteral(_) => self.version as u64, + PacketType::Operator(op) => op.sub_packets.iter().map(Packet::version_sum).sum(), + } + } +} + +#[derive(PartialEq, Eq, Debug)] +struct LitteralPacket { + value: u64, +} + +#[derive(PartialEq, Eq, Debug)] +struct OperatorPacket { + sub_packets: Vec, +} + +impl std::str::FromStr for Packet { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let s = s.trim(); + let mut bits = BitVec::::new(); + bits.resize(4 * s.len(), false); + + for (i, c) in s.chars().enumerate() { + let bit_index = i * 4; + let digit = c.to_digit(16).context("character wasn't hex digit")?; + bits[bit_index..(bit_index + 4)].store(digit); + } + + bits.as_bitslice().try_into() + } +} + +impl<'bits, Store> TryFrom<&'bits BitSlice> for Packet +where + Store: BitStore, +{ + type Error = anyhow::Error; + + fn try_from(bits: &'bits BitSlice) -> Result { + let version: u8 = bits[0..3].load(); + let type_id: u8 = bits[3..6].load(); + + match type_id { + 4 => { + let mut value = 0; + for i in (6..).step_by(5) { + let val = bits[(i + 1)..(i + 5)].load::(); + value = (value << 4) + val; + + if !bits[i] { + break; + } + } + + Ok(Packet { + version, + type_id, + packet: PacketType::Litteral(LitteralPacket { value }), + }) + } + _ => unimplemented!("Operator packets aren't implemented yet"), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED1: &str = "D2FE28"; + const PROVIDED2: &str = "38006F45291200"; + const PROVIDED3: &str = "EE00D40C823060"; + + const PROVIDED4: &str = "8A004A801A8002F478"; + const PROVIDED5: &str = "620080001611562C8802118E34"; + const PROVIDED6: &str = "C0015000016115A2E0802F182340"; + const PROVIDED7: &str = "A0016C880162017C3686B18A3D4780"; + + #[test] + fn part1_provided() { + assert_eq!( + PROVIDED1.parse::().unwrap(), + Packet { + version: 6, + type_id: 4, + packet: PacketType::Litteral(LitteralPacket { value: 2021 }), + } + ); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index 3427e05..f281e9a 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -15,3 +15,4 @@ pub mod day12; pub mod day13; pub mod day14; pub mod day15; +pub mod day16; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 4dcd949..524f73b 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -17,6 +17,7 @@ use aoc2021::day12; use aoc2021::day13; use aoc2021::day14; use aoc2021::day15; +use aoc2021::day16; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -35,6 +36,7 @@ fn main() -> Result<()> { day13::run, day14::run, day15::run, + day16::run, ]; aoc::run(days) From 78f059b65cd688dcaa8efe0946a4c113e255e141 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 17:32:08 +0100 Subject: [PATCH 087/134] 2021: day16: part 1 --- aoc2021/src/day16.rs | 136 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 6 deletions(-) diff --git a/aoc2021/src/day16.rs b/aoc2021/src/day16.rs index 53dec9e..c7c815b 100644 --- a/aoc2021/src/day16.rs +++ b/aoc2021/src/day16.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::ops::Range; use anyhow::{Context, Result}; use bitvec::prelude::*; @@ -29,14 +30,18 @@ enum PacketType { struct Packet { version: u8, type_id: u8, + bits_used: usize, packet: PacketType, } impl Packet { fn version_sum(&self) -> u64 { + let version = self.version as u64; match &self.packet { - PacketType::Litteral(_) => self.version as u64, - PacketType::Operator(op) => op.sub_packets.iter().map(Packet::version_sum).sum(), + PacketType::Litteral(_) => version, + PacketType::Operator(op) => { + version + op.sub_packets.iter().map(Packet::version_sum).sum::() + } } } } @@ -69,6 +74,20 @@ impl std::str::FromStr for Packet { } } +const VERSION_RANGE: Range = 0..3; +const TYPE_ID_RANGE: Range = 3..6; + +const TYPE_LENGTH_ID_INDEX: usize = 6; +const LENGTH_INDEX: usize = 6 + 1; + +const TLID0_SUBPACKET_LENGTH_BITS: usize = 15; +const SUBPACKET_START_INDEX_TLID0: usize = LENGTH_INDEX + TLID0_SUBPACKET_LENGTH_BITS; +const SUBPACKETS_BIT_LENGTH_RANGE: Range = LENGTH_INDEX..SUBPACKET_START_INDEX_TLID0; + +const TLID1_SUBPACKET_NUMBER_BITS: usize = 11; +const SUBPACKET_START_INDEX_TLID1: usize = LENGTH_INDEX + TLID1_SUBPACKET_NUMBER_BITS; +const SUBPACKETS_NUMBER_RANGE: Range = LENGTH_INDEX..SUBPACKET_START_INDEX_TLID1; + impl<'bits, Store> TryFrom<&'bits BitSlice> for Packet where Store: BitStore, @@ -76,17 +95,20 @@ where type Error = anyhow::Error; fn try_from(bits: &'bits BitSlice) -> Result { - let version: u8 = bits[0..3].load(); - let type_id: u8 = bits[3..6].load(); + let version: u8 = bits[VERSION_RANGE].load_be(); + let type_id: u8 = bits[TYPE_ID_RANGE].load_be(); match type_id { + // LitteralPacket 4 => { let mut value = 0; + let mut end = None; for i in (6..).step_by(5) { - let val = bits[(i + 1)..(i + 5)].load::(); + let val = bits[(i + 1)..(i + 5)].load_be::(); value = (value << 4) + val; if !bits[i] { + end = Some(i + 5); break; } } @@ -94,10 +116,45 @@ where Ok(Packet { version, type_id, + bits_used: end.unwrap(), packet: PacketType::Litteral(LitteralPacket { value }), }) } - _ => unimplemented!("Operator packets aren't implemented yet"), + // OperatorPacket + _ => { + let length_type_id = bits[TYPE_LENGTH_ID_INDEX]; + let mut sub_packets = Vec::new(); + let len = if length_type_id { + let subpacket_num: usize = bits[SUBPACKETS_NUMBER_RANGE].load_be(); + let mut start_index = SUBPACKET_START_INDEX_TLID1; + + while sub_packets.len() < subpacket_num { + let packet: Packet = bits[start_index..].try_into()?; + start_index += packet.bits_used; + sub_packets.push(packet); + } + + start_index + } else { + let length: usize = bits[SUBPACKETS_BIT_LENGTH_RANGE].load_be(); + + let mut start_index = SUBPACKET_START_INDEX_TLID0; + while start_index != SUBPACKET_START_INDEX_TLID0 + length { + let packet: Packet = bits[start_index..].try_into()?; + start_index += packet.bits_used; + sub_packets.push(packet); + } + + SUBPACKET_START_INDEX_TLID0 + length + }; + + Ok(Packet { + version, + type_id, + bits_used: len, + packet: PacketType::Operator(OperatorPacket { sub_packets }), + }) + } } } } @@ -122,8 +179,75 @@ mod tests { Packet { version: 6, type_id: 4, + bits_used: 21, packet: PacketType::Litteral(LitteralPacket { value: 2021 }), } ); + + assert_eq!( + PROVIDED2.parse::().unwrap(), + Packet { + version: 1, + type_id: 6, + bits_used: 49, + packet: PacketType::Operator(OperatorPacket { + sub_packets: vec![ + Packet { + version: 6, + type_id: 4, + bits_used: 11, + packet: PacketType::Litteral(LitteralPacket { value: 10 }) + }, + Packet { + version: 2, + type_id: 4, + bits_used: 16, + packet: PacketType::Litteral(LitteralPacket { value: 20 }) + }, + ], + }), + } + ); + + assert_eq!( + PROVIDED3.parse::().unwrap(), + Packet { + version: 7, + type_id: 3, + bits_used: 51, + packet: PacketType::Operator(OperatorPacket { + sub_packets: vec![ + Packet { + version: 2, + type_id: 4, + bits_used: 11, + packet: PacketType::Litteral(LitteralPacket { value: 1 }) + }, + Packet { + version: 4, + type_id: 4, + bits_used: 11, + packet: PacketType::Litteral(LitteralPacket { value: 2 }) + }, + Packet { + version: 1, + type_id: 4, + bits_used: 11, + packet: PacketType::Litteral(LitteralPacket { value: 3 }) + }, + ], + }), + } + ); + + assert_eq!(PROVIDED4.parse::().unwrap().version_sum(), 16); + assert_eq!(PROVIDED5.parse::().unwrap().version_sum(), 12); + assert_eq!(PROVIDED6.parse::().unwrap().version_sum(), 23); + assert_eq!(PROVIDED7.parse::().unwrap().version_sum(), 31); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 925); } } From c42041017dd128d868b4de7fb6649a242fc4a9ef Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 17:53:06 +0100 Subject: [PATCH 088/134] 2021: day16: part 2 --- aoc2021/src/day16.rs | 136 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 16 deletions(-) diff --git a/aoc2021/src/day16.rs b/aoc2021/src/day16.rs index c7c815b..688fa8a 100644 --- a/aoc2021/src/day16.rs +++ b/aoc2021/src/day16.rs @@ -1,7 +1,7 @@ use std::fmt::Write; use std::ops::Range; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use bitvec::prelude::*; const INPUT: &str = include_str!("../input/day16.txt"); @@ -10,6 +10,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -20,6 +21,12 @@ fn part1(input: &str) -> Result { Ok(packet.version_sum()) } +fn part2(input: &str) -> Result { + let packet: Packet = input.parse()?; + + Ok(packet.value()) +} + #[derive(PartialEq, Eq, Debug)] enum PacketType { Litteral(LitteralPacket), @@ -44,6 +51,48 @@ impl Packet { } } } + + fn value(&self) -> u64 { + match &self.packet { + PacketType::Litteral(lit) => lit.value, + PacketType::Operator(op) => match op.op_type { + OperatorType::Sum => op.sub_packets.iter().map(Packet::value).sum(), + OperatorType::Product => op.sub_packets.iter().map(Packet::value).product(), + OperatorType::Minimum => op.sub_packets.iter().map(Packet::value).min().unwrap(), + OperatorType::Maximum => op.sub_packets.iter().map(Packet::value).max().unwrap(), + OperatorType::GreaterThan => { + debug_assert_eq!(op.sub_packets.len(), 2); + let pack1 = &op.sub_packets[0]; + let pack2 = &op.sub_packets[1]; + if pack1.value() > pack2.value() { + 1 + } else { + 0 + } + } + OperatorType::LessThan => { + debug_assert_eq!(op.sub_packets.len(), 2); + let pack1 = &op.sub_packets[0]; + let pack2 = &op.sub_packets[1]; + if pack1.value() < pack2.value() { + 1 + } else { + 0 + } + } + OperatorType::EqualTo => { + debug_assert_eq!(op.sub_packets.len(), 2); + let pack1 = &op.sub_packets[0]; + let pack2 = &op.sub_packets[1]; + if pack1.value() == pack2.value() { + 1 + } else { + 0 + } + } + }, + } + } } #[derive(PartialEq, Eq, Debug)] @@ -51,9 +100,21 @@ struct LitteralPacket { value: u64, } +#[derive(PartialEq, Eq, Debug)] +enum OperatorType { + Sum, + Product, + Minimum, + Maximum, + GreaterThan, + LessThan, + EqualTo, +} + #[derive(PartialEq, Eq, Debug)] struct OperatorPacket { sub_packets: Vec, + op_type: OperatorType, } impl std::str::FromStr for Packet { @@ -148,11 +209,26 @@ where SUBPACKET_START_INDEX_TLID0 + length }; + let op_type = match type_id { + 0 => OperatorType::Sum, + 1 => OperatorType::Product, + 2 => OperatorType::Minimum, + 3 => OperatorType::Maximum, + 4 => unreachable!("impossible, would parse as a litteral packet"), + 5 => OperatorType::GreaterThan, + 6 => OperatorType::LessThan, + 7 => OperatorType::EqualTo, + _ => bail!("unknown type id: {}", type_id), + }; + Ok(Packet { version, type_id, bits_used: len, - packet: PacketType::Operator(OperatorPacket { sub_packets }), + packet: PacketType::Operator(OperatorPacket { + sub_packets, + op_type, + }), }) } } @@ -163,19 +239,19 @@ where mod tests { use super::*; - const PROVIDED1: &str = "D2FE28"; - const PROVIDED2: &str = "38006F45291200"; - const PROVIDED3: &str = "EE00D40C823060"; + const PART1_PROVIDED1: &str = "D2FE28"; + const PART1_PROVIDED2: &str = "38006F45291200"; + const PART1_PROVIDED3: &str = "EE00D40C823060"; - const PROVIDED4: &str = "8A004A801A8002F478"; - const PROVIDED5: &str = "620080001611562C8802118E34"; - const PROVIDED6: &str = "C0015000016115A2E0802F182340"; - const PROVIDED7: &str = "A0016C880162017C3686B18A3D4780"; + const PART1_PROVIDED4: &str = "8A004A801A8002F478"; + const PART1_PROVIDED5: &str = "620080001611562C8802118E34"; + const PART1_PROVIDED6: &str = "C0015000016115A2E0802F182340"; + const PART1_PROVIDED7: &str = "A0016C880162017C3686B18A3D4780"; #[test] fn part1_provided() { assert_eq!( - PROVIDED1.parse::().unwrap(), + PART1_PROVIDED1.parse::().unwrap(), Packet { version: 6, type_id: 4, @@ -185,7 +261,7 @@ mod tests { ); assert_eq!( - PROVIDED2.parse::().unwrap(), + PART1_PROVIDED2.parse::().unwrap(), Packet { version: 1, type_id: 6, @@ -205,12 +281,13 @@ mod tests { packet: PacketType::Litteral(LitteralPacket { value: 20 }) }, ], + op_type: OperatorType::LessThan, }), } ); assert_eq!( - PROVIDED3.parse::().unwrap(), + PART1_PROVIDED3.parse::().unwrap(), Packet { version: 7, type_id: 3, @@ -236,18 +313,45 @@ mod tests { packet: PacketType::Litteral(LitteralPacket { value: 3 }) }, ], + op_type: OperatorType::Maximum, }), } ); - assert_eq!(PROVIDED4.parse::().unwrap().version_sum(), 16); - assert_eq!(PROVIDED5.parse::().unwrap().version_sum(), 12); - assert_eq!(PROVIDED6.parse::().unwrap().version_sum(), 23); - assert_eq!(PROVIDED7.parse::().unwrap().version_sum(), 31); + assert_eq!(PART1_PROVIDED4.parse::().unwrap().version_sum(), 16); + assert_eq!(PART1_PROVIDED5.parse::().unwrap().version_sum(), 12); + assert_eq!(PART1_PROVIDED6.parse::().unwrap().version_sum(), 23); + assert_eq!(PART1_PROVIDED7.parse::().unwrap().version_sum(), 31); } #[test] fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 925); } + + const PART2_PROVIDED1: &str = "C200B40A82"; + const PART2_PROVIDED2: &str = "04005AC33890"; + const PART2_PROVIDED3: &str = "880086C3E88112"; + const PART2_PROVIDED4: &str = "CE00C43D881120"; + const PART2_PROVIDED5: &str = "D8005AC2A8F0"; + const PART2_PROVIDED6: &str = "F600BC2D8F"; + const PART2_PROVIDED7: &str = "9C005AC2F8F0"; + const PART2_PROVIDED8: &str = "9C0141080250320F1802104A08"; + + #[test] + fn part2_provided() { + assert_eq!(part2(PART2_PROVIDED1).unwrap(), 3); + assert_eq!(part2(PART2_PROVIDED2).unwrap(), 54); + assert_eq!(part2(PART2_PROVIDED3).unwrap(), 7); + assert_eq!(part2(PART2_PROVIDED4).unwrap(), 9); + assert_eq!(part2(PART2_PROVIDED5).unwrap(), 1); + assert_eq!(part2(PART2_PROVIDED6).unwrap(), 0); + assert_eq!(part2(PART2_PROVIDED7).unwrap(), 0); + assert_eq!(part2(PART2_PROVIDED8).unwrap(), 1); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 342997120375); + } } From 4f36262761ca9df1f87eebff43c362a772ae0559 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Thu, 16 Dec 2021 18:01:56 +0100 Subject: [PATCH 089/134] 2021: day16: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 1c4a956..bc171a7 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -15,6 +15,7 @@ use aoc2021::day12; use aoc2021::day13; use aoc2021::day14; use aoc2021::day15; +use aoc2021::day16; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -32,6 +33,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day13", |b| b.iter(|| day13::run().unwrap())); c.bench_function("day14", |b| b.iter(|| day14::run().unwrap())); c.bench_function("day15", |b| b.iter(|| day15::run().unwrap())); + c.bench_function("day16", |b| b.iter(|| day16::run().unwrap())); } criterion_group! { From 0446f11a46f5b44c8fa6ea04670dcdd515249dd1 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 14:12:35 +0100 Subject: [PATCH 090/134] 2020: bump nom version I was getting a compilation error (something in the latest Rust compiler?), related to a nom dependency (bitvec v0.19), but nom 7 does not depend on bitvec by default anymore, yay! The move + clone closures feel kind of wrong though --- Cargo.lock | 70 ++++++++------------------------------------ aoc2020/Cargo.toml | 2 +- aoc2020/src/day18.rs | 6 ++-- 3 files changed, 17 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b620f0d..3c4ec6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,7 +88,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", - "bitvec 0.22.3", + "bitvec", "rand", ] @@ -100,12 +100,6 @@ dependencies = [ "criterion", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "atty" version = "0.2.14" @@ -129,18 +123,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitvec" -version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" -dependencies = [ - "funty", - "radium 0.5.3", - "tap", - "wyz 0.2.0", -] - [[package]] name = "bitvec" version = "0.22.3" @@ -148,9 +130,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" dependencies = [ "funty", - "radium 0.6.2", + "radium", "tap", - "wyz 0.4.0", + "wyz", ] [[package]] @@ -427,19 +409,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.108" @@ -482,14 +451,19 @@ dependencies = [ ] [[package]] -name = "nom" -version = "6.1.1" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d521ee2250f619dd5e06515ba405858d249edc8fae9ddee2dba0695e57db01b" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ - "bitvec 0.19.4", - "lexical-core", "memchr", + "minimal-lexical", "version_check", ] @@ -576,12 +550,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - [[package]] name = "radium" version = "0.6.2" @@ -748,12 +716,6 @@ dependencies = [ "serde", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "syn" version = "1.0.82" @@ -926,12 +888,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "wyz" version = "0.4.0" diff --git a/aoc2020/Cargo.toml b/aoc2020/Cargo.toml index c42c975..10346de 100644 --- a/aoc2020/Cargo.toml +++ b/aoc2020/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" aoc = { path = "../aoc" } anyhow = "1.0" itertools = "0.9" -nom = "6.0" +nom = "7.0" [lib] path = "src/lib.rs" diff --git a/aoc2020/src/day18.rs b/aoc2020/src/day18.rs index 12df6fe..4df8254 100644 --- a/aoc2020/src/day18.rs +++ b/aoc2020/src/day18.rs @@ -84,7 +84,7 @@ fn operator_expr(input: &str) -> IResult<&str, Expr> { fold_many0( pair(delimited(char(' '), operator, char(' ')), term), - first_term, + move || first_term.clone(), |acc, (op, val)| Expr::Op(Box::new(acc), op, Box::new(val)), )(i) } @@ -97,7 +97,7 @@ fn plus(input: &str) -> IResult<&str, Expr> { delimited(char(' '), char('+'), char(' ')), term_plus_priority, ), - first_term, + move || first_term.clone(), |acc, (_, val)| Expr::Op(Box::new(acc), Operator::Addition, Box::new(val)), )(i) } @@ -107,7 +107,7 @@ fn mul(input: &str) -> IResult<&str, Expr> { fold_many0( pair(delimited(char(' '), char('*'), char(' ')), plus), - first_factor, + move || first_factor.clone(), |acc, (_, val)| Expr::Op(Box::new(acc), Operator::Multiplication, Box::new(val)), )(i) } From 026470220b25e36545fb951490f8fb9aed5cd9c2 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 18:22:38 +0100 Subject: [PATCH 091/134] 2021: day17: part 1 --- aoc2021/input/day17.txt | 1 + aoc2021/input/day17_provided.txt | 1 + aoc2021/src/day17.rs | 159 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 1 + aoc2021/src/main.rs | 2 + 5 files changed, 164 insertions(+) create mode 100644 aoc2021/input/day17.txt create mode 100644 aoc2021/input/day17_provided.txt create mode 100644 aoc2021/src/day17.rs diff --git a/aoc2021/input/day17.txt b/aoc2021/input/day17.txt new file mode 100644 index 0000000..ba5668c --- /dev/null +++ b/aoc2021/input/day17.txt @@ -0,0 +1 @@ +target area: x=277..318, y=-92..-53 diff --git a/aoc2021/input/day17_provided.txt b/aoc2021/input/day17_provided.txt new file mode 100644 index 0000000..a07e02d --- /dev/null +++ b/aoc2021/input/day17_provided.txt @@ -0,0 +1 @@ +target area: x=20..30, y=-10..-5 diff --git a/aoc2021/src/day17.rs b/aoc2021/src/day17.rs new file mode 100644 index 0000000..b3734b6 --- /dev/null +++ b/aoc2021/src/day17.rs @@ -0,0 +1,159 @@ +use std::cmp::Ordering; +use std::fmt::Write; +use std::ops::RangeInclusive; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day17.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let area: TargetArea = input + .parse() + .context("couldn't parse input to target area")?; + + let min_x_vel = if area.min_x() > 0 { + (0..).find(|x| ((x * (x + 1)) / 2) >= area.min_x()).unwrap() + } else if area.max_x() < 0 { + -(0..) + .find(|x| ((x * (x + 1)) / 2) >= area.max_x().abs()) + .unwrap() + } else { + 0 + }; + + let max_x_vel = if area.min_x() > 0 { + area.max_x() + } else if area.max_x() < 0 { + area.min_x() + } else { + 0 + }; + + // Rust ranges can only be increasing, so swap values around if negative + let (min_x_vel, max_x_vel) = (min_x_vel.min(max_x_vel), min_x_vel.max(max_x_vel)); + + // we could launch the prob downward, but in that case max Y reached would always be 0 + let min_y_vel = 0; + let max_y_vel = 5000; // idk + + (min_x_vel..=max_x_vel) + .flat_map(|x_vel| (min_y_vel..=max_y_vel).map(move |y_vel| (x_vel, y_vel))) + .filter_map(|(x_vel, y_vel)| throw(x_vel, y_vel, &area)) + .max() + .context("couldn't find any trajectory") +} + +fn throw(mut xvel: isize, mut yvel: isize, area: &TargetArea) -> Option { + let (mut pos_x, mut pos_y) = (0, 0); + let mut highest_y = 0; + + loop { + if area.contains(pos_x, pos_y) { + return Some(highest_y); + } + + // Three cases where we can stop here: + // - probe is lower than area, and gravity pulls it even lower + // - probe is on the left, and x velocity goes left + // - probe is on the right, and x velocity goes right + if (pos_y < area.min_y() && yvel <= 0) + || (xvel <= 0 && pos_x < area.min_x()) + || (xvel >= 0 && pos_x > area.max_x()) + { + // the probe will never reach the area, we can stop the simulation here + return None; + } + + // - The probe's x position increases by its x velocity. + pos_x += xvel; + // - The probe's y position increases by its y velocity. + pos_y += yvel; + // - Due to drag, the probe's x velocity changes by 1 toward the value 0; that is, it + // decreases by 1 if it is greater than 0, increases by 1 if it is less than 0, or does not + // change if it is already 0. + match xvel.cmp(&0) { + Ordering::Less => xvel += 1, + Ordering::Greater => xvel -= 1, + _ => {} + } + // - Due to gravity, the probe's y velocity decreases by 1. + yvel -= 1; + + // update highest seen y + highest_y = highest_y.max(pos_y); + } +} + +struct TargetArea { + x_range: RangeInclusive, + y_range: RangeInclusive, +} + +impl TargetArea { + fn contains(&self, x: isize, y: isize) -> bool { + self.x_range.contains(&x) && self.y_range.contains(&y) + } + + fn min_y(&self) -> isize { + *self.y_range.start() + } + + fn min_x(&self) -> isize { + *self.x_range.start() + } + + fn max_x(&self) -> isize { + *self.x_range.end() + } +} + +impl std::str::FromStr for TargetArea { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let s = s + .trim() + .strip_prefix("target area: ") + .context("missing target area while parsing")?; + + let (x, y) = s.split_once(", ").context("couldn't split on comma")?; + + let x = x.strip_prefix("x=").context("couldn't find `x=`")?; + let (min_x, max_x) = x.split_once("..").context("couldn't split on `..`")?; + let (min_x, max_x) = (min_x.parse()?, max_x.parse()?); + + let y = y.strip_prefix("y=").context("couldn't find `y=`")?; + let (min_y, max_y) = y.split_once("..").context("couldn't split on `..`")?; + let (min_y, max_y) = (min_y.parse()?, max_y.parse()?); + + Ok(Self { + x_range: min_x..=max_x, + y_range: min_y..=max_y, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day17_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 45); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 4186); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index f281e9a..cf569f2 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -16,3 +16,4 @@ pub mod day13; pub mod day14; pub mod day15; pub mod day16; +pub mod day17; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 524f73b..7dc5fe7 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -18,6 +18,7 @@ use aoc2021::day13; use aoc2021::day14; use aoc2021::day15; use aoc2021::day16; +use aoc2021::day17; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -37,6 +38,7 @@ fn main() -> Result<()> { day14::run, day15::run, day16::run, + day17::run, ]; aoc::run(days) From ba06e006b96c8e66b9d604e7e2198dcedc3c702a Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 18:32:18 +0100 Subject: [PATCH 092/134] 2021: day17: part 2 --- aoc2021/src/day17.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/aoc2021/src/day17.rs b/aoc2021/src/day17.rs index b3734b6..9e6ab15 100644 --- a/aoc2021/src/day17.rs +++ b/aoc2021/src/day17.rs @@ -10,6 +10,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -51,6 +52,42 @@ fn part1(input: &str) -> Result { .context("couldn't find any trajectory") } +fn part2(input: &str) -> Result { + let area: TargetArea = input + .parse() + .context("couldn't parse input to target area")?; + + let min_x_vel = if area.min_x() > 0 { + (0..).find(|x| ((x * (x + 1)) / 2) >= area.min_x()).unwrap() + } else if area.max_x() < 0 { + -(0..) + .find(|x| ((x * (x + 1)) / 2) >= area.max_x().abs()) + .unwrap() + } else { + 0 + }; + + let max_x_vel = if area.min_x() > 0 { + area.max_x() + } else if area.max_x() < 0 { + area.min_x() + } else { + 0 + }; + + // Rust ranges can only be increasing, so swap values around if negative + let (min_x_vel, max_x_vel) = (min_x_vel.min(max_x_vel), min_x_vel.max(max_x_vel)); + + // let's assume that the area is always lower than (0, 0) + let min_y_vel = area.min_y(); + let max_y_vel = area.min_y().abs(); + + Ok((min_x_vel..=max_x_vel) + .flat_map(|x_vel| (min_y_vel..=max_y_vel).map(move |y_vel| (x_vel, y_vel))) + .filter_map(|(x_vel, y_vel)| throw(x_vel, y_vel, &area)) + .count()) +} + fn throw(mut xvel: isize, mut yvel: isize, area: &TargetArea) -> Option { let (mut pos_x, mut pos_y) = (0, 0); let mut highest_y = 0; @@ -156,4 +193,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 4186); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 112); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2709); + } } From 551f57f7ffbc6bd284aeb4474b2f4a272d9dc76f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 18:37:36 +0100 Subject: [PATCH 093/134] 2021: day17: bench --- aoc2021/aoc2021_bench/benches/aoc2021_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index bc171a7..bde1796 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -16,6 +16,7 @@ use aoc2021::day13; use aoc2021::day14; use aoc2021::day15; use aoc2021::day16; +use aoc2021::day17; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -34,6 +35,7 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day14", |b| b.iter(|| day14::run().unwrap())); c.bench_function("day15", |b| b.iter(|| day15::run().unwrap())); c.bench_function("day16", |b| b.iter(|| day16::run().unwrap())); + c.bench_function("day17", |b| b.iter(|| day17::run().unwrap())); } criterion_group! { From 2bc1b97c2d4ebc62943c2ca661a634aacc6b98e3 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 18:39:49 +0100 Subject: [PATCH 094/134] 2021: day17: better bounds for part 1 --- aoc2021/src/day17.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aoc2021/src/day17.rs b/aoc2021/src/day17.rs index 9e6ab15..8a0181a 100644 --- a/aoc2021/src/day17.rs +++ b/aoc2021/src/day17.rs @@ -42,8 +42,8 @@ fn part1(input: &str) -> Result { let (min_x_vel, max_x_vel) = (min_x_vel.min(max_x_vel), min_x_vel.max(max_x_vel)); // we could launch the prob downward, but in that case max Y reached would always be 0 - let min_y_vel = 0; - let max_y_vel = 5000; // idk + let min_y_vel = 1; + let max_y_vel = area.min_y().abs(); (min_x_vel..=max_x_vel) .flat_map(|x_vel| (min_y_vel..=max_y_vel).map(move |y_vel| (x_vel, y_vel))) From 7a8b7c994e8cac68486fe6e053946c4dcd5a1e2c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 18:48:12 +0100 Subject: [PATCH 095/134] 2021: day17: improvement ideas --- aoc2021/src/day17.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aoc2021/src/day17.rs b/aoc2021/src/day17.rs index 8a0181a..1def61b 100644 --- a/aoc2021/src/day17.rs +++ b/aoc2021/src/day17.rs @@ -1,3 +1,10 @@ +//! Improvement ideas: +//! +//! X and Y coordinates are independant, so we can compute them separately, and keep track of which +//! values of X and Y can ever reach the target area, and if so, keep the step numbers where they +//! match. Some cross referencing can then isolate the valid trajectories. +//! +//! This already runs in 1ms though so... maybe later use std::cmp::Ordering; use std::fmt::Write; use std::ops::RangeInclusive; From 5ffa2012bee1b214b4246beb60419c46d10df8de Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 17 Dec 2021 18:52:15 +0100 Subject: [PATCH 096/134] cargo: bump lock --- Cargo.lock | 62 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c4ec6b..757f897 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.48" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "aoc" @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", @@ -203,9 +203,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags", "textwrap", @@ -223,7 +223,7 @@ dependencies = [ "clap", "criterion-plot", "csv", - "itertools 0.10.1", + "itertools 0.10.3", "lazy_static", "num-traits", "oorandom", @@ -245,7 +245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ "cast", - "itertools 0.10.1", + "itertools 0.10.3", ] [[package]] @@ -300,7 +300,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -381,9 +381,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -394,6 +394,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "js-sys" version = "0.3.55" @@ -411,9 +417,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.108" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "log" @@ -437,15 +443,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -534,9 +540,9 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" dependencies = [ "unicode-xid", ] @@ -653,9 +659,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "same-file" @@ -680,9 +686,9 @@ checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" [[package]] name = "serde" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" [[package]] name = "serde_cbor" @@ -696,9 +702,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" dependencies = [ "proc-macro2", "quote", @@ -707,11 +713,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] From c92553fa4025edf45301c2dd02bf4c2a0fa74573 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 21 Dec 2021 14:07:22 +0100 Subject: [PATCH 097/134] 2021: day21: part 1 --- aoc2021/input/day21.txt | 2 + aoc2021/input/day21_provided.txt | 2 + aoc2021/src/day21.rs | 109 +++++++++++++++++++++++++++++++ aoc2021/src/lib.rs | 2 + aoc2021/src/main.rs | 3 + 5 files changed, 118 insertions(+) create mode 100644 aoc2021/input/day21.txt create mode 100644 aoc2021/input/day21_provided.txt create mode 100644 aoc2021/src/day21.rs diff --git a/aoc2021/input/day21.txt b/aoc2021/input/day21.txt new file mode 100644 index 0000000..94d668d --- /dev/null +++ b/aoc2021/input/day21.txt @@ -0,0 +1,2 @@ +Player 1 starting position: 4 +Player 2 starting position: 2 diff --git a/aoc2021/input/day21_provided.txt b/aoc2021/input/day21_provided.txt new file mode 100644 index 0000000..3f69194 --- /dev/null +++ b/aoc2021/input/day21_provided.txt @@ -0,0 +1,2 @@ +Player 1 starting position: 4 +Player 2 starting position: 8 diff --git a/aoc2021/src/day21.rs b/aoc2021/src/day21.rs new file mode 100644 index 0000000..a926b65 --- /dev/null +++ b/aoc2021/src/day21.rs @@ -0,0 +1,109 @@ +use std::fmt::Write; +use std::iter; +use std::ops::RangeInclusive; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day21.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut lines = input.lines(); + let mut player1_pos: PlayerPos = lines + .next() + .and_then(|line| line.trim().strip_prefix("Player 1 starting position: ")) + .and_then(|pos| pos.parse().ok()) + .map(PlayerPos::new) + .context("couldn't find player 1 pos")?; + let mut player2_pos: PlayerPos = lines + .next() + .and_then(|line| line.trim().strip_prefix("Player 2 starting position: ")) + .and_then(|pos| pos.parse().ok()) + .map(PlayerPos::new) + .context("couldn't find player 2 pos")?; + + let mut player1_score = 0; + let mut player2_score = 0; + let mut dice = DeterministicDice::new(); + + while player2_score < 1000 { + let mv = dice.next_3_sum(); + + player1_pos.advance_by(mv); + player1_score += player1_pos.pos(); + + std::mem::swap(&mut player1_pos, &mut player2_pos); + std::mem::swap(&mut player1_score, &mut player2_score); + } + + let loser_score = player1_score; + + Ok(loser_score * dice.rolls()) +} + +struct PlayerPos(usize); + +impl PlayerPos { + fn new(pos: usize) -> Self { + debug_assert!((1..=10).contains(&pos)); + + // represented from 0 to 9 for modulo ease of use + Self(pos - 1) + } + + fn advance_by(&mut self, mv: usize) { + self.0 = (self.0 + mv) % 10 + } + + fn pos(&self) -> usize { + self.0 + 1 + } +} + +struct DeterministicDice { + iter: iter::Cycle>, + rolls: usize, +} + +impl DeterministicDice { + fn new() -> Self { + Self { + iter: (1..=100).cycle(), + rolls: 0, + } + } + + fn next_3_sum(&mut self) -> usize { + self.rolls += 3; + + self.iter.next().unwrap() + self.iter.next().unwrap() + self.iter.next().unwrap() + } + + fn rolls(&self) -> usize { + self.rolls + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day21_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 739785); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 908595); + } +} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index cf569f2..7e99714 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -17,3 +17,5 @@ pub mod day14; pub mod day15; pub mod day16; pub mod day17; + +pub mod day21; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 7dc5fe7..6ba207f 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -20,6 +20,8 @@ use aoc2021::day15; use aoc2021::day16; use aoc2021::day17; +use aoc2021::day21; + fn main() -> Result<()> { let days: &[DayFunc] = &[ day01::run, @@ -39,6 +41,7 @@ fn main() -> Result<()> { day15::run, day16::run, day17::run, + day21::run, ]; aoc::run(days) From a5fd485c1031746f85a291702e751bfb0bc0b2d5 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 21 Dec 2021 14:40:45 +0100 Subject: [PATCH 098/134] 2021: day21: part 2 --- aoc2021/src/day21.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/aoc2021/src/day21.rs b/aoc2021/src/day21.rs index a926b65..274439b 100644 --- a/aoc2021/src/day21.rs +++ b/aoc2021/src/day21.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::fmt::Write; use std::iter; use std::ops::RangeInclusive; @@ -10,6 +11,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -48,6 +50,68 @@ fn part1(input: &str) -> Result { Ok(loser_score * dice.rolls()) } +fn part2(input: &str) -> Result { + let mut lines = input.lines(); + let player1_pos: PlayerPos = lines + .next() + .and_then(|line| line.trim().strip_prefix("Player 1 starting position: ")) + .and_then(|pos| pos.parse().ok()) + .map(PlayerPos::new) + .context("couldn't find player 1 pos")?; + let player2_pos: PlayerPos = lines + .next() + .and_then(|line| line.trim().strip_prefix("Player 2 starting position: ")) + .and_then(|pos| pos.parse().ok()) + .map(PlayerPos::new) + .context("couldn't find player 2 pos")?; + + let (player1_score, player2_score) = + quantum_dice_game(player1_pos, player2_pos, 0, 0, &mut HashMap::new()); + + Ok(player1_score.max(player2_score)) +} + +type Cache = HashMap<(PlayerPos, PlayerPos, usize, usize), (usize, usize)>; + +fn quantum_dice_game( + pos1: PlayerPos, + pos2: PlayerPos, + score1: usize, + score2: usize, + cache: &mut Cache, +) -> (usize, usize) { + // We swap players on each recursive call, so player 2 is the previous player 1. Player 1 is the + // only one who played, so we only need to check his score. + if score2 >= 21 { + return (0, 1); + } + + // Memoization + if let Some(wins) = cache.get(&(pos1, pos2, score1, score2)) { + return *wins; + } + + let (mut wins1, mut wins2) = (0, 0); + // 3 = 1 + 1 + 1 + // 4 = 1 + 1 + 2, 1 + 2 + 1, 2 + 1 + 1 + // ... + // 9 = 3 + 3 + 3 + for (mv, times) in [(3, 1), (4, 3), (5, 6), (6, 7), (7, 6), (8, 3), (9, 1)] { + let mut pos1 = pos1; // copy + pos1.advance_by(mv); + + // We swap out player 1 and 2 for the next recursion + let (w2, w1) = quantum_dice_game(pos2, pos1, score2, score1 + pos1.pos(), cache); + + wins1 += w1 * times; + wins2 += w2 * times; + } + + cache.insert((pos1, pos2, score1, score2), (wins1, wins2)); + (wins1, wins2) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] struct PlayerPos(usize); impl PlayerPos { @@ -106,4 +170,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 908595); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 444356092776315); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 91559198282731); + } } From f3f3b40d477fd3c6cfe8899ad520efb685e3e5b4 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 5 Dec 2022 22:57:19 +0100 Subject: [PATCH 099/134] 2022: day 01 part 1 --- Cargo.lock | 16 + Cargo.toml | 2 +- aoc2022/Cargo.toml | 18 + aoc2022/aoc2022_bench/Cargo.toml | 17 + .../aoc2022_bench/benches/aoc2022_bench.rs | 14 + aoc2022/input/day01.txt | 2253 +++++++++++++++++ aoc2022/input/day01_provided.txt | 14 + aoc2022/src/day01.rs | 63 + aoc2022/src/lib.rs | 3 + aoc2022/src/main.rs | 11 + flake.lock | 8 +- flake.nix | 2 +- 12 files changed, 2415 insertions(+), 6 deletions(-) create mode 100644 aoc2022/Cargo.toml create mode 100644 aoc2022/aoc2022_bench/Cargo.toml create mode 100644 aoc2022/aoc2022_bench/benches/aoc2022_bench.rs create mode 100644 aoc2022/input/day01.txt create mode 100644 aoc2022/input/day01_provided.txt create mode 100644 aoc2022/src/day01.rs create mode 100644 aoc2022/src/lib.rs create mode 100644 aoc2022/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 757f897..aa0f66e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,22 @@ dependencies = [ "criterion", ] +[[package]] +name = "aoc2022" +version = "0.1.0" +dependencies = [ + "anyhow", + "aoc", +] + +[[package]] +name = "aoc2022_bench" +version = "0.1.0" +dependencies = [ + "aoc2022", + "criterion", +] + [[package]] name = "atty" version = "0.2.14" diff --git a/Cargo.toml b/Cargo.toml index 6604557..a228d23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = ["aoc20*", "aoc20*/aoc20*_bench"] -default-members = ["aoc2021"] +default-members = ["aoc2022"] [profile.release] debug = true diff --git a/aoc2022/Cargo.toml b/aoc2022/Cargo.toml new file mode 100644 index 0000000..9fe9672 --- /dev/null +++ b/aoc2022/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "aoc2022" +version = "0.1.0" +authors = ["Antoine Martin "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../aoc" } +anyhow = "1.0" + +[lib] +path = "src/lib.rs" + +[[bin]] +name = "aoc2022" +path = "src/main.rs" diff --git a/aoc2022/aoc2022_bench/Cargo.toml b/aoc2022/aoc2022_bench/Cargo.toml new file mode 100644 index 0000000..e5ef4bc --- /dev/null +++ b/aoc2022/aoc2022_bench/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "aoc2022_bench" +version = "0.1.0" +authors = ["Antoine Martin "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc2022 = { path = "../" } + +[dev-dependencies] +criterion = "0.3" + +[[bench]] +name = "aoc2022_bench" +harness = false diff --git a/aoc2022/aoc2022_bench/benches/aoc2022_bench.rs b/aoc2022/aoc2022_bench/benches/aoc2022_bench.rs new file mode 100644 index 0000000..618c7f5 --- /dev/null +++ b/aoc2022/aoc2022_bench/benches/aoc2022_bench.rs @@ -0,0 +1,14 @@ +use criterion::{criterion_group, criterion_main, Criterion}; + +use aoc2022::day01; + +fn aoc2022_all(c: &mut Criterion) { + c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); +} + +criterion_group! { + name = all_days; + config = Criterion::default().sample_size(200); + targets = aoc2022_all +} +criterion_main!(all_days); diff --git a/aoc2022/input/day01.txt b/aoc2022/input/day01.txt new file mode 100644 index 0000000..e1e0531 --- /dev/null +++ b/aoc2022/input/day01.txt @@ -0,0 +1,2253 @@ +4601 +1583 +2995 +5319 +3352 +1722 +4331 +5840 +3339 +5341 +3415 +1297 +1610 +2703 + +5928 +1266 +6405 +4354 +2815 +1621 +3545 +1733 +2162 +1155 +3674 +4055 +4262 +2115 + +25873 +16103 +17042 + +6479 +1521 +6902 +6331 +6146 +1591 +2063 +2149 +1463 +1865 +2598 +6893 +3617 + +1431 +8935 +8134 +8885 +8698 +8884 +7982 +3617 +7079 + +34031 +8383 + +3697 +1199 +3703 +1322 +5679 +1627 +5910 +1092 +6445 +2371 +3672 +2281 +2710 +5111 + +17480 + +58355 + +3711 +2406 +2101 +1406 +5376 +2149 +4608 +6768 +6322 +3792 +4249 +2342 +2014 + +6197 +6908 +8484 +3901 +3001 +7880 +5165 +2536 + +3964 +4229 +4898 +4544 +3535 +6329 +1573 +4988 +1424 + +57606 + +16325 + +6038 +11538 +13026 +12734 +6077 + +4696 +3914 +2375 +1188 +1247 +1594 +1843 +5297 +6053 +1114 +3179 +5968 +1430 +4268 +2514 + +6684 +2321 +3946 +1746 +7583 +10379 +3696 +10110 + +5834 +5944 +9336 +9638 +3373 +4279 +9942 + +7208 +7801 +3771 +8183 +1824 +8217 +1545 +3041 +7369 +5980 + +8368 +6180 +3100 +4801 +4430 +6758 +3023 +3394 + +2545 +4992 +3347 +5830 +3764 +3237 +2431 +3406 +1408 +5601 +6548 +4625 + +32334 + +1112 +5471 +10983 +8298 +4342 +4221 +7807 + +5733 +2012 +5928 +3503 +2785 +4867 +1515 +4819 +3569 +3353 +5997 +4921 +5498 +3234 +5588 + +11040 +5547 +12070 +2168 +7603 +7245 +4966 + +13027 +12518 +15381 +3251 +14935 + +15858 +29295 + +2476 +4289 +10350 +3953 +10089 +6953 +5555 +3007 + +61732 + +5567 +4895 +6095 +4880 +2945 +6022 +2129 +5010 +4100 +3554 +3410 +1820 + +9902 +33605 + +15331 +15615 +5062 +15073 + +5940 +2252 +1233 +2582 +3624 +2754 +2304 +3189 +4060 +3862 +5164 +1487 +2776 +1807 +3385 + +6798 +2385 +3755 +10299 +11500 +6478 +1911 + +1469 +9309 +1785 +17145 + +3363 +3210 +3285 +4491 +5992 +2927 +4098 +2133 +3191 +2810 +4694 + +31006 +1582 + +4356 +6146 +2051 +6503 +9487 +9244 +4808 +7761 +7108 + +1771 +6062 +7135 +5575 +3278 +1221 +2547 +7266 +5444 +7395 + +10634 +1196 + +1361 + +2810 +3106 +8654 +9455 +3778 +4219 +8882 +9387 +5128 + +7114 +1441 +6146 +4752 +2388 +6420 +7350 +1624 +6050 +5469 +6751 + +5570 +4674 + +2074 +3476 +4064 +9446 +2889 +4871 +6298 +2970 +8588 + +3482 +8492 +2226 +4951 +6733 +5463 +3183 +4807 +4806 + +6974 +10251 +4637 +9558 +5153 +4665 + +6860 +6949 +1524 +4201 +4397 +2278 +4909 +1353 +2074 +1920 +7439 +1040 + +4135 +1411 +5536 +8004 +3090 +1036 +6613 +6353 +6810 + +3932 +4743 +1615 +3201 +3791 +6357 +2511 +3440 +2290 +4741 +2844 +3121 +3641 +3497 + +4549 +5142 +4438 +2945 +4576 +4871 +4795 +6007 +4884 +1031 +2111 +4388 +4705 +5725 +3425 + +45444 + +6688 +9460 +2727 +6989 +6789 +12460 + +7310 +5910 +7822 +7627 +7600 +4793 +3152 +5747 +5197 +8006 + +23983 +33879 + +1020 +4783 +5117 +3628 +3065 +6131 +5543 +1576 +1159 +3721 +3182 +1409 +2738 +5084 + +42750 + +8509 +4370 +1042 +5664 + +59445 + +1589 +5133 +6413 +6578 +3301 +8256 +7749 +4321 +8190 +5025 + +27739 +18609 + +5447 +4022 +4069 +1437 +2811 +6929 +2754 +1108 +7390 +3995 +3480 +3225 + +4240 +6959 +3289 +8063 +4751 +4896 +4611 +6256 +1105 +1334 +7598 + +27831 + +1821 +5333 +7853 +6574 +7985 +3972 +2306 +1875 +1857 +6386 + +12780 +2513 +22939 + +9625 +3785 +8050 +7432 +11772 +10914 + +1387 +3439 +4644 +3880 +1878 +3911 +5329 +1480 +5779 +2083 +3886 +5525 +3930 +4813 +2570 + +15763 +2839 +14258 +1460 + +6193 +3397 +3222 +3262 +3735 +2406 +5588 +2068 +2862 +3271 +1401 +3957 +5690 +4632 + +15070 +5164 +8902 +9580 +4271 + +4494 +5665 +7242 +7687 +7031 +6135 +2670 +3315 +6146 +8085 + +2625 +24285 + +4414 +5985 +2681 +7036 +6486 +2501 +4408 +8582 +5150 +4295 + +1082 +1497 +5638 +4643 +1413 +5969 +1515 +4016 +4856 +3287 +3122 +2948 +3711 +5031 +4692 + +6445 +2261 +2132 +3517 +2461 +2767 +2071 +2176 +6357 +1304 +6034 +1346 + +1318 +4719 +2054 +1433 +6514 +3729 +4329 +1026 +1502 +2611 +1363 +6379 +3617 + +1885 +7519 +2849 +5167 +3136 +4819 +8018 +4110 +2666 +6098 +4943 + +6575 +1624 +6004 +4178 +7453 +5979 +6736 +3883 +7109 +1271 +1175 + +9494 +12633 +11576 +3547 + +4653 +6777 +4497 +2246 +4666 +4675 +4440 +7227 +3808 +2425 +6014 +7305 + +2538 +6155 +4321 +6239 +6279 +1445 +5592 + +4920 +5435 +1392 +4122 +10513 +6359 +1574 +7222 + +9013 +2150 +8377 +8884 +4108 +5427 +1605 +6907 + +7861 +10554 +1210 +1346 +5296 +4419 +9147 + +1858 +2956 +2070 +10271 +5810 +2632 +9429 +3941 + +4306 +4972 +6216 +6345 +3971 +3920 +6295 +3552 +1399 +5425 +5218 +4512 +3376 +4460 + +4107 +4484 +5148 +5456 +7902 +2185 +3439 +7199 +9514 + +11030 +12096 + +2886 +1561 +14057 +7480 +12186 + +8600 +4085 +11755 +4564 +1697 +6345 +10176 + +2538 +10138 +8328 +10621 +13322 +13907 + +5450 +3403 +5776 +5967 +3873 +2761 +5992 +2251 +2278 +4673 +3442 +2720 +2556 +4848 +5967 + +2806 +8228 +9047 +10630 +4367 +4917 +4084 +7893 + +2842 +18343 +1497 +19962 + +3985 +10986 +1431 +1569 +8053 +8987 +6474 + +5733 +2237 +6183 +1642 +1005 +4389 +1889 +2385 +2470 +6338 +2200 +3399 +3659 +4092 + +6579 +5872 +4229 +1081 +2254 +1229 +5218 +4267 +6906 +2818 +1084 +3655 +2294 + +1882 +5005 +3805 +2088 +6809 +4982 +1935 +6789 +1961 +1842 +5988 +2859 +3965 + +2313 +1021 +5090 +1309 +5110 +3142 +4102 +2919 +6010 +3079 +5786 +3701 +2659 +5728 + +4251 +1899 +4119 +8941 +6677 +2161 +2119 +2772 +3122 + +7821 +6113 +5150 +3486 +2072 +4089 +2820 +3161 +7589 +1787 +5988 + +10582 +8240 +1934 +1504 +9070 +1186 +7766 +1066 + +6700 +6181 +3238 +1940 +1229 +3688 +1375 +5873 +2328 +6384 +7446 +7246 + +5542 +6771 +1964 +4532 +3011 +2300 +1451 +6726 +4595 +2926 +5237 +5020 +6129 + +15008 +4409 +6769 +2211 + +11825 +8947 +17411 +2893 + +8460 +11664 +2304 +6865 +2132 +9174 + +15540 +16925 +12015 +7621 + +1439 +11886 +3028 + +4604 +1057 +5342 +4723 +7773 +3373 +7488 +8028 +3246 +6355 +1939 + +2921 +4447 +3472 +5175 +5909 +5936 +5263 +3993 +1589 +3906 +4865 +3156 +2010 + +10089 + +5964 +7650 +4692 +1537 +3281 +3162 +1064 +4567 +3910 +2229 +3566 + +15533 +17311 +11818 +6179 + +4583 +4577 +3573 +1379 +3761 +1048 +4799 +4275 +3515 +5637 +5435 +3801 +5933 +1926 + +11841 +16030 +3213 + +4307 +7300 +1237 +5513 +6799 +2402 +2554 + +67023 + +1573 +6798 +3002 +7536 +2373 +5994 +10122 + +1149 +1836 +7129 +6621 +7432 +2468 +4028 +6560 +5127 +3781 +7035 +5845 + +13729 +10212 +10942 +10087 +10080 +6493 + +6850 +5969 +3370 +5400 +6433 +4762 +5702 +6193 +1836 +1507 +2637 +3051 +1394 + +5465 +10565 +4923 +1671 +9789 +9150 +6466 +8013 + +31283 + +2001 +6032 +6765 +3896 +7593 +3175 +3447 +1718 + +6062 +7630 +6302 +4448 +1014 +4756 +4696 +4069 +5663 +2181 +6153 + +9228 +1871 +11739 +10894 + +7435 +6290 +3249 +9358 +9196 +8951 +5023 +4910 +9686 + +3823 +4247 +7159 + +4630 +3352 +7700 +7752 +3343 +4577 +2448 +10326 + +10002 +28943 + +2592 +4430 +4077 +2126 +4628 +6466 +5919 +7019 +2667 +2573 +7038 +3153 + +2837 +12151 +9774 +1574 +3046 +13079 + +6949 + +5306 +7432 +4274 +6835 +7057 +5695 +4727 +5581 +6516 +3903 +3138 + +4083 +4247 +1806 +2753 +3612 +3509 +5498 +2160 +5814 +1502 +5760 +4663 +1354 +1592 + +59040 + +3738 +7624 +4539 +8649 +9418 +5495 +1178 +8389 + +4458 +5283 +2572 +3530 +6228 +4711 +2621 +2131 +6363 +5611 +3236 +2314 +2547 +1905 + +3744 +1413 +2997 + +2214 +4673 +4481 +5827 +3752 +5489 +5301 +7568 +6869 +2928 +2900 + +11668 +7579 +2324 +7245 +14362 + +1191 +5622 +2764 +3241 +3690 +3627 +2637 +4043 +3012 +2773 +4276 +1127 +3649 + +5327 +6535 +4821 +5531 +3037 +4700 +6287 +6476 +2266 +7550 + +3054 +5023 +1296 +4394 +5649 +1822 +6609 +7038 +5836 +6571 +6918 + +9473 +5377 +8449 +4839 +3118 +7861 + +8784 +3880 +5133 +6131 +2114 +5196 +10405 +1040 + +5003 +5888 +6058 +6910 +3155 +3278 +1159 +3863 +4565 +1181 +2716 +6431 +3014 + +7633 +4984 +1297 +4524 +5183 +3717 +12038 + +5908 +7784 +11211 +7635 +2060 +5502 +9179 + +6537 +6895 +3455 +4799 +5557 +3497 +4467 +1694 +5227 +1663 +2377 +3538 +4529 + +9371 +2421 +9789 +7373 +6459 +6405 +7775 +8218 + +2077 +8589 +3417 +7811 +10255 +4325 +7168 + +5963 +2806 +3512 +2369 +5721 +3852 +3022 +3764 +6152 +1158 +6460 +4694 +1909 +2655 + +7789 +3030 +3621 +6269 +3149 +6405 +2288 +3512 +5674 +1301 + +6120 +2629 +6348 +7105 +3459 +6678 +5903 +4519 +3074 +2086 +3927 + +2924 +12290 +1873 +5613 +3098 +8641 + +24464 +37206 + +7180 +13271 +4832 +10691 +9084 + +4915 +1440 +1841 +1476 +7124 +1692 +7480 +4583 +1896 +3475 +5424 + +6864 +3187 +4680 +5159 +4314 +3148 +1060 +7290 +2080 +8308 + +2412 +16405 +15203 +5606 +9411 + +13201 +6242 +11906 +15782 +12558 + +5319 +7968 +6732 +9702 + +7203 +3571 +7241 +8764 +3466 +6032 +6608 +6898 +7189 +2749 + +6184 +7590 +4976 +4289 +8553 +8238 +5844 +8314 + +3264 +2924 +2586 +1234 +3126 +5269 +6147 +6029 +2384 +6440 +6161 +1708 +2928 +2336 + +24565 +31964 + +11118 +10621 +1430 +3312 +1135 +6740 +9456 + +16874 +4385 +8675 +4237 + +1537 +4313 +5552 +2195 +3530 +2433 +3056 +3693 +1151 +4297 +2017 +4917 +3823 +3388 +1580 + +5795 +2642 +3822 +1824 +2366 +3800 +2020 +4065 +2758 +2677 +3951 +5175 +4433 +1199 +3212 + +4183 +2822 +6355 +4427 +6384 +2931 +4892 +3148 +5802 +3885 +4892 +5233 +4269 +4286 + +3711 +5430 +6115 +5561 +5066 +2796 +3886 +1960 +6083 +4657 + +11662 +12901 +6891 +3897 + +1086 +4333 +1477 +1046 +5670 +3996 +1909 +3544 +5143 +1387 +6319 +3084 +3136 +6084 + +36111 +14790 + +6552 +8491 + +6636 +9718 +15736 +1619 + +9531 +7507 +7311 +5991 +6901 +12139 +10580 + +10956 +7878 +9100 +11884 +2906 +10388 + +7767 +4040 +5872 +1060 +2299 +1008 +3597 +2749 +5025 + +1550 + +5364 +7108 +8661 +8894 +9240 +10008 +4243 + +46695 + +4195 +2850 +2978 +4995 +2944 +5773 +3669 +3662 +4471 +6343 +4258 +1252 +6408 +5995 + +9482 +11898 +9022 +8167 +9232 + +2647 +1990 +2948 +5314 +2341 +3828 +2513 +2091 +4173 + +9640 +2690 +8774 +11619 +11201 +2429 +7216 + +3433 +5914 +5223 +4879 +1349 +4692 +2906 +3761 +4416 +4813 +2751 +4474 +2057 +1675 + +9803 +8986 +3617 +2175 +1412 +8370 + +7671 +6448 +6759 +1857 + +25790 +14495 + +1872 +6441 +4585 +4053 +4142 +5844 +2089 +3387 +2660 +5890 +6499 +3769 +2710 + +23432 +16915 + +1351 +2656 +6557 +1149 +5054 +1681 +6871 +2643 +3158 +1617 +4087 +6498 +4993 + +5494 +10055 +2730 +5800 +2923 +8037 +3448 +1527 + +5803 +18165 +21951 + +4766 +3809 +4678 +3184 +9687 +7825 +7222 +6638 +2016 + +1801 +1717 +4955 +6088 +1848 +4033 +7023 +3551 +5970 +1415 +7027 +7411 + +25450 +11523 +22548 + +1566 +4742 +3947 +2708 +2019 +3479 +4735 +6002 +7042 +1828 +7071 +1535 + +14218 +5232 +10228 +3340 +7975 + +8837 +3510 +10363 +11854 +2821 +7627 +10186 + +1102 +3749 +1436 +1561 +3098 +3849 +3726 +2041 +1100 +1532 +5473 +4643 +5922 +4739 +1216 + +4408 +7369 +1369 +4742 +7109 +4368 +3468 +2777 +3296 +6999 +5777 +5019 + +3750 +12190 + +15694 +12690 +14834 +15532 +1955 + +8702 +1209 +3012 +3074 +8390 +6779 +6117 +2544 +3900 +6374 + +4126 +5772 +7149 +3949 +2371 +2374 +2469 +7839 +7898 +2871 +5808 + +1108 + +9610 +4374 +10275 +2595 +9413 +8906 +6402 +1551 + +6560 +8632 +5064 +2152 +3443 +4229 + +13104 +24831 +17968 + +4648 +5332 +4866 +1048 +4089 +4710 +1406 +2544 +5319 +4685 +4622 +6080 +5899 +3266 + +5694 +12879 +4015 +16066 +1600 + +11186 +31873 + +3871 +6382 +5076 +3606 +4283 +7913 +11124 + +9959 +14807 +17825 +5880 + +3914 +14183 + +8104 +8322 +10254 +3957 +1410 +9402 +2012 + +1130 +4640 +5738 +3860 +1510 +3067 +5021 +5321 +2820 +1269 +3433 +5216 +5585 +1344 + +5975 +9879 +4969 +9796 +1404 +6772 +3240 +1954 + +12512 +13741 +6425 +13234 +10597 +12414 + +2031 +2255 +3306 +1831 +1601 +1959 +4452 +5054 +4967 +5392 +4040 +4989 +4385 +5838 +5043 + +3165 +10185 +10580 +1626 +5436 +9644 +10842 + +5139 +8090 +1045 +5867 +5987 +8488 +2409 + +1045 +2843 +3543 +3224 +2855 +3318 +4192 +4600 +5773 +4074 +4705 +4716 +1798 +5274 +2443 + +6325 +7878 +4932 +7543 +8073 +2113 +5481 +8138 +2151 +1296 + +6007 +2506 +2346 +3631 +1526 +4875 +3099 +5253 +6281 +2057 +3209 +2622 +2930 +4926 + +2901 +4561 +2361 +4474 +8508 +6515 +5024 +2201 +4402 +6922 + +4219 +24714 +17196 + +38164 + +1900 +5727 +3935 +5498 +6165 +4621 +3347 +4387 +5982 +4213 +1742 +1302 +2452 +3923 + +9558 +7131 +15662 +9101 +13730 + +6474 +2222 +6539 +3747 +5995 +5573 +6288 +4684 +5121 +2226 +1722 +1117 +1020 + +3565 +3489 + +18395 +20407 + +57158 + +19992 + +3636 +4392 +4584 +5421 +3159 +5817 +2303 +1013 +1758 +1802 +4630 +4261 +1524 +1639 + +4652 +1967 +4765 +4946 +3023 +2732 +2749 +5258 +5935 +6428 +3053 +6328 +2389 +5681 + +5450 +1993 +2824 +3596 +2658 +8545 +6577 +3024 +4001 +1780 + +7902 +6187 + +1349 +6028 +3307 +1964 +5116 +2308 +6108 +4286 +1689 +3324 +3728 +4946 +4267 +3801 +3806 + +14183 +29320 + +32460 +25012 + +3317 +5545 +7302 +4936 +7934 +6094 +7971 +2497 +8130 +3752 + +4195 +2147 +7770 +4214 +4737 +7962 +5942 +4478 +3816 +7508 +6693 + +26013 +8614 +19828 + +1144 +2361 +4371 +4246 +3442 +1693 +5137 +5806 +2434 +1413 +3135 +4028 +4757 +6005 + +2351 +4927 +3004 +3384 +1545 +2172 +3407 +4120 +3954 +1806 +2342 +5847 +5228 +1005 + +11490 +7855 +9775 +10577 +3232 +5211 + +8316 +2984 +13490 +15716 +7433 + +11288 +14551 +10056 +14839 +7241 + +4573 +2731 +3358 +4850 +6352 +5419 +1021 +6611 +6489 +3794 +6089 diff --git a/aoc2022/input/day01_provided.txt b/aoc2022/input/day01_provided.txt new file mode 100644 index 0000000..2094f91 --- /dev/null +++ b/aoc2022/input/day01_provided.txt @@ -0,0 +1,14 @@ +1000 +2000 +3000 + +4000 + +5000 +6000 + +7000 +8000 +9000 + +10000 diff --git a/aoc2022/src/day01.rs b/aoc2022/src/day01.rs new file mode 100644 index 0000000..57e623f --- /dev/null +++ b/aoc2022/src/day01.rs @@ -0,0 +1,63 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day01.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let inventories = input + .split("\n\n") + .map(str::parse::) + .collect::>>()?; + + inventories + .iter() + .map(Inventory::total_calories) + .max() + .context("inventory list was empty") +} + +struct Inventory(Vec); + +impl std::str::FromStr for Inventory { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(Inventory( + s.lines() + .map(|line| line.parse::().map_err(anyhow::Error::new)) + .collect::>>()?, + )) + } +} + +impl Inventory { + fn total_calories(&self) -> u64 { + self.0.iter().sum() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day01_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 24000); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 68923); + } +} diff --git a/aoc2022/src/lib.rs b/aoc2022/src/lib.rs new file mode 100644 index 0000000..784a117 --- /dev/null +++ b/aoc2022/src/lib.rs @@ -0,0 +1,3 @@ +#![warn(clippy::explicit_iter_loop, clippy::redundant_closure_for_method_calls)] + +pub mod day01; diff --git a/aoc2022/src/main.rs b/aoc2022/src/main.rs new file mode 100644 index 0000000..98d4d03 --- /dev/null +++ b/aoc2022/src/main.rs @@ -0,0 +1,11 @@ +use anyhow::Result; + +use aoc::DayFunc; + +use aoc2022::day01; + +fn main() -> Result<()> { + let days: &[DayFunc] = &[day01::run]; + + aoc::run(days) +} diff --git a/flake.lock b/flake.lock index 7f2e0b6..f8b7e1c 100644 --- a/flake.lock +++ b/flake.lock @@ -32,16 +32,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1637593665, - "narHash": "sha256-R7jKS7A+0tZS8qD5pBr1UFcMiTdsw5bfoxgXbYsoWhM=", + "lastModified": 1669834992, + "narHash": "sha256-YnhZGHgb4C3Q7DSGisO/stc50jFb9F/MzHeKS4giotg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "98747f27ecfee70c8c97b195cbb94df80a074dda", + "rev": "596a8e828c5dfa504f91918d0fa4152db3ab5502", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-22.11", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 31a64b2..ffaa247 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11"; rust-overlay.url = "github:oxalica/rust-overlay"; flake-utils.url = "github:numtide/flake-utils"; }; From 8e1328571b993069595515198bd1c64b3d13cc0c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 5 Dec 2022 23:04:07 +0100 Subject: [PATCH 100/134] 2021: bump bitvec to 1.0 --- Cargo.lock | 16 ++++++++-------- aoc2021/Cargo.toml | 2 +- aoc2021/src/day16.rs | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa0f66e..8976861 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,9 +141,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.22.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", @@ -347,9 +347,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "funty" -version = "1.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "generic-array" @@ -574,9 +574,9 @@ dependencies = [ [[package]] name = "radium" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -912,9 +912,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wyz" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] diff --git a/aoc2021/Cargo.toml b/aoc2021/Cargo.toml index e31557d..a33f86c 100644 --- a/aoc2021/Cargo.toml +++ b/aoc2021/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" aoc = { path = "../aoc" } anyhow = "1.0" rand = "0.8" -bitvec = "0.22" +bitvec = "1.0" [lib] path = "src/lib.rs" diff --git a/aoc2021/src/day16.rs b/aoc2021/src/day16.rs index 688fa8a..d02fd94 100644 --- a/aoc2021/src/day16.rs +++ b/aoc2021/src/day16.rs @@ -122,7 +122,7 @@ impl std::str::FromStr for Packet { fn from_str(s: &str) -> Result { let s = s.trim(); - let mut bits = BitVec::::new(); + let mut bits = BitVec::::new(); bits.resize(4 * s.len(), false); for (i, c) in s.chars().enumerate() { @@ -149,13 +149,13 @@ const TLID1_SUBPACKET_NUMBER_BITS: usize = 11; const SUBPACKET_START_INDEX_TLID1: usize = LENGTH_INDEX + TLID1_SUBPACKET_NUMBER_BITS; const SUBPACKETS_NUMBER_RANGE: Range = LENGTH_INDEX..SUBPACKET_START_INDEX_TLID1; -impl<'bits, Store> TryFrom<&'bits BitSlice> for Packet +impl<'bits, Store> TryFrom<&'bits BitSlice> for Packet where Store: BitStore, { type Error = anyhow::Error; - fn try_from(bits: &'bits BitSlice) -> Result { + fn try_from(bits: &'bits BitSlice) -> Result { let version: u8 = bits[VERSION_RANGE].load_be(); let type_id: u8 = bits[TYPE_ID_RANGE].load_be(); From a25dc5beae0fdb35dafd70f4d70de20b671c19fd Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 5 Dec 2022 23:08:19 +0100 Subject: [PATCH 101/134] bump Cargo.lock --- Cargo.lock | 262 +++++++++++++++++++++++------------------------------ 1 file changed, 115 insertions(+), 147 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8976861..07ae2c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "aoc" @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -186,9 +186,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "byte-tools" @@ -204,12 +204,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cast" -version = "0.2.7" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version", -] +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cfg-if" @@ -230,16 +227,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", "cast", "clap", "criterion-plot", "csv", - "itertools 0.10.3", + "itertools 0.10.5", "lazy_static", "num-traits", "oorandom", @@ -256,19 +253,19 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" dependencies = [ "cast", - "itertools 0.10.3", + "itertools 0.10.5", ] [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -276,9 +273,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -287,25 +284,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ + "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", - "lazy_static", ] [[package]] @@ -341,9 +337,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "funty" @@ -362,9 +358,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -397,9 +393,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -412,15 +408,15 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -433,15 +429,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -459,15 +455,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] @@ -480,34 +476,39 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "nom" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", - "version_check", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + [[package]] name = "oorandom" version = "11.1.3" @@ -522,9 +523,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -535,39 +536,39 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.34" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -580,14 +581,13 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -602,29 +602,19 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "rayon" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" dependencies = [ - "autocfg", "crossbeam-deque", "either", "rayon-core", @@ -632,22 +622,21 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "regex-syntax", ] @@ -660,24 +649,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -694,17 +674,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "semver" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" - [[package]] name = "serde" -version = "1.0.132" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" [[package]] name = "serde_cbor" @@ -718,9 +692,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.132" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" dependencies = [ "proc-macro2", "quote", @@ -729,24 +703,24 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.73" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.4", "ryu", "serde", ] [[package]] name = "syn" -version = "1.0.82" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -776,27 +750,21 @@ dependencies = [ [[package]] name = "typenum" -version = "1.14.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "walkdir" @@ -811,15 +779,15 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -827,13 +795,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -842,9 +810,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -852,9 +820,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -865,15 +833,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", From 2ca6bce781fc21a62a2f3caf7b9f224a429bf9a7 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 5 Dec 2022 23:28:51 +0100 Subject: [PATCH 102/134] 2022: day01 part 2 --- aoc2022/src/day01.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/aoc2022/src/day01.rs b/aoc2022/src/day01.rs index 57e623f..230ce57 100644 --- a/aoc2022/src/day01.rs +++ b/aoc2022/src/day01.rs @@ -1,3 +1,4 @@ +use std::collections::BinaryHeap; use std::fmt::Write; use anyhow::{Context, Result}; @@ -8,6 +9,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -25,6 +27,16 @@ fn part1(input: &str) -> Result { .context("inventory list was empty") } +fn part2(input: &str) -> Result { + let inventories = input + .split("\n\n") + .map(|line| line.parse::().map(|inv| inv.total_calories())) + .collect::>>()?; + + Ok(inventories.iter().take(3).sum()) +} + +#[derive(Debug)] struct Inventory(Vec); impl std::str::FromStr for Inventory { @@ -60,4 +72,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 68923); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 45000); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 200044); + } } From ed660127529aa7e76c41f4d807e39dc7b6aa62df Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 00:01:28 +0100 Subject: [PATCH 103/134] 2022: bench: criterion 0.4 --- Cargo.lock | 145 ++++++++++++++++-- aoc2022/Cargo.toml | 7 + aoc2022/aoc2022_bench/Cargo.toml | 17 -- .../benches/aoc2022_bench.rs | 0 4 files changed, 136 insertions(+), 33 deletions(-) delete mode 100644 aoc2022/aoc2022_bench/Cargo.toml rename aoc2022/{aoc2022_bench => }/benches/aoc2022_bench.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 07ae2c3..2423e93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anyhow" version = "1.0.66" @@ -29,7 +35,7 @@ name = "aoc2015_bench" version = "0.1.0" dependencies = [ "aoc2015", - "criterion", + "criterion 0.3.6", ] [[package]] @@ -45,7 +51,7 @@ name = "aoc2018_bench" version = "0.1.0" dependencies = [ "aoc2018", - "criterion", + "criterion 0.3.6", ] [[package]] @@ -61,7 +67,7 @@ name = "aoc2019_bench" version = "0.1.0" dependencies = [ "aoc2019", - "criterion", + "criterion 0.3.6", ] [[package]] @@ -79,7 +85,7 @@ name = "aoc2020_bench" version = "0.1.0" dependencies = [ "aoc2020", - "criterion", + "criterion 0.3.6", ] [[package]] @@ -97,7 +103,7 @@ name = "aoc2021_bench" version = "0.1.0" dependencies = [ "aoc2021", - "criterion", + "criterion 0.3.6", ] [[package]] @@ -106,14 +112,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", -] - -[[package]] -name = "aoc2022_bench" -version = "0.1.0" -dependencies = [ - "aoc2022", - "criterion", + "criterion 0.4.0", ] [[package]] @@ -214,6 +213,33 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "2.34.0" @@ -221,10 +247,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags", - "textwrap", + "textwrap 0.11.0", "unicode-width", ] +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap 0.16.0", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "criterion" version = "0.3.6" @@ -233,8 +280,8 @@ checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", "cast", - "clap", - "criterion-plot", + "clap 2.34.0", + "criterion-plot 0.4.5", "csv", "itertools 0.10.5", "lazy_static", @@ -251,6 +298,31 @@ dependencies = [ "walkdir", ] +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap 3.2.23", + "criterion-plot 0.5.0", + "itertools 0.10.5", + "lazy_static", + "num-traits", + "oorandom", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + [[package]] name = "criterion-plot" version = "0.4.5" @@ -261,6 +333,16 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-channel" version = "0.5.6" @@ -373,6 +455,12 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -382,6 +470,16 @@ dependencies = [ "libc", ] +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "itertools" version = "0.9.0" @@ -521,6 +619,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + [[package]] name = "plotters" version = "0.3.4" @@ -679,6 +783,9 @@ name = "serde" version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_cbor" @@ -738,6 +845,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/aoc2022/Cargo.toml b/aoc2022/Cargo.toml index 9fe9672..1f0e257 100644 --- a/aoc2022/Cargo.toml +++ b/aoc2022/Cargo.toml @@ -10,9 +10,16 @@ edition = "2021" aoc = { path = "../aoc" } anyhow = "1.0" +[dev-dependencies] +criterion = { version = "0.4", default-features = false, features = [ "rayon" ] } + [lib] path = "src/lib.rs" [[bin]] name = "aoc2022" path = "src/main.rs" + +[[bench]] +name = "aoc2022_bench" +harness = false diff --git a/aoc2022/aoc2022_bench/Cargo.toml b/aoc2022/aoc2022_bench/Cargo.toml deleted file mode 100644 index e5ef4bc..0000000 --- a/aoc2022/aoc2022_bench/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "aoc2022_bench" -version = "0.1.0" -authors = ["Antoine Martin "] -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -aoc2022 = { path = "../" } - -[dev-dependencies] -criterion = "0.3" - -[[bench]] -name = "aoc2022_bench" -harness = false diff --git a/aoc2022/aoc2022_bench/benches/aoc2022_bench.rs b/aoc2022/benches/aoc2022_bench.rs similarity index 100% rename from aoc2022/aoc2022_bench/benches/aoc2022_bench.rs rename to aoc2022/benches/aoc2022_bench.rs From 1d9433098d62a43fae5beaa68629fe1f61f4f4b6 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 00:41:45 +0100 Subject: [PATCH 104/134] flake: bump to latest rust version (1.65) --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index f8b7e1c..2affeb8 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "flake-utils": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { @@ -17,11 +17,11 @@ }, "flake-utils_2": { "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "owner": "numtide", "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "type": "github" }, "original": { @@ -48,11 +48,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1637453606, - "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=", + "lastModified": 1665296151, + "narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8afc4e543663ca0a6a4f496262cd05233737e732", + "rev": "14ccaaedd95a488dd7ae142757884d8e125b3363", "type": "github" }, "original": { @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1638584238, - "narHash": "sha256-s9ABdhsYMTz0Qp1EoORN1O8PlJ68390iGv0+KUwaktg=", + "lastModified": 1670207212, + "narHash": "sha256-uuKbbv0L+QoXiqO7METP9BihY0F7hJqGdKn7xDVfyFw=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "4a918c124e43188e8a1d2492a731befe47effa71", + "rev": "18823e511bc85ed27bfabe33cccecb389f9aa92d", "type": "github" }, "original": { From 008fb72a9818b80b3d586bda51091a4792661e42 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 01:17:46 +0100 Subject: [PATCH 105/134] all: fix clippy lints for rust 1.65 --- aoc2019/src/day03.rs | 2 +- aoc2019/src/day12.rs | 4 ++-- aoc2019/src/intcode/mod.rs | 6 +++--- aoc2020/src/day11.rs | 7 +++---- aoc2020/src/day16.rs | 5 ++--- aoc2020/src/day18.rs | 2 +- aoc2021/src/day03.rs | 8 +------- aoc2021/src/day04.rs | 2 +- aoc2021/src/day14.rs | 2 +- aoc2021/src/day16.rs | 18 +++--------------- flake.nix | 4 +++- 11 files changed, 21 insertions(+), 39 deletions(-) diff --git a/aoc2019/src/day03.rs b/aoc2019/src/day03.rs index 40a1f9a..38727f4 100644 --- a/aoc2019/src/day03.rs +++ b/aoc2019/src/day03.rs @@ -18,7 +18,7 @@ pub fn run() -> Result { } fn manhattan_distance(a: &Point, b: &Point) -> u64 { - (a.x - b.x).abs() as u64 + (a.y - b.y).abs() as u64 + (a.x - b.x).unsigned_abs() + (a.y - b.y).unsigned_abs() } fn part1(first_wire: &Wire, second_wire: &Wire) -> Result { diff --git a/aoc2019/src/day12.rs b/aoc2019/src/day12.rs index fa3aa55..a178241 100644 --- a/aoc2019/src/day12.rs +++ b/aoc2019/src/day12.rs @@ -233,12 +233,12 @@ impl Planet { fn potential_energy(&self) -> u64 { let pos = &self.position; - pos.x.abs() as u64 + pos.y.abs() as u64 + pos.z.abs() as u64 + pos.x.unsigned_abs() + pos.y.unsigned_abs() + pos.z.unsigned_abs() } fn kinetic_energy(&self) -> u64 { let vel = &self.velocity; - vel.x.abs() as u64 + vel.y.abs() as u64 + vel.z.abs() as u64 + vel.x.unsigned_abs() + vel.y.unsigned_abs() + vel.z.unsigned_abs() } fn total_energy(&self) -> u64 { diff --git a/aoc2019/src/intcode/mod.rs b/aoc2019/src/intcode/mod.rs index a93ba8b..10ec3e1 100644 --- a/aoc2019/src/intcode/mod.rs +++ b/aoc2019/src/intcode/mod.rs @@ -226,7 +226,7 @@ impl Intcode { let val1 = op1.get(&mut self.memory, self.relative_base)?; let val2 = op2.get(&mut self.memory, self.relative_base)?; - let res = if val1 < val2 { 1 } else { 0 }; + let res = i64::from(val1 < val2); dst.set(res, &mut self.memory, self.relative_base)?; self.ip += 4; @@ -235,7 +235,7 @@ impl Intcode { let val1 = op1.get(&mut self.memory, self.relative_base)?; let val2 = op2.get(&mut self.memory, self.relative_base)?; - let res = if val1 == val2 { 1 } else { 0 }; + let res = i64::from(val1 == val2); dst.set(res, &mut self.memory, self.relative_base)?; self.ip += 4; @@ -263,7 +263,7 @@ impl Intcode { } pub fn get_day02_output(&self) -> Option { - self.memory.get(0).copied() + self.memory.first().copied() } pub fn get_last_output(&self) -> Option { diff --git a/aoc2020/src/day11.rs b/aoc2020/src/day11.rs index 8a05a0a..9d068a5 100644 --- a/aoc2020/src/day11.rs +++ b/aoc2020/src/day11.rs @@ -111,9 +111,8 @@ impl Layout { count += self .grid .get(i) - .map(|line| line.get(j)) - .flatten() - .map(|&cell| if cell == value { 1 } else { 0 }) + .and_then(|line| line.get(j)) + .map(|&cell| u8::from(cell == value)) .unwrap_or(0); } @@ -131,7 +130,7 @@ impl Layout { let (i, j) = (i.wrapping_add(di as usize), j.wrapping_add(dj as usize)); - let cell = self.grid.get(i).map(|line| line.get(j)).flatten(); + let cell = self.grid.get(i).and_then(|line| line.get(j)); match cell { // keep going, the next seat is farther away diff --git a/aoc2020/src/day16.rs b/aoc2020/src/day16.rs index 69f30d2..da0f583 100644 --- a/aoc2020/src/day16.rs +++ b/aoc2020/src/day16.rs @@ -22,8 +22,7 @@ fn part1(input: &str) -> Result { Ok(tickets .iter() - .map(|t| t.invalid_values(&fields_vec)) - .flatten() + .flat_map(|t| t.invalid_values(&fields_vec)) .sum()) } @@ -224,7 +223,7 @@ mod tests { let matches = assign_field_positions(fields, tickets); - let expected = (&["row", "class", "seat"]) + let expected = ["row", "class", "seat"] .iter() .copied() .enumerate() diff --git a/aoc2020/src/day18.rs b/aoc2020/src/day18.rs index 4df8254..287ae2e 100644 --- a/aoc2020/src/day18.rs +++ b/aoc2020/src/day18.rs @@ -113,7 +113,7 @@ fn mul(input: &str) -> IResult<&str, Expr> { } fn num(input: &str) -> IResult<&str, Expr> { - map_res(take_while1(|c: char| c.is_digit(10)), |res: &str| { + map_res(take_while1(|c: char| c.is_ascii_digit()), |res: &str| { res.parse().map(Expr::Num) })(input) } diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index 919e327..a96113c 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -30,13 +30,7 @@ fn compute_gamma(binary_numbers: &[&str], size: usize) -> u64 { let mut gamma = 0; for pos in 0..size { - let digit = if count_ones(binary_numbers, pos) > (binary_numbers.len() / 2) { - // majority of ones - 1 - } else { - // majority of zeroes - 0 - }; + let digit = u64::from(count_ones(binary_numbers, pos) > (binary_numbers.len() / 2)); gamma = (gamma << 1) | digit; } diff --git a/aoc2021/src/day04.rs b/aoc2021/src/day04.rs index 15a1250..d18cff5 100644 --- a/aoc2021/src/day04.rs +++ b/aoc2021/src/day04.rs @@ -120,7 +120,7 @@ impl Grid { fn unmarked_numbers(&self) -> impl Iterator + '_ { self.number_to_pos .iter() - .filter_map(|(num, &(x, y))| (!self.access_grid(x, y)).then(|| *num)) + .filter_map(|(num, &(x, y))| (!self.access_grid(x, y)).then_some(*num)) } fn access_grid(&self, x: usize, y: usize) -> bool { diff --git a/aoc2021/src/day14.rs b/aoc2021/src/day14.rs index a91b2a6..feaf38e 100644 --- a/aoc2021/src/day14.rs +++ b/aoc2021/src/day14.rs @@ -73,7 +73,7 @@ impl std::str::FromStr for Rules { let (pair, res) = l.split_once(" -> ").context("couldn't parse rule")?; Ok(( ( - *pair.as_bytes().get(0).context("couldn't parse rule")?, + *pair.as_bytes().first().context("couldn't parse rule")?, *pair.as_bytes().get(1).context("couldn't parse rule")?, ), res.bytes().next().context("couldn't parse rule")?, diff --git a/aoc2021/src/day16.rs b/aoc2021/src/day16.rs index d02fd94..c744926 100644 --- a/aoc2021/src/day16.rs +++ b/aoc2021/src/day16.rs @@ -64,31 +64,19 @@ impl Packet { debug_assert_eq!(op.sub_packets.len(), 2); let pack1 = &op.sub_packets[0]; let pack2 = &op.sub_packets[1]; - if pack1.value() > pack2.value() { - 1 - } else { - 0 - } + u64::from(pack1.value() > pack2.value()) } OperatorType::LessThan => { debug_assert_eq!(op.sub_packets.len(), 2); let pack1 = &op.sub_packets[0]; let pack2 = &op.sub_packets[1]; - if pack1.value() < pack2.value() { - 1 - } else { - 0 - } + u64::from(pack1.value() < pack2.value()) } OperatorType::EqualTo => { debug_assert_eq!(op.sub_packets.len(), 2); let pack1 = &op.sub_packets[0]; let pack2 = &op.sub_packets[1]; - if pack1.value() == pack2.value() { - 1 - } else { - 0 - } + u64::from(pack1.value() == pack2.value()) } }, } diff --git a/flake.nix b/flake.nix index ffaa247..cd0a5af 100644 --- a/flake.nix +++ b/flake.nix @@ -10,7 +10,9 @@ let overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { inherit system overlays; }; - myRust = pkgs.rust-bin.stable.latest.default; + myRust = pkgs.rust-bin.stable.latest.default.override { + extensions = ["rust-src" "rust-analysis"]; + }; in { devShell = pkgs.mkShell { From 6c64f744f715a85b05699519cea8733dd60fc044 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 01:22:17 +0100 Subject: [PATCH 106/134] ci: update checkout to v3 --- .github/workflows/rust.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index a8b4a92..f6aee6f 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Format run: cargo fmt --all -- --check - name: Lint From c1f352162cf21d418f85b253c74b970d5c8b4a65 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 16:14:01 +0100 Subject: [PATCH 107/134] 2022: day02 --- aoc2022/input/day02.txt | 2500 ++++++++++++++++++++++++++++++ aoc2022/input/day02_provided.txt | 3 + aoc2022/src/day02.rs | 202 +++ aoc2022/src/lib.rs | 1 + aoc2022/src/main.rs | 3 +- 5 files changed, 2708 insertions(+), 1 deletion(-) create mode 100644 aoc2022/input/day02.txt create mode 100644 aoc2022/input/day02_provided.txt create mode 100644 aoc2022/src/day02.rs diff --git a/aoc2022/input/day02.txt b/aoc2022/input/day02.txt new file mode 100644 index 0000000..3914035 --- /dev/null +++ b/aoc2022/input/day02.txt @@ -0,0 +1,2500 @@ +A Z +A Y +B X +B X +C X +B X +A X +A X +C X +A X +A X +A Y +B X +A Y +C X +C X +A X +A Y +C X +B X +A X +B X +A X +A X +B Y +B Y +A X +A X +A X +A X +A X +A Y +A X +B X +B Y +A Y +C Z +C X +A X +A Y +A X +A X +A Y +A X +A Y +A X +B X +C X +A X +B X +A X +C X +A Y +B X +B X +A X +A X +C Y +B X +A X +C X +B X +B X +A X +A X +B X +A Y +C X +A Y +A X +A X +A Y +B X +A X +A X +A X +B Y +A X +A X +A Y +A X +A X +B Y +B Y +B X +C X +B Y +A X +C X +C X +A Y +A X +A Z +B X +C X +A Y +B X +A X +A X +A X +A Y +C X +A X +A Z +A X +A Y +B Y +A X +C X +B X +A Y +B Z +B X +C Y +B X +B Z +A Y +B X +C X +C Y +A X +A Y +A X +B X +A Y +B Y +A X +C Y +A Y +B Y +A X +B Y +B X +B Y +A X +B Y +A X +C Z +A X +C X +A Y +A X +C X +A X +A X +A X +C X +B Z +A X +B Y +B X +A Y +A X +A X +B Y +B Y +A Y +B X +A X +C Y +A X +C X +A X +A X +A X +A X +A X +C Z +C X +A Z +C Z +A X +A Y +B X +C X +B X +B Y +C X +B X +A X +A X +A X +A Y +B X +B Y +A X +C X +A X +A X +A X +A X +C Y +A Z +C X +A X +A Y +B X +A Y +A X +A Y +A X +A X +A X +A X +A Y +A X +B X +A X +A X +C Y +C Y +A X +C X +A X +A X +C X +C X +B Z +B X +B X +A X +A Y +B Y +A X +A X +C X +C X +C X +B X +C X +B Y +A X +B Y +B X +B X +A X +B Y +A Y +C X +B X +C X +A Y +B X +C X +A X +C X +A X +B Y +A X +A X +B Z +C X +B X +C X +B X +A X +A X +A X +A X +A X +C X +C X +A X +A Z +A Y +A X +A X +A X +A X +C Y +C Y +B Z +A X +A X +B X +B X +A Y +A X +B Y +A X +B Y +A X +C Y +C X +A Y +B Y +C X +A X +A X +A X +A Y +A X +A X +A X +B Y +B X +C X +C Y +A Y +A Z +B X +C X +B X +C X +A X +B Z +B Y +A X +C X +A Y +B X +B X +A Y +A X +A X +A Y +A X +B X +A X +A X +C Y +C Y +A Y +A Y +B Y +B Y +B Y +B X +A X +A Y +B Y +B X +A Y +A X +A Y +C X +C X +B Y +A Y +B Y +A Y +A X +B Y +B X +C X +A X +A X +A X +B Y +B X +A X +B Y +A Y +A X +C X +A X +B Y +A X +A X +B Y +A Y +A X +C Y +B Z +A Y +C X +A Y +A X +B Y +A X +B Y +B Y +B X +B X +A X +A X +C X +B Y +B X +C X +B Y +A X +A X +A X +A X +B Y +C X +B X +A X +A X +A Y +C Y +A Y +B X +A X +B X +A X +A Y +B Y +A X +C X +C X +A Y +B X +C Y +A Y +B X +A X +A Y +C X +A X +A X +B Y +A Y +B X +B Y +B Y +A X +A X +A X +B Y +A Y +A X +B X +A Y +A Y +B X +C Y +A X +A Y +A X +B X +A X +B X +C Z +A X +A X +B Y +A X +A X +A X +C Z +C X +A Z +C Y +B X +A Y +B X +A X +A Y +A X +C X +A X +A X +C Y +A Z +C Y +B Y +B X +B X +A Y +C X +B X +A Z +A X +A Z +C X +A X +C Z +C X +B Z +C Y +B Y +A X +B Y +A X +A X +C X +B X +A X +C Z +B Y +B Y +A Y +B Y +A X +A X +B Y +A X +A X +C Y +C X +A X +C Y +C X +B X +B X +A X +B Y +A Y +A X +B Y +B Y +B X +B X +A X +B X +B X +B Y +B Y +C X +B X +B X +A X +A X +A X +A X +A Y +C Y +A X +A Y +C Z +A Y +C X +A X +C Y +A X +A X +A Y +A Z +A Y +A Y +A X +A Y +A Z +C X +C Z +B X +A X +A X +B X +A X +A X +A X +C X +A X +A Y +A X +A X +A Y +C Z +C X +A X +A X +A Z +A X +C X +A Y +C X +A Y +C X +C X +A X +A X +A Y +B Y +C X +C X +B X +B Z +B X +B X +A X +C X +A Y +C X +A Z +B X +B Y +A Y +A Y +A X +A Y +A X +A X +A Y +A X +A X +B Z +A X +A X +A X +B Y +B Y +C Z +A Y +A Y +B Y +A X +B X +C X +C Y +C X +B X +C X +A Y +A X +A X +B X +C X +B X +A Y +B X +B Z +A Y +A X +A Y +B X +B Z +A X +A X +C X +A X +A Y +A X +B X +A X +A X +A Z +B X +B Y +C Y +C X +A Y +A X +B Y +C X +A X +C Y +A X +A Y +A Y +A X +A X +C X +C X +A Y +A Y +C X +A X +B X +C X +B Y +C Y +C X +B X +B Y +C X +B X +B Y +A X +A X +B X +A Y +A X +B X +A X +C Y +A X +B X +A Y +C Y +A X +A Y +A Z +C Z +A X +A X +C X +A X +B X +A X +C X +C X +A Y +A X +C Y +A Y +A X +B Y +A X +A Y +A X +C Z +C Z +C X +A X +A X +A X +A X +C X +A X +C X +B X +B X +A X +A Y +B Y +B X +B X +A Y +A Y +A X +A X +B Y +B X +A X +C X +B X +C X +B Y +B Z +B Y +A X +A X +A X +A X +A X +B Y +A X +C X +B Z +A X +C Y +A X +B X +C Y +A X +A Y +B X +A X +B Y +B X +A Y +C Y +C X +A Y +A X +A X +A X +C X +B X +C X +A Y +A X +A Y +C Z +C X +A X +A Y +B X +B X +B X +B X +A X +B X +A Z +B Y +A X +A X +A X +C Z +A Y +A Y +C X +C X +C Y +B Y +A Y +A X +A X +C Y +A X +C X +A X +A X +C Y +A Y +A X +C X +A X +A Y +C X +A Y +A X +A X +A X +B X +B X +A X +B Y +C Y +C X +A Y +B X +B X +B Z +C X +B Y +A Y +C Z +B X +C X +A X +A Y +B Y +B X +C Z +B X +A X +C X +C X +A X +A X +A Y +B Y +B X +A Y +C Y +B Y +B Y +A X +A Y +A X +B X +A Y +A X +A Y +A X +B Z +B X +A X +A Y +A X +B Y +A Y +A X +A X +C X +A X +A X +A X +A X +B Y +B X +A X +A X +C Y +C X +A Y +A X +B X +A X +B X +B X +B Y +A X +B X +B Y +A X +B X +C X +A X +A X +C Z +A X +B X +A X +B X +B X +B Y +A X +B Y +C Y +A X +C X +A X +B X +B Y +A X +C X +B X +A X +C Y +C X +B X +A X +B X +A Z +C Y +A X +A X +B X +A Y +B X +A X +A Y +B X +A X +C Y +A X +C X +B X +A X +C Y +C X +A X +B Y +B X +A Y +B X +A X +B X +A Y +B X +A X +A X +C X +A X +A X +A X +A X +C X +C X +B X +B Y +B X +B Z +A X +B X +B Y +B X +B X +A X +A Z +A Z +A X +B Y +A X +B X +B Y +A X +B Y +B X +A X +C X +C Y +A X +A X +B X +B X +B Y +A X +C X +B Y +A X +A Z +A X +C Y +A Y +B X +C X +C X +A X +B X +C X +A Z +A X +A X +B Y +C X +A X +A Y +C Z +B X +A Y +A X +A Z +C Y +A X +C X +A X +C Y +B X +A X +A X +B Y +A X +B X +B X +B X +C X +C X +A X +C Z +A X +C Y +A X +C Y +A Y +B Y +B X +B Y +B X +C Y +B Y +B Y +B X +B Y +A Y +A Y +C Z +A X +A X +A X +A Z +B X +B Y +B X +B Y +A X +C X +B X +A X +C Y +B X +C X +C Y +B Y +A X +B Y +B X +C X +B X +C X +B X +A X +C X +B Z +B Z +C X +A Y +B X +A Y +A X +B X +C Y +C X +A Y +C Y +B Z +B Y +B Y +B Y +B Z +B Y +A X +A X +A Y +B Y +B Y +A X +A Z +C X +A X +A Y +C X +A Y +A X +B X +A X +A X +C X +A X +A X +C Y +B Y +A Y +A X +A X +B Y +A X +B X +A X +A X +B X +B X +A X +B Y +A X +A Y +B Y +A Y +A X +C X +A Y +A X +C X +A X +A X +B X +C Y +C Y +B X +B Z +A X +A Y +A X +A X +C Z +A X +B X +A Z +A X +A X +A X +A X +A X +A X +C X +B X +B X +C X +A X +A X +A X +A X +A X +A X +B X +A X +C X +A Y +A X +A X +A X +A X +B X +B Y +A Y +A X +A X +C X +C X +A X +A X +C X +A X +A X +A X +A X +A X +A X +C X +A X +A X +A X +A X +B X +A X +A X +B Y +C Y +A X +A Y +C Y +A X +B X +B X +A X +A X +A X +B X +A X +A X +A X +A Y +A X +B Y +A Y +A X +A Y +A X +C X +A X +C Y +B X +B X +A X +A X +A X +A X +A X +C Y +A Z +A X +B X +B X +A X +A X +C Z +A X +B Z +B Y +C Y +A X +A X +C X +B X +B X +B X +C X +A X +A Y +B Y +C X +A X +B Y +A X +C Z +B X +A Y +A X +A X +C Y +A X +A X +C X +A X +B X +B Y +B Y +B X +A X +A Y +C X +A X +A X +A X +B X +C X +B Y +A X +A X +A Y +A X +A X +B X +C X +C X +A Y +B X +A X +A X +A X +B Y +A X +B X +A X +A X +A X +A Y +A X +A Z +C X +B Y +B X +A X +B X +C X +A X +A X +B X +A X +A X +A X +A X +B X +A X +C X +A Y +B X +C X +A X +B X +A X +B Y +A X +C Y +A X +C Y +C X +B Y +A Y +A X +A X +B X +A X +C X +A X +A Z +B X +A X +A X +A Y +A X +A X +C X +B Y +C Z +A X +A Y +B X +B X +A X +B Y +C X +A X +B X +A Y +B X +A X +A Y +A X +A X +C Y +B X +A Y +C X +C X +A Y +A Y +A X +B Z +A Y +C X +C X +C Y +A Y +B X +B Z +A X +B Y +A X +A X +B X +A Y +C X +C Y +A X +B Y +A Y +A X +B Z +B Y +A X +B X +A X +A X +B Y +A Y +A X +A X +A X +A Y +A X +A X +C X +A X +A X +C X +A X +A X +C Z +B X +A Y +A X +B Y +B X +A X +A X +A X +C Y +C Y +B Y +A X +C X +C X +B X +A X +A X +A X +A Y +A X +A X +B Z +C X +A X +A X +A X +B Y +B X +C X +B X +A X +B X +A X +C X +A X +C X +A X +C X +B Y +B X +A X +A X +B Y +B X +B X +A X +B X +C Y +A X +A Y +A Y +A Y +A Z +B Y +A X +A X +A X +A X +A Z +A X +A X +A X +B Z +B Y +C Y +A X +A X +B X +C X +A Y +A X +B X +A X +A X +B X +B Y +A X +B X +C X +B X +A X +A X +A X +A X +B X +B X +C Y +B X +B X +A X +B X +A X +B Y +B X +A X +A X +A Y +B X +A X +B Y +A Y +B Y +B X +A Z +A X +B Y +A X +B X +A X +A X +A X +B Y +B X +A X +C Z +A Y +A Y +C X +B Z +B X +C Z +B X +B X +A X +A X +B Y +C X +A X +A Z +B X +A X +A X +B Y +A X +A X +A X +B Y +A X +C Y +A X +C Y +A X +C Y +B X +A Y +A X +B X +A X +B Y +A X +B X +B X +A Z +A X +C Y +B Y +A X +A X +C X +B Y +C Y +C X +A Y +B Y +A Y +A Y +B X +A X +A X +A X +A X +A Y +A X +A X +A X +B Y +A X +A Y +C X +A X +B X +A X +A X +A X +C Z +A X +A Y +A X +C Z +B Y +B X +A X +A Z +A X +A X +A Y +A X +A X +A X +B Y +A X +B X +A X +A X +A X +A X +B X +B Z +C X +C X +C X +B Y +A X +B Y +B X +A Y +B X +B X +A X +C Y +B X +A X +A X +A X +A X +A X +A X +B Y +C Y +B X +C Y +B Y +C X +A Y +C X +B X +C X +B X +A X +A X +B Y +A X +C X +A Y +C X +C X +B Y +A X +C X +C X +B Z +A X +C X +A Y +B Y +A X +A Y +A X +B X +A X +A X +B Y +A Z +A X +B Y +B X +A X +A Y +B X +B X +A X +A X +A Y +A X +C X +A X +B X +C X +C X +C Y +A X +B X +B Y +A X +C X +A X +B Y +A X +B X +B Z +A X +A X +A X +B X +C X +C X +B X +A Y +A X +A Y +A X +A X +A X +A X +C Y +B X +A X +A X +A X +B Y +A X +B X +B Y +A Z +A Y +A X +A Y +A X +A Y +B Z +A X +B Y +B Z +B X +A X +C X +C Y +A X +A X +A X +B X +A Y +C X +A X +B Y +A Y +B X +B X +A X +A Y +B X +A Y +C X +A X +C X +A X +C X +A X +A X +C X +A X +A X +A Y +B X +C X +B Y +A Y +A X +A X +A X +A Z +B Y +A X +A X +B Y +A Y +B Y +A X +B Y +B X +A X +A X +A X +B X +B Y +A X +C Z +B Z +A X +A X +A X +B X +B Y +A X +B Z +A X +A Y +A Y +A Y +C X +B Y +A X +A X +C Y +B X +A Y +A X +A X +B Y +C X +C X +C X +A X +A X +A X +B Z +A X +C X +A X +A X +B X +B X +A X +C Y +A X +B X +C X +B Y +A X +B Y +C X +A X +C X +B Y +A X +A Y +C X +C Z +A X +C X +A X +A X +C X +A Y +C X +B Y +A X +C Z +A X +B X +B Y +A Y +A X +A X +A X +A X +A Y +A Y +B X +C X +A Y +A X +C X +B X +B Y +C X +B X +A X +B X +A X +C Y +A X +A X +A X +A X +C X +A X +B X +A X +B X +A X +A Y +C X +C Y +C X +A Z +B X +A Z +A X +B Y +A Y +B X +A X +B Y +A Y +A X +B Y +A X +B X +A X +A X +A X +A X +B Y +A Y +A X +A X +B X +B Z +A Y +A Y +C Y +C Y +A X +C X +A X +B Y +B X +B Y +B X +C X +B X +C X +A X +B Y +A X +B X +A X +B X +C Y +B X +A X +A Y +A X +B Y +C X +C X +A X +B Z +A X +A X +B Y +A X +A X +B X +A Y +C X +A X +C Y +A Y +C X +A Y +A X +A X +A X +A Y +B X +B X +A Y +C X +B Y +A Y +B X +B X +B X +B X +A X +B X +B X +A X +C X +A X +C X +C X +A X +C X +B X +A Y +A Z +A X +A X +A X +A Y +A X +A X +C Z +A X +B X +C X +A X +B X +C X +C X +A X +B Y +A X +A X +A X +A Y +B Y +B Y +A X +B X +A X +C X +A X +B Y +C Y +C X +C X +B X +B X +C X +A Y +B X +A X +A X +A X +A X +A Y +B X +B X +C Y +C Y +B Y +B X +A X +C Y +A X +C Z +C X +A X +B Z +A X +A Z +C X +B Y +A X +A Y +A X +B X +A Y +C X +C Y +B X +B X +B Y +B Y +C X +B Y +B Y +B X +C X +C X +A X +A X +A Y +A X +A Y +B X +A X +B Y +B X +A X +A X +A Y +B X +B X +A X +B X +C Y +A Y +B Y +C Y +B Y +A X +B Y +B X +B Z +A Y +A Y +C Y +B X +A X +A X +B Y +A X +A X +B X +A X +A X +A X +B X +B X +B Y +A X +C X +A X +B X +A X +A X +A Y +B X +B X +B X +C X +B Y +C Z +A X +C X +A X +B X +A X +A Y +B Y +A Z +A X +C X +A Y +A X +A X +A X +A X +A Y +A X +C X +A X +C Y +B X +A X +A X +A X +A X +A X +C X +A X +B X +B Y +B Y +B X +C Z +C X +B X +C Y +A X +A X +A X +A X +A X +C X +A X +B X +C X +C X +A X +A X +B X +A X +A X +A X +B X +A X +C X +A X +A Y +A X +B Y +A X +B X +A Y +C X +B X +C Y +C Y +B X +A X +B X +C X +A X +C X +A X +C X +B X +B X +C X +C X +B X +B X +C Y +B X +A X +B X +B X +B Y +A Y +B X +A X +C Y +A Y +C Y +A X +B Y +A X +A X +A X +B Y +B X +A Y +A X +A X +A Y +B X +B Y +A Y +B X +C X +C Z +B X +A Y +A X +C X +A X +C X +B Z +C X +A Y +A X +C X +B Y +A Z +B Y +A X +A X +A Y +C X +A Z +A X +B Y +A X +B X +A Y +A Y +A X +A X +A X +C Y +B X +A X +B X +B Y +B Y +A X +A X +A Y +A X +C X +B X +C X +B X +B X +C Y +A Y +B X +A X +A X +A X +C X +C X +A X +B X +A X +A X +A Z +A X +C X +B X +A X +C Y +A Y +C Y +B Y +B Y +B Z +A X +C X +A X +B Y +B Y +A X +B Y +A X +B Y +B X +B X +C X +B Y +B X +A X +A Y +B X +A X +B Z +A Y +B X +B X +A Y +C Y +B X +B Y +A X +B X +A Y +A Y +B X +B Y +B X +A X +C X +A X +A X +A X +B Y +A Y +B X +C X +C Z +A X +B Y +A Y +A X +B X +A X +A Y +A X +A Y +A X +A X +A X +C X +A Y +C Y +A X +A X +C Z +B X +A Y +B X +B X +B X +B X +B X +A X +A X +B X +B Y +A X +C Y +C X +A X +A X +A X +A X +A X +A X +A X +A Y +B Y +A X +A X +A Z +C Y +C Y +B X +C Z +A X +A X +A X +B Z +B Y +A X +A X +A X +B X +A X +C X +C X +C X +B X +A X +A X +C Z +B Z +C Y +A X +A X +A X +C Z +A X +A X +C X +C X +A X +C Y +A X +A Y +A X +A X +A Z +C X +C X +A Y +B X +B X +A Y +A X +B X +C Y +A X +A Y +B Z +A X +C Y +A X +B Y +A X +A Y +A X +C Z +A X +B X +A X +B Y +A X +A X +A X +A X +A X +B Y +C X +A X +B X +A X +A Y +A Z +A X +A X +B Y +B X +C X +A X +A X +B X +B Y +B Y +A Y +B Z +B Y +A X +A X +A X +A X +B X +C Y +A X +A X +A X +A X +A X +A X +A X +A X +B Y +A X +B X +C X +C X +C X +C X +A X +B Y +A X +B X +B X +A X +A X +C Z +A X +B X +B X +C X +A X +B X +B X +B X +B X +B Y +A X +B X +A Y +A X +A Y +B Y +A X +C Y +B X +A X +A X +A X +A Z +A Y +A X +C X +C X +B X +A X +A X +B X +A X +A Y +C Z +A Y +B X +B Y +A X +C Y +B Z diff --git a/aoc2022/input/day02_provided.txt b/aoc2022/input/day02_provided.txt new file mode 100644 index 0000000..db60e36 --- /dev/null +++ b/aoc2022/input/day02_provided.txt @@ -0,0 +1,3 @@ +A Y +B X +C Z diff --git a/aoc2022/src/day02.rs b/aoc2022/src/day02.rs new file mode 100644 index 0000000..97a24e5 --- /dev/null +++ b/aoc2022/src/day02.rs @@ -0,0 +1,202 @@ +use std::fmt::Write; + +use anyhow::{bail, Context, Result}; + +const INPUT: &str = include_str!("../input/day02.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut score = 0; + for line in input.lines() { + let round: RoundPart1 = line.parse()?; + score += round.score(); + } + + Ok(score) +} + +fn part2(input: &str) -> Result { + let mut score = 0; + for line in input.lines() { + let round: RoundPart2 = line.parse()?; + score += round.score(); + } + + Ok(score) +} + +#[derive(Debug)] +enum Shape { + Rock, + Paper, + Scissors, +} + +impl std::str::FromStr for Shape { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "A" | "X" => Ok(Self::Rock), + "B" | "Y" => Ok(Self::Paper), + "C" | "Z" => Ok(Self::Scissors), + _ => bail!("unsupported shape encoding: {}", s), + } + } +} + +impl Shape { + fn score(&self) -> u64 { + match self { + Self::Rock => 1, + Self::Paper => 2, + Self::Scissors => 3, + } + } +} + +struct RoundPart1 { + opponent_move: Shape, + my_move: Shape, +} + +impl std::str::FromStr for RoundPart1 { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (opponent_move, my_move) = + s.split_once(' ').context("couldn't split round on space")?; + let opponent_move = opponent_move.parse()?; + let my_move = my_move.parse()?; + + Ok(Self { + opponent_move, + my_move, + }) + } +} + +impl RoundPart1 { + fn outcome(&self) -> Outcome { + match (&self.opponent_move, &self.my_move) { + (Shape::Rock, Shape::Rock) => Outcome::Draw, + (Shape::Rock, Shape::Paper) => Outcome::Won, + (Shape::Rock, Shape::Scissors) => Outcome::Lost, + (Shape::Paper, Shape::Rock) => Outcome::Lost, + (Shape::Paper, Shape::Paper) => Outcome::Draw, + (Shape::Paper, Shape::Scissors) => Outcome::Won, + (Shape::Scissors, Shape::Rock) => Outcome::Won, + (Shape::Scissors, Shape::Paper) => Outcome::Lost, + (Shape::Scissors, Shape::Scissors) => Outcome::Draw, + } + } + + fn score(&self) -> u64 { + self.outcome().score() + self.my_move.score() + } +} + +struct RoundPart2 { + opponent_move: Shape, + outcome: Outcome, +} + +impl std::str::FromStr for RoundPart2 { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (opponent_move, outcome) = + s.split_once(' ').context("couldn't split round on space")?; + let opponent_move = opponent_move.parse()?; + let outcome = outcome.parse()?; + + Ok(Self { + opponent_move, + outcome, + }) + } +} + +impl RoundPart2 { + fn shape_to_play(&self) -> Shape { + match (&self.opponent_move, &self.outcome) { + (Shape::Rock, Outcome::Lost) => Shape::Scissors, + (Shape::Rock, Outcome::Draw) => Shape::Rock, + (Shape::Rock, Outcome::Won) => Shape::Paper, + (Shape::Paper, Outcome::Lost) => Shape::Rock, + (Shape::Paper, Outcome::Draw) => Shape::Paper, + (Shape::Paper, Outcome::Won) => Shape::Scissors, + (Shape::Scissors, Outcome::Lost) => Shape::Paper, + (Shape::Scissors, Outcome::Draw) => Shape::Scissors, + (Shape::Scissors, Outcome::Won) => Shape::Rock, + } + } + + fn score(&self) -> u64 { + self.outcome.score() + self.shape_to_play().score() + } +} + +enum Outcome { + Lost, + Draw, + Won, +} + +impl std::str::FromStr for Outcome { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "X" => Ok(Self::Lost), + "Y" => Ok(Self::Draw), + "Z" => Ok(Self::Won), + _ => bail!("unsupported outcome encoding: {}", s), + } + } +} + +impl Outcome { + fn score(&self) -> u64 { + match self { + Self::Lost => 0, + Self::Draw => 3, + Self::Won => 6, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day02_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 15); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 11150); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 12); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 8295); + } +} diff --git a/aoc2022/src/lib.rs b/aoc2022/src/lib.rs index 784a117..c10d8ec 100644 --- a/aoc2022/src/lib.rs +++ b/aoc2022/src/lib.rs @@ -1,3 +1,4 @@ #![warn(clippy::explicit_iter_loop, clippy::redundant_closure_for_method_calls)] pub mod day01; +pub mod day02; diff --git a/aoc2022/src/main.rs b/aoc2022/src/main.rs index 98d4d03..6f39647 100644 --- a/aoc2022/src/main.rs +++ b/aoc2022/src/main.rs @@ -3,9 +3,10 @@ use anyhow::Result; use aoc::DayFunc; use aoc2022::day01; +use aoc2022::day02; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run]; + let days: &[DayFunc] = &[day01::run, day02::run]; aoc::run(days) } From 5e6ffb470e5424a88d3c203eca100734fdb11884 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 16:17:40 +0100 Subject: [PATCH 108/134] 2022: bench day02 --- aoc2022/benches/aoc2022_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2022/benches/aoc2022_bench.rs b/aoc2022/benches/aoc2022_bench.rs index 618c7f5..65817f5 100644 --- a/aoc2022/benches/aoc2022_bench.rs +++ b/aoc2022/benches/aoc2022_bench.rs @@ -1,9 +1,11 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2022::day01; +use aoc2022::day02; fn aoc2022_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); + c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); } criterion_group! { From aa6fb34f4401d354300232311881700bf9ea72ad Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 17:56:14 +0100 Subject: [PATCH 109/134] 2022: day03 --- aoc2022/input/day03.txt | 300 +++++++++++++++++++++++++++++++ aoc2022/input/day03_provided.txt | 6 + aoc2022/src/day03.rs | 164 +++++++++++++++++ aoc2022/src/lib.rs | 1 + aoc2022/src/main.rs | 3 +- 5 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 aoc2022/input/day03.txt create mode 100644 aoc2022/input/day03_provided.txt create mode 100644 aoc2022/src/day03.rs diff --git a/aoc2022/input/day03.txt b/aoc2022/input/day03.txt new file mode 100644 index 0000000..a29ec79 --- /dev/null +++ b/aoc2022/input/day03.txt @@ -0,0 +1,300 @@ +vvMQnwwvrwWNfrtZJfppmSfJSmSg +BzGqjlBqBBmztHNFzDHg +llRCPlTPPqBjPhqhlBRBClhqWcTWrWNcMbQbdrdLccccrnvM +wMhwbTWpQjbpWHMQppzTHhjtlCjPSSJCCtlqRlJVFJFt +ggdvvnvDgdDmNcBrrcDntFRFqHJJtSJqvlVSRlJq +fggNNffGmcBrmBfcDzzzpHbsGTpszwwTbp +BPdPPBggrPtrpbtvPBBdgrFmhhQThGGlbbTZnzZQzZfn +ccjWRJVNcTGmnWWFmh +DMNmsMHwRNBrggdPDPdt +TfsfHLQbBtBFQbQsBmPwwlnPGZFwwdwWFZZw +MRpcvJMJVSMrVMpVSvhhnclwgWwDZgWgWgWglwcG +GCzjRJjVjSSrvfNQtLmQNsQbjB +FrSPFjtVvwsqSwcG +hDHdWDngpgZTDgHzzHwNNqlwNvZJlGqcQGsl +wDzLTDHgFffLtRft +CnCJNVqvCBJBNZmfPcPMcFLVcwmd +HgzjHFghSFtrLfwPchPM +QDpjgDSQlHHlDQQRzRzsBRRvWnWvJvZnqWBJNF +mGHcFPFqzPtcfPwDGVVpgLgSlgBl +rCvddTrnsbDLVSDwjSjd +QWhWQThswssMQMMMvhTzPqJzmzftHccJfHFhFm +cPbNpLVFTPbbFrpTLQBzqqmgnnBhgLMM +vvSwWCZCRZCDZtGwzdgWdQmzqgnQddJn +vCltGltCGmRRmCvDjjtHFpbcFfbbfssbpNPpHFpH +WLLQMWZLSPMPWmrwhnjhZZhpHJHljBDB +csbtCfFgCftGljHwHcBnpnJR +tsvgszNtfMwPzWqPrS +NbDZrbrFQQqqQtQqQDtTcBvCLBLswsZhscCGBZ +ljmWRzVRpbndMWmmfdsTsCBsGwTVVVCGCGws +ffRpnllHRMfdWzdnmRNQNNSFQQFNbrFHHrNH +LccGzWNjcvNLGTmHNsNLMlMwMpMPGlMCwFwDDGCw +fZZtfrZgrfQSnnnSnJRCglHpCwwHwpglDClFMw +SqJQnffJRnfQQVRhrQtrhnThcLhzNzHdTjhsTWzjdmcm +QJQwJMSbtbRgMQMQVZpCZsrrhpZBwrLLvs +qCNPGWdqhpphsWrB +DcNPNnqjdGDqjmPGGJRFMQmgtlQmQJCSgb +blTRbDnHRGGBwnGPCtFPWzVCDvFWtL +pdSJprqhhZSdqSdZNhVzZWtzLVgVPvzjLzWv +rrsqsmrMpPHlwTsRHn +mbNhgbRSLmTwswFm +vHjHBWMHBzMqWZVZBzHzcwwwdcFLcpLspdzwpwQd +HfMWMfvjWtZHqWDlhSnnnJNnbhslDb +lwsvPPnqlwwwsPcHTgqcRcSccmgQ +CVWBWCFpFzWfFjWjhNSQJJmcVcHRZJNTSc +zdhfzBtfLLtfFClbrDvsPvtPbnmv +PntVQbDnQHcDVvhtbtDhcbPcFTrrNfjqmmPTTZqMLZZMjFZm +lgJCpCFCSCGCpllWMfZqTNNZrMjrJTTM +CSzSwgFlzsGBzQcQhsnnDbVdtc +THzqvrVrWzhqhWwqhTbNNDRtFRmmpFDDVsFLLsdddF +MbZSSScZSGCJCjZlCjdPmpRmFLDtctdmFRsp +GfJQlnZjSMnllbJCQbClnZQrhNwwqhBzTNhrffqhqWhTqz +BdBdmDZHFFbrHHStPSRtPCzSRNDS +JGGpwqLJGMTLpLlMpqLhJtzCCSGQSPzNNczVVPVzSV +WwpllfslqfhffLwhfJpJlqlwdBmZnrdFHBFBBmNHFsFmdZmn +jZfQZnZfnbRfjCnfbSSmVpqmNmVpCqlhCqqPpP +MdJMwMvvLDssLtFMsMtLDsvvDRmmmPhWzWzphpmqDVzPDWNp +TsLdMrvRtLJtGdtGRRtFTBjSBrScnSZjnbcgQgHfnB +RZfmlRlWJmWLLRscrslJqvvMdVwmddvPddQPVDdDwz +GStFbFCbntbjNnjFhFvdHfhzHfzzQdMHwPdD +BSGpFbbjbNjnNNFSbRsLlWqgrZrfRgsBlg +ztHczmrmcNNzHsPSTwsPHSQPQT +CFCRjlvbClCjBdPDFQdwBsqn +llbRgjClJCVVMMCssfmNZWszrNgzGL +mmFldllVlmtdWFvPPFBcSSBW +DZzZGzZswQZHwQZjZzWWTSSvjSdvPvvWjJTS +DpQQggwzZGdmbCldgVgf +PJJvhqzVGbTFqzqbbGTlLmrtrZMnnZnntlJnrD +fNwRcQBCRNddNgLtgDnttqrMMtlr +RfRdNWQHcqHscdfRdGPFbFPpvpVWWzPzVS +DRgjZRRDggTfjfRvwWzHGGHPWDswvv +dhbmpcCmchgCpsGzWPdVGvWHwP +hpMMMpCQMnChFgNRQffTRrSN +gfqPCHWtPMMjCtffgjQWGLvGdZcdLLGZcLFGZBWG +pJTDsnnnvBjnFwvj +zJRpTbNrTSppRVblgbljMgMfCfbC +fGrGwqggtbVmtzbf +CTMjNQcJjJTBNCjMNZFNBcCZHbmWZHVLZDDWVtDzzbVmlV +hMvTcNMFMhQjTTBFBNMhwpspwgnGtvtnSgdwrRpG +RfFdqPdMMGPVgWmNVN +QwrTsbnSsSQpwlSSbNNWDmGLVjjmLWwNVB +rpcclTCprmZQSbprSTpRRRfqMfHHCHfhMhvFJM +LnJJsMtLbzsPPVPJbrTBlTWlfRfqnTrrlr +VDHVQNFGgNTrSjSBjq +CHFHGmvDGdZZGCQZVDgDHVbwLLwtMwwmJLJbLPPMbczt +qNNNBllFBzFjjzwGqGgLrWgrtQjdmmtQmQpp +ZMHJCPhMZRsRCsCPsSJZLmQdQgrtQwQwQZwdWg +CnMPbbRbsPhCnbfhMPRPllnFGqwTTFzTzNvBGBGc +wZWlBFZQgBzTzpZwBlVpzWBWnNMmnMvMcMJMmLGnVmqLqGMq +PdSDfJbCHsHHdJjsRRhjjPjmLqnnrLMLcrnLvdLMNccvGn +tSJtSCtbJhDhtzlFQZlTZTFp +TNqZDqmMDZNMFSGHjSGBRBdN +CrrwVwsPjjBHddPf +rpWggQVspQWcgtLwcHZZzDDMLDvvnnMzDM +lWrWmPwmGlZwZjdLZLzV +cFcDJhJnmqBqDCRpZzVLNsFLjLzdds +qJchTDCBHDWglmrfWPHH +RgLRnTJWnfHDcQQBfg +bZpNwdwbdMvVPsHHJMQfSSfP +mVbdNNdrbCzZbdZvbWTGrhqjTJtRWttRjq +TMtqqBJLrwqrZPlHHGhGnlBhzv +bFgNcpDRnpgggjCzvWDWhQhQWQHHvz +jnnVgjcgcTZMJqJVtT +dVSjmdHrfGPddrQgstFgzsQfsMFQ +hvJJCCJDcCtwBVFQzzBD +RWCnTvWTLRnJJLJllWhTLSprVdNZVGHGNGGnrdGSZH +gvMSHFZtBBMBMFZHzjnqLsLGMCzRWWMn +QJmDrhbNDbJfPQhDmQPRLszRlnjCzzWqrRnlsL +PcJVhJbJJNcNDmfDmjJmbhTfBvpwVSdggtgvgSFZwgvtgpdZ +PBClRHHClRlFljllZSBBBllppVGDLpZVVVsGpmGcNDpGLL +MvNwnbMwccVsswDG +MqnNbzMMrQfnqtttqfQWQQnRdCSHgHPglRFBRWlHjWRlCW +lldwdfSBWphHBggZghFs +DjDbDVRzDmLRzRLGJjPssrLZPhdshFHrssTZ +mvddMzvmmDDvvwQqWftCfqWqfM +gpTTwNWGWMSMgJjnvpvvJbJppn +lQvmLFdfrQzRFctlrLdRLVPnhPPbVDPDfjnVbfhJjV +FLFqccvmmtcQtrmQccRFLlRLSSWBSgTWNwsggqMBsqWGHMNG +PjPtVQrPVjrVPLLDQVFLTTWWqbSZwRwzqwSbSbbbwFSq +lBnGJBnfflRRNZwbqb +HJMGgmfpRMHGGdgncJHLDjjtVDQctLCvQCjTtr +VvmvjRGwRwvhmhRvvvVCCTTJjfWqfDMMcJlcCD +NpNbPfpSnngZbbLMFJWTMlLFqJJDMD +bNSfdSHQZgVQzwhhvRmQ +MhmHcDhChhcPVMDPDPQdFhQHnbNpZbZnprnrmNnjNbsllbnp +WWqGCWSCzsGbbGNgjN +LzwqBLSvwJCLPVMVDLdhMP +mNVLLffSLVWdZCcFZCZrSbGr +glvcwszTlsRDrHQCZFCvGH +gTBRlJnwhzgTgsTnggslsJRTpLNmjmNNcdVLdhfpLpdLVmLc +pCgfDrDrgccfppmDnhHMGqGbpHHSqzGLlqHS +tFtjQRPFFZRVNRcQGbLzLFMSGzSbWLqH +QRNTZjvjTTwtwNfmcTgfnCgnnBhm +hcPBhqPzqWPccHWHHWqnPdssPVfFFmZDnVDDms +NSLNCTRQZndRmDfnRD +QSGTGbjTSTJHBlbZZBbh +dgcWgVgWdvZSbbRtjLRZZZ +MMDPPfTnPTQrFDMpHzmmLztLnsszRtwbtS +rDfDqfHTpCSJqlCCGq +bjsgllstBbpNpslBpdBgqljgGwzJzDzwLGGrwLQQdJDwGhQh +nncmnmHHnmWRWmPfJCnvPRMrzvDhZZLGQwhDLhhMzZZZ +mffccVHRRPTTNlpNbNjJVslJ +DgPstgPtgPNNcjQQrtPJJCRSZTwSGJZZCZCJGD +dHVvpzdBBhVqzWqvhvHdzGSZlTRCSRJrwSSCwJCWGT +zpvVVqMBrzqrhFBvjbNPcPLnjcQtMcnj +gBcmTCFghhCCBnBhWWwFbwLdwHFMLMdp +LVzlZzPPMMzWWrwH +ljqjsGlZPPqqlVsPqDVqjQQctNTnRcNLtCNmmnRTRthBGG +LPRrrBNNjLBRJNdrGPRBfBrLwFqmDbdbTbTgmmgwmttFwtmH +QQcVvnQphlWsCQCCVpnvptTJgbtqwHDwbJtJHFsTHw +ppcJVQvpvMVMCvQZQVVZCCSRZPSjNRRZBPPPPzLjSLGf +MLtRnjQsRMJcDQJnSrsfqVVvGwbbbqgggg +WBFCNlFFFhFBlCHbplFWdpWZfVqPPwqTGdqTGvwrPVvTqvTr +HClCHzFzFBhmnjtQzMMSMnbD +sVnMCsdlMRcMFBGz +JvwwgrJDfgDmmggQrhNfhQQftjFrGRRtZFGBRZFHzjGcjrcj +PBJJvgDPNllPddVCPl +fmmRSnfnMnFSmMmmzTDSBFHtlJJqHJJqdHQdTCdtCCdt +WggGpNVVgWdwwHQtlGlC +hjbWppbLbLZLjVPPjPLSRRMvDlmSzDzBSnBFZf +nVttMPnPLjnJLjcnPVCjJJLcssfggBNlffgcNsWTcGcgNsBF +HQbwhmDrRrgFsWlQGNls +pZdbGzGrGpVttPLttv +LLbMrMHLDdWhmgbqqt +jGSQZQTpQGVVRSlQMQRljZmgmJBSvggvBWhJmJWvddmt +VjlQFGMVrFFrDrPw +DZVDwGZlJlVlwZVDzNdqfjMDnjqzNnWf +pmtpLRQFhSFpmpRgRtHNFznNdqWBjzWfnBjMWf +rHRrhStppHdJcGJrrssCsV +pgQqHwgPcPCddCjdWtdp +VfZGVFfNVhZhzjjjLz +fNNBBnGVNfBfRSRjBRQHJQTwJcJTgHPwTngr +MZdlzWzthMgrwmGmqZNqNs +VvJQJPVDBJQThwwNsRqsvRsHHm +BDQQPTnDDBQQBVfTBQPdFctzzdtztMMtnhcWcd +LjWjDShflZRRcZzfHH +srNwQPBsrVRhNmRGHzmM +rBdgQTrhdPndQTrsQQsrPwnTpLLCWDpSCLtCnvtSWpJjDCvl +gSlvDwCvcmcTQTFtRMjWHFVVHwtj +rbsphZZzBshGZssMffTVRFfFpWpfTH +GZNhZBhPBzTPNLDcDlCDCJNmlg +smZjGfvjbWWffQtf +dwRrdlVdDdgDbNtgcgQSNStQ +FdFVwdblFlzVrlwrTlndZHHZGhmLhhssjHhMjnjq +QFvQVFLLgVrFLBVgGhTtllPvmHRRGbTm +hDCCNCNCJNzWDZnqJDzSNCTnbRttHGRnccbPRtmmlmHc +qJshNMCNdVFVfsLB +FcLZZPFjdZcZMPcRjcRTgbpJlwbbTlmdTlGlwD +nrrNrHWBNSWvBqvvrhBqzStrgGnnmbwsbbJbwwJnmwmgJTlD +BCrrNvqWvSQPcCGZZRQQ +vPwcJblJzJbJcJFcwBSvJNdWRLtdsddGWWddWRWsMF +mDZmmDZDHVhfmjZgjVDfhTZHtsNptRsMntnWdsMnGtRntG +mhQrQDDhgqTTNfhmVQVBrPlBczSJbbCbCCPPvb +ZjbjLlbZjGqsgJTfHggrVvlB +tFDRFRnMFnnWtDdMdDRhzHfTJhJhffHvHTBHTgcfJV +nztDtdWzCCMSptSdFRRswZjsLbjwZmwqwGqpQV +vnvmmVnmVbrBJlzgWQWVNFzNHV +MwSjZhSwPjMwfDRzgWlNpWvHlgNNNP +CfSZjSfftwZDChDRSnccnrvBbbGrtBvctr +LCBRQRBQwRrCVLVWSrCSwCptzvhthvGGhdHzwppTTddv +mFnJJmnmFFFfPLNNmqqNJDpGnGtbHTtHvhnHbzvHvpGv +lMMPLqDmNMVSjjgMCS +zzPzbLjHLjfQPQHwwjddFNsNSJjDMsdNMFsC +BqqtmgDhcqdSFCdsqddF +GtcmrvhgcZlvZtBhtVgrvrvtnWzDnQbfnwlfWWRHWbbwzHRL +JfWHWZcMMdDLMPjRnCJjRbFgnblF +ShtBTSmBhTtqtfmqSTNvmjVjnFbFnnlrlqgCnrFnVg +vfzTTthppmdzPLHLWdGZ +tdvrvGgGTSScnHcjcg +zLLVfzPPcDZnPjSPpD +LfffNFLNlNbJwrctthWqNdNq +NdjJtfVNZnnFFdtfGfFNcvpbMDbzdcTbbzpvmcDR +PHMSHCHHWrRCvzDzDChT +BqPWSHwllSQWrLHQHPqlBBNfttZMjFQfjGtZtNjJJjnN +CpZtMCMQQpCVWjMDVjPVQsWWqJJhbTcddPlfhTRqchcJblhh +NwDSGNmGRccqNJfT +SBSSmgrrgGHnvSzwGVWDCzMCpLZtMsstLM +sbjHQsBlBQrrGjQjBqCRSnSCpnfngLnFhJngFfSP +zHVctHDcZtdJffnPpcSpFn +ZdwNMztdvzVdrqblvWsqHvBR +jPdjFPSbVDMMbqZzQWzQ +hFRrJlpprGhtlJGQzmCRmZBWQCHRQR +vThNplJpNhltNNlvcGDvwVFgnPwvSgPSSfjS +DhDTPQpTDmQbDQrrrWtWPJNNrrsJ +qqGjgwCgVRjMSRwMMGRGqjwvsNJJBZtrstvNBvHWHJvL +VqqgfjzfgfFGVjRggCGznhlbTpQchcshpdFlnDbn +DpTQTBbCZQVJQZJjrFllGdlvMPlMLqGBGvLl +hmnWHWWNzzmHsmWRlGGpdLgLHGlqvgqg +RzcWRhRnRnfmswfwtzzRWrDTrrFCQTCpQpcCrjjQCp +HLvpHvGcBTDFznvfqT +hCPQbPZPbjSbwwjCPChSClJJfzqTggTFDfsJngDg +StqmmZbdqrQmhQrrhZWcRcGBpBHWVcLctMWp +dNnRNbRdbRJMBMBVVThn +rNrsLNscFsCDjpwTMgBGWMGjJjWBVJ +wNcLpqHNsCprsfLFsHwRvPSSPRZRtRQSqtQPmP +PPhGfbthhBDVsTDtDqRR +mCmSNmqpcqjjrCScWRsZDpHsDQRZQDZDss +CcWzNmccrjjvqBGzzdPGnv +SDRmCSFfcSFFcfDmDBFSCfdVJhpzZjNJTNzRTvjzjhzNjTtZ +ngGsltrMWrblNpNTJJplJN +PGGnGsWngrGLQHHtHHHgWsHSBLqqfLcqBdVdcCDDBFdCDm +VPjGwhwVPhrnqhzJmQvQTQvmzBzw +ZBDBRbLLdtfRLlddLlCLCZMgmFJQFDcvzMQmgMzzJJFJ +LHLWltHlRZCtBVhVVHPjGSpphp +JqhlhdnnmfRVVSpzWLjzVLGpvB +stQtFTTrsZQPFQNNDtQgLzzSLvjvLGLBGSZGGWJv +DDDFFgDPbTwbTTJMCMcbCqqmmRRCnb +JbDWPDPPJJDMDjHPZHGbHGVZTBhrzBpdzszdTTphdNdWdrpv +RmRRqllqffwFtqwLCsqTNvpCsqCNqvdN +fmfLmStlnnfnRtfcnQbbjPjPPggZGVsMQMbb +WJggvGDJSwWgSfgvfSMGqqQHBcPjcHChcQBCssDHCTTQ +mlRnbrnbnltblwdnnpbLRdCCjCTHTjPTTsQcTrHHhCcj +bFLbdmzRpvSwfFFNWN +BHnDnQHnHMWLwzWPzD +dmlZCrdqLZzZVZJM +tRRtdlLCjLmqCRsrSLrvvRQNFQnbgRTQQNHTBbGQQh +ZrQPQWCrJnPdQSNTmBJNTHGHJN +zhFRfswjwhhsFttfsfvQftRtLTzmBTHGTBmzMLHHLmGHNTTS +hQhwqVjQwsdggrZZCWVl +VjfnQgVQjblChfjVJlbzLtrSLlTGtztHTtsTGH +DDqWQDQMWmDwWNwcqdWvpSrtLpLsptMprMStstMz +vQcddRdRvWcwWRmmmmddZmmfVnnngJJbZnCBnBhhFbhCgJ +gVgDnnmJdQVdJJgtgDjBsBhsBSPRSRRSSwccSbSqwPcCPcSC +HrQHlHFpQfTHzzWzwScPPCRfLbPSfCSR +TTQlZNTzlZNMWvrZMlpnhnVtnDDnVNtVJnjmhg +MCmmssFnZJcNNszfpvvrpvJzvwpp +BRRRWQWbSRGGRTTtZHWSqTrvDfgfdfrrwrDgfbvfzfrd +jRBhWRWTSRttQBZMNchNCsmFMchP +GBDncllqcSlNFZWBFWPjHVbw +LQphJlJzLCwPjHbpHZvV +hzCMJLMzTsrdrszQCCCTCQCDlqqnNmggqfGmgdmGgcmSNt +hFVVbqJsqhcnBRTRGBTh +lwdDpmzdNznzZBgGRRjR +HdmvNvSCmDmwNDFrMJMqJFCRfsbq +ctnbTcFTnbwSSfrrMLRhpJLMRdpwdJJR +vdGCVBmGVHPLBRWhpRLJJZ +VmQPHqvsPdlQsVHDftnlFTbffnbttfTF +LBJZHrhLThHddcMLVtcMcL +CPMNFDDMpGqFjjSPDPDqdvmdtQgVQQcQWcQgQQsj +DzFDFMRSFPSGTJJTJBwwRhBw +dpldqlqlRppFTHpbjbnLRLVnnGfjtG +NNJTcmhzvJQNgMJBwcGtjtGbttfhtsGGnhnt +rzcwmgvcvrBNvvmMgvcBzwHPCTWWprqPHqTFWdPCWDTF +BNllDRTNqDNvNDDLBcDvBCLVJrVdJdtrnrCHggtrdd +mppFMFjpMFZQZQGjFCdgrCrCdrvVGtJJCC +PZsQmfPphvPjSsjmPjfZllBwcNRDNcDqNNWbTclS +fjqZBSDSDwwsQwCDND +rrdMdjVWtTTPslsslFLTLCsJ +rvPWbvcmHjmdPbHvrvBHgqRRgqHGgfZGfHRS +ggTQgsgwFrTrggbMTvSdmjfCmmQDcmqjDjmc +nLZnRhNZnnNHZhZVStCcDqjcqmjSjH +RWGNnhzBnJJRRWNRBNZNLZhFMTFPvrTrTlsggPwSlFMWTw +RNmnPRnLGcQmzBQpHHjTltjtlfgspbsq +CZvCJwZMMCCMdFVcwJJsgTTHfsTlbfbgbT +SSVFhWCZdSCcWCcWdrvhzmnnnLNGDRDNzzLNGz +jPwfPwNfFpFNQpDjdMcjcrdddDHD +tzsRsGRLzhLhvqvhHMlqqV +LRBnRBGSnBSGsGSGmGtBJCmnNWZpPpTNPMwQMPNJFZTTNwWT +PCrStRPSPvZQcZPvqvfjSRWFFNFJFLZTTJTTVZFFGLFF +DlpBzBntHDzhlpGJVHLwTMFLVLTL +gptBBdgzpsBbpQvvPQPRqrdcCC diff --git a/aoc2022/input/day03_provided.txt b/aoc2022/input/day03_provided.txt new file mode 100644 index 0000000..f17e726 --- /dev/null +++ b/aoc2022/input/day03_provided.txt @@ -0,0 +1,6 @@ +vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw diff --git a/aoc2022/src/day03.rs b/aoc2022/src/day03.rs new file mode 100644 index 0000000..1270cfa --- /dev/null +++ b/aoc2022/src/day03.rs @@ -0,0 +1,164 @@ +use std::{collections::BTreeSet, fmt::Write, str::FromStr}; + +use anyhow::{bail, Context, Result}; + +const INPUT: &str = include_str!("../input/day03.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut priorities = 0; + for line in input.lines() { + let rucksack = RucksackSplit::from_str(line)?; + let item = rucksack + .find_duplicate() + .context("rucksack didn't have any duplicate!")?; + priorities += item.priority(); + } + + Ok(priorities) +} + +fn part2(input: &str) -> Result { + let mut priorities = 0; + let mut lines = input.lines(); + while let (Some(first), Some(second), Some(third)) = (lines.next(), lines.next(), lines.next()) + { + let first = Rucksack::from_str(first)?; + let second = Rucksack::from_str(second)?; + let third = Rucksack::from_str(third)?; + + let priority = first + .items + .intersection(&second.items) + .copied() + .collect::>() + .intersection(&third.items) + .next() + .context("the three elves didn't have any item in common!")? + .priority(); + + priorities += priority; + } + + Ok(priorities) +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +struct Item(u8); + +impl TryFrom for Item { + type Error = anyhow::Error; + + fn try_from(value: u8) -> Result { + match value { + b'A'..=b'Z' | b'a'..=b'z' => Ok(Self(value)), + _ => bail!("unsupported item kind: `{}'", value), + } + } +} + +impl Item { + fn priority(self) -> u64 { + match self.0 { + b'A'..=b'Z' => (self.0 - b'A' + 27).into(), + b'a'..=b'z' => (self.0 - b'a' + 1).into(), + _ => unreachable!("shouldn't happen if Item is constructed from TryFrom"), + } + } +} + +struct RucksackSplit { + first_half: BTreeSet, + second_half: BTreeSet, +} + +impl std::str::FromStr for RucksackSplit { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + if s.len() % 2 != 0 { + bail!( + "rucksack should contain an even number of items, this one contained {}", + s.len() + ); + } + + let half = s.len() / 2; + let mut bytes = s.bytes(); + let first_half = (&mut bytes) + .take(half) + .map(Item::try_from) + .collect::>()?; + + let second_half = (&mut bytes) + .take(half) + .map(Item::try_from) + .collect::>()?; + + debug_assert!(bytes.count() == 0, "something went terribly wrong!"); + + Ok(Self { + first_half, + second_half, + }) + } +} + +impl RucksackSplit { + fn find_duplicate(&self) -> Option { + self.first_half + .intersection(&self.second_half) + .next() + .copied() + } +} + +struct Rucksack { + items: BTreeSet, +} + +impl std::str::FromStr for Rucksack { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut bytes = s.bytes(); + let items = (&mut bytes).map(Item::try_from).collect::>()?; + + Ok(Self { items }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day03_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 157); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 8018); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 70); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2518); + } +} diff --git a/aoc2022/src/lib.rs b/aoc2022/src/lib.rs index c10d8ec..eef213c 100644 --- a/aoc2022/src/lib.rs +++ b/aoc2022/src/lib.rs @@ -2,3 +2,4 @@ pub mod day01; pub mod day02; +pub mod day03; diff --git a/aoc2022/src/main.rs b/aoc2022/src/main.rs index 6f39647..fefc61d 100644 --- a/aoc2022/src/main.rs +++ b/aoc2022/src/main.rs @@ -4,9 +4,10 @@ use aoc::DayFunc; use aoc2022::day01; use aoc2022::day02; +use aoc2022::day03; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run]; aoc::run(days) } From 175318322e77b54dad6aa1e28080286e97bcf8c9 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 6 Dec 2022 18:36:59 +0100 Subject: [PATCH 110/134] 2022: bench day03 --- aoc2022/benches/aoc2022_bench.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aoc2022/benches/aoc2022_bench.rs b/aoc2022/benches/aoc2022_bench.rs index 65817f5..9daac04 100644 --- a/aoc2022/benches/aoc2022_bench.rs +++ b/aoc2022/benches/aoc2022_bench.rs @@ -2,10 +2,12 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2022::day01; use aoc2022::day02; +use aoc2022::day03; fn aoc2022_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); + c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); } criterion_group! { From 516fed49be72301e847591d56325141f377e653e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 2 Dec 2023 13:56:56 +0100 Subject: [PATCH 111/134] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-utils': 'github:numtide/flake-utils/5aed5285a952e0b949eb3ba02c12fa4fcfef535f' (2022-11-02) → 'github:numtide/flake-utils/ff7b65b44d01cf9ba6a71320833626af21126384' (2023-09-12) • Added input 'flake-utils/systems': 'github:nix-systems/default/da67096a3b9bf56a91d16901293e51ba5b49a27e' (2023-04-09) • Updated input 'rust-overlay': 'github:oxalica/rust-overlay/18823e511bc85ed27bfabe33cccecb389f9aa92d' (2022-12-05) → 'github:oxalica/rust-overlay/47fe4578cb64a365f400e682a70e054657c42fa5' (2023-12-02) • Updated input 'rust-overlay/flake-utils': 'github:numtide/flake-utils/c0e246b9b83f637f4681389ecabcb2681b4f3af0' (2022-08-07) → 'github:numtide/flake-utils/cfacdce06f30d2b68473a46042957675eebb3401' (2023-04-11) • Added input 'rust-overlay/flake-utils/systems': 'github:nix-systems/default/da67096a3b9bf56a91d16901293e51ba5b49a27e' (2023-04-09) • Updated input 'rust-overlay/nixpkgs': 'github:NixOS/nixpkgs/14ccaaedd95a488dd7ae142757884d8e125b3363' (2022-10-09) → 'github:NixOS/nixpkgs/96ba1c52e54e74c3197f4d43026b3f3d92e83ff9' (2023-04-13) --- flake.lock | 68 +++++++++++++++++++++++++++++++++++++++++------------- flake.nix | 2 +- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/flake.lock b/flake.lock index 2affeb8..9e3cf68 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,15 @@ { "nodes": { "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -16,12 +19,15 @@ } }, "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", "owner": "numtide", "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", "type": "github" }, "original": { @@ -32,27 +38,27 @@ }, "nixpkgs": { "locked": { - "lastModified": 1669834992, - "narHash": "sha256-YnhZGHgb4C3Q7DSGisO/stc50jFb9F/MzHeKS4giotg=", + "lastModified": 1701389149, + "narHash": "sha256-rU1suTIEd5DGCaAXKW6yHoCfR1mnYjOXQFOaH7M23js=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "596a8e828c5dfa504f91918d0fa4152db3ab5502", + "rev": "5de0b32be6e85dc1a9404c75131316e4ffbc634c", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-22.11", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1665296151, - "narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=", + "lastModified": 1681358109, + "narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "14ccaaedd95a488dd7ae142757884d8e125b3363", + "rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9", "type": "github" }, "original": { @@ -75,11 +81,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1670207212, - "narHash": "sha256-uuKbbv0L+QoXiqO7METP9BihY0F7hJqGdKn7xDVfyFw=", + "lastModified": 1701483183, + "narHash": "sha256-MDH3oUajqTaYClCiq1QK7jWVMtMFDJWxVBCFAnkt6J4=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "18823e511bc85ed27bfabe33cccecb389f9aa92d", + "rev": "47fe4578cb64a365f400e682a70e054657c42fa5", "type": "github" }, "original": { @@ -87,6 +93,36 @@ "repo": "rust-overlay", "type": "github" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index cd0a5af..953bff2 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; rust-overlay.url = "github:oxalica/rust-overlay"; flake-utils.url = "github:numtide/flake-utils"; }; From 0df2dd8dd801d01e01009abd57a583457a928f00 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 2 Dec 2023 14:24:43 +0100 Subject: [PATCH 112/134] 2023: day01: part 1 --- Cargo.lock | 9 + Cargo.toml | 4 +- aoc2023/Cargo.toml | 21 + aoc2023/input/day01.txt | 1000 ++++++++++++++++++++++++++++++ aoc2023/input/day01_provided.txt | 4 + aoc2023/src/day01.rs | 50 ++ aoc2023/src/lib.rs | 1 + aoc2023/src/main.rs | 11 + 8 files changed, 1099 insertions(+), 1 deletion(-) create mode 100644 aoc2023/Cargo.toml create mode 100644 aoc2023/input/day01.txt create mode 100644 aoc2023/input/day01_provided.txt create mode 100644 aoc2023/src/day01.rs create mode 100644 aoc2023/src/lib.rs create mode 100644 aoc2023/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 2423e93..38c1399 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,6 +115,15 @@ dependencies = [ "criterion 0.4.0", ] +[[package]] +name = "aoc2023" +version = "0.1.0" +dependencies = [ + "anyhow", + "aoc", + "criterion 0.4.0", +] + [[package]] name = "atty" version = "0.2.14" diff --git a/Cargo.toml b/Cargo.toml index a228d23..2896c26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,9 @@ [workspace] members = ["aoc20*", "aoc20*/aoc20*_bench"] -default-members = ["aoc2022"] +default-members = ["aoc2023"] + +resolver = "2" [profile.release] debug = true diff --git a/aoc2023/Cargo.toml b/aoc2023/Cargo.toml new file mode 100644 index 0000000..30be3b6 --- /dev/null +++ b/aoc2023/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "aoc2023" +version = "0.1.0" +authors = ["Antoine Martin "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../aoc" } +anyhow = "1.0" + +[dev-dependencies] +criterion = { version = "0.4", default-features = false, features = [ "rayon" ] } + +[lib] +path = "src/lib.rs" + +[[bin]] +name = "aoc2023" +path = "src/main.rs" diff --git a/aoc2023/input/day01.txt b/aoc2023/input/day01.txt new file mode 100644 index 0000000..25b1572 --- /dev/null +++ b/aoc2023/input/day01.txt @@ -0,0 +1,1000 @@ +zlmlk1 +vqjvxtc79mvdnktdsxcqc1sevenone +vsskdclbtmjmvrseven6 +8jkfncbeight7seven8 +six8dbfrsxp +2zpcbjdxcjfone68six +zqmzgfivethreefdnlhpeight8798 +fivenineone6 +6sixzvdsprdqlftwonine +lqztrmztwo8dg +four6onerv2pfhm +plvzrs5 +5282gdnc918 +pskjsrchjpxoneonenine96fivefour +fivefour2hhtprpjndm4 +6qbdcfdjsd1lmldklflteight +gctgdhpkkjninekj65rkqg8 +eight6gcjlsmzt5 +5chvmhmfgl7xkjfdpdbp +5tpzpnrgpftrnine +threeonehqbzktq1 +685fivetwofour4lvgxgdb +9jdxljkfqttstqxdzdsztsxrfjbkqmmsqzseven +twostcllbpndtwo15seven +8fivetwofivetjfvsxzs5kdkpxgxvsfhr7 +sevenlvrc2fivefivesixqkzdkrfour +45jjpmnscmmk +lhxgbfjtcknpvz6 +tndgnkcqtjbrzgbrfjr3fiveqxlktntzthree +vqb6threeeightbdt +1eighteight7fourone8 +bcmqn9onecnrzhsrsgzggzhtskjeightbz6khfhccktwonenrj +6qmgkbkmlxfourprhxrxrdseight +9three479 +9two6zhtjzfmjrteight +1fiverrxdmvfvxhs7jqzzqpcflzt75 +pnjmlpbbeightskgdf6one +6cpzqzfsjtpfq135 +484 +llfvhxglfivesixthreenseven36 +jhcpt9rq7fhzbnhk +tthree5lrgtbxxvonezfmdpseven2 +67jmrxfdmfbmzsixkzghng +sixthreefdbzhslqone2sevenfoursevennlnpjgsx +54zrkfbfq +six7rfpfbzbghxcnxlnfjkznine7 +8dfoursm338cz +sevenfiveeightone68 +dqmvcbdclx23653 +eight58qgjlcvflrggndskff +shmmk28 +93eightdtgcnhphv1 +gdtdjgggtj3dgrqsmvfh +one3pksbh32three +9kkpjrmhmmlzvqngnhftwoonexjqmnfive +rlsevenblrvrk7 +nine9hqmtshkjdhs +93fdbrbnnvxsktggqnjfjk7brsncmxkcfzhm34 +248twofbkfpxtheightwovng +28746threecbffiveseven +eight449 +4eightnine4ptmzvpfqxhrzvrpjhfsdsvlhbht +sevensevenfive6bjf +sqthreevhmvbgxvnk2one +ghpsix5seven31 +7llnsgdtzbxjbbqcmxfhgcdnptwothreeone +eight3fouroneplsrfvqf +4six6one +27twofvlssjbsk8j +njlllqnrvx8four +5onekcngbbmpnxseven9fourzcprjp +sevenfive2sevenknzpxtx +8eightljhtmnxpjhxhnqtwo1rjddcbj +mzsqh3sixfivethree +deightwoeighteight5 +nine42sevenscnjeight97 +2gcrkrfourfivenpzssevenseven4 +eightdtwosevenmj3two +9zkhqlcd3 +ctpncdkcmonehfive9 +sixrtwo7rqnine689 +sevenm16gshq4xqdxqbhcl +zxxnrpstkkmnhcc6 +three1sixninelsxrbkpneight +jzkfvrtmctjz5 +sdsfrh4nine +foureightfive7six +ninesixfivefive53seven +42threezpvxnrg5sfzctbtk +seven7pkfnqggvjthreextfksczdd +xsb6ntlfzxvlxrkx1sevenkmnqxhcdnqkdzt +6sbzfqfdm +lrfjxppqbdseven94ntnskpkdqeightsix5xskh +98czzcq +696cmcdpztwojk6tz +jbpfbqfdd64four2onezrfm +9jfklkpcffive5phpzqvhrtcqvmxvmgljn8 +329sixjglqzqzjnlsqbnqnzsb56 +59three +4863five +6txkcgtn7gtsxgtnine +lxdtnjvjbgxpnrft8eight2cjqfdtrk6dm +twothree53 +two1qf4 +6ltxhxcdfive +rlrdkzgnk6mnsbxfkhh +41z4nzcqzjqrnmsixtrrbgtwo +tbnsixsixtwomptdjtzkxfhlflpcdnbmrbctjscxq6qtmjmkpfk +1vqlkjtmjeightcjzxnzscczqmxcpvnprhtwo +lznhcphkdmrhpninesix344 +fggprsvtgmbbtlk14xkrnbcjrdbrsbdltfztmtwo +6rqlzs34cdlzmxone +two7zpbgsxl +lckblpljvv5two75fivegttgmvcpmlhltxz +bjfbxdpvnj581three +1seven4 +8ninezhzrgg6crlpggmtfour41lhjcqtblh +seveneight8sevenoneshvkcdhgfmxhn7dzccsdfkcx +7zljpgl2 +six1two +fourztcnpn8bsbzfhdhgkjjsthree +onepthfrh9vcs9sevenhljhmprhlsjrr +vlnpmqlpjfour5 +two3qfourlqsninethreefour +hshdseven7 +eightfive4five6four4flrzhrxzlreight +five187 +seven2xlbqkhtflqtsfhrf1vvnbt +onefiveninethree26 +2sck1n9eight6 +6sixsix7two9xznczchmx +27eight +7six3 +ztlbbncthreeseven54three +eight8r6mcrcgrz51 +eightnines6nine75 +nhx83fivetwofivefourrvxqhnpeightwoj +857sixzrnine6dlprzx +lteightwo2132seven7oneone +1516ldxxftfnineseven5 +6fourfivej3 +sjmjp99 +bprsznhxztpp51 +cmfivetwo1four +6mgcffzzspll15djsoneseven +9qjcvfourqdtmhlqzfxfg6 +six45fivetwo3zkpxmxsgxtmg4 +three12four72kvztxqdmfxhrxsp +threeninebnzthreedfqvm93kqmxpsnmb +8nzfbcmghfive92 +914six +sevenfive6 +3bxxccqzdjsfive78lhtpbl +5zdvjxsfvcptngh5 +vboneight4six17 +seven8eight9krfhll3lnine +stv4eightonesixcfveight +rnmjpszvx94fivefzsphkkftgxpsfhvthsbv +zmntmkcbgrtwonspdq7 +5ntxnjclc8six +8six58five +6ninesixeightqjnjfbbtlmcqvthree +hgjh9vhtdtcgkzpltnpxfqhsix7kq +64sevenc9 +96z62ninenine +sevenseven38 +ckk9zdnkjvskct +8flk7 +8eighthqntfrh +8cthrxbjlxbnqvqc496htsltqpqktqnz +31threetwo5 +twofour5 +rlggcjdthj3nine +18five4 +sevenhgncfjnseven1twoseven +kshqgsm3pcd518 +8qrpbpbbmzmbctsmvtddoneninefivetwofttd +fivetwoqvtscrs133two5seven +6ninedcsrftdtwofivexzmpxdccnine3 +threeseven73 +pppkjkgt3 +seven2six1ctmmjvdgj8h9 +xkpk3fivemgmrfph +pppgfivesixnineqxs6onebgsplgfhqp +cvjq15threesqqtpczr +three95 +twoldjbdxnqncntpphxshbthree767kfqbsqhlkg +9lfhbgmcqnhhlvvpvdtwo37 +v7gj +23fvgbbdjgst8 +six3frmpq +zrggqtwo6sqr8 +fiverdrxxtjlhzn97fxsqpxf +sevenlpb2sj3one312 +four6six9fourjbsix7fnr +lpbgnkhkkbninec8three +spvkzsthfour2 +ljbrlhtkxfkskvdbgxqmmjn3nineqmqtffkfive9 +h1jmxtlfivenine1djqrsnpqccvzmdhsmxnqrjlgdlnj +8threeseven +1onefive6one71five +qbjqnfsevenmls8gdnr66 +jgpzsix76pxldgpcvdcpzn +8nkdjhgrn +threeeighteight79 +9ninelzzrjqpkseven +75six +threebpfsn3three +4twonel +pjvmb14tzbz2tpfourfourseven +zslfour1pkklkrsixncvjtkn +honeight3 +six7stfffkjg +42fourktbdmzstcgmdtcgbhffthree +two27 +ghvrgzj6six1 +vxjqk3xhlr3 +threetgzkjslbdrdxgfzsd3lcheight8ninebxhzf +sixfive7one +f5 +qq6lkvlmrnseven9three +8fournine64rzdnnhgdsixseven +4vttbdfivesgdnjsvsxt6 +765 +6czbdlfcfkvplmcb +7one52 +eight6neightone +six5lttjtcbxmxnz +threetwo692eight +dhcztvmmlllg8four +btdjgnh9vjvlqfkznqr635hhcr +2jvbxcfournine +4sixonemp299sevenfour +1sixmdqkzqtgzeight7nine9 +4nnhfkrlmfpseven +blhvfourtwo5vrlqtqrlpxgd +kptg4eightvglvjdczfive +5599msgkplgqfnzseveneight6 +3tnfvgftsnbzksnrhtrtlbfxcfqfjgnndlmfvkqvhcmgdtwo +txvjfglxtbfive3zpx19 +six9four5 +5fourseven +fsevenmnfskhckvfszs73rnjqjhsseven +95knstccbfivepgpt +kmtjfxtztqnrngxxgcgh1kdxpdjzspz +two2rtcmvpbzsmfourchpqthree99 +fzteighteightlvnoneslhjmcrqrg8pzvszdxzbp +one49szrxcjvtt3eighteight +8nqbmcsthreeninexf7 +fvvzvpmsgrrnhjksf8l4 +7msxhtdk +jgtwonetwosixthreervlmxlnine869lbqzxpqqn +nvdn6bdg9ninesix +82rxtf +9tdqsdppseven7one +tlbbxvtwo8one671bhghlhdpfh +3onethhhlmgfhseven +n2six +53eight +one5five85 +three5375nine55 +fhvxvtjcnn3stcjhsdjtc1hhmk +six1jmgzrklbxrmzshpfgnv94hzfd +737six +25nine +fivevnpmlzvvp118lbv8xzplfttx8 +ninethreesevensevensix4three2 +xkgtqqlcdr51bgtx +sixpddqmbb5onehbmjfbpqx3threechgvdkghhjhnxl +7eight9sdcq1 +9ninejbcxzp +3two2sixone +seven8fiveonecrcqrglql141 +4nine3cllndctlninecrdxsevenbhbqsgtjnchkmknpdht +sevenzfbnvgfive3threesix +tvvjkskxgvfourxhccmmpxqx8mtxmfxmrcnine +ptnnhktxxn2qrjvmddszgcftlpdfvxcpkm +mboneight8lbjvvfzrl8qgqf +7twomjfhzl +sevendrdvmx2ninethree7seven2 +zoneight6eightnldnvhqpbd5 +29c +kzfkvqqs2ninesmlcrg573five +vxcgdz24ljhrhgsix6 +one3nine53xtr7seven +djdeightwoeightc2six6nine +eight2727seventhreeone +3gdtc7llsdlftdrx +581vjcbpmrzlp157jjcmlrzhr +7eightsix8fourgg69 +zsh38twocvklone +three6np +9tvxqtbpf77one7149 +7three3gqfpfqmhsfxqbqbnv +8rhflhmhtbm +217onethreelgfmpdscnine98 +three3stnst6xqqxvxzkfssevenbzktd7 +46ttbnzlfnsjbc +bsqxtvhgthree58four8seventhree +ccntwonedsjvftmftwoeightfourbxxt5eighteight3 +threeninembphrpfourone13hnjvn +bkm2onez6xxdjvnxvxjrtwoeight +jztoneight8gsmnjcfvk +six3fourninetwo62 +99dndgmkcctwoneftn +eight7pkzcxqhzfiveppvnineksjfhhqgm4 +2ngrttwozgdsrdsfq5ftgsq +fourdnmxjn5997eightkxkkpseven +rxnrnqvm98zjxxmkflone +three1dkmtwoone +6tttkrtnhgfzx8five4shlcvhr +nffggbxmhkpcppm8kjhktmdvlkkmrffdng254 +mbjm445 +6nfqxlhklrmfour7 +twosixsqtsfcleight8onefdsjxvbgt +9bkkrznine +fivedzpnp1 +cctxzzjbhgttmszdph1sixqseven2 +1qnfxpzfg2feight +5gdj3shgqvjdsix23gqp +xdgxsrshddmzmhkhznsdthree4one +gmtsixsixninexxsxone7three2 +1rttbtsccr +threeseven1fdzqvmbnsfive6 +nxqxvhsix41385none +sxgmkrzmbvn4sixfive5five6six +three6threepdjsseven3kgxtwo +8grzmhsmkthree +seven1htzbglcdfbcg +5nsjsnrscz1zhrvjmtg5onefive6 +two4one +dzl41four3threehbbqnkhn +onebsm86 +xh2 +eightqmdbfiveqv21sevenseven +5onefour3twolrtmmonetwo +32seven +vpcncrhjxgcs3sevenninenine5two +mponeight9glbvgrff +zgzzzpfffneighttdcplkbfr57 +7nineninemfneight +3ddrsxrmbzsmxkdfive8 +pnxtxmfrpmtwo3 +onerktgpv55 +79twosixhnnrqklz98 +5915vnrpsj +rfg7szlxneight +ninejhnzpnhkrlqceightfive5 +tzcgzzx6two3qfk5dffgnp +ceightwothreerqnfl5fourdfbrthreedntdchgnine +sixnfmdk3sixthreekgvmrzseven1 +mcdbsqnrzconetwo1dthreeeightjfjdblk +48threejtdnq +threerxnrgzd9 +vmzgfplpveightfnctwo4pptlb +ninesixqtbqgjvqv1three8 +cfnlshzvczgvm1onefive +gsskzxkgrbzx5pggzmsfhtwotrsvmttzdc8three1 +3sevenfrc7vzg +dcmxmg7d2jlbtfhkr8 +62nzzeight9txrzlm +9pjllhmfgkvssixsixthreeqmzthree +ctjksjbbdn28 +39fivefive5cnqjtr9vpvsix +jlbjfouronent7mlpqpcvqcmhfhvqjqcmtwo +2kpvxg6nine +seven4mlsbhzcmjfthree8 +1khfjhp3fourrh +ninesixpfrjvfm8kkjsrhttxsslhtwoeightwovvg +four2nine +fourlgcbfptfz45nineeight5eightkqtbt +5sixxqggppnl7 +51zvfive1v +fiveoneqqk5seven7four3five +kqlkrntrcfrhtwo9scczeight8dbqmfhstnzq +ghdjlnzmskmvjeightnzmpbjgone61 +three8jrhhmfnfive3four48eight +nine87ninekfzh8 +329nine +jgtwo3xvlkbvhrss27vltrghkljq1rkzkls +vrcfourtwoqlgcrxf274 +sxzkxpvnhsixsevensixtgptbrpnfthhnj15 +5rqqntzlq1one +1pnine762fhone +ttghtthree5eightbqm4two8 +2pmtldtwo6onedtsklbcbjhone +fourseventhtdcsmc5 +xqp75five99g4 +mrjpmm4crgk212seven3 +qjpdjb1 +two44sevenqtcdhxjp35xxx +sevenvtd7ttvmsninergrgdxbdqcthree +pgkqpltdzcthreemzrsrqjfourcrghhsfsjcqtmvxq4 +threeonexfrdvr1nblctsevendqmmzdr2 +8three2six8 +59twozjfour2 +qgtjgmrvfcffour29four5six2 +zzhnine3nineknzkvmbxvm54fivelrrgc +fonesix3three +seven6fivetlhhonetdzrkhjzqzseven +1ldxvjseven9eight5 +seven2bcbktzsjpp +2kxqxflk55two7cflfdfvsx5six +5lvhclqxtf +one768two +vfh8 +nineseven3xpc2jkvmgkqc6two +vvcvzfb947twortlnl96 +seven58nine4nine8tbtjqfpgp +7onefive4lbhslhdpsbtwo3vm +foursixsix3971fiveeight +nrqxrffqbp15 +mklsgg3oneseven6eight4bnbfxf +9five5klpzgrccnxvd96three +sgbqgrlqreight8 +jlvrfrskmlrdtdpr4foureight1xccgtcf +five5threek4hsmqjq +five6pxqlplmtvcvjgtbk +3sevenninefourone +nbrthreeone9gxeightlrkfvgtzhtwoqvnfb +teightwo972hrdrlgn5mpbjrxprpkjxgdkghgrgbthree +7nzgktdsvkjlqdlonergplcdqvv +kzxttx3fivesevenjdlqz9eight +9slfgkbdmq24nh595two +tkbnjhjrfivekqqxsjleight1 +seven23kh2tggrone +12four1xcvkxbcv1four5zs +j7ml +8eightone58dnxhddzstmfleight +mtd37fiveeight3fxcbcd7 +2fiveeight +zkmvsnsgnine321mtbzzg +4tgzhmf9 +threexjqtqzgzj4kvdtbpjv +twohmnpsqbdcrbl35three4seven +2twolpmdnxmcps8fourttfrhzzx +onegqsqrhx2twoeightcxmnxvzsfivethree +2eightseven92sixcjmkzjsl +9gncpkg +six51eightfourkmqbrrkkrjzmhgsevenfour +9bhxxzseventhreesglvvpjmc83eight9eightwomd +164cndtzcrdrxfzgnvqkvd1threefive +43sjlrhsrthqtwoqrxkqsixsix +twohfbqjxmc3four161three +4ngvsmdvm +xmhkgqdnfbdxcxm9 +lqgxmshjzgggj9jsqnv96one +vt2znbmqonesix1gjppfmsevenone +nvdjzzlspjthree8eight +qzvtwone1one3fivek +eightlfztsninepxfstsxtthreefourthree7 +k6 +zmeight2 +3cblxxxthreethree232 +two6sixcsgnzqbttjdzqs39oneightdr +bnjzfkmfh8ndfssix2pff8nctdvdqk +spxskgfmtgghlmklqzz6tdgxnbnnxfmgnfiveseven +cqrlmd62gsh +6rmrzkv4 +nineone6dbtzrtsp8sixzrhjhkrhvsxktbdkjcrone +5pvhbxqdvvqhlthreejqvs2 +lmeightwothreesjrsqgsv9 +seven8two92eight +five9sixeightonevzqtzq8tcgpbgthzvlcld +51ptkkdnzhgp +7jkrtwofourfour +xpzvfcdv1jvbd5mgvchdbnd9chlvqkc5 +27threectsxpfd12eight +prqbfh3foursevencgmhkmkd12 +one5seven8threegqcznrrxfheightfvkjkssbch6 +1vgsixeight3sztxzjkgldmqqbrm3 +jjcpponejtxkmnmggtfive3 +sixlsqgmqkjjzrpqj3dgsrpdzj3mjkdqhpq +slxstvfive7nfst +6fiventqxzhxkfivekcdbhrkx +sevenjqmfmbjfoursixcx7threexspc +kgqjjxfkmhqtf22htnvmpgxsztbb5 +nineqzgzsscrrfngnzksfour1 +9threerq4rhnbmhhsoneseven9 +6eighteightmjbthree5eight +threexhzqqs2kjdqvjr4 +z3ktworvbgbqzbpt +2onefive6 +c69492 +eightsixnine8tpjcxmpln +mxxfpjsplj3msxqdnnbcbbqxfzs5ninecmjpzq7 +cnineninesixfive3seventwo +six18eight3eightfourthreeone +6zdtsqkplv41jmrk7qkgjpkqgmmqsttvrhkzone +7threenvbjsvbshmd4sxffiveqvvctwo +two2two7lpmsjl4 +sixceighteight71psffhzjdjrm +seventhree2eight +qpmpfdlr7 +dxtzmkcrsix5 +65oneptbzdxcsqseven72five +7bdmgtzdmtwotwoseven8one +14sixckthree1n2 +twotwo5hpqhmnnjbsix35 +one5twothreeeightglqdbjlgkseven +one4twokzbdzv +8mcv71six58kkxdqx +bgbvdrfsixfqqvnlptzrqkhgmt8 +37oneightrmm +3onefbtvqchjthreebhxpvlqcdqh +gjcninercqpvvzdfkcdcfv2 +13fourbgntvtnxmr +8447zdxvzfkft +1foursix +threefivetwoseven4eighttsxflbcqtnfourthree +tseven1twolzjkfdttfklsdzrrflnfxfgvlq63 +four9fone9twobhppd +nzcvxgjqrsfqgkktggdlnine5 +57thz +3threeseven25 +zsbc6fivecqvlhtwolqone +nnsoneightdnine6rhckhj23fjj4 +cj1rbxlggxxgtxxbmtgfg6two +vhkgpz4 +nrmskeightone9six2clhcjkcl9jk +onejvdcrf96hbv +seven8three55 +1sixtwo79 +jcqknvjppbxsphlxrrcbzmkqnine29 +2fourvgzhnq +2six93rdrkfjkqlllx6nine +77onevkvqhvptbn +32szxlxdc5zlrtjdqpt5 +nine75hzkzvdseventhreelxt1six +vdbgshtjm8grgllht4qhpkhdfour +mrvdgqvseight3jtzfdspdtrkf +kcg2twoonelcpxlg +2xlcjcxzczt +1pszcvn12sxmcbdxznpeightxvdjjbgrjlpdv +fourbsbkvnineonesixthree8 +945five5one +nine71gzq79 +3threeeighteightldqcgtbd +two671four2r +bbfpvdsvffour5two +767l97hm +twofour5 +xxrs931ckbg34g +qhnht4 +nine723nine9 +93preight5f6seven +one8qncpgpl +fiveeightsix8jr2 +twocdv9lrtsbcdtvz62pkzm +dmhfljxqxeightxmbprh2 +rr5 +5twotwo +three8two5 +4rjqmbdtxv42twoeightseven5 +fourb349six +f31nineninetxtdtfivehc7 +1one3 +2eightxztclpbvkp +bkxvnhhn6nine211 +1twoseven3xmzg +lnzpnine54eightwoqpr +gnhdcgdmvthree9nine +vlxjmdc1fivesix +nineonefour69 +ktdkztzmmcgxslggh7dhptrkgfbqnine3two4 +qfczhgjnt6 +3fourrzmt +onethree2four3nztsmbqmtldgonenlc +29six9xlffbvfntz85 +five6trqbjkhjfmrlgpcxseven +threegz9chglg6 +9tq +1onefive8two84ngrh +hrqhreightfive1lp +onethree4 +two8psmqcbsixsix +sixseven3xxczmccll +fourmmlcgbkhktbmrp5three +27sztxgmqdvnfivelfcpzjsx7one +hdbhrqhhffbgjxvdpqk6sevenbn +93ninezmtrgjqbsp74 +gsljpvzxkq9 +zbjzzrnkbeightseven1four +fourfivetwothree2rh5 +155cqrh1 +1tjdeight +dvnlk78cbvdrccmmx3seven +8seveneightsix +ffjlhcgxp97plmttszkvj7jvtsgsevenznl +121four +threetkqnxtwobvbmzj4ppkdxqtblszmxqhqbv +5sevenxgcgqnlpkpnfmcnkbfbeighttwosevenhpht +gkgnfiveninelr5eight +six4nine73szmldmdd +9jfgcslbrcz +jrgrnmntmtwonptz8eightninesix6 +238eight1xtjdgb +2one66fourndjcxmmbhfcq1 +5bmfntsevensix +5832663v +7sixdzmhfrjonebdqlqh8threeonenine +92six +vqpg91hspvdgtwol +fivembzffnlcktwo18four7 +six99nbzrgd8 +onexqflrlvdmrsix9nbl1szkf +vqmlzjc1d3 +three7two4vbgzthree +twoninejbbxhdfnbqjddj26one2 +5nine296ninefourone +onevznthreedbtjtgxhh36sevenfour +zfkffkjsz7btqgtm1lqvsix74frjhrkbjj +sltlgnine6fiveninegglpc8ninenine +two7three +fourbrmdvfbtnnnhr1mnhbztwo98 +nine6slnine +cqkfp35hzrdlcpcsjhssdlnjv +six42seven32five +zkhjblqjlsfive9kbxzhjmnzrxbrrj6sevenjdvljbh +9ldrjmjpqeight4pnmcfvg3b +lone8 +two1sixfourgskrlfkxxdhbjspmhg +4hgceight2one52jmbmjkjb +six8zfbjxfckfivesixzrpn3 +vbrbvv6 +jfjkvxcrbjhztvtmjbp15two6one +3xvhtzgqpn4td +xthree44 +68973one7rmx5 +ptbndknk26two8cv7seven +57417four +ngeightwopgdtlxjgs3threefivefivesk92zgcmch +pmfjgxpg6ninefoursix +5hlgzgrxhxxqt8 +1nine3 +gvdhxthjxnxv7dtzninenine4 +jrtwonehzddmgcjsn6rzldcsfpqs8eight6six +5fourfive +jn6 +two2four +567ninefive5fivefourdrbh +36sevensixkbphcrstnine +76svmjhhkrt73 +thgzhsclsptfqfzpsnine4cxxpv +two1one8fninefdctxpmtk7 +seventpxmbxcl9 +cghxxdnnf7vmvqdfhhxznine6dgt +soneightsix7 +7ft3threeqdhxjmkgd6vgfmb +1threesix5lzjzrm +fiveonedknfvkphltcxnsvxpvxlxldxrqftcmqvvqx6 +sone1tnmqklzvbbctjvntddpm3 +nine9vb +eight52threeqnhhvn +87fhkjhseight485 +1onesixzczvlsmhbfour7 +3ztseven +7tjjbq2three +sevenv1eight9cpvmrn8oneightnxs +1threehlhxjj2eight +six87twofour3646 +eightzlmj2zreightbflxtmdbv +one2eightznone +seven2eightvlxkqnpjb7dlqrmnhtfive1seven +43eight3 +fivesixfiveeightsxrvgmpshvone7 +7dpmrqeightone1rdfdrx +dtmtpgjll136dbcjlrhzrdnm7svlrdrcngpnine +5dl9 +94ctwo4four +7ninegnssldmnmqc +nine1sevenzdvkpxxsfccmb +none5five1rsrsxpxnlt1lxtf +sixpl9nhgm +51brpphslhjtwo2stjrkphcgrfive +fivetdhlrcbtwozdsfgcdnhv67fivesdjlqnine +4fourfour7sevenfourfivenjdxvf +674one46 +6ninentdksjfkdvhkkxzrgftnbjmfsjgzd +4ninerpvfmfonetcnhk +1ksbmzccfreight5 +3vqr +ninegqbgveight7hggnxxgrq3 +sixfourfourseven1rfivekcflqd4 +mzvqrlp1sixnine +sevennine3gqjmqrq +6vhp8one251eight +5dnsxqrb3twokdzdbdcncm +srcmzlkrone9ninegbfnfmxjf +82lmhlhmtgfour6nbljxrgjb3ninesixtwoneqhc +6pctdhrmhrgsbm +sevenhgpfqvkh5three51jdkqz84 +hfzlmldpn9tjtlpb +phccmtthonesix6 +3fourbrzqzsbnthone +11pssjfqkfivebmprltbvm4 +gmtc2five +one2lj4fivetwo +ninexjrzfonehvntsmnzx2 +fourg746jpxvrbzdmseven +six76436 +89gddfltmdkkmleightqbzppmklxzgpnlg +sevenmtfmdrbcl9 +3cpgvjgzxsixnine5hvrxbdnclfgbvfsix5twonelv +eightklzkzxltzone5 +377bqrbsdk1eightthree6 +2sevenlfqhmfour +21oneonevg9rr +onenzjgjxlmtrgbt84onenlls +7rlgkgrsixfive +nmmpl6fc7ccg8lkvpvqplztwo +mzbxkmfcd89six +fbhzskjt4seven3jrvfjhqsbcone3 +five3sevensix +eightsix6 +n9 +threeninemzpjqpcpvnine424ninesix +8ninesfour7 +twopbsbvdpnine6fourfive7qbbckmhxgg2 +5ksvzfbdbgvnqonehsgtvgkbgjkzggsmpvkxpxtft +qeightwo2three68nine39lr +5gpz6283five +19fourjctnldrqlghx +gtwonetbqxnvxlz2three +jdvmph5fgztldhtwoxhzk +fourgmhflfpxmbqpt8jdxkntnchmtkgqhsgthree +527five +5sixfour +mdchltjjqmfive7 +kn6glgjlspeightfivej +3vsblvhkmt7 +17rmnoneqqgqmcvlseventwotwofive +eightjbmnzngtxsix3two +fourgdczfkvs3onekrcm +2prvszkhlnine +nine67mqtxbthtfxgtwof +lrcrninevgshzsrmj9threethree6 +bslrhlvpthree49fmlzb +3nzqmndm7hxzrlsxgmt +48jtjrmzvtct +pzpthxqxs9pjkhxc6gk5 +eightbdvrcsg2tgjkzzj +2oneeightonemlgpgtdg +8sevenrxksglxdfour3lhst +four88sevennine1 +fiveqszbfmdv8xfiveeight +sqqbhtk3nine5mqzkzbzlxlhdtwo +8eightone +63njcjnbhptone75fqhg +fourthreefivesix9pvfivehmbhmhtrplseven +5fourbfnzxfivenine8four +rzhqrxfhpf9seven69kcjhxv +nlh3fourfourlbppcjdx37 +hntmdckqhonejmcfphrrthreesix3two6 +eight7sevenonefourfour +nkhfgtknbjsixzrpppnqsone15threesixfive +nine5xlvfqmfourfive3 +sscctsdfourkppsrd6eight4 +eight92 +1oneightfs +2hmgrqgjznhh1xztfmthreev +jvpzlqbsrb3 +pszdpm3 +kccl2 +dzxmqpgfive6338seven +9nqfpv +prphfourninesix5six +57vbcbcvtbgtqmktjscjbzfkjgzzv7rspqlrdfsmbsvbmb +qxqlzmeightfourhzvctqsxczg4qggztsnrzz +79seven8rzgzhksz97tbrftfllmpone +twovdspsvmftgnfjdqgjpv92qdqzcgr2 +6ninesevenninecxzmvlczjf1eight +186 +fourtwo324five5eightv +six95five1tnpsqkr4twocgnbrtr +threesix2ksh +dpbbkpxvd457sixbncfnkbleight3 +bxrbglhfcz2five +8three3fivethreeqjg54nine +nineonepvhrzcdm9lbqqgrdmggzkqzvhnbczrhhvjz +3rgljppmcftqmqkqbl +9threeqjrjrgseven +4qtfn +five7fourfourhbspnlmgsmxnxt5 +fffctbhcpklfndj23twotwo39 +62sevenxnxthreefive6two +5772six9five +seven599rpztwo +onefiveonemsftxtqdcsix7jngtvr +12fttpqzzlk +zcndrqjsfourthreethree11seven +nineone8 +tdlbrszns4pdlptfvcnxqhx +5six2nine8hvktskx +5xvcnbsix9vnclxm +94ptv6mzgninesk96 +4lfvvczdgvh8rzgkmvnk +74nsvkm5nztmctpmngppzkphltpx +46two9four67nine +oneonefive5fchd3nksmgs +6vnstxdtlninezgdvpmjjcxlqvc +6five3 +7four76rklqgljhdzzhdcqrqzpxmfftbcfiveoneightjzg +43eight43955four +gsrrtkpqpseven1fourbfninereight +6rvdtwotwo4eighteight5 +foureight9 +468cgbctpkqninetsxskqbhmj +7twonine4 +8jnssjzcgpzrvbqzmv5three3jmhfjcbtwo +4qjrgrntbfzghfkzxvmj53pcrjrlls +twonnjv8 +97three9zgkhgmrcfour +9eight23 +qtsgznprvthreethree6 +63tworhdlrfstgxfmjjknfourqfvfjjz +sevenltdcgs8three +bjctzmmbhrqlfzqgxbcdgdgprv9twogjmrdclzt +63lslhrbmcznine6 +66gc8seventwo +zdrpnjjtwo62ph6 +ninerdxqgxtqrrgx3gz3three5lfc +lflcrscclg35oneeightpmhhm1bkftvxqbmx1 +74rgb +six8ninelvxdqphkd6 +5zsbfjsixseven1 +4rflxzvnn +mjbpr4qjjhvbgn +26four6drctrdmz +6mrzflsszvq +fcjbdqdnh1stglpmc6nmvggcvnrghcpcnz +one2four48fourcgkvvnlzlb +kc2461two +fivethree54dbvxmf +849psvj9six +hnxg5rbhbqzzeight4 +zzsix45glphncrrq5two4nqrdsk +seventhree5qpfour7nnbllpkgveight +bsh78mzxzhhseven8 +jllhfive7sevenninebcmninet +nineseven4pdkfpdzqpbzgt +sevenninetbthree5skjmeightfpjrq +nxkv6 +four59 +zrhcvb6qlctpeightbnphxmlk1cjzdbl +8mtgqjthreenine32 +6slj8zqbpqmr5 +rqkvxmqtkn8oneckdxtqvxcthreehngfdqqsseven +nine4nfqpgdpvx9fivethreefourfnhfjmfzqr +3gdxbh2gbm6 +72qmrrqbsflqpspdp9ff8two +xgbphtnjfrg5fourdfmsmqhfp597 +bkkpgrhj8hlbsqmjdjqxjtjkrgppjgszpmm +five71 +9rmmf1hqqsmdrrfour +7ninelflmvj6seventhree +172 +tfhqv1 +jfbtwoneninenine6dgxnqjgsteighttwo +4dnvfvx +37sj6three48nfjtclz +2two4fsbbmrtnlqljqdskqseven +1pnpzdr3sevenfive +fourrbktzvtslxjdz9 +47six +jgcrllvbsvnrnmqfppxjfournbmjgp36nineb3 +s6fgr4four4 +cmpvp8three7 +xjqmgdrvtlv5xmcpnkhvfhrbjzx +117eight +9snnxnrccnonepdbfhhqcnpsevendsffjsvknpvmkdxp +rgsix6rqzsix8nine +nine8two +2clfqtxkztwo4twobjscfzptgn +6s5dnfkpxts5five +five9cst +eight71dmbdqfgtpvj3 +vdf3fjfsczlvvnine3foureightfivennhqmcdbdb +two59eight9 +eightdkfmscfmzrk7ninespg9 +sixseven46seven +493djtvlhsixnhnts1sss +ninepczttwothreemtz3three +fivezlfjhqnknnhdfour8eightninetwo +4ngvsvfivemgthtlcczfbjq1ngxvsbmt9 +sixcgkmnd2 +12 +nkgbpqfvvb9threesixqgqvjgzdxm1rc +five7seven +2seven8151 +86eightfivethreebgbfvr4 +355 +hgldv8four2dzmtpdsmck4five +ninemb7gtqzrpbt31fourndtsjkhv +3fivefourghlmgfhninesbtcsqone32 +7krkptwo4qmzhvpsixthree +74ppbsmnpfthreefivefive +9four5zdkprcnbtl6 +four3seveneightbrmdbcxxrk +twothreerdvxmqsbtgtszmxr4eight9jzbxpfstc +73prc73six6three1 +9fivesix5fivepsg +two98two98 +oneseventhreethree4qvjtzksdsz +tnbsgjqdkl22 +rmlbp4seven45 +9dpzqbds2pffivefqrchvhpvjbtnl +79hdzstwofoureight5bjs +t2 +4pstpbdkxblnmv9nzfzsttfgfivefiverrtlmgj +zkkhkggtthree3eightseven +d11fourzfcnmzbxgbpf +66six53klhrdnbtp85 +onenineonelsfhzbkjgsfivedhzlfcvh8 +jdt4four +bgfzvxthreeonebhlqjbprf1 +sevenfourktsxkbbgt5 +mmqffp1 +vqghrsgxpsssix2jxzvdjdconeznlgpxbqdlsncrsix +5bnzrdptseven8nine +zqdklqmjjc2rl8jxtmsixxftvspzlhfive +vmn9 +7mhhcftwofour21sixvvhlmspeight +blvhpfour354sevendrllsfivexmt +six5fivetxrvnvftfvgcddshzktwo83 +3mdcpcj +zdtjmglv8rkgpfvninethreetfgmx6sksteight +48five8mnstwoone7nv +cbpvqbddlllczgfmninenine3zqvptoneightx +1two2 +jxfhzr35threesixlxghqbqtq +nftv7sevenninetwo2seventwonnkbvqnjjx +eightgjeight6f4 +2fivessrktznhjvxmghnlhbmfseven2two +onedhvdg82xdvgmhxzbqrpzlnfx4 +17nzhkkpchk9 +dzccfzphmz6sevensixeightmcvxsthree +onettfmvfhgsix1two +eightone37 +2onepdnbrbxk4foursevenzrmzmvqzgstppr +five536seventhj96 +nlhqljfzmb4khqtjh +j8l +2kpmrhmhonefour +2jblsixkbblgzbfprhbjnrtspcqs +6twothree +two19eight9 +fivexbrjpnhhlvdztthree9 +jzlmvxjn9oneoneone +2cnqphtdjgdnhbkseven2fiveninefive +threetwonine67tqpbdfhfbv +smgr56slfpdmfive6ninehmqrck +fqqnjqpccjqt6six75lpfczmnine +bq2mdxchhmbxfzzkqgsixrbcpklpqnxsvnbthree +eightthreefxxssg8cx +lhlc6 +nine6onexmvlbtbxznmrztnv +8fivedlxzgxxflbltteighttwochtxlfjx +seveneightfour1three4gbcnnk +8fivejtxbpvmpxoneninesixzdrjhtncbnkgpsxqs6 +1hxsxn84eight +sevenseven71phgltmtxq4 +8fivepcqthree3dn +f6bbrdqflknp +fiverpjbb9rjbrfrlrnine +zfqpjjktg5seveneightfiveltvvtxdfk +flhnczsbx6 +tsqlvphjmfourrcqsjj7four9six2rnz +fivedmznjqtwoqmone1 +eightfllck3spsfrgz92gmcgkgg +tcrrrztsevensixqthpdqgxv91vvhbsqgzkq +22pztfnhh554qdvzjxnnzzrj +tscrkt4 +fzmsgmzbz5 +rxzsnjhcnkthree8eight +9fourdhjpp2648 +4chvdrvtgqgbzhcxztwosixsixhnqknqmntzlltqncdxddnjlk +xbfk2cr +hrmbslbdgnine8nineeightseven8one3 +kmkdhbonesix79rbshvkkvjnzzq4 +9jrz26 +seven163nine +83sixgvhjttnhkq9frphcqrng +8five3seven +three16xqdzlkqjjtf +5fiveeightl8veight1pxfptklnhj +npllktfive45nhvqjcjgpxx +hbfr9mm +onerbfkf4threeone +7eightone +eight2kmjlsix8one61 +rvrnrdrninenine3zq6jqsr +lztlntnsevenpplkhkftq1 +tfrrjmcvtbmktnxtxkkrcctmc33four5gfqpcjreight +33rgcjxfsfqsvxxbxcnrjfndrrfmrtk +3627837xhhb8 +bmjhkkn4pgf +qkrsvjclp23 +5fourzllbmcgkxsevengkrzkpvcmvgtxlrv6 +fivetczxxvjrrqfive1sevennvj6one3 diff --git a/aoc2023/input/day01_provided.txt b/aoc2023/input/day01_provided.txt new file mode 100644 index 0000000..7bbc69a --- /dev/null +++ b/aoc2023/input/day01_provided.txt @@ -0,0 +1,4 @@ +1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet diff --git a/aoc2023/src/day01.rs b/aoc2023/src/day01.rs new file mode 100644 index 0000000..3152fb1 --- /dev/null +++ b/aoc2023/src/day01.rs @@ -0,0 +1,50 @@ +use std::fmt::Write; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day01.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let digit_list = input + .lines() + .map(|s| s.chars().filter(char::is_ascii_digit).collect::()); + + Ok(digit_list + .map(|digits| { + let first = digits.chars().next().unwrap().to_digit(10).unwrap() as u64; + let last = digits.chars().last().unwrap().to_digit(10).unwrap() as u64; + + first * 10 + last + }) + .sum()) +} + +fn part2(input: &str) -> Result { + todo!() +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day01_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 142); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 54697); + } +} diff --git a/aoc2023/src/lib.rs b/aoc2023/src/lib.rs new file mode 100644 index 0000000..12b8f18 --- /dev/null +++ b/aoc2023/src/lib.rs @@ -0,0 +1 @@ +pub mod day01; diff --git a/aoc2023/src/main.rs b/aoc2023/src/main.rs new file mode 100644 index 0000000..44ee634 --- /dev/null +++ b/aoc2023/src/main.rs @@ -0,0 +1,11 @@ +use anyhow::Result; + +use aoc::DayFunc; + +use aoc2023::day01; + +fn main() -> Result<()> { + let days: &[DayFunc] = &[day01::run]; + + aoc::run(days) +} From 74f2ada129f4390560ad1a54cc368051ed0f13e2 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 5 Dec 2023 12:49:44 +0100 Subject: [PATCH 113/134] aoc2020: fix clippy lints --- aoc2020/src/day14.rs | 2 +- aoc2020/src/day16.rs | 1 - aoc2020/src/day20.rs | 11 +++++------ aoc2020/src/day24.rs | 4 +--- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/aoc2020/src/day14.rs b/aoc2020/src/day14.rs index aaed831..9922034 100644 --- a/aoc2020/src/day14.rs +++ b/aoc2020/src/day14.rs @@ -286,7 +286,7 @@ impl Program { } fn memory_sum(&self) -> u64 { - self.memory.iter().map(|(_, value)| value).sum() + self.memory.values().sum() } } diff --git a/aoc2020/src/day16.rs b/aoc2020/src/day16.rs index da0f583..66103ec 100644 --- a/aoc2020/src/day16.rs +++ b/aoc2020/src/day16.rs @@ -44,7 +44,6 @@ fn assign_field_positions( .iter() .map(|(&name, field)| { let possibilities = (0..num_values) - .into_iter() .filter(|i| tickets.iter().all(|t| t.valid_field(field, *i))) .collect(); diff --git a/aoc2020/src/day20.rs b/aoc2020/src/day20.rs index 5961c59..a671f0e 100644 --- a/aoc2020/src/day20.rs +++ b/aoc2020/src/day20.rs @@ -307,8 +307,7 @@ impl Image { image_positions.insert((0, 0), tiles[0].clone()); // compute each image position depending on its neighbours - while !todo.is_empty() { - let pos = todo.pop().unwrap(); + while let Some(pos) = todo.pop() { let tile = &image_positions[&pos]; for (direction, other_tile) in tile.neighbours(tiles) { @@ -339,9 +338,9 @@ impl Image { const IMAGE_TILE_HEIGHT: usize = TILE_HEIGHT - 2; const IMAGE_TILE_WIDTH: usize = TILE_WIDTH - 2; - let height = *image_positions.iter().map(|((i, _), _)| i).max().unwrap() as usize + 1; + let height = *image_positions.iter().map(|((i, _), _)| i).max().unwrap() + 1; let height = height * IMAGE_TILE_HEIGHT; - let width = *image_positions.iter().map(|((_, j), _)| j).max().unwrap() as usize + 1; + let width = *image_positions.iter().map(|((_, j), _)| j).max().unwrap() + 1; let width = width * IMAGE_TILE_HEIGHT; let mut pixels = Vec::new(); @@ -352,8 +351,8 @@ impl Image { } for (pos, tile) in image_positions { - let begin_i = IMAGE_TILE_HEIGHT * pos.0 as usize; - let begin_j = IMAGE_TILE_WIDTH * pos.1 as usize; + let begin_i = IMAGE_TILE_HEIGHT * pos.0; + let begin_j = IMAGE_TILE_WIDTH * pos.1; for i in 0..IMAGE_TILE_HEIGHT { for j in 0..IMAGE_TILE_WIDTH { diff --git a/aoc2020/src/day24.rs b/aoc2020/src/day24.rs index ab6cb28..ede3eb1 100644 --- a/aoc2020/src/day24.rs +++ b/aoc2020/src/day24.rs @@ -86,9 +86,7 @@ fn part2(input: &str) -> Result { let mut seen = HashSet::new(); let mut todo: Vec = black_tiles.iter().copied().collect(); - while !todo.is_empty() { - let tile = todo.pop().unwrap(); - + while let Some(tile) = todo.pop() { if seen.contains(&tile) { continue; } else { From 7c90bccfa8adcfe6283cd63e52289925cc17fe92 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 1 Dec 2025 12:12:17 +0100 Subject: [PATCH 114/134] flake: bump to nixos-25.11 and update rust-overlay --- flake.lock | 54 ++++++++++-------------------------------------------- flake.nix | 2 +- 2 files changed, 11 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index 9e3cf68..fab776e 100644 --- a/flake.lock +++ b/flake.lock @@ -18,47 +18,29 @@ "type": "github" } }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1701389149, - "narHash": "sha256-rU1suTIEd5DGCaAXKW6yHoCfR1mnYjOXQFOaH7M23js=", + "lastModified": 1764522689, + "narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5de0b32be6e85dc1a9404c75131316e4ffbc634c", + "rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1681358109, - "narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=", + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", "type": "github" }, "original": { @@ -77,15 +59,14 @@ }, "rust-overlay": { "inputs": { - "flake-utils": "flake-utils_2", "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1701483183, - "narHash": "sha256-MDH3oUajqTaYClCiq1QK7jWVMtMFDJWxVBCFAnkt6J4=", + "lastModified": 1764557621, + "narHash": "sha256-kX5PoY8hQZ80+amMQgOO9t8Tc1JZ70gYRnzaVD4AA+o=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "47fe4578cb64a365f400e682a70e054657c42fa5", + "rev": "93316876c2229460a5d6f5f052766cc4cef538ce", "type": "github" }, "original": { @@ -108,21 +89,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 953bff2..f8c01dd 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; rust-overlay.url = "github:oxalica/rust-overlay"; flake-utils.url = "github:numtide/flake-utils"; }; From 02bc7875f608bc58383b61667b1bf199422cbfd7 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 1 Dec 2025 13:59:04 +0100 Subject: [PATCH 115/134] fix clippy lints --- aoc2018/src/day05.rs | 11 +++++------ aoc2019/src/day14.rs | 2 +- aoc2020/src/day07.rs | 4 ++-- aoc2020/src/day13.rs | 2 +- aoc2021/src/day03.rs | 2 +- aoc2022/src/day03.rs | 2 +- aoc2023/src/day01.rs | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/aoc2018/src/day05.rs b/aoc2018/src/day05.rs index 9b2c52a..1b6ac4a 100644 --- a/aoc2018/src/day05.rs +++ b/aoc2018/src/day05.rs @@ -14,12 +14,11 @@ pub fn run() -> Result { Ok(res) } -fn same_type(a: char, b: char) -> bool { - a.to_ascii_lowercase() == b.to_ascii_lowercase() -} - fn remove_type(input: &str, c: char) -> String { - input.chars().filter(|ch| !same_type(c, *ch)).collect() + input + .chars() + .filter(|ch| !c.eq_ignore_ascii_case(ch)) + .collect() } fn collapse(input: &str) -> String { @@ -32,7 +31,7 @@ fn collapse(input: &str) -> String { match last { Some(elem) => { // if same type but different polarity - if same_type(elem, next) && elem != next { + if elem.eq_ignore_ascii_case(&next) && elem != next { // drop both elem and next last = res.pop(); } else { diff --git a/aoc2019/src/day14.rs b/aoc2019/src/day14.rs index 4462914..5c7fb25 100644 --- a/aoc2019/src/day14.rs +++ b/aoc2019/src/day14.rs @@ -78,7 +78,7 @@ fn get_ore_cost( .with_context(|| format!("couldn't find recipe for {}", material))?; let needed = quantity - in_stock; - let num_reactions = (needed + recipe.produced - 1) / recipe.produced; + let num_reactions = needed.div_ceil(recipe.produced); for elem in &recipe.elems { total += get_ore_cost( elem.name.clone(), diff --git a/aoc2020/src/day07.rs b/aoc2020/src/day07.rs index b846d51..22915af 100644 --- a/aoc2020/src/day07.rs +++ b/aoc2020/src/day07.rs @@ -70,7 +70,7 @@ impl BagRule { all_bags: &HashMap, memoized: &mut HashMap, ) -> bool { - return match memoized.get(&self.color) { + match memoized.get(&self.color) { Some(value) => *value, None => { let value = self.contains.iter().any(|(_, c)| c == color) @@ -85,7 +85,7 @@ impl BagRule { value } - }; + } } fn num_inner_bags(&self, all_bags: &HashMap) -> usize { diff --git a/aoc2020/src/day13.rs b/aoc2020/src/day13.rs index 5fe9974..8a36cb2 100644 --- a/aoc2020/src/day13.rs +++ b/aoc2020/src/day13.rs @@ -91,7 +91,7 @@ fn find_timestamp(input: &str) -> Result { } fn satisfies_constraint(solution: u64, (remainder, divisor): (u64, u64)) -> bool { - ((solution + remainder) % divisor) == 0 + (solution + remainder).is_multiple_of(divisor) } #[cfg(test)] diff --git a/aoc2021/src/day03.rs b/aoc2021/src/day03.rs index a96113c..e4aa948 100644 --- a/aoc2021/src/day03.rs +++ b/aoc2021/src/day03.rs @@ -84,7 +84,7 @@ where break; } - let one_is_more_common = count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2); + let one_is_more_common = count_ones(&numbers, pos) >= numbers.len().div_ceil(2); let digit_of_interest = strat(one_is_more_common); numbers.retain(|number| number.chars().nth(pos).unwrap() == digit_of_interest); diff --git a/aoc2022/src/day03.rs b/aoc2022/src/day03.rs index 1270cfa..a58b5dd 100644 --- a/aoc2022/src/day03.rs +++ b/aoc2022/src/day03.rs @@ -84,7 +84,7 @@ impl std::str::FromStr for RucksackSplit { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - if s.len() % 2 != 0 { + if !s.len().is_multiple_of(2) { bail!( "rucksack should contain an even number of items, this one contained {}", s.len() diff --git a/aoc2023/src/day01.rs b/aoc2023/src/day01.rs index 3152fb1..4e0fb86 100644 --- a/aoc2023/src/day01.rs +++ b/aoc2023/src/day01.rs @@ -28,7 +28,7 @@ fn part1(input: &str) -> Result { .sum()) } -fn part2(input: &str) -> Result { +fn part2(_input: &str) -> Result { todo!() } From e2fd5ad58ba49dd09b17baad91d6137deecb219c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 1 Dec 2025 13:59:45 +0100 Subject: [PATCH 116/134] cargo: bump lockfile --- Cargo.lock | 431 +++++++++++++++++++++++++++-------------------------- 1 file changed, 219 insertions(+), 212 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38c1399..07046b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] [[package]] name = "anes" @@ -10,9 +19,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "aoc" @@ -137,9 +146,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" @@ -180,23 +189,11 @@ dependencies = [ "byte-tools", ] -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byte-tools" @@ -206,9 +203,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cast" @@ -218,15 +215,15 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "ciborium" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -235,18 +232,18 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half", + "half 2.7.1", ] [[package]] @@ -262,14 +259,14 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "bitflags", "clap_lex", "indexmap", - "textwrap 0.16.0", + "textwrap 0.16.2", ] [[package]] @@ -317,7 +314,7 @@ dependencies = [ "atty", "cast", "ciborium", - "clap 3.2.23", + "clap 3.2.25", "criterion-plot 0.5.0", "itertools 0.10.5", "lazy_static", @@ -352,67 +349,54 @@ dependencies = [ "itertools 0.10.5", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "csv" -version = "1.1.6" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] @@ -428,9 +412,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "funty" @@ -449,9 +433,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -460,9 +444,20 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] [[package]] name = "hashbrown" @@ -481,9 +476,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", @@ -509,45 +504,31 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.138" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "md-5" @@ -562,18 +543,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "minimal-lexical" @@ -583,9 +555,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -593,34 +565,24 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "once_cell" -version = "1.16.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "opaque-debug" @@ -630,15 +592,15 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "os_str_bytes" -version = "6.4.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "plotters" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -649,39 +611,42 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -724,53 +689,64 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "regex" -version = "1.7.0" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[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.11" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -781,18 +757,13 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "serde" -version = "1.0.149" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -802,15 +773,24 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half", + "half 1.8.3", "serde", ] [[package]] -name = "serde_derive" -version = "1.0.149" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" +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", @@ -819,20 +799,22 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.89" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "itoa 1.0.4", + "itoa", + "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "syn" -version = "1.0.105" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -856,9 +838,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" [[package]] name = "tinytemplate" @@ -872,69 +854,56 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", - "winapi", "winapi-util", ] [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -942,28 +911,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -987,11 +959,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -1000,6 +972,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "wyz" version = "0.5.1" @@ -1008,3 +995,23 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] + +[[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", +] From d9c8d8155cc48fdca0e1505fc6fcc97dffb7b528 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 1 Dec 2025 14:05:26 +0100 Subject: [PATCH 117/134] ci: update checkout to v6 --- .github/workflows/rust.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index f6aee6f..0dd21f7 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 - name: Format run: cargo fmt --all -- --check - name: Lint From d310ec45c03b59dca29f6ba4ccf4efc612477f83 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 1 Dec 2025 15:03:54 +0100 Subject: [PATCH 118/134] 2025: day01 --- Cargo.lock | 8 + Cargo.toml | 2 +- aoc2025/Cargo.toml | 16 + aoc2025/input/day01.txt | 4392 ++++++++++++++++++++++++++++++ aoc2025/input/day01_provided.txt | 10 + aoc2025/src/day01.rs | 135 + aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 11 + 8 files changed, 4574 insertions(+), 1 deletion(-) create mode 100644 aoc2025/Cargo.toml create mode 100644 aoc2025/input/day01.txt create mode 100644 aoc2025/input/day01_provided.txt create mode 100644 aoc2025/src/day01.rs create mode 100644 aoc2025/src/lib.rs create mode 100644 aoc2025/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 07046b5..abcf848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,6 +133,14 @@ dependencies = [ "criterion 0.4.0", ] +[[package]] +name = "aoc2025" +version = "0.1.0" +dependencies = [ + "anyhow", + "aoc", +] + [[package]] name = "atty" version = "0.2.14" diff --git a/Cargo.toml b/Cargo.toml index 2896c26..9841ba8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = ["aoc20*", "aoc20*/aoc20*_bench"] -default-members = ["aoc2023"] +default-members = ["aoc2025"] resolver = "2" diff --git a/aoc2025/Cargo.toml b/aoc2025/Cargo.toml new file mode 100644 index 0000000..41f873e --- /dev/null +++ b/aoc2025/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "aoc2025" +version = "0.1.0" +authors = ["Antoine Martin "] +edition = "2024" + +[dependencies] +aoc = { path = "../aoc" } +anyhow = "1.0" + +[lib] +path = "src/lib.rs" + +[[bin]] +name = "aoc2025" +path = "src/main.rs" diff --git a/aoc2025/input/day01.txt b/aoc2025/input/day01.txt new file mode 100644 index 0000000..95c8342 --- /dev/null +++ b/aoc2025/input/day01.txt @@ -0,0 +1,4392 @@ +L32 +L15 +R38 +R47 +L40 +L9 +R27 +L7 +R27 +R37 +L26 +R49 +R29 +L24 +L42 +R29 +R2 +R47 +R19 +L46 +R1 +L30 +R34 +L16 +R41 +L32 +R46 +L17 +R34 +R9 +L22 +L42 +R22 +L15 +L15 +L42 +R42 +L6 +R42 +R34 +R13 +L2 +L9 +L45 +R3 +R30 +L5 +R11 +R18 +L42 +R68 +L94 +R7 +L15 +R34 +L26 +R23 +L97 +L18 +R61 +L96 +R88 +L16 +L19 +L7 +L93 +R50 +R67 +L17 +L38 +L62 +R91 +L14 +R89 +R15 +R42 +L46 +L93 +R16 +R24 +R76 +R50 +R30 +R20 +L57 +L43 +L97 +L1 +L54 +R52 +L95 +R95 +L94 +L24 +L64 +R60 +R68 +R32 +L50 +R58 +R6 +L92 +L121 +R33 +R288 +L20 +L4 +L1 +R25 +R86 +R49 +R65 +L48 +R948 +L48 +L1 +R77 +R42 +L70 +L98 +L7 +L30 +L758 +R293 +R94 +L510 +R14 +R5 +R14 +R37 +L55 +R185 +R16 +R870 +L40 +L18 +L152 +R10 +R914 +L84 +L51 +L447 +L2 +R57 +R43 +L448 +L80 +R83 +R45 +L94 +L10 +R88 +R57 +L31 +L10 +L187 +L86 +R73 +R54 +R32 +L8 +R117 +L4 +R9 +L56 +R56 +L13 +L265 +L22 +L335 +R35 +R30 +L60 +L70 +R28 +L428 +L516 +L4 +R462 +R675 +R6 +L22 +L58 +L43 +R60 +L60 +L11 +R94 +R66 +L49 +L73 +L83 +L7 +L95 +L84 +L64 +R28 +R33 +R45 +L17 +R94 +L887 +L390 +L81 +L38 +L95 +L13 +R38 +L11 +L917 +R17 +R61 +R47 +L659 +L50 +R59 +R80 +R44 +L35 +L47 +L191 +L79 +L30 +R79 +L79 +R88 +R97 +R27 +R6 +R37 +L8 +R139 +L552 +L71 +R48 +R19 +L246 +L95 +L56 +R397 +L14 +L93 +R80 +R86 +R11 +R585 +L85 +L91 +L909 +R92 +R8 +L82 +L50 +R45 +L24 +L51 +R59 +L15 +L82 +R58 +L31 +L27 +L727 +R55 +L24 +R47 +L74 +L98 +R29 +R92 +R17 +R83 +L29 +L35 +R52 +R312 +R54 +L20 +R27 +R60 +L91 +L96 +R95 +L29 +R47 +L14 +R64 +L52 +L445 +L23 +L84 +L93 +R63 +R89 +L52 +L78 +R78 +L37 +L11 +L111 +L40 +L901 +R26 +R50 +L676 +L57 +R343 +L5 +L81 +R491 +L12 +R21 +L21 +R592 +R99 +L870 +R83 +L112 +R84 +L55 +R72 +R41 +L13 +L67 +L233 +L62 +R62 +R75 +R25 +L85 +R6 +L21 +R92 +R61 +L71 +R10 +R42 +R66 +R99 +L28 +L71 +R616 +R96 +R65 +L37 +L22 +R49 +L44 +R77 +R95 +L97 +R5 +L3 +L584 +R51 +L67 +L7 +R7 +L153 +R76 +R77 +R6 +L13 +L93 +R23 +R977 +L10 +L21 +R31 +R55 +R31 +L36 +L67 +R938 +R99 +L20 +R43 +L43 +R26 +L51 +R37 +R88 +L36 +R648 +R288 +R84 +R67 +R55 +R72 +L309 +R31 +L45 +L55 +L1 +L68 +L71 +R32 +R26 +R982 +L729 +L954 +L98 +R10 +L8 +L4 +L87 +L84 +L84 +R63 +R86 +L97 +R386 +R14 +R86 +R26 +R29 +L17 +R33 +L963 +R26 +R603 +L66 +L71 +R14 +R86 +L60 +R14 +L54 +R92 +L37 +R301 +L56 +R787 +L87 +L49 +R52 +L596 +R8 +R51 +R49 +L29 +L41 +L45 +L36 +L16 +R16 +L945 +L19 +R52 +L52 +L55 +L17 +R72 +R72 +L39 +R72 +R95 +R26 +L11 +R39 +R46 +L1 +R1 +R10 +L55 +R74 +L29 +R85 +R9 +R43 +L37 +R48 +L48 +R35 +R80 +L47 +L319 +L103 +L98 +L21 +L27 +R63 +L563 +L86 +L14 +L752 +L96 +L46 +L6 +L65 +L35 +L86 +L39 +L869 +R51 +R49 +R24 +L830 +L99 +R99 +R14 +R67 +R70 +R34 +L98 +R13 +L17 +L849 +R66 +R60 +R859 +R82 +R799 +L34 +L47 +L48 +R61 +L9 +R31 +L54 +R77 +R38 +R485 +R66 +R43 +L9 +L80 +R76 +L21 +R555 +R70 +L67 +R69 +R24 +R74 +L27 +L63 +R954 +R97 +L61 +L61 +L31 +R46 +L943 +L97 +R48 +L23 +R661 +R57 +L57 +R87 +L87 +L98 +L346 +L62 +R62 +L41 +L85 +L30 +R2 +L26 +R477 +L53 +R83 +L902 +R85 +R34 +R64 +L690 +L72 +L286 +R66 +L96 +R1 +L44 +R246 +R11 +R390 +L290 +L94 +L6 +R143 +R57 +L26 +L18 +R536 +L92 +L136 +L18 +L54 +R8 +L3 +L59 +R16 +L26 +R96 +R76 +L15 +R15 +R10 +L86 +L586 +R28 +R34 +R58 +L603 +L53 +R36 +L38 +R370 +L70 +R1 +R75 +R49 +L89 +R57 +R43 +R16 +R493 +L87 +R73 +L11 +L387 +R67 +L74 +R34 +L967 +R7 +L84 +L70 +R4 +R50 +R39 +L82 +L57 +R289 +L31 +L46 +R66 +L78 +L53 +R53 +R96 +R599 +L98 +L97 +L46 +L54 +L86 +L62 +L58 +R22 +L953 +L63 +R308 +L39 +R3 +R512 +R16 +R98 +L98 +R17 +R83 +R2 +R33 +R87 +L96 +R174 +R270 +L51 +R81 +L571 +R71 +L90 +L41 +L314 +R45 +L55 +L45 +L815 +L23 +L34 +L978 +L50 +R955 +R87 +R58 +L65 +R77 +L99 +L90 +R71 +R193 +L71 +L16 +R64 +L64 +L28 +R885 +R13 +R63 +R446 +L91 +L688 +L61 +R61 +R10 +L92 +L88 +L40 +R99 +L489 +R41 +L80 +L526 +R1 +R152 +L36 +R15 +R33 +L229 +L71 +L43 +R243 +L40 +R40 +L554 +R54 +L20 +L80 +L10 +R89 +R121 +L632 +R46 +R54 +L24 +L44 +L33 +L877 +L88 +L4 +L98 +L258 +L57 +R15 +L9 +L58 +R51 +R217 +R47 +R21 +L69 +R45 +R84 +R65 +L94 +R20 +R80 +R805 +L5 +R48 +R52 +R835 +L35 +L71 +L12 +L17 +R18 +L61 +L22 +L612 +L75 +L48 +R844 +R59 +L13 +L604 +L86 +L41 +L59 +R241 +L41 +L9 +L28 +L427 +R83 +L19 +R59 +R65 +L36 +L88 +R935 +R984 +L19 +L14 +L956 +R70 +R960 +L19 +R813 +R31 +L5 +R61 +L695 +L846 +L23 +R23 +R61 +R39 +L61 +R43 +L17 +R835 +R52 +L52 +L36 +L759 +L86 +R44 +L8 +R45 +R17 +L17 +R69 +L969 +R55 +L55 +L39 +L61 +R13 +L28 +R28 +R87 +R331 +L31 +R461 +R14 +R37 +L12 +R59 +L227 +L33 +L668 +R92 +L3 +R57 +R30 +R93 +L88 +R43 +R94 +L49 +R25 +L75 +R50 +L54 +L46 +R994 +R48 +L42 +R63 +L63 +R7 +R24 +L651 +R73 +L53 +L91 +R91 +R11 +R89 +R44 +R93 +L2 +R65 +L277 +L60 +L42 +R88 +R13 +L922 +R34 +L34 +R87 +L82 +L55 +L78 +L35 +R7 +R125 +L41 +L28 +L711 +L678 +R589 +R3 +L3 +L494 +R89 +R36 +R69 +R51 +R483 +L334 +R95 +L95 +R24 +R68 +R769 +R39 +R44 +R77 +R24 +R87 +R69 +R94 +R23 +L41 +R51 +R72 +L71 +L81 +L4 +L44 +L23 +R49 +L26 +L10 +L90 +L98 +L63 +R60 +L92 +L999 +L69 +L39 +L424 +L76 +R68 +L68 +L23 +L74 +L878 +R8 +L233 +R17 +L17 +R13 +R94 +L85 +R92 +L14 +L25 +R305 +R24 +R236 +R32 +R23 +R22 +L292 +L44 +R819 +R7 +L47 +L860 +L20 +L80 +L10 +L38 +L66 +R14 +R20 +L20 +R8 +L628 +R21 +R59 +L924 +R29 +L665 +L31 +R13 +L335 +L518 +R90 +L81 +R81 +L19 +R28 +R86 +R86 +R23 +R75 +L75 +L91 +L77 +R26 +R19 +L7 +L60 +L33 +R404 +R96 +L719 +R619 +L42 +R42 +R281 +L16 +R77 +R58 +L57 +L63 +L24 +R50 +L6 +R87 +L39 +R752 +R208 +L37 +R25 +R56 +L69 +R517 +L387 +L543 +R89 +R604 +L27 +L36 +L82 +R57 +L120 +R775 +R70 +R814 +L70 +R47 +L71 +L57 +R37 +L81 +R81 +L389 +L11 +R47 +L847 +R83 +R25 +L59 +L220 +R306 +R65 +R39 +L89 +R65 +R85 +R88 +L88 +R816 +R14 +R770 +R58 +L58 +R151 +L251 +R25 +R282 +L7 +L97 +L3 +R88 +L6 +R18 +R29 +R72 +L162 +L51 +R12 +R25 +R975 +L91 +L109 +L314 +L86 +R85 +R85 +L47 +R86 +R93 +R98 +R12 +L83 +R571 +R2 +R8 +L410 +R25 +L18 +R440 +R53 +R81 +L81 +R55 +L34 +L26 +L164 +R7 +R62 +R57 +L57 +L44 +R25 +L50 +R69 +L92 +R640 +R1 +L49 +L19 +L181 +L38 +L446 +R784 +R33 +L1 +L41 +R784 +L90 +L85 +L50 +L50 +R39 +L93 +R78 +L50 +L19 +L29 +L63 +R10 +R985 +L83 +R565 +L57 +L83 +L99 +R99 +R35 +R65 +L15 +L88 +L14 +L86 +R13 +R90 +L84 +L16 +L86 +L14 +L79 +R36 +R43 +L66 +L66 +R532 +L86 +L861 +R47 +R1 +R67 +L12 +R144 +R89 +R8 +L43 +L46 +R892 +L94 +R94 +L80 +R80 +L776 +R76 +L1 +R25 +L56 +R27 +L91 +R91 +R40 +R235 +L93 +L50 +R465 +L50 +L42 +L91 +R35 +L366 +R22 +R88 +L97 +R229 +R8 +R72 +L586 +R86 +L61 +R47 +R14 +L17 +L90 +L4 +L73 +L56 +L460 +L67 +R81 +L15 +L74 +R789 +R39 +R73 +R11 +L74 +L63 +L82 +L39 +L35 +L44 +L57 +R57 +R408 +L10 +L77 +R97 +L18 +L15 +R6 +R89 +R48 +R26 +R284 +R62 +R657 +L641 +R860 +R9 +L27 +R742 +L930 +L29 +L41 +R57 +R43 +R77 +R17 +R6 +R68 +L7 +R14 +R80 +L55 +L75 +L26 +L24 +L775 +R50 +R59 +R91 +L42 +R62 +R280 +R92 +L92 +R51 +R3 +R46 +L22 +L78 +L32 +L220 +L34 +R501 +L44 +L571 +R76 +L20 +L91 +L94 +R72 +L562 +R272 +L34 +L63 +L8 +R13 +L79 +L79 +R424 +L810 +R93 +R90 +R72 +L72 +L219 +L32 +R15 +R55 +L32 +L887 +R59 +L79 +L1 +R212 +L730 +R39 +R90 +R510 +L15 +L30 +R91 +R21 +L67 +L2 +L98 +L630 +L681 +R27 +L16 +L430 +L23 +R53 +R84 +R88 +R91 +R95 +L58 +L38 +R86 +L48 +R81 +L39 +L42 +L35 +L65 +R26 +R4 +L30 +R92 +R346 +R574 +L12 +R64 +R36 +L621 +L89 +R76 +R39 +R887 +R64 +L56 +R268 +L96 +L1 +L402 +L269 +R46 +L64 +L533 +L49 +R42 +R158 +L255 +R80 +R240 +R5 +L88 +L82 +L550 +L683 +R49 +R86 +L2 +L12 +L36 +L152 +L78 +R41 +R85 +L16 +R68 +L369 +L1 +L4 +L1 +R75 +R651 +R32 +R20 +L93 +L188 +R78 +L32 +L91 +R48 +R90 +R85 +L11 +L40 +L11 +R62 +R42 +L369 +L673 +L893 +R762 +R15 +R416 +L33 +R27 +L894 +R4 +L76 +L12 +R29 +R59 +R596 +R67 +R126 +R953 +R142 +L88 +L80 +L40 +L280 +L77 +L23 +L61 +R1 +R54 +R8 +R98 +R26 +L27 +R706 +R348 +R48 +R33 +L64 +L68 +L2 +L26 +R74 +R26 +L74 +L36 +L64 +L3 +R3 +R388 +L29 +L837 +L95 +L27 +R506 +L137 +L369 +R49 +R319 +R32 +R69 +L299 +L8 +R38 +R40 +R60 +R62 +R36 +L98 +L4 +R4 +L74 +L3 +R77 +R24 +L79 +R55 +L512 +L61 +L95 +L33 +L92 +R79 +L53 +R54 +R72 +L2 +L55 +R98 +L204 +R98 +L98 +L96 +L18 +L82 +L22 +R15 +R88 +R19 +R6 +R892 +R2 +R615 +L15 +R984 +R16 +L28 +R804 +R72 +R52 +R48 +R41 +L789 +L72 +L82 +R54 +L42 +R542 +R43 +L84 +R141 +L12 +R782 +R92 +L68 +L92 +R80 +L53 +R71 +L98 +L2 +R97 +L343 +L55 +L99 +L726 +L64 +L10 +R66 +R56 +R20 +R58 +L78 +R78 +R22 +R35 +L195 +R38 +R94 +L837 +L61 +R25 +R86 +L27 +R20 +R89 +R62 +R91 +R14 +L68 +L88 +L79 +L21 +R28 +L328 +L89 +L877 +L789 +R55 +R29 +R30 +L290 +L73 +L13 +R726 +L303 +L78 +R81 +L33 +L96 +L88 +L992 +R30 +R55 +L985 +R16 +R84 +R90 +R70 +L260 +L40 +R4 +L95 +R939 +L34 +L4 +R97 +R14 +R30 +R84 +R5 +L47 +R47 +L445 +L55 +L69 +L90 +R79 +R36 +R579 +L60 +R725 +L52 +L203 +R883 +R91 +R40 +L38 +R3 +L24 +R53 +L53 +R98 +R2 +R78 +R68 +R54 +R31 +L6 +L25 +R78 +R46 +R83 +R58 +L29 +R54 +L90 +L442 +L206 +L450 +R35 +R63 +R95 +R818 +R31 +R253 +L19 +L812 +R63 +L5 +R478 +R42 +R56 +R429 +L26 +R3 +R36 +L42 +R40 +L64 +L76 +R39 +R61 +L147 +R43 +R4 +L4 +L94 +L84 +L27 +L260 +R32 +L76 +L887 +R30 +L30 +L99 +L78 +R72 +R205 +R16 +R977 +R92 +R95 +R824 +R96 +R80 +L98 +L582 +L31 +L605 +R99 +L83 +L70 +R86 +L33 +R66 +R19 +L85 +L68 +L56 +R93 +R61 +R7 +L82 +L68 +R50 +L6 +L110 +L484 +L29 +L14 +L57 +R72 +R10 +L382 +L39 +L71 +L84 +L79 +R73 +L955 +R55 +R63 +L13 +R508 +R29 +L371 +L15 +L38 +L7 +R688 +R46 +L90 +L38 +L6 +L56 +L51 +R94 +L25 +R82 +L87 +R121 +L34 +L23 +R923 +R71 +R47 +L96 +L569 +L56 +L99 +R76 +L95 +R21 +L31 +L69 +L56 +R46 +R16 +R5 +L14 +R77 +L74 +R495 +L470 +L79 +L80 +R928 +L96 +L57 +R39 +R20 +L80 +R80 +R85 +R15 +L403 +R607 +R96 +L63 +R63 +L395 +L5 +L204 +R4 +L93 +R10 +R439 +L95 +R39 +L36 +R936 +L224 +L76 +L761 +R61 +R21 +L421 +L32 +L46 +L67 +R45 +R75 +R25 +L826 +L98 +L544 +L8 +L67 +R753 +R61 +R29 +L11 +R92 +L81 +L73 +L27 +L96 +L4 +R1 +L12 +L628 +R94 +R1 +L56 +R3 +R97 +R889 +L89 +R146 +L46 +R72 +L53 +R381 +R59 +R13 +R365 +R96 +R346 +L857 +R83 +R89 +L86 +R95 +R97 +R567 +L2 +L65 +L44 +R957 +R548 +R60 +R79 +L85 +L57 +L49 +L47 +R38 +L59 +R36 +L477 +R80 +L12 +L71 +R26 +R81 +R75 +L68 +L11 +L46 +L354 +L37 +L14 +L95 +L752 +R376 +L34 +R40 +L30 +R46 +R645 +L22 +R64 +R13 +R93 +R207 +L961 +L39 +L389 +L11 +L91 +L9 +L89 +L311 +R218 +L18 +L33 +L13 +R81 +L40 +L70 +L71 +R68 +L22 +L88 +R89 +R221 +R721 +L43 +R30 +L54 +L78 +R268 +R74 +R60 +R91 +R92 +L40 +L999 +R56 +R368 +R32 +L33 +R76 +L33 +L10 +R93 +L47 +L47 +R23 +L320 +R72 +R326 +L567 +R729 +L57 +R95 +L309 +L69 +R6 +R72 +L557 +L25 +R61 +R21 +L3 +R3 +R17 +L32 +R52 +R63 +R736 +R64 +R3 +R491 +R6 +R77 +R52 +R71 +L99 +L7 +L64 +L299 +R269 +L91 +R79 +R37 +R32 +R12 +R86 +R671 +R452 +R522 +L41 +L844 +L50 +L65 +L17 +R6 +R39 +L579 +R44 +R64 +R885 +R306 +R920 +L68 +R63 +R737 +R12 +R27 +R20 +R72 +R87 +L22 +L96 +L432 +L48 +R70 +L35 +R45 +L97 +R6 +L41 +R9 +L38 +R61 +R58 +L97 +L49 +L54 +L23 +R8 +L976 +L70 +L513 +L55 +L660 +R31 +R35 +L85 +L42 +L35 +L78 +L73 +L31 +R66 +R93 +R93 +L794 +L98 +R87 +R50 +L40 +L48 +L482 +R108 +L26 +L81 +R94 +R9 +L355 +L606 +L91 +R30 +R10 +R59 +R31 +R31 +R69 +R254 +R11 +L793 +R528 +L22 +R60 +R50 +L88 +L79 +R69 +L40 +L50 +R42 +R93 +R23 +R29 +R13 +R552 +L50 +L774 +L70 +R42 +L85 +R322 +R15 +R71 +R80 +L3 +L12 +L50 +L38 +L579 +L14 +L94 +L127 +L568 +L224 +L242 +R48 +R43 +L873 +L270 +R11 +L11 +R57 +R36 +L73 +L20 +L652 +R19 +R33 +L59 +L51 +R112 +L802 +L61 +L739 +L84 +R84 +L11 +R11 +L25 +L75 +R24 +L32 +L92 +R4 +L26 +L78 +L362 +L38 +R64 +L683 +R333 +R86 +L30 +R30 +L42 +L16 +R58 +R60 +L86 +L64 +L29 +L36 +R55 +L9 +R9 +R97 +R45 +R78 +R40 +R82 +R858 +R69 +L92 +R28 +L105 +L306 +L94 +R41 +L463 +R22 +L18 +R22 +L603 +R108 +L9 +L814 +R55 +L58 +R17 +R50 +L44 +L47 +R41 +R49 +L55 +R75 +R42 +R89 +L68 +L663 +L69 +L11 +R11 +R40 +R666 +L49 +L57 +R9 +R87 +L96 +L58 +R58 +L25 +L75 +L35 +L60 +R62 +L67 +L132 +R32 +R606 +L306 +L265 +L35 +R32 +R70 +L20 +L44 +L98 +R31 +L71 +R995 +L95 +R57 +L78 +L79 +R92 +R8 +R42 +R15 +R43 +L8 +R32 +L509 +L4 +L11 +L16 +R24 +L58 +L50 +R32 +L84 +R69 +L17 +R578 +R33 +L313 +L225 +R66 +L901 +L889 +L76 +L81 +L92 +L75 +L25 +R9 +L321 +L34 +L90 +R36 +R72 +R28 +L25 +L72 +L3 +R21 +R88 +L809 +R96 +R397 +L93 +R185 +R33 +R93 +L11 +R29 +L29 +R46 +R46 +R8 +R1 +L1 +R1 +L70 +L11 +R89 +R76 +L86 +L99 +L25 +L75 +L68 +R63 +R5 +R88 +R16 +R96 +R37 +R63 +R9 +R265 +R96 +L70 +R68 +R83 +L3 +R52 +R632 +L63 +L83 +L86 +R55 +R22 +R34 +L11 +L3 +L97 +R42 +L26 +R167 +L78 +L921 +L87 +L97 +L60 +R24 +L64 +L15 +R85 +L54 +L16 +L78 +R178 +R41 +R10 +L75 +L90 +R255 +L41 +L50 +L76 +R26 +R155 +L41 +L6 +L30 +L16 +R6 +L68 +L91 +L11 +L21 +R46 +L68 +R43 +R2 +R48 +R59 +L59 +R66 +L75 +L13 +R174 +R31 +R89 +L3 +L70 +R53 +R79 +R40 +R981 +L57 +R22 +R14 +R33 +R10 +R299 +R79 +R671 +L71 +L61 +L639 +R41 +L41 +R52 +R48 +R209 +R91 +R84 +R96 +L80 +R89 +R17 +R94 +L26 +R26 +R87 +L87 +R807 +L7 +R818 +R92 +R90 +R63 +R37 +L290 +L736 +L36 +R897 +L82 +L675 +R891 +R479 +L60 +R94 +R18 +L565 +L57 +L78 +L50 +R950 +R39 +R77 +L16 +L27 +L81 +R32 +L89 +L66 +R323 +L63 +R1 +R419 +L19 +R70 +L45 +R45 +L22 +L441 +R9 +L46 +R34 +R68 +R98 +L435 +L64 +L86 +L546 +R73 +R83 +R18 +L47 +R87 +L8 +L34 +R59 +R22 +R78 +R60 +L57 +L55 +R86 +R26 +L60 +R71 +R71 +R32 +L74 +R796 +R950 +L382 +L42 +R68 +R96 +L91 +R30 +R52 +L77 +R5 +L660 +R955 +R77 +R644 +L21 +R99 +L99 +L287 +R26 +L39 +L2 +R53 +L769 +R29 +R93 +L72 +R24 +L56 +L25 +L91 +R16 +L10 +L649 +L546 +R5 +L95 +R95 +R81 +L21 +L60 +R63 +R137 +L9 +R283 +L44 +L39 +L11 +L880 +R19 +L19 +R3 +R97 +L79 +L9 +L21 +R804 +R89 +L27 +R43 +R71 +L93 +R46 +L54 +R377 +R954 +L1 +R285 +R182 +L67 +L83 +R30 +R861 +R592 +L27 +L46 +L539 +L188 +L422 +R22 +R82 +R58 +L40 +R43 +L26 +R83 +L555 +L75 +L338 +L78 +R58 +R88 +L734 +L66 +R1 +L501 +L4 +R83 +L54 +R2 +L63 +L97 +R32 +L43 +L95 +R46 +R428 +R36 +R29 +R76 +R41 +R45 +L42 +L49 +L71 +R79 +L79 +R33 +L203 +L88 +L42 +L45 +R91 +R28 +L55 +R381 +L606 +R46 +R13 +R47 +R81 +L58 +R892 +R54 +R31 +L7 +R880 +L31 +L67 +R25 +L15 +L46 +L51 +L31 +R76 +R938 +R84 +L26 +L29 +L775 +L892 +L40 +R34 +R73 +L978 +L222 +R99 +L99 +L862 +R32 +L70 +L80 +R65 +R15 +R869 +R853 +L84 +L552 +L104 +R18 +R93 +R7 +L68 +L32 +L13 +R70 +L1 +R806 +R37 +L35 +L44 +R50 +R449 +R81 +L57 +L73 +R30 +R99 +R802 +R550 +R49 +L49 +R309 +L60 +L28 +R928 +R26 +L40 +R14 +L46 +R722 +R24 +L93 +R85 +L904 +L72 +L916 +R36 +R1 +R77 +L7 +R93 +R84 +R16 +L33 +L86 +R52 +R867 +L585 +L441 +L74 +R53 +R47 +L520 +L87 +L92 +L47 +R80 +L48 +L986 +L76 +L24 +R453 +R66 +L19 +R18 +L18 +L33 +R78 +R235 +L97 +L983 +R801 +L601 +L35 +L23 +R12 +R746 +L73 +R73 +L82 +L65 +L53 +L46 +L655 +L9 +L90 +R2 +R698 +L40 +L63 +L228 +R31 +L99 +L1 +R811 +R2 +R35 +R52 +R39 +L33 +R27 +R2 +R968 +L98 +L14 +L21 +R20 +R537 +L83 +R369 +R59 +R135 +L211 +L96 +R63 +R3 +R634 +R38 +R64 +R80 +R708 +R34 +L23 +R952 +L53 +L86 +L67 +R53 +R9 +L9 +L65 +R8 +L434 +L9 +L373 +L294 +L96 +L30 +R93 +R76 +R734 +R90 +L25 +L961 +L81 +L33 +R52 +L852 +L2 +R2 +L826 +L74 +R5 +R660 +R35 +L27 +L73 +R40 +R11 +L51 +R930 +R599 +R637 +R733 +R101 +L97 +R97 +R22 +L87 +L35 +R43 +R14 +R13 +R68 +R46 +R235 +L19 +R64 +R36 +R559 +L32 +R65 +R637 +L5 +R32 +R44 +L74 +L158 +R32 +R64 +L94 +R60 +L69 +R40 +R39 +L82 +R42 +L84 +R84 +L597 +R20 +L68 +L55 +R83 +L83 +L60 +R60 +R52 +L30 +L94 +R37 +L98 +R33 +R47 +L49 +R1 +L799 +L3 +R732 +L24 +R74 +L958 +R64 +R15 +R64 +R36 +L21 +L997 +R21 +R79 +L92 +R5 +R73 +L79 +L37 +R40 +R454 +L46 +L58 +L61 +L81 +L74 +L91 +L35 +R430 +R70 +L59 +R27 +R932 +L670 +R70 +L71 +L48 +L3 +R22 +R73 +L73 +R887 +L28 +R41 +R11 +L911 +R60 +L476 +R415 +R8 +R96 +L95 +L82 +R374 +R86 +R14 +L6 +L23 +R707 +R333 +R61 +R828 +R17 +L17 +L35 +L39 +L826 +R9 +L9 +L52 +L54 +R98 +R8 +R30 +L60 +L69 +R99 +L65 +L391 +R56 +L618 +R143 +L95 +L96 +R66 +R48 +R52 +R171 +R52 +L17 +L52 +L54 +L13 +L48 +R53 +L117 +R25 +L689 +L11 +L17 +R17 +R3 +L36 +L42 +L48 +R23 +R2 +R98 +R30 +R12 +L942 +L5 +R29 +R76 +L31 +L369 +R10 +R90 +L558 +L42 +R3 +R97 +R858 +L58 +L77 +R84 +R95 +L13 +L89 +L93 +R37 +L521 +R27 +L24 +R2 +R58 +R92 +L78 +L63 +R963 +L985 +L88 +R73 +R96 +L186 +R48 +R45 +R89 +R19 +R89 +L18 +R691 +R27 +L40 +R40 +R12 +R49 +R39 +R30 +L30 +R39 +L98 +R59 +R89 +L89 +R1 +R22 +L23 +R676 +R24 +L55 +R23 +R92 +L360 +L18 +L82 +L89 +R89 +L49 +L51 +R36 +L73 +L63 +L14 +L81 +L986 +L37 +L82 +R44 +L467 +L304 +R69 +L42 +L109 +L3 +R412 +R514 +L14 +L7 +L78 +L15 +L87 +R33 +L56 +R75 +R443 +L42 +L866 +L278 +L22 +R94 +R9 +R94 +L97 +R23 +L823 +R20 +L20 +L85 +R5 +L25 +R768 +L63 +L50 +R5 +R103 +R576 +R8 +L40 +L67 +R55 +R316 +R84 +R10 +L80 +L20 +L29 +R726 +L87 +L110 +L6 +L94 +R45 +R855 +L71 +L62 +L67 +R21 +R79 +L60 +R60 +R196 +L20 +L47 +R25 +R46 +L9 +L503 +L90 +L98 +L455 +L84 +R839 +L56 +R14 +L45 +L14 +L36 +L83 +L80 +L53 +R53 +R247 +R53 +L771 +L80 +R101 +L50 +R62 +R53 +R396 +R58 +R35 +L80 +R285 +R860 +R31 +R38 +L38 +R81 +L81 +L14 +L886 +R13 +L13 +R32 +R68 +R59 +L89 +L31 +L597 +R33 +R78 +R47 +R59 +L90 +R731 +R69 +L169 +L23 +R10 +L98 +L369 +R55 +R57 +R68 +L41 +R28 +L87 +R63 +L19 +R69 +R87 +L80 +L72 +L48 +L47 +R20 +L73 +L956 +R6 +R32 +R156 +R62 +L12 +R20 +R8 +L182 +L74 +L860 +R40 +L40 +L92 +L18 +L90 +R79 +L79 +R41 +R62 +R324 +R401 +R572 +L51 +L571 +L90 +R12 +R37 +L50 +R2 +L28 +L61 +L74 +L726 +L94 +L7 +L99 +R42 +L80 +R11 +L73 +R11 +R2 +L13 +L305 +R95 +L28 +R22 +R5 +R66 +L55 +R95 +R5 +L66 +L34 +R553 +L24 +L29 +L85 +L1 +R23 +R63 +R41 +L91 +L485 +L96 +L169 +R88 +R69 +L57 +R22 +L7 +L15 +L37 +R5 +R39 +R7 +R86 +L81 +L81 +L238 +R9 +L17 +L58 +R15 +R51 +R26 +L26 +R86 +R514 +R74 +L130 +L99 +R255 +L79 +L21 +L16 +L30 +R39 +L87 +R94 +R13 +R68 +L81 +L80 +R9 +R971 +R63 +L99 +R79 +L43 +R32 +L32 +L77 +R58 +R19 +R899 +R41 +R67 +R8 +L15 +L89 +R689 +L421 +R702 +R19 +L41 +R41 +R55 +R317 +L67 +L45 +L58 +R798 +L41 +L15 +L97 +L84 +L27 +L81 +L55 +R32 +L32 +L515 +L46 +R61 +L80 +L32 +R812 +R4 +R239 +L43 +L30 +L70 +R2 +R98 +L568 +R57 +R11 +L62 +L98 +R60 +L72 +R72 +R959 +R54 +L15 +R965 +L54 +L909 +L4 +R612 +R5 +L13 +L31 +L57 +L54 +R60 +R11 +R63 +R1 +R11 +R15 +R322 +L96 +R18 +R19 +R28 +L10 +R70 +L70 +R18 +L86 +R594 +L73 +R747 +R494 +L434 +R40 +L69 +R94 +L67 +L76 +L82 +R434 +L273 +L383 +R30 +R37 +L84 +R2 +L763 +L839 +L92 +L69 +R99 +L18 +L81 +R16 +L16 +R55 +L455 +R56 +L42 +R86 +L48 +R29 +R84 +R35 +L36 +R731 +R437 +R56 +L789 +L29 +L81 +R45 +R4 +R5 +R31 +R26 +R95 +R5 +R823 +L48 +R65 +L55 +L672 +L13 +R52 +L52 +R54 +L60 +L955 +L339 +R12 +L12 +L94 +L6 +L294 +L706 +L42 +R523 +L845 +R16 +R437 +L89 +R36 +L56 +L80 +R46 +L643 +R76 +L971 +R775 +R17 +R57 +L57 +R65 +L65 +L62 +L89 +L49 +L81 +L19 +R605 +L58 +R53 +L31 +L52 +L17 +R44 +L368 +L528 +L48 +L92 +R87 +R25 +R96 +L16 +R282 +R18 +L330 +R730 +R45 +R42 +R65 +L95 +R32 +R56 +L245 +L32 +L44 +L520 +R4 +R401 +R691 +L37 +L29 +R750 +L92 +R8 +L53 +L29 +R82 +R80 +R95 +L920 +R412 +L267 +L4 +R440 +L36 +L90 +R90 +R502 +R98 +L45 +R45 +L7 +L495 +R11 +L3 +L6 +L51 +R51 +L2 +L898 +L61 +L86 +R298 +R392 +L55 +R12 +R80 +R920 +R88 +L864 +L91 +R37 +L25 +R55 +L92 +R5 +R31 +R81 +L23 +R698 +L75 +R312 +L14 +R777 +R61 +L61 +L51 +R53 +L269 +R67 +R73 +R27 +R8 +L508 +L473 +R82 +L90 +R217 +R88 +R76 +R857 +R97 +R8 +L462 +R67 +L808 +L950 +R55 +R42 +L58 +L91 +R96 +R947 +L40 +R340 +L74 +R571 +L82 +L793 +R90 +L12 +L5 +L97 +L316 +L82 +L75 +R152 +L13 +L64 +L14 +L86 +L796 +R27 +R69 +R36 +R352 +R12 +L167 +L13 +L20 +L68 +R82 +R45 +L41 +L18 +L47 +L446 +L54 +L91 +R333 +L95 +L22 +R22 +L74 +R38 +L20 +L39 +R85 +L76 +R74 +L82 +L6 +R36 +R64 +L27 +R27 +L86 +R86 +L40 +L20 +L86 +L65 +R28 +L12 +L573 +R529 +R39 +L10 +R19 +R491 +L169 +R888 +L5 +L37 +L65 +L5 +L107 +L3 +R97 +R36 +R95 +L178 +R56 +R291 +R98 +R8 +R83 +R371 +R69 +L72 +R649 +R76 +R25 +L1 +L20 +L65 +R16 +R27 +L58 +R246 +L46 +L75 +L82 +L43 +R439 +R61 +R46 +R52 +R21 +L29 +R10 +L51 +R691 +R60 +L840 +L85 +L75 +R95 +R63 +L80 +L56 +L22 +R668 +R212 +L62 +R82 +R24 +L124 +R17 +R15 +R68 +L30 +R306 +R24 +R56 +L11 +L913 +L32 +L721 +L79 +L53 +L47 +R39 +R82 +L476 +R134 +L79 +L9 +R9 +R89 +R11 +L71 +L29 +L35 +R93 +L931 +R78 +R18 +L23 +L51 +L81 +R7 +R291 +R68 +L934 +R52 +R48 +L50 +R50 +R77 +L77 +R503 +R97 +R21 +L21 +R39 +L83 +L202 +R13 +R933 +R145 +L545 +L13 +R90 +R93 +R95 +R735 +L327 +L73 +L44 +L656 +R40 +R60 +L6 +L94 +R15 +L15 +R4 +L4 +R60 +L52 +L408 +L75 +L21 +R685 +R95 +L608 +R89 +R35 +L55 +R89 +L94 +L740 +R50 +R11 +R96 +R85 +L42 +R6 +L6 +R370 +L770 +R558 +R211 +R69 +L238 +L84 +L258 +L42 +L962 +L48 +L36 +R589 +R41 +R16 +R84 +R38 +L38 +R70 +R81 +R149 +L94 +L6 +R741 +R36 +L64 +L20 +L693 +L140 +L89 +R29 +L211 +R11 +L13 +L49 +L938 +L62 +R62 +R71 +R21 +L258 +R66 +L9 +L76 +L38 +R46 +R97 +R11 +R648 +L66 +R95 +R92 +R563 +L87 +L59 +L4 +R87 +R77 +R23 +L885 +R57 +R5 +R11 +R267 +R22 +L77 +R27 +L25 +R498 +L74 +L16 +L10 +L712 +L979 +L64 +L45 +R95 +R205 +R394 +R295 +L46 +L43 +L83 +R159 +R95 +L897 +R963 +L37 +R10 +R890 +R733 +L54 +L479 +R49 +L79 +R799 +R931 +R269 +R587 +L38 +R82 +R64 +L30 +R66 +L94 +R35 +R721 +R38 +L47 +R47 +R80 +L709 +L15 +R84 +L55 +R215 +R26 +R95 +L57 +L97 +R20 +R76 +R72 +R65 +L372 +R795 +R77 +R78 +L78 +R34 +R66 +R81 +L66 +L65 +R50 +R34 +R932 +R234 +L35 +R295 +R85 +L7 +L938 +R809 +L34 +L41 +L34 +R17 +R47 +L64 +R54 +L17 +R60 +R27 +L24 +R57 +R10 +L31 +L36 +R96 +R738 +L10 +R326 +R553 +L67 +L65 +L76 +L95 +R82 +R18 +L78 +R732 +R884 +L68 +R9 +R20 +R88 +R94 +R14 +R5 +R11 +R89 +R926 +L58 +L68 +L831 +R23 +R91 +R30 +L48 +R90 +R13 +L68 +L95 +L14 +R54 +L45 +L75 +L990 +R694 +L29 +L570 +L77 +L76 +L66 +L911 +R286 +R14 +L54 +R6 +L6 +L78 +L235 +R67 +R579 +L79 +R713 +R534 +L67 +L66 +L23 +R263 +L25 +L67 +R428 +L18 +R35 +L75 +R59 +L2 +R82 +L71 +L31 +R7 +R527 +R797 +L31 +R86 +L91 +L86 +R88 +R34 +R839 +R81 +L47 +L35 +R60 +R2 +R694 +R81 +R25 +L44 +R342 +L546 +L98 +L54 +L2 +L98 +R944 +R56 +L24 +R71 +L47 +L65 +R53 +L84 +R52 +R79 +L726 +L62 +R753 +L42 +R94 +L3 +L49 +R66 +L370 +R4 +R49 +R18 +R10 +L177 +R878 +L78 +L804 +R88 +L62 +R78 +L519 +R19 +R97 +R69 +L91 +R16 +R45 +L36 +R61 +R18 +L79 +L7 +R58 +L54 +L731 +L266 +L15 +L59 +L57 +L782 +R13 +R38 +L614 +R51 +R25 +L44 +L256 +L72 +R4 +R64 +L547 +L40 +R692 +L1 +R915 +L6 +R61 +R85 +R43 +R679 +R9 +R19 +R95 +L94 +L38 +L68 +R41 +L41 +R16 +R43 +R12 +L331 +L87 +R47 +L69 +L84 +L47 +L40 +L60 +R63 +L19 +L44 +R61 +L108 +R47 +R95 +L95 +R432 +R71 +R53 +R86 +L418 +L24 +R39 +L531 +L8 +L452 +R32 +R45 +L58 +L43 +L77 +L47 +L95 +L306 +L99 +R85 +R15 +L26 +R726 +R81 +L81 +R64 +R92 +R30 +R2 +R412 +R51 +R28 +L79 +L42 +R27 +L21 +L51 +L13 +R415 +L5 +L76 +L13 +R60 +L81 +R99 +L99 +R4 +L804 +R715 +L52 +L63 +R80 +L98 +L82 +L6 +R56 +R650 +L46 +L54 +R40 +R60 +L8 +R8 +R176 +R45 +L18 +L3 +L67 +R73 +L49 +L9 +R52 +R74 +R431 +R95 +L30 +R738 +R92 +L17 +R17 +L46 +R204 +R46 +R96 +L5 +L131 +R32 +L96 +L66 +L634 +L39 +R639 +L92 +L15 +L93 +L5 +R6 +R35 +L36 +R804 +L18 +L48 +L7 +R83 +R569 +L35 +L48 +L125 +L67 +R92 +R98 +L98 +L15 +L753 +L30 +R747 +L21 +R57 +L635 +R747 +R3 +R17 +R79 +L45 +R53 +L4 +R49 +R89 +L38 +L26 +R876 +L337 +R71 +L23 +R37 +L398 +R9 +R70 +L11 +L12 +R42 +R2 +L56 +R48 +L37 +L55 +L68 +R32 +L64 +R91 +R13 +R51 +R76 +L17 +L69 +L45 +R72 +L73 +L13 +L72 +L55 +L16 +L10 +L32 +L62 +R61 +R39 +R52 +R79 +L48 +L61 +L96 +R57 +R19 +R79 +R45 +R35 +R15 +R85 +R1 +R64 +L65 +L51 +L76 +L17 +R44 +R4 +R15 +L30 +R32 +L48 +L43 +L19 +R27 +R15 +R2 +R22 +L23 +R11 +R34 +R50 +L30 +R34 +R36 +R7 +R27 +L34 +L10 +L48 +L48 +L27 +R21 +R2 +L49 +L24 +R49 +L15 +L44 +L41 +R43 +L20 +L47 +R20 +R7 +R11 +R1 +L44 +R2 +L31 +R7 +R21 +R7 +R23 +R6 +L8 +L14 +L47 diff --git a/aoc2025/input/day01_provided.txt b/aoc2025/input/day01_provided.txt new file mode 100644 index 0000000..53287c7 --- /dev/null +++ b/aoc2025/input/day01_provided.txt @@ -0,0 +1,10 @@ +L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82 diff --git a/aoc2025/src/day01.rs b/aoc2025/src/day01.rs new file mode 100644 index 0000000..9ee3904 --- /dev/null +++ b/aoc2025/src/day01.rs @@ -0,0 +1,135 @@ +use std::{fmt::Write, str::FromStr}; + +use anyhow::{bail, Result}; + +const INPUT: &str = include_str!("../input/day01.txt"); +const DIAL_SIZE: u16 = 100; + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + Ok(res) +} + +enum Rotation { + Left(u16), + Right(u16), +} + +impl FromStr for Rotation { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let dir = &s[..1]; + let num = s[1..].parse()?; + + match dir { + "L" => Ok(Rotation::Left(num)), + "R" => Ok(Rotation::Right(num)), + _ => bail!("rotation can only be left or right, got `{}'", dir), + } + } +} + +impl Rotation { + fn apply(&self, state: u16) -> u16 { + match self { + Rotation::Left(num) => { + let num = num % DIAL_SIZE; + if num > state { + DIAL_SIZE - (num - state) + } else { + state - num + } + } + Rotation::Right(num) => (state + num) % DIAL_SIZE, + } + } + + /// Counts the number of zeroes encountered while rotating the dial. Does NOT take the initial + /// state into account if it is 0. + fn apply_and_count_zeroes(&self, state: u16) -> (u16, usize) { + match self { + Rotation::Left(num) => { + let zeroes = (num / DIAL_SIZE) as usize; + let num = num % DIAL_SIZE; + if num > state { + ( + DIAL_SIZE - (num - state), + zeroes + if state != 0 { 1 } else { 0 }, + ) + } else { + let new_state = state - num; + (new_state, zeroes + if new_state == 0 { 1 } else { 0 }) + } + } + Rotation::Right(num) => ( + (state + num) % DIAL_SIZE, + ((state + num) / DIAL_SIZE) as usize, + ), + } + } +} + +fn part1(input: &str) -> Result { + let rotations = input + .lines() + .map(Rotation::from_str) + .collect::>>()?; + + let res = rotations + .iter() + .fold((50, 0), |(state, mut count), rot| { + let new_state = rot.apply(state); + if new_state == 0 { + count += 1; + } + (new_state, count) + }) + .1; + Ok(res) +} + +fn part2(input: &str) -> Result { + let rotations = input + .lines() + .map(Rotation::from_str) + .collect::>>()?; + + let res = rotations + .iter() + .fold((50, 0), |(state, count), rot| { + let (new_state, zeroes) = rot.apply_and_count_zeroes(state); + (new_state, count + zeroes) + }) + .1; + Ok(res) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day01_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 3); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 1092); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 6); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 6616); + } +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs new file mode 100644 index 0000000..12b8f18 --- /dev/null +++ b/aoc2025/src/lib.rs @@ -0,0 +1 @@ +pub mod day01; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs new file mode 100644 index 0000000..87fb660 --- /dev/null +++ b/aoc2025/src/main.rs @@ -0,0 +1,11 @@ +use anyhow::Result; + +use aoc::DayFunc; + +use aoc2025::day01; + +fn main() -> Result<()> { + let days: &[DayFunc] = &[day01::run]; + + aoc::run(days) +} From db1bae8a76e3c24fb013aab598021040ae87f91b Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 2 Dec 2025 17:44:22 +0100 Subject: [PATCH 119/134] 2025: setup bench for day01 --- Cargo.lock | 1 + aoc2025/Cargo.toml | 7 +++++++ aoc2025/benches/aoc2025_bench.rs | 14 ++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 aoc2025/benches/aoc2025_bench.rs diff --git a/Cargo.lock b/Cargo.lock index abcf848..5e6c990 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,6 +139,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", + "criterion 0.4.0", ] [[package]] diff --git a/aoc2025/Cargo.toml b/aoc2025/Cargo.toml index 41f873e..c1208d6 100644 --- a/aoc2025/Cargo.toml +++ b/aoc2025/Cargo.toml @@ -8,9 +8,16 @@ edition = "2024" aoc = { path = "../aoc" } anyhow = "1.0" +[dev-dependencies] +criterion = { version = "0.4", default-features = false, features = [ "rayon" ] } + [lib] path = "src/lib.rs" [[bin]] name = "aoc2025" path = "src/main.rs" + +[[bench]] +name = "aoc2025_bench" +harness = false diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs new file mode 100644 index 0000000..73c5a0c --- /dev/null +++ b/aoc2025/benches/aoc2025_bench.rs @@ -0,0 +1,14 @@ +use criterion::{criterion_group, criterion_main, Criterion}; + +use aoc2025::day01; + +fn aoc2025_all(c: &mut Criterion) { + c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); +} + +criterion_group! { + name = all_days; + config = Criterion::default().sample_size(200); + targets = aoc2025_all +} +criterion_main!(all_days); From f0dc93b0bb5c8f54478e820a0640bf15dbdd3c5e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 3 Dec 2025 16:49:26 +0100 Subject: [PATCH 120/134] 2025: day02: part 1 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day02.txt | 1 + aoc2025/input/day02_provided.txt | 1 + aoc2025/src/day02.rs | 116 +++++++++++++++++++++++++++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 3 +- 6 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 aoc2025/input/day02.txt create mode 100644 aoc2025/input/day02_provided.txt create mode 100644 aoc2025/src/day02.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index 73c5a0c..6f8d4de 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -1,9 +1,11 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2025::day01; +use aoc2025::day02; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); + c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day02.txt b/aoc2025/input/day02.txt new file mode 100644 index 0000000..2bc9ca3 --- /dev/null +++ b/aoc2025/input/day02.txt @@ -0,0 +1 @@ +52-75,71615244-71792700,89451761-89562523,594077-672686,31503-39016,733-976,1-20,400309-479672,458-635,836793365-836858811,3395595155-3395672258,290-391,5168-7482,4545413413-4545538932,65590172-65702074,25-42,221412-256187,873499-1078482,118-154,68597355-68768392,102907-146478,4251706-4487069,64895-87330,8664371543-8664413195,4091-5065,537300-565631,77-115,83892238-83982935,6631446-6694349,1112-1649,7725-9776,1453397-1493799,10240-12328,15873-20410,1925-2744,4362535948-4362554186,3078725-3256936,710512-853550,279817-346202,45515-60928,3240-3952 diff --git a/aoc2025/input/day02_provided.txt b/aoc2025/input/day02_provided.txt new file mode 100644 index 0000000..a3f22ef --- /dev/null +++ b/aoc2025/input/day02_provided.txt @@ -0,0 +1 @@ +11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124 diff --git a/aoc2025/src/day02.rs b/aoc2025/src/day02.rs new file mode 100644 index 0000000..6a3a33c --- /dev/null +++ b/aoc2025/src/day02.rs @@ -0,0 +1,116 @@ +use anyhow::{anyhow, Context, Result}; +use std::{fmt::Write, ops::RangeInclusive, str::FromStr}; + +const INPUT: &str = include_str!("../input/day02.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + Ok(res) +} + +struct IdRange(RangeInclusive); + +impl FromStr for IdRange { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (left, right) = s + .split_once('-') + .ok_or_else(|| anyhow!("couldn't find dash in range: `{}'", s))?; + let (left, right) = ( + left.parse() + .with_context(|| format!("couldn't parse left member of range: `{}'", left))?, + right + .trim() + .parse() + .with_context(|| format!("couldn't parse right member of range: `{}'", right))?, + ); + + Ok(IdRange(left..=right)) + } +} + +impl Iterator for IdRange { + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +fn get_num_digits(num: &u64) -> usize { + let mut digits = 0; + let mut num = *num; + while num != 0 { + num /= 10; + digits += 1; + } + digits +} + +fn is_repeated_twice(num: &u64) -> bool { + let num_digits = get_num_digits(num); + if !num_digits.is_multiple_of(2) { + return false; + } + let half = num_digits / 2; + let mask = 10_u64.pow(half as u32); + + *num / mask == *num % mask +} + +fn part1(input: &str) -> Result { + let ranges = input + .split(',') + .map(IdRange::from_str) + .collect::>>()?; + + Ok(ranges + .into_iter() + .map(|range| range.filter(is_repeated_twice).sum::()) + .sum()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day02_provided.txt"); + + #[test] + fn repeated_twice() { + assert!(is_repeated_twice(&11)); + assert!(is_repeated_twice(&22)); + assert!(is_repeated_twice(&99)); + assert!(is_repeated_twice(&1010)); + assert!(is_repeated_twice(&1188511885)); + assert!(is_repeated_twice(&222222)); + assert!(is_repeated_twice(&446446)); + assert!(is_repeated_twice(&38593859)); + + assert!(!is_repeated_twice(&111)); + assert!(!is_repeated_twice(&121)); + assert!(!is_repeated_twice(&1)); + } + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 1227775554); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 26255179562); + } + + //#[test] + //fn part2_provided() { + // assert_eq!(part2(PROVIDED).unwrap(), 6); + //} + + //#[test] + //fn part2_real() { + // assert_eq!(part2(INPUT).unwrap(), 6616); + //} +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index 12b8f18..28326d5 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -1 +1,2 @@ pub mod day01; +pub mod day02; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 87fb660..1cb26fa 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -3,9 +3,10 @@ use anyhow::Result; use aoc::DayFunc; use aoc2025::day01; +use aoc2025::day02; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run]; + let days: &[DayFunc] = &[day01::run, day02::run]; aoc::run(days) } From ef970ed47ab4d92bbcd91f39d863f60e398bf853 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 3 Dec 2025 17:54:19 +0100 Subject: [PATCH 121/134] 2025: day02: part 2 --- aoc2025/src/day02.rs | 86 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/aoc2025/src/day02.rs b/aoc2025/src/day02.rs index 6a3a33c..3a119df 100644 --- a/aoc2025/src/day02.rs +++ b/aoc2025/src/day02.rs @@ -6,6 +6,7 @@ const INPUT: &str = include_str!("../input/day02.txt"); pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -72,6 +73,54 @@ fn part1(input: &str) -> Result { .sum()) } +fn has_identical_chunks(num: &u64, chunk_size: usize) -> bool { + // build a "mask" for our chunk size + let mask = 10_u64.pow(chunk_size as u32); + + // this is what all chunks should look like to satisfy our condition + let target = *num % mask; + + let mut num = *num; + while num > target { + // shift num right by 10^(sub_digit_num) + num /= mask; + if num % mask != target { + return false; + } + } + + true +} + +fn is_repeated_at_least_twice(num: &u64) -> bool { + let num_digits = get_num_digits(num); + if num_digits < 2 { + return false; + } + + has_identical_chunks(num, 1) + || (2..=(num_digits / 2)).any(|n| { + // walk all possible divisors of our number of digits + if !num_digits.is_multiple_of(n) { + return false; + } + let chunk_size = num_digits / n; + has_identical_chunks(num, chunk_size) + }) +} + +fn part2(input: &str) -> Result { + let ranges = input + .split(',') + .map(IdRange::from_str) + .collect::>>()?; + + Ok(ranges + .into_iter() + .map(|range| range.filter(is_repeated_at_least_twice).sum::()) + .sum()) +} + #[cfg(test)] mod tests { use super::*; @@ -104,13 +153,34 @@ mod tests { assert_eq!(part1(INPUT).unwrap(), 26255179562); } - //#[test] - //fn part2_provided() { - // assert_eq!(part2(PROVIDED).unwrap(), 6); - //} + #[test] + fn repeated_at_least_twice() { + assert!(is_repeated_at_least_twice(&11)); + assert!(is_repeated_at_least_twice(&22)); + assert!(is_repeated_at_least_twice(&99)); + assert!(is_repeated_at_least_twice(&111)); + assert!(is_repeated_at_least_twice(&999)); + assert!(is_repeated_at_least_twice(&1010)); + assert!(is_repeated_at_least_twice(&1188511885)); + assert!(is_repeated_at_least_twice(&222222)); + assert!(is_repeated_at_least_twice(&446446)); + assert!(is_repeated_at_least_twice(&38593859)); + assert!(is_repeated_at_least_twice(&565656)); + assert!(is_repeated_at_least_twice(&824824824)); + assert!(is_repeated_at_least_twice(&2121212121)); - //#[test] - //fn part2_real() { - // assert_eq!(part2(INPUT).unwrap(), 6616); - //} + assert!(!is_repeated_at_least_twice(&1121)); + assert!(!is_repeated_at_least_twice(&121)); + assert!(!is_repeated_at_least_twice(&1)); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 4174379265); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 31680313976); + } } From 0566f562ecdef049c1e2802fe176be9abaf22f8f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 3 Dec 2025 18:12:10 +0100 Subject: [PATCH 122/134] 2025: bump criterion version --- Cargo.lock | 120 ++++++++++++++++++++++++++++++++++++++++++++- aoc2025/Cargo.toml | 2 +- 2 files changed, 119 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e6c990..77d7393 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,12 +11,27 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + [[package]] name = "anyhow" version = "1.0.100" @@ -139,7 +154,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aoc", - "criterion 0.4.0", + "criterion 0.8.0", ] [[package]] @@ -222,6 +237,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cc" +version = "1.2.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -273,11 +298,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "bitflags", - "clap_lex", + "clap_lex 0.2.4", "indexmap", "textwrap 0.16.2", ] +[[package]] +name = "clap" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +dependencies = [ + "anstyle", + "clap_lex 0.7.6", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -287,6 +331,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + [[package]] name = "criterion" version = "0.3.6" @@ -338,6 +388,31 @@ dependencies = [ "walkdir", ] +[[package]] +name = "criterion" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" +dependencies = [ + "alloca", + "anes", + "cast", + "ciborium", + "clap 4.5.53", + "criterion-plot 0.8.0", + "itertools 0.13.0", + "num-traits", + "oorandom", + "page_size", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + [[package]] name = "criterion-plot" version = "0.4.5" @@ -358,6 +433,16 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "criterion-plot" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" +dependencies = [ + "cast", + "itertools 0.13.0", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -425,6 +510,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "funty" version = "2.0.0" @@ -511,6 +602,15 @@ dependencies = [ "either", ] +[[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" @@ -605,6 +705,16 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "plotters" version = "0.3.7" @@ -819,6 +929,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "syn" version = "2.0.111" diff --git a/aoc2025/Cargo.toml b/aoc2025/Cargo.toml index c1208d6..a5d2468 100644 --- a/aoc2025/Cargo.toml +++ b/aoc2025/Cargo.toml @@ -9,7 +9,7 @@ aoc = { path = "../aoc" } anyhow = "1.0" [dev-dependencies] -criterion = { version = "0.4", default-features = false, features = [ "rayon" ] } +criterion = { version = "0.8" } [lib] path = "src/lib.rs" From 9543dcb9b17d5b2d15c98c5fc8df85d37b6fe3d8 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 3 Dec 2025 18:28:14 +0100 Subject: [PATCH 123/134] 2025: day02: use log10 for digit number computation --- aoc2025/src/day02.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/aoc2025/src/day02.rs b/aoc2025/src/day02.rs index 3a119df..6388ad5 100644 --- a/aoc2025/src/day02.rs +++ b/aoc2025/src/day02.rs @@ -41,13 +41,7 @@ impl Iterator for IdRange { } fn get_num_digits(num: &u64) -> usize { - let mut digits = 0; - let mut num = *num; - while num != 0 { - num /= 10; - digits += 1; - } - digits + num.ilog10() as usize + 1 } fn is_repeated_twice(num: &u64) -> bool { From 8a22da8ba11a4645de8009fb0a818286f49a724b Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 8 Dec 2025 12:08:24 +0100 Subject: [PATCH 124/134] 2025: day03: part 1 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day03.txt | 200 +++++++++++++++++++++++++++++++ aoc2025/input/day03_provided.txt | 4 + aoc2025/src/day03.rs | 92 ++++++++++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 3 +- 6 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 aoc2025/input/day03.txt create mode 100644 aoc2025/input/day03_provided.txt create mode 100644 aoc2025/src/day03.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index 6f8d4de..4cbc578 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -2,10 +2,12 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2025::day01; use aoc2025::day02; +use aoc2025::day03; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); + c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day03.txt b/aoc2025/input/day03.txt new file mode 100644 index 0000000..611b5dc --- /dev/null +++ b/aoc2025/input/day03.txt @@ -0,0 +1,200 @@ +2213322222223222132231233322432224423222226232323522232215252332221122222231232224232722131522422232 +9869755494885236452767647548826258555668838497687557968652485746757835445145546687436356799481798587 +1333642233323333373233223535543332333343733333323333333333315334333323343343333333332321233332333333 +2412331232332223332211413223433332213222252142221323322122212223222321231322513323122332321233233222 +7233333554333634354333355353442655334523373532334435335733343124433353732333236335456441345343535443 +2542623755573343945454412366525442424744334132133146357442166333737542732631343535567546644733453327 +3223423125721322245221313311333222222222322321672232321322215121332232323522331112523842131211222231 +1341524443834221222553325236443534253327533543493534348242333119334424249244524325448544522322512344 +2122222234421423322222232231221455261322312321232223321232322112233222233223322222121221322232225222 +2172228252452422574523272252246532513514251543422251252233622213162235313243341322723224223472223342 +4333333322374312333333442252233332323343236421333332132232233523333223643444244332233333333314343374 +5564564445425635543326425252871657266475435535644335444428545455444345414454654413464444444543452332 +7454483454246843436686564547347643444463364743844643844454433455547944454424656442455444258453453949 +3545239364734434356884585159793673287754643667512332857278643456465359873642643268698837552366444279 +2222614212122412212232521222222222322162224122212255224652222252322242352254132522221123221222222222 +4654734524468553536655551947342343744798353537531365525555255373383337465222438553556563343546674795 +4223343232434234223443433132443232333433233241333323334444234334443434435341513522333132223342423334 +2434743225152133244934233332223333342332742413225323434322133133342225263461325222442331344323333621 +4363333625436326121432327152115232112437232426739557622735333213153454854223553223332333163322332262 +3291224524551531661124222122232433443332372352223452323152254212524224475353217335338132112225138382 +2532334224334412444233531343333232434672372334424223232433234233235242243334444434532142565432224543 +6575467444354636644724356545439443727633232211663455734655446347433346552413539455535454456546344467 +2212123522212256112142223212223223926221423333322111142121322246521222623231121222222233122682282232 +2427422153354454221223483334425221233131444333342323144413423342141422222343422242225233412322852334 +2223222262222351122221222542222356232422221312224223222121224242221142612223533222222326212112222231 +1122221221423121122222221122242426222322222218222222222122222424232223133224227122232222225212322431 +2223225222263221223122232222231322132249422122222222212343223233221231112333321122224822122212112221 +2234133242122472222333323231152222313322242231321234122233314332232125212342222222141222224223222243 +3222421121132228332482223722323212227931233222232311122728212342422323911121332241322122212225222224 +3342221445144453253254314734532247546356242543223144334535244724343441632342442234353332554531544544 +6644254436227552262158566262526533915631231552333722416565536354544652263755643341664563253253335325 +2212221212221266252415512232524121224221462212225225525255242115212235231241252544312222525112533222 +1212222242222222122121231123212212232222221112225222122222212212222222222322221222222333222222232121 +8437515934322544325244332733235426312213422543233274311523432242324234425333225643164333335325158723 +4955559385766953565255766876476558356667683243721462495465455956585541549636358359356553352726754357 +2321212231311222332231233622451222223233632131325333155422313242233246235373323463222222233151352225 +5554455544442245353244364445444442964455743554423443344234626245334485444521454444353644544434348444 +3584546435435438362463553335553744339333343334752434593543434442333333333374362737434422835322244974 +2224322223132222332322223422213222223821212223222243223232222232232222362222323122422922222223222321 +7532213233323334215212222423122123222322425222323732234174212342242222239222238232423135916233324313 +4725333553331231732334534535433413336333334433335633862233333333343434333253574633253313333533322533 +2222122222233222222212322321212122221322122123122322232112231321222234222233122122113113222142221222 +7618667762444757529352444283355721866946122758937266864545275866446765437263255944277544354266743555 +8775885395735793768798676737467545866325994734656888365669834844567693699478564767598836687838775796 +2323222163231422333232265212225222433552125522231421223232222242111255222111234232222234643453222212 +3212222223211242222322222423924221333231242222215221222222222412222332242222342226222112342222222423 +2312517442152222775232225322152322134642256726212312232253122631232442222322774322261522237322225221 +1412232232122132322214222245123232224232423122523323323512434322222122322223232324512223213223221225 +4624745444557739264643334474753442344576454464364444542355443444953574753765466446534445555247546645 +4444445543553433353354455144453453542444435444454565454246452554274346433345434464454144453534444454 +5222221211223232461222322221422324122212222121524122122224222221222226222282222211433212232262313272 +4443424217342232322234144234322244432422332123432122562423442343241152444222734444343343324245233331 +4625363444334325314433134332342626273324257534444232232533221335211222233354622142319633834554323252 +6411222232214222222522522212115422324312321212512352222222222521221222222422213215222323222542332225 +4443435744444443443454344444553646453444473243634337443343333445443444444444544642353434424344143344 +4222322212142222131123232424122212623122325223232222122222324172123313113213221112221214131212326232 +3628228272226822792212222291522222262281252222222122523312222224388323226222431232246223822272242222 +6452232522272722232314236322514222212124422122363122133442752472323254631272561324232244232223412433 +2232232212252263221723231243261132732225353342123222262123232223621135231232353226314132222321322523 +2234532142534352552432224445238325213424373452334233522333242532331322332283352427475226322153223244 +9472212243122222252422922222363422333321126243222123963224222212173222233224252234412121222122821213 +8687898777877956884675896696763989727598788596888366975787785653266667396852928885385879777658746578 +4742438327346661542272567435214432666247432532364464374423432252594887642242783264284248334549366538 +2843543444552553332333549456453152452655123452245534625343434434394353525145545815233325253353558525 +3244334344333322333336326524543522543353334524333542335243334463433424253344265152434334435422433433 +5123213122132653223552342918633223322124141221532722222222633832112321232362321212223224311252232323 +2254522224536212312521242224331285151323234522312332222153222222233213252422324212324255413222233635 +6932637327758743246546437713551343621222422345652667325366263533277364672223242653614462113113621452 +2664332353263783333136373783525676334732434213262462433235335292339233763346833362333754633332336332 +1223222424223252223213121222322322216422412224222612422223221222312122222125212222415122232226422521 +3542584332435333333233354353545344224553534123354453332523352334552335453523343512333213234387634133 +6477957673773844477447976677777779677788757572445797735766653875666759654537677675353627655576767927 +2122863223233922223222231121222335332223122512323122233223421212114232222322232221223392322222521322 +4312524534123246451432343643224311242447241134644264223443332245433262232641376442432172472222642235 +2275325124326274246343242342674425241126422624221639763313155173323211554216434553212654542522244512 +1538376354635334634345152866523443431672342341845227336436433755352916223414454255126676464326465453 +2462132262212214732224191166344355414456333232523325425323262172634333344212243223136153134622523124 +2631319623233673572328447522142326723725312315363222557334327382237347133534333342445538226351733877 +6674525765645736755277426478666374433478565771746335482576661384446336527753576379765114777324835247 +1445214354534443124443143152322124342543358432243223532332224344453244325421233463452464443336435444 +3723543344762463142452771243123333533262534743357433433442333434323237223413433322343122246434425297 +2522212232142222322222221222222123222513232222522212222241212423221222221232222422123182421222222352 +4649425575652455655345524446535555664456453353551334555552535554525353745544253454663345473375355545 +2634673446446644485645555244654443495523355587664334545525752374784735443457755455456485493456463553 +2242233312853232212222233154124241433323223342432114322372333333333232333133312323424253242333222527 +2252222222122622131222221211221252222222262122342222322122323222252212223225224113322222213227122112 +7145153421321212213232213242421325372523143232242542622222334162232643213463222315224332241623233632 +3324124233321322222222324392322321322222222224223432342142234421321364212212331212326242323313313333 +2472266245644522634774327358522262635513323335182372254462662143946277975225436422277562365266655423 +3454443243442454643335544534416344433344445654442214445434214514463442433444324544444345444345543344 +4367979552245565165576424776225962637573364823785465568368636312742298786276647827575676469244525653 +3225626443313133323723323323333314253554364347343365333323333336333733232322233333323433327322332332 +2573343343233434433434335363345452556353493431488327365413335557454378339752343364644435453325754543 +3332172133227223334324253377332133233323223333532233333322112735223232322223234272123323333632212223 +3454534475343444535444424745434444444344455444623375454534443434344544444438232474343544535454434444 +2644342235344483342633422636454456365233515643444645826444442446956214445156322264445433443453544256 +2223435334423434443323343432344434441333333333334433523433332124432343243433314444324423343343444233 +3212252222442321323221225293213122528329522211182223418222232142225234221221222222423222321246232122 +4353432493542334325235547332734383332234542144323893258347384435444429271453353353448434142247423122 +8337935245577558348845559668464454534353766484438335543755757443777274244484345834388345496944455467 +3443463333334453433232243443222334133233433234432324222432323533323324433242132332332124242343233322 +1435542554154543564533441335544555244531645445572234345443345431434433534143565444437433564233354423 +3333312334342233331223233234233423333333333222332233423337233233333323213132222322314332323333244443 +3144453439443334333662444343463453336433435352354493435346436453383544432444466337453337853423233436 +2621273163344422333343232136211636224222434231116342222542232213433324642324241176224342723221422332 +3233236263233353563335231233252323223521334126123623332512327322312223333223215221283522467362232326 +2232223222222222223224222222222221221211221222123322422321223212222221322222212221222221222222342222 +4443435431454234435334436543423453441422434424434246438432132274643321323342524533232532212314424334 +3434222234424123524222452333431221233121324331412242454221434433122432415442443243322313221343241245 +2321552222525121432422322331221528511324222222222223251323221222325322125252122222212222223233125422 +2113322212122312221212122222122232221222332422312233422223123112132122232232231222235122334122222212 +3732434222332433314434542433334343433225344323314343343423334323322433232435323333324234332413313341 +2243352221342443222271236434365322934422234223125222337624122643272322622437441322243413243473882412 +2527574826427351353683632227267232139241272336778354926836323453363482545233625417243233594635373371 +2352124323843333323253365635322233542433122438331432234333233233552321434213213222343343494522232371 +1322321231222372222321132512312222322322224462222223322222222221223222233121722212522142211233221233 +5444455244355434653244514353733425555432435524445462355644544453443433445226446336553853553454444444 +3332233333334338391321272312134322233863322333432334333383232342334223332333234786233333432424325933 +1423223524424321433522322244232223331233231333313336222333934223422133232353433212332232224322322433 +3846414434329535333324434434463744365584534935533343538345434362733943434244645366346976364533243345 +4643437654442357354452643453433595563365355434644545556753685648354446745633345454324745655324554344 +2131424213433334334241312123344324133131413343442431244222441243341422141411322341334123242221356789 +7416322321423422532433252263461535237341336423224758925417544133763249354532465584557477436637134868 +3532232342543633244356234447125413363324323324222289345334243223343344349423623323132345434545334456 +2222222223122224523322222414412221222312521311252212471135216121622212122422823223224222252322223322 +6844572852724766364376246428458471423425425655656355452483274422366737555436524246373644225524226684 +3242324353115355355323223333323433133532332325223553622433333532532333223134223363333333733357422553 +3626353353644274241533142456273326314323662575363324353232556433624425644535422316323346623244545532 +2724454534154225253459433524763422545426423332642224232423242219414234215362382511227546231223755232 +7442133222243344231433423324322522433233342443244242433423242443424324213224132442463664334134342334 +3463633243546333375266535312435244564434333724665664625374363683533955743535443448446155363433352435 +2264222222213232253131424222232214292212282234282122225323422451223621252222122222122222532326531252 +7615864866564643665565345652664464866686665436644563376466655765566766633576745646454764727756626448 +3232682631537442445212595232662334363343227323835122465351345356353233643332543416323346345346643365 +2477354147362541612246656262342473335717542264534245221467537422444573332674431531423425215312544289 +2334432533153324242344341754352431132342242483614364474473434824424423481248441342313143738143793223 +2453444254242142424354527214334534514423135772455224332544144347235744422234224425443544453243344614 +5212223252122422331232123222142312233422245334462222222225244224221242232221512243232224234433555222 +4663361654535434444435333426543336213653424435533654435334427263236324336542736224533733545413433239 +3363338333145338474323437333462332324223453341452444327323423238343353864322373218432131334133331333 +6252146332321485753632148626252215423622661447732432532425663473353884553422633662223652246821433466 +6323212434222112525725474243264325545472241252227222635137276274422143227243432646722261633476517122 +2292128532222284521512222622221222422421324224222681233623522223223262427233231272222123235231221181 +4286246955215254312515631624225942342242521826335223234535339245216232525515324431229213242425522424 +2622122232123521122122322223322225522212213235316222222233213212622122172232222411222222312122211732 +2392322272325242232246227222232731732621613276422282332227135645532724216422152724335327741242231462 +2133344331342334353334326416233445424328334428226343632383533126256345224276253624433232223322429335 +1313445155233335142345133432424315243344534322414122115152312323134555232124514425531444334531116789 +2176422423121432443422442232123322224224142721224212222312511322231432233234223323244211222332222122 +1323212331222132233231423322222222214333233212344223434312442222492221354321222342223332373533322621 +4664434362444745561444535453345435524434346435454274864444654324476633565349444454455353443364156363 +1638584275546117346163717254773527552852888544638242767347444874466266733617618166164466374362765419 +6484454656734464566656446354242553953738747675494353263545534655932284732414565465456217445446466422 +3485414422321524833475231333422824247332244623522414142222262253355414452434234344554242224422224624 +2333263233433521134582215333224332925436375333333336732316531375333522444212233753383365335354643243 +2322132222223221323111333232222233332322122232221312232253222222232322332431323222322231242312325223 +5335322444334334442443232426223323234447129221322222234335221422223321222322222324423233342232233364 +2233232223252234233222422323332233122122213133422132233223243122322122142422223322242222332521212211 +2243222246232222212215234223244341293823233413422262122231434142334224211122243244723212111327343722 +3313433324333323233333323332233423333523353312313633334213233333425232634123313333625322322224342122 +2223221221321122424222323113232211222413233225122222222312222222225361224122154344233232252313223232 +6426445154869355363363722336455335472343572534323456253645532493615956527636643453556642545246266326 +4342252241221222341214232232226432422223222214311224253224847131242221312222431142152243223533228364 +3122222221312333212221331241133322212322122433312122322332322212332222212322222142232224224432241333 +4758777554587868737644678898656677787655757385768789874455858856835848887478458889776575587488744887 +2222222322222222132444434221222223222211212222421221422124222221223422331422622421122212232221222222 +5543453232434923234235323433433652346343532235133533353325643323414321344433315332531344244423332533 +1422222221222222212122311222212124122222322232222122112222222222122221212242222322212222211512242221 +5624318328343613762342133122287362233222333228233526432235723228212317225232222321322843831822233343 +4745555462555745374333447645563565846565658565674475358542453455774373535925543556456253364455655565 +2231323341221332332231232222211222122232242312343424133212222221221623132213242312314213213122222113 +2342415122621132242242322221225542255222222222112241222232223222323213522222122246221231225232243224 +6223131445352273462225532517237771421222422217426141752312626563272261233221417286234434252324661125 +5222222212212422212223223322211422113212222441222322222222432222222222222222132132522224131242222451 +3422323526233255413253234422122625354565276426242722342264341342322432242227231221345261423232251243 +4455444352444254693544224343146552455424553454457554355354334375444452434455453544443455535455225454 +6695865665676765678566666576961755966654564567555567567556642646397966556665359666465757356556757769 +8357544347353366537753222233513443263326227543433534321424453266343553435425423918643343433235261323 +2222222222222221222113122221132222411225322222222222222441122332222222232132115232313221145522221221 +2224124212242232553331122222231252712234224682324732533127244253223113212252422561212242222267412142 +2155131243437642435225242233334327262528545127324323242251223242215932221342512431224563331215223232 +3233233821422242243223423226322333331221244225322333614732324322164332232342254245324342223324333333 +5323233433722283363642223343334264332334256668558433344333335344774523223633116853423338533332265733 +6636218835567665856535755855763526554865876567668671763558535573733875754666654864563576447378687647 +3242212222532222453222221222221414445243225223253221212124423422213112225222222212136322222122223223 +3246242324335263534434465364444433354444733144444444634444442415237463482176214523646425165642842254 +2222122121452242222112223321223211222122412432421222323122222422224234323112221412442225322222244223 +5555533353644375536354623527576345645257454546563754453235344566547743535526353443675773695567647537 +3333334233422333245534448312255264263533563132333625233423334335232332233333924442432512333355242243 +5335324246344212334344347222166443335324633214664133136352235644245321635434234446546333352834514533 +3232232233742222122234123363441422152241262422235221425422492124252122242244323222152522222164124334 +3462333528242224232212331221524224225335332337777262223233218633225162762134332832833282226832233352 +2632332326122221121112263242232222122432223221342223342224123122112324132321112262322121522112113221 +2643223122321323333222122131322331333331122234423732236222323333323223232221311311224272231332243223 +1222223121241124122212232223223222122522221122332123122232231322212311251223333222513332338312123112 +2152323434738233433164425517324546331332242235424332433322422413432633344543243344744343237342432312 +4131322231422253332322233423433322322232222122431221333113333223333234213123233223231323332233334323 +2463363425242612416264341654545345115236122326652335252424331225332623114245461624526144136446312789 +5832235534333334323334233312133213343133323333875344483233343683364244333343536273324539333242273393 +5336252424463368242344342182144524854253313325351235445322225455244424225253125634815634443442624924 diff --git a/aoc2025/input/day03_provided.txt b/aoc2025/input/day03_provided.txt new file mode 100644 index 0000000..7255fca --- /dev/null +++ b/aoc2025/input/day03_provided.txt @@ -0,0 +1,4 @@ +987654321111111 +811111111111119 +234234234234278 +818181911112111 diff --git a/aoc2025/src/day03.rs b/aoc2025/src/day03.rs new file mode 100644 index 0000000..bf0e1d3 --- /dev/null +++ b/aoc2025/src/day03.rs @@ -0,0 +1,92 @@ +use std::{cmp, fmt::Write}; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day03.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + Ok(res) +} + +fn find_max_tens_digit(bank: &[u8]) -> Option<(usize, u8)> { + // We don't include the last byte since it cannot be the digit for tens, otherwise we'd have no + // byte left for the units digit. + bank[..bank.len() - 1] + .iter() + .copied() + .enumerate() + // We want the max, but use min + Reverse because min selects the FIRST minimum, while max + // selects the LAST maximum, and we want the first (to leave more choices available to us + // for the units digit). + .min_by_key(|&(_idx, val)| cmp::Reverse(val)) +} + +fn find_max_units_digit(sub_bank: &[u8]) -> Option { + sub_bank.iter().copied().max() +} + +fn compute_max_joltage(bank: &[u8]) -> Result { + let (idx, tens) = find_max_tens_digit(bank).context("couldn't find tens digit in bank")?; + let units = + find_max_units_digit(&bank[(idx + 1)..]).context("couldn't find units digit in bank")?; + let (tens, units) = ((tens - b'0') as u64, (units - b'0') as u64); + Ok(tens * 10 + units) +} + +fn part1(input: &str) -> Result { + let mut sum = 0; + for line in input.lines() { + let joltage = compute_max_joltage(line.as_bytes()) + .with_context(|| format!("couldn't compute joltage for bank `{}'", line))?; + sum += joltage; + } + + Ok(sum) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day03_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!( + compute_max_joltage("987654321111111".as_bytes()).ok(), + Some(98) + ); + assert_eq!( + compute_max_joltage("811111111111119".as_bytes()).ok(), + Some(89) + ); + assert_eq!( + compute_max_joltage("234234234234278".as_bytes()).ok(), + Some(78) + ); + assert_eq!( + compute_max_joltage("818181911112111".as_bytes()).ok(), + Some(92) + ); + // added this test to check for min + Reverse usage + assert_eq!(compute_max_joltage("9892".as_bytes()).ok(), Some(99)); + assert_eq!(part1(PROVIDED).unwrap(), 357); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 17034); + } + + //#[test] + //fn part2_provided() { + // assert_eq!(part2(PROVIDED).unwrap(), 4174379265); + //} + + //#[test] + //fn part2_real() { + // assert_eq!(part2(INPUT).unwrap(), 31680313976); + //} +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index 28326d5..89345b1 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -1,2 +1,3 @@ pub mod day01; pub mod day02; +pub mod day03; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 1cb26fa..7719183 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -4,9 +4,10 @@ use aoc::DayFunc; use aoc2025::day01; use aoc2025::day02; +use aoc2025::day03; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run]; aoc::run(days) } From 261480afa3db1dfff2c38ff92030f677b02d2f4f Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 8 Dec 2025 12:26:58 +0100 Subject: [PATCH 125/134] 2025: day03: part 2 --- aoc2025/src/day03.rs | 69 ++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/aoc2025/src/day03.rs b/aoc2025/src/day03.rs index bf0e1d3..7058be1 100644 --- a/aoc2025/src/day03.rs +++ b/aoc2025/src/day03.rs @@ -7,14 +7,12 @@ const INPUT: &str = include_str!("../input/day03.txt"); pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } -fn find_max_tens_digit(bank: &[u8]) -> Option<(usize, u8)> { - // We don't include the last byte since it cannot be the digit for tens, otherwise we'd have no - // byte left for the units digit. - bank[..bank.len() - 1] - .iter() +fn find_max_digit(bank: &[u8]) -> Option<(usize, u8)> { + bank.iter() .copied() .enumerate() // We want the max, but use min + Reverse because min selects the FIRST minimum, while max @@ -23,22 +21,37 @@ fn find_max_tens_digit(bank: &[u8]) -> Option<(usize, u8)> { .min_by_key(|&(_idx, val)| cmp::Reverse(val)) } -fn find_max_units_digit(sub_bank: &[u8]) -> Option { - sub_bank.iter().copied().max() -} +fn compute_max_joltage(mut bank: &[u8], batteries: usize) -> Result { + let mut joltage = 0; + for battery in 0..batteries { + // We don't include the last [batteries - battery - 1] bytes since we need at least these other + // digits for the final number + let not_in_search = batteries - battery - 1; + let (idx, digit) = find_max_digit(&bank[..(bank.len() - not_in_search)]) + .context("couldn't find max digit in bank")?; -fn compute_max_joltage(bank: &[u8]) -> Result { - let (idx, tens) = find_max_tens_digit(bank).context("couldn't find tens digit in bank")?; - let units = - find_max_units_digit(&bank[(idx + 1)..]).context("couldn't find units digit in bank")?; - let (tens, units) = ((tens - b'0') as u64, (units - b'0') as u64); - Ok(tens * 10 + units) + let digit = (digit - b'0') as u64; + joltage = joltage * 10 + digit; + bank = &bank[(idx + 1)..]; + } + Ok(joltage) } fn part1(input: &str) -> Result { let mut sum = 0; for line in input.lines() { - let joltage = compute_max_joltage(line.as_bytes()) + let joltage = compute_max_joltage(line.as_bytes(), 2) + .with_context(|| format!("couldn't compute joltage for bank `{}'", line))?; + sum += joltage; + } + + Ok(sum) +} + +fn part2(input: &str) -> Result { + let mut sum = 0; + for line in input.lines() { + let joltage = compute_max_joltage(line.as_bytes(), 12) .with_context(|| format!("couldn't compute joltage for bank `{}'", line))?; sum += joltage; } @@ -55,23 +68,23 @@ mod tests { #[test] fn part1_provided() { assert_eq!( - compute_max_joltage("987654321111111".as_bytes()).ok(), + compute_max_joltage("987654321111111".as_bytes(), 2).ok(), Some(98) ); assert_eq!( - compute_max_joltage("811111111111119".as_bytes()).ok(), + compute_max_joltage("811111111111119".as_bytes(), 2).ok(), Some(89) ); assert_eq!( - compute_max_joltage("234234234234278".as_bytes()).ok(), + compute_max_joltage("234234234234278".as_bytes(), 2).ok(), Some(78) ); assert_eq!( - compute_max_joltage("818181911112111".as_bytes()).ok(), + compute_max_joltage("818181911112111".as_bytes(), 2).ok(), Some(92) ); // added this test to check for min + Reverse usage - assert_eq!(compute_max_joltage("9892".as_bytes()).ok(), Some(99)); + assert_eq!(compute_max_joltage("9892".as_bytes(), 2).ok(), Some(99)); assert_eq!(part1(PROVIDED).unwrap(), 357); } @@ -80,13 +93,13 @@ mod tests { assert_eq!(part1(INPUT).unwrap(), 17034); } - //#[test] - //fn part2_provided() { - // assert_eq!(part2(PROVIDED).unwrap(), 4174379265); - //} + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 3121910778619); + } - //#[test] - //fn part2_real() { - // assert_eq!(part2(INPUT).unwrap(), 31680313976); - //} + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 168798209663590); + } } From 8f2d42bb732f616eaaaa140a6f1e51b330b197ec Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 8 Dec 2025 16:14:58 +0100 Subject: [PATCH 126/134] 2025: day04: part 1 --- aoc2025/input/day04.txt | 136 +++++++++++++++++++++++++++++++ aoc2025/input/day04_provided.txt | 10 +++ aoc2025/src/day04.rs | 120 +++++++++++++++++++++++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 3 +- 5 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 aoc2025/input/day04.txt create mode 100644 aoc2025/input/day04_provided.txt create mode 100644 aoc2025/src/day04.rs diff --git a/aoc2025/input/day04.txt b/aoc2025/input/day04.txt new file mode 100644 index 0000000..adb48e7 --- /dev/null +++ b/aoc2025/input/day04.txt @@ -0,0 +1,136 @@ +@@.@..@@@.@@@@.@.@@@.@.@@@..@@@...@.@@@@@@@@.@@@@.@@.@.@.@@@.@.@@@..@@@@@@.@@@.@...@.@...@@@@.@@@.@@@@@@@@@..@...@....@@.@.@.@..@@@@@@@@ +@.@@@.@@@.@@@@@@.@..@@@@@@@@@@..@.@.@@@@@@..@...@@.@@@.@..@@@@.@@.@@@.@@.@@@@@.@@@@@@....@@@@@.@@@@.@@.@@@@@.@.@.@@@.@.@..@@@..@@@.@@@@. +@@@..@@@..@@.@@.@.@@...@.@@@@..@@@.@@@@.@@@....@@@...@@@.@@@.@.@@.@.@..@@.@@@@.@@@@.@@@@...@@@.@@@@@.@.@@@@@.@.@@@@@@..@.@@@@..@.@@@@@@@ +@.@@@@@.@@.@@.@@..@@@@@@..@@..@.@@@@..@@.@.@..@@@...@.@.@.@@@.@@@@@@@.@@...@.@@@@.@@@@.@@.@.@.@.@.@..@@..@@@.@.@@@@@@@@@@.@.....@@@@@@.. +@@@@@@.@@@@.@@@@@.@.@@..@@@@@@@@@@@@.@@@@.@@@@@.@.@.@@.@@.@..@.@@..@@@@@.@@...@@..@@.@@@....@@@@.@@@@..@....@..@...@..@@.@...@@.@@@@.@.. +.@@@@..@.@.@..@.@.@@.@@@@@@@@@.@@.@.@@@@@.@@.@.@@@@.@@@@.@@@.....@@@@@.@@@.@@@@.@@.@@@@.@@@@@.@@@@@@.@@@...@@@@@@@@.@@.@@@@..@@..@..@@@@ +@...@@@@.@@.@@@.@@@@@.@..@@.@@...@@@@@..@@@@@@..@.@@@@.@.@@@@@.@@.@@..@@.@@@@@@@.@@.@@@@@@@@@...@@@.@.@@.@.@@@@@@@@.@@@.@@....@@@@@.@@.. +@.@...@.@@@@@@@@.@..@.@@@.@@@@@@@.@@@@@@@@...@.@...@@@@@@@..@@@@@@.@@@@@@@@@@@.@@@@@....@@@@@@.@@.@..@.@@@@@@..@.@.....@.@@.@.@..@@@@@@. +@@@..@@.@@@....@@@@@@@..@.@..@@@@@..@@.@@..@.@@.@@.@@.@....@@@@..@@@.@@.@@.@.@@@@.@@...@..@..@@@@@@@@.......@...@@@@@.@...@..@...@.@.@@@ +.@@@.......@@@@@@@.@@@...@@@@@.@.@@@@@...@@@@..@@@@@.@..@@.@@@@...@@.@..@...@.@@..@.@@@@@..@.@@@.@.@@@.....@..@.@@.@...@@@@.@..@.@....@@ +..@@@@@...@@.@@@@@@@.@@@@...@@@@@@.@@....@@..@@@...@.@.@@@.@@@@@@@@@.@@@....@@..@@.@.@...@@@.@@@@@@@@@@..@@..@@@@@@.@@..@@@@@@.@@@@@@@.@ +@@@@@@@@@.@...@@@..@@.@@@.@....@.@@@@@@.@@@.@.@@.@.@..@.@.@.@@.@.@@..@@.@@.@@.@@@@@.@@@@@@.....@.@.@@@@@@.@@@@@.@@@@.@@.@@@.@..@@..@.@@. +@.@@@..@..@..@.....@@.@..@@.@@@@.@@@@@@.@..@@@@@.@..@@@@@@@.@@.@@@@@.@@@@@@...@@@@..@.@.@.@.@@.@@@@@@@..@@....@.@.@@.@@@..@...@@@..@@@@@ +.@@@@.@@.@@@.@...@@.....@.@@@@..@.@@.@.@@@@@@@@@@..@@..@@@@.@@.@@@@.@@.@.@@.@@@@@@.@..@...@@@@.@@@@@@..@@@.@.@@.@.@@.@.@..@@@@@@..@.@@.@ +.@@.@.@.@..@@@@..@@@@.@@.@@.@@..@@.@@@@@@@@@@@@.@.@@@...@.....@@.@@@@@.@@@@@@@.@@.@@.@@...@@@@..@..@.@@@@@@@.@@@@@..@@@.@@.@@.@@.@@...@. +@.....@@@@.@@..@@@@@..@@@...@@...@@.@@.@.@.@@@..@@@@@@@@.@@..@@@.@@.@..@@....@..@@.@.@@@@@@.@@.@@@.@.@@@..@@.@@@@.@@.@@..@@..@@@..@.@@@. +@.@@.@..@@@@@@.@@@..@.@@@@.@@@.@@@@@@.@.@.@@@..@.@@@.@@@@.@.@@@.@@..@@.@@@@@.@@@@.@@@@@@.@@@@@@@@.@@@@@@.@@...@..@@@@.@...@@@@@@...@@@.. +..@@.@.@@@@..@.@@.@@..@@@@@.@..@.@@@.....@@..@@..@@@@.@@@@@@@.@@.@.@@@.@@..@@@@@@@@@..@@.@@.@@..@..@.@@@...@@@@.@...@@@@@@@@@.@@..@@@..@ +@..@...@@@@.@.@@@@@.@@@@@@@@@@.@.@@@@@@.@.@@@@.@@..@.@.@.@@@@@.@.@.@@.@@.@@@.@@....@@@@@@@@@.@.@@.@.@.@@@@..@@@.@@.@@@...@@..@...@..@@.@ +@..@....@.@..@@.@...@@@..@@.@@@.@@.@@@@@@@@@@@@@.@@@@.@..@...@...@..@@.@@@@@.@.@@.@@@@.@.@@.@@@@@@..@@@.@@.@....@@...@.@@@.@@.@.@@@@..@@ +@@@@@@.@@@@.@.@@@@@.@@@@.@..@.@@.@@..@@@@@@.@@@@..@..@..@..@@@.@@..@@@.@.@.@@..@@@.@@@@@.@@.@.@@@...@@@@..@@@....@.@@.@@.@@@.@@@..@@@@@@ +.@@...@......@@@...@@@....@@@@..@@.@@..@@@@@@.@@.@..@@@@@.@..@@@@@.@@.@.@@@.@.@@.@.@@@.@@..@@@..@@@.@..@.@@.@@.@@@@@.@@@@@@@@@@@@..@..@@ +.@.@.@@..@.@@@.@.@.@@@.@@.@.@..@.@@..@@..@.@@@@@@@@@@@@.@@@@.@@@@.@@.@@...@@..@@.@@@@.@.@.@@@.@...@.@@@@..@@.@@@@@@@@@@@@.@.@.@@@.@@@@@. +.@..@.@@@.@@.@@@@.@@@@.@@@.@@..@@@..@.@.@.@...@..@..@@@.@..@..@.@@@@.@.@@@@.@@.@@@@@@@.@@@.@@@@..@@..@@@@..@.@.@@@@@@.@@@@.@@@@.@.@@@.@. +@@.@@.@@@.@.@...@@.@@.@@@.@@.@@@.@.@@@@@@@@.@@.@@.@@..@@.@.@@@@.@..@@@@@.@@@..@@@@@.@@@@.@@@@@.@@...@@.@@..@@@@.@@@.@.@.@@@@.@@.@.@@@@@. +@@..@@@@@@@@@..@.@@.@@@@@@@@@..@@@@.@@@@.@@@.@@@...@....@@@@.@@@@@....@@@@@@@.@@@@@..@@.......@@@@@@@.@..@@@@@.@....@@.@@.@@@@.@@@.@.@@@ +@@@@@.@@@@@@.@@.@@.@.@@@.@@@.@@.@.@@..@@@.@..@@.@@.@.@@..@@@..@.@@@@@@@.@@.@@@.@@@...@.@..@.@@.@@@.@@@.@@@@..@@@@.@@.@@@.@.@@@@.@..@@@.. +..@@@@@@.@@@.@@@@@@.@@@@@.@@..@@@@.@@@@..@...@.@@@@@..@...@..@.@@.@....@@@.@.@.@..@@@@@@@@@.@@@@..@@@.@@@@..@@@@.@@.@@.@.@@..@.@.@@@@@@@ +.@@@.@..@@@.@@@@..@@@.@@@.@@@@@.@@.@@@..@@@.....@.@.@.@@@...@@@@..@.@@@@@@@@@.@@@@@.@.@.@.@@@.@@@.@@@@....@.@@@...@.@@.@@..@@.@@@@@@@@@@ +@..@.@@@.@@@@@@@@@@..@@@.@.@@.@.@.@@.@@.@@@@@@@.@@@.@@@@.....@@.@.@@@.@.@.@@@@@.@.@.@.@@@@@@@@@@@@@@@@@.@..@@@@@@.@@@.@@@.@.@@..@..@@@@. +@@.@.@@@@..@....@@..@@@@@@.@@.@@@..@...@@..@@@@.@@..@@.@..@@@@@@@@@@.@@....@.@@@.@.@@@.@...@@@@@@@@..@@@.@@@..@.@@@@@@@@@@.@@..@.@@@.@@@ +.@.@@.@@@@@.@@@@@@@.@.@@..@.@@@@@@@.@..@..@.@@@@@@@@@@@.@@@..@@@@@@.@.@@@.@.@@@@@@..@@..@@.@@@@@.@.@@.@..@@@@@@...@@..@@@@@@@@.@.@.@@..@ +@.@@@@@@@@@@.@@@@@@.@.@@..@@.@@@@.@@@@..@@@.@@@@@@@@@.@@.@@.@@..@@@.@@@@@@@@....@...@..@@@@.@@@.@..@@@..@@.@@@.@.@@@.@...@..@@@@@.@@@.@@ +.@.@@@@@@.@@@@@@.@@@@@@@@@.@.@@.@@@@.@.@@.@....@@@....@@@.@@.@@@@.@@@..@@@.@@@@@@@@@@@..@@.@@@@@....@@@@@.@@@@@@@@@@@@@@@...@@.@..@..@@@ +@@.@..@..@@@@..@.@@.@@@.@@@@@@@..@@@@@@...@.@.@.@@@.@@@.@...@@.@@@..@.@.@@@@@@@@.@..@.@@@@@@@@.@....@@@.@@.@@@@@.@@@..@@@@.@@@@.@@@@@@.@ +@@.@@.@@..@@.@.@.@.@.@@.@@@..@@@@@@@@@.@..@@.@@@@.@.@@..@.@@@.@@@@@.@.@@@@....@.@@@.@.@@@.@@@@.@.@@@.@..@@@.@@@@.@@.@.@@@..@@@@.@@@@@.@. +@.@@.@.@@@...@.@@.@....@...@@@..@....@@@.@@@@@@.@.@@...@@.@@@..@@.@@@@@@@@@@@.@@.@@.@@.@@..@@..@@@@@@@@@.@@@@.@@@.@....@@@..@@@..@...@@@ +@@.@...@..@.@.@..@.@@@.@...@.@.@@@@@@@@@@@@.@@@@.@......@@.@.@@@@.@@.@....@@@@.@.@@.@@.@@@.@@@@@@..@.@.@..@@@@.@.@@@.@@@..@@@@.@@...@@.@ +@@...@@@.@@@@@@@.@...@@@.@.@@.@.@@@@.@.@..@..@@@@@@.@@..@@@.@@..@@.@@@@@.@.@@@..@@@@@.@@.@.@@@.@@.@.@...@@@@.@@@.@@.@@@..@@...@@.@@@.... +@@@@@.@@@@@@@.@..@@@@@@@@..@.@@.@@@..@@@@@@.@.@.@@.@@..@..@.@@@@@@@@@.@..@@.@@@@@@.@@@@.@@.@@@@.@@@@@@@@.@.@@.@@@....@@@@@..@@..@.@....@ +..@@@...@@@@@@@@.@@@@@@.@@@@@@@@@@@@..@@@.@.@.@@...@..@@@@@@@.@@..@@.@@.@@@@..@@.@..@.@..@@.@.@@.@@@@@@@@@.@@@@@@@@...@.@....@@@@@..@@@@ +@@@@@@.@@@.@.@.@@@.@.@@.@.@@@@@@@..@@@..@@@@@.@@@.@@@@@@.@..@@...@@.@@.@@@@@@@@.@@@@@.@@.@@..@.@@.@@..@@@@..@@@.@@@@@.@@@.@@@@.@@.@@@@@@ +@@@..@.@...@@@..@@.@@@.@.@@@@.@@@@@.@@..@@@@@@.@@@@..@@..@.@@..@.@@@@.@@@@@.@@@@..@..@.@....@.@.@@.@...@@.@@.@@@@@.@@@@@@@@@@.@@@@..@@@. +@@@@....@@.@@@@@@@@@@@@.@@.@...@@@.@@.....@@@@.@@..@@@@.....@..@@@.@..@..@@@@@@@@.@@.@.@.@@@@@@.@@.@@.@@@@.@.@.@@.@@@@@..@@@@.@..@@.@.@@ +@@@...@@@@.@..@.@@@@@@@..@@@@.@@@.@@.@@.@..@@@@..@@@@..@.@.@.@....@@@@.@@.@.@@@@.@@@@@@@@.....@.@@@@.@@.@.@@.@@@@@@@..@.@@@@@.@@@..@@@@@ +@@@@@@..@@@@.....@.@@.@@@@@@@..@@@..@.@@.@@...@@..@@.@@....@@.@.@@@.@@@@@.@@@@.@@.@@@@...@..@@@@.@.@@@@.@@@@@@@.@.@@@......@.@@@.....@@@ +@@@@@@@@.@@.@@.@...@.@@.@.@@...@@.@@@@...@@.@@.@..@@.@.@@@@@.@@...@@...@.@@.@@.@..@..@..@@@@@...@.@@.......@@@@@@@@@@@@@.@.@@@@@@@@@@.@@ +@.@.@..@.@..@@@.@@.@@@@@@.@@@...@@@.@@@@@.@.@@.@@.@@...@@.@@@@...@.@.@.@@@@@.@@..@@@@@...@@@@@@..@@@...@.@@@..@@.@@@@@@@.@@@@..@@@..@..@ +@@@@@@@@..@.@@@@@..@@.@...@@@@..@..@@..@@@@..@@@@@@@@@@@@.@@@@@@@.@@@@@@..@.@@@.@.@@@.@@@@@@.@@@@@@@@@@@@@@@@.@@@.@.@.@@..@...@@@@@@@.@@ +@.@@@@@@....@@@@..@.@@@@@.@@@@@.@@@@@@@@@.@.@.@..@.@@.@...@..@@@@@@@@@@@@@@@@@.@..@@.@@@@@@.@.@...@@.@@@@.@@@@@@...@.@@@@..@@@..@.@@.@@. +.@.@.@.@.@@.@@.@@@.@.@@@...@@@@.@@@@@.@@@@.@@@@@@.@.@@..@...@@.@@@...@@@@@@@..@@@@.@@.@@@@@@..@.@.@@@..@.@@...@@..@@.@@.@.@@@.....@.@.@@ +@@@@@@@.@.@@..@..@..@..@.@@@@@@.@@@@@.@@@....@@.@@@@@...@@@@@@@@@@..@...@@.@@.@.@@@@@@.@@.@@@..@@.@@@.@@@.@..@.@.@@@.@@.@@.@.@@..@.@@@@. +.@.@@@@@...@.@@.@.@@@@@@.@.@@@.@@@@.@@...@.@@@@@.@@..@@@..@.@.@@@@@...@@..@@@...@.@@....@.@...@.@@@@@@.@@@@@.@..@@...@.@..@@@@@@@@..@..@ +@@@@@@@@.@...@@@..@@@@@@@@@..@@....@@.@@.@@.@@@.@.@.@.@...@.@@...@..@@@.@.@@@@@.@@......@@@@.@@@@@@@..@...@@@@@.@@.@@@..@@@@.@@@@@@@@@@@ +@@.@.@@..@.@@@.@@@@@.@.@@.@@@@@....@@@.@..@@.@.@..@@@...@@.@@@@@.@.@.@@.@@..@@.@@.@.@@@@..@@@@@@@@@@@.@..@.@@.@@.@@@@.@@@@@..@@.@@..@@@@ +.....@...@@@.@@@@.@..@@@..@@.@...@@@@@.@@.@..@@@.@.@@@.@@@.....@.@@@.@@@...@.@@@@@@..@@....@..@@.@.@@@@...@@@@@@@@@.@@@@..@@@@@@@.@.@.@@ +.@@.@@..@@.@..@.@@@@.@@...@.@@@@.@@.@@...@...@@@@.@...@.@.@@@@@@@@@..@.@..@.@@@....@@.@@.@@..@.@@@@@@.@@@@......@@@@...@.@..@..@@@@..@.. +@@@.@@@@@@@@@.@...@@.@@@@..@..@.@@@@.@@.@@@.@.@@.@.@.@@.@..@@@.@@...@.@@@@..@@@@.@@..@@.@@.@@@..@@.@@@@@.@.@@@.@@.@@@.@.@@@...@..@.@.@@@ +@@@.@@@@@@@.@.@@@@@.@@@@@@@@@.@@@@@@.@@.@@@..@@@@.@@@@@..@@.@.@@.@.@@@.@@@..@@@.....@@@..@@@..@@.@@..@..@@@.@@.@.@@@@.@.@@@@.@@@@.@.@@@@ +@@@@@@@.@@.....@@..@@@@@@.@@@...@.@@..@.@@@.@@...@...@@.@.@.@.@@@@@.@@@.@@@...@@.@..@@@@.@@.@@@.@@@@..@.@@@.@@@@@..@@@@.@@@.@@@@.@@@.@@@ +@@@.@@@@..@@.@..@@@.@.@@..@@@.@..@@.@@@.@.@@@@@@.@@@@@...@@.@@@@@..@@@@.@@.@@@.@..@@@...@@.@@.@@.@..@@.@..@@@..@@@@@.@..@@.@@.@.@@.@.@@@ +@...@@.@@.@@@@.@.@..@.....@.@@..@@..@...@@@@@@@@.@@@@@@.@@..@@...@@@@@@@@..@@@.@@@.@@@@.@@.@@..@@@@.@.....@@@@.@@.@@.@.@.@@@@@@.@@@@@..@ +@.@@@..@@@@@@@@@@@...@@@.@.@@@...@..@@.@.@@@.@@@.@@.@@@@@...@.@.@@@@@@@@@.@@@@.@@@..@@@@@...@@@@..@.@..@@.@@@@@@@@@@@@.@@.@..@@...@@.@@@ +@@@@@...@@.@@@@@@@.@@@.@.@@@.@.@......@@@@..@@.@@@@.@@..@@.@@@@.@@@...@.@.@@@.@.@@@.@..@.@.@@@@..@.@@@@@..@@.@..@@@@.@@@.@.@@.@@..@..@.. +@@.@...@@@@..@@..@@@.@@...@.....@@...@.@...@@..@@@..@@..@....@@.@@@@@@@@@.@@@@@..@.@@@@@@@@@.@@.@@@..@@.@@@.@@@.@@@@.@.@@@.@...@@@.@.@@@ +@..@@@.@.@.@.@@....@.@@.@.@...@@@@...@.@...@@@@@....@@@@@...@@@@@@@@.@@@@@@.@.@.@@@.@@..@.@@..@..@@.@@@...@...@@@@....@@.@@.@@@..@...@@@ +@@@@..@..@@@@@@@@@.@@.@.@.@.@.@@@@@@.@.@@.@@.@@@@..@@@...@@@@.@..@@@.@..@..@@.@@@...@@@...@@..@@@.@.@@@..@.@@@@@@.@@@@@@@.@@..@@@.@@..@@ +.@.@..@@@@@@@@@@@@@@@@@@.@@...@@@@@@..@@@..@@..@@@@.@.@...@@.@.@@@@@@@@.@...@@...@@@@@@@@@@.@@@@.@.@.@..@.@.@.@@@@.@@@@@@@@@@@...@@@@..@ +.@@..@@@.@@@@@@@@@@.@.@@@...@.@.@.@@@.@.@@.@@.@@........@@@@.@..@@..@@@@@.@@@@@.@@@....@.@@@...@.@@@@@.@.@@@@@@@.........@@@..@.@.@@@@@. +@@.@..@@@@.@.@@..@@@@.@@@@..@.@@@.@@@.@@@@@.@.@@@.@@..@.@.@@@@@@@..@..@@@..@@@@@@@@...@@@@..@@@@@@@@@.@...@@@@@.@@.@.@@@@@@@@@@.@@@@@@@. +@.@@..@@@@.@@@@@.@@.@..@@.@@.@@.@..@.@.@@@@@.@..@@@..@@.@@.@@@.@@@@@.@.@.@..@.@.@@.@@.@@...@@@@@@@.@@@@@@@@@..@.@.@@@@.@@.@@@@@@@.@@@@.. +@@@@.@@@@..@@...@..@@....@@.@@@.@...@@.@..@.@@@@@.@@@@@@@@@@@@..@@@@@@..@@@@@@@@..@.@.@.@@@..@@@@@...@@@.@@.@...@@@.@@@.@.@@@.@@.@..@.@@ +@@@@..@.@@@@.@@.@.@.@@@@@.@..@@@@..@@@@@..@@@.@@@@@......@@@@@@..@@.@@@@@.@@.@@.@.@.@@@...@@.@@@@@@@@@@..@@...@.@@..@@@@@@.@@@.@@@@.@@@@ +..@.@@@@@@@@@.@.@@..@@.@@.@@@...@.@.@@@@.@.@..@@..@@@.@@@.@@@@@@@@@@.@@.@..@@.@@...@.@...@@.@@.@.@..@.@..@@@@..@@@@@.@.@@@@....@@@.@@@@@ +.@@.@.@@.@@.@@.@@@@.@@.@@@@@@@@@@.@@....@.....@.@@@@...@.@@.@.@@@@@.@@@@@.@@@@@@@@@@@.@.@@@@.@@@..@@@@.@@@@@...@.@.@@@@.@@@@@.@.@@@.@... +.@@@..@@@@.@@..@..@.@.@@@.@@@@@@...@@@.@.@@@@@@@@@@...@@.@.@@@.@.@@@@.@@..@@..@.@@@@..@@@.@.@@.@@...@@.@.@@@@@@@.@.@@.@@.@@@@@@@.@.@@@.@ +@@@@@.@.@@@.@@@@@@@.@@.@...@.@@@....@.@@.@@@@@@@@@..@.@..@.@@@@.@.@@@@.@@@.@@@...@@@@@@..@@@@.@@@@@@@@@@@..@@@..@@@..@@@@.@@.@..@@@@.@.@ +...@.@....@@@@@..@@@..@@@@@@@@@@@@@@@@@.@...@@@@@@@@@@..@@@@@@@.@@..@@@.@@@..@@@@@@@.@@@.@..@@.@...@@@@@@@@.@.@.@@@.@@@.@@.@@.@.@@.@@@.@ +@@@@@@@@@.@@@@@@@..@@@@@@@@@@.@@@@@@.@@@@@@.......@.@@@@@@.@@@@@@@@...@.@@.@..@@..@@@@@@@.@.@@@@@@@@@@..@@@@.@.@@..@.@@@@@...@.@.@@@.@@@ +@@@@.@@...@@@@@@@@@@@@@@..@@..@..@.@@.@@@...@..@.@@@@@@@@@@@@@@.@@@@....@@@@@@@..@@@@@@@@.@@@@.....@@@@.@.@@@@.@.@@@..@@@..@@@@.....@..@ +@.@@@@@@@@@.@..@@...@@@.@.@@.@@.@..@@....@@..@@@...@....@..@.@.@.@.@@.@@@@@@@@@@@.@@...@.@@.@@@.@@@.@.@@@@@@@@.@.@...@@.@@@@@.@..@@.@@@@ +@.@@.@@@@@@.@@@@@@@@.@@@@.@@.@@@@.@@.@@.@@@..@@@@.@.@..@@@@@@@..@.@.@@.@@@@@.@@@@@.@.@....@@.@@@...@@@.@@@.@@@@@@.@@.@@@..@@@...@@@@..@. +@@@@.@...@.@.@@@@@@.@@..@@.@@@.@@@@@.@@@.@.@@@@@@.@.@@@@@@@@@@...@.@..@.@@@@@@.@@.@@@.@.@@..@@@@@...@@@@@..@@@@..@.@..@..@@@@@@@@..@@@@. +@.@@....@@@@@@.@@@.@@@@@@.@..@.@@.@..@..@...@@@@@@@.@@@.@@@...@@@@@@@@@...@@@..@..@@@.@@@.@.@@..@@@@@@@@.@@.@@..@@.@..@..@@@@@@@@@..@.@@ +.@@@@@@@..@@.@@.......@@.@.@.@@@@@.@@@@@@@.@@.@@.@@.@@.@@@@@@.@@@@..@.@@.@@@@@@@.@...@@....@.@@.@.@...@.@@@@.@@@@.@@.@...@@.@@.@.@@@.@.@ +.@@.@..@@.@...@..@@@@.@@@.@@....@..@@@@@@@@.@@....@@@@@@@@@@@@..@@@.@..@@@@.@@@..@@.@.@@.@@@@@@@@@@@@.@@@.@@.@@.@.@...@@@@.@....@..@.@.. +@@@@@@@@@@.@..@.@.@@@@@@@@@.@.@@@@@.@.@@@@@@.@.@.@@...@@@@@@@...@@@@.@@.@@@@@@..@@@.@@@@.@@.@@@@@...@@.@...@@@...@@...@.@@@@..@@.@@.@@@@ +.@.@@@..@.@@.@@@.@@@@@.@@@@.@@@@@@@.@@@.@.@@@@@.@@.@@.@@@.@@@@@@@...@@@@@.@@@...@@@@.@..@@@.@@@@.@@@@@@@@@@..@@@...@...@.@.....@@..@..@@ +@@@@@.@.@.@.@@@@@@.@.@.@.@@..@.@@.@@@@@@..@..@@@@@@..@@.@@..@@@@@@@@.@@.@@@.@@@@.@.@.@@....@@@@@@@.@.@@.@@@@.@.@@.@...@@.@@@@@@@.@.@@@@. +@@@.@.@@@@.@@@..@@@@.@@..@@.@.@@@@.@@@..@@@.@@@@.@@.@.@@.@@@.@@@@@@@@@.@....@@@@@..@...@.@..@@@@@@@..@...@.@@@@@@@.@.@...@.@.@.@.@@@@@@. +.@@.@.@.@..@.@..@@@.@@.@.@@@.@.@@@@@@@@@.@@.@@@@@.@@@@.@...@@@@@.@@@@@@@@@@@.@@@@.@@@.@@.@..@@.@@@@..@.@.@@.@@.@@..@@@.@@@...@@@.@@@..@@ +.@..@@.@@@@@.@@...@@@.@@@@..@..@@@@@@.@.@@@.@@@.@@..@..@@@@.@@..@@@@@...@@@@@@.@.@..@@@@.@@@@.@@@@.@.@@.@@@..@.@@@@.@@@@@@@@.@.@.@@@@@@. +..@@.@@.@@.@@@@.@@.@@@@..@@.@@@@@.@@..@@.@.@@@....@@@@@@..@.@.@@@@.@@@@@.@.@.@....@@.@..@.@@.@@@.@@@@@.@@@@..@.@@@..@@.@@@..@@.@@@..@.@@ +.@@@@.@....@.@@@@@@@.@@@..@@@@@...@..@.@@@.@.@..@@@@@.@@@@@@@@@@.@@@@@.@@@@@@@..@.@@@.@@@@@@@@.@@@@...@@@@@@..@@@.@@@@@@@@.@@.@@@@@@.@@. +...@@.@.@..@..@@@@@.@...@.@@@@@@.@.@@@@@@@.@@.@..@@@@@@.@@.@...@.@@.@@@..@@@@@@@@@.@@@.@.@..@@@@@@.@@@@@@.@@@@@@.@@@@...@@.@.@...@@.@@@@ +@...@@@@@.@.@@...@@@.@..@@@@.@@@@.@..@@@.@@@.@@@@@..@.@@.@@@@@..@.@.@.@@@@@@@.@@@.@@@@.@@@@.@...@@@@..@...@@@...@@@.@@.@@..@.@@@@@@@.@@@ +@@@@@@@@@@@..@@.@.@@@.@@@@@@@..@...@@@@@@@.@.@@@@.@..@..@.@..@@@@.@@.@.@.@@@..@@.@@@.@@@@.@..@.@@.@.@@@.@@@@@@.@@@@@@..@@.@@....@.@@@..@ +@.@.@@@.@@@@@@@@@@@@@@@.@@@@@@@@@@@.@.@@..@@@..@.@..@@...@.@@...@..@@@@@..@@.@.@@@.@.@@@@@@.@@@@.@@@.@..@@.@.@@@@@...@@@@@@@@@.@@@@.@@@. +.@@@.@@@.@@.@...@.@..@@.@@@@@@..@.@..@.@.@.@@@@@..@..@.@.@..@@@.@..@@@.@@.@.@@.@@@@@@@@.@.@@.@@@..@@..@@.@.@@@.@@@.@@.@@@@@@@.@@@@@.@@@@ +.@@@@.@.@.@...@@@@.@@@@@..@@..@@@@@@@@@@.@.@@.@@@..@@@@@..@@@@@@@@@.@@@@@@@.@.@@@@@.......@@@@@@@@@@@@...@@@.@@.@@@@@@@.@@..@..@@@@@@@@@ +@@@@..@...@@.@.....@.@.@.@@@..@.@.@@.@..@.@@.@@.@.@@.@@@@@@@.@...@..@.@@..@.@.@.@@.@@@@.@@.@@@.@@@@@@@.@.@@@..@...@@@@@@.@@@@.@@@@@@.@@@ +@@@@@..@..@...@@@@.@@@.@.@.@@.@@..@@..@@@.@@@.@..@@@......@.@.@.@.@..@@@@@..@.@.@@@...@@@@....@@.@@@@@@.@..@.@.@@@@@@@@@..@@@@@.@.@@..@@ +@.@@@.@.@..@@.@.@@...@.@..@@@@.@@.@@@@@@@@@@@@@@@@@@.@@...@@@@@@@@@@@@.@@@@@@@@@@..@@@..@@@@@@@.@@@@@@.@.@@@.@@@@@@@.@.@@.@@@.@@@@.@@..@ +@@.@@@@@.@@@.@@@@@.@@.@@@@@@@@@.@.@@@.@@@..@@@@@.@@..@@.@.@.@@...@.@...@@@@@@.@@@..@@@.@@@@@@@@.@..@.@.@@...@..@@@...@@@@.@@.@@@..@@.@@@ +@.@@@@@.@@.@@.@.@.@.@@@@@@.@...@@@@..@.@.@.@@.@@@@@.@..@@@.@@.@@.@@@@@@@.@.@...@@@@@.@@@@@@@.@@@@@@.@@@..@@.@..@@.@@@.@@@.@@.@@@@@@@@@@@ +...@..@@@..@@..@@.@.@.@.@.@.@.@@.@..@@@@.@@@.@@@@@@@@@@@@@..@@.@.@@..@@@@@@...@..@.@.@@@@.@@@.@@@@@...@@@@.@@@.@..@.@..@.@@@.@.@.@@@@.@@ +.@@@@.@.@.@.@@@..@..@.@.@.@@@@@...@@@@@.@@@.@@..@.@.@@.@..@@@@.@@.@@@.@.@@.@.@..@.@@@@.@.@@@@@@.@.@.@@@..@.@@@@@.@..@@@...@.@@@.@@.@..@@ +@@@.@@.@@.@.@@@..@@.@@@@@@.@@@.@...@@@@.@@@.@@..@@@.@.@.@@@@@.@@@..@.@.@@.@@@@@@.@@.@@@@@...@..@@.@@@.@@@..@@@@@@@@.@.@@@@.@.@@...@@@@@@ +@@@@.@.@..@@@@@@@@@.@@@@...@@@@@@@@.@@.@@@..@@@.@.....@@@@.@@@..@..@..@.@.@@@..@@@..@@.@..@@@@.@@@@.@@.@.@@.@@.@@@@@@@..@@.@@.@@.@@@..@. +.@@@.@@...@.@.@@..@.@@@@.@.@@@@.@@@@..@.@@..@@.@.@@@@@..@@@@@@..@@@@@@@@.@.@@@@@@@@@@@@.@@@@@.@..@@@.@@..@.@@.@..@.@@@@.@..@.@.@@.@@@.@@ +.@@...@@@@@@..@@@@@.@.@...@@@@.@@@.@@@@@@@.@@@@@..@...@.@@@@.@....@@@@@@@@.@.@@@.@.@@@@.@@@@..@@.@.@@@....@.@@@.@..@@.@.@.@@@.@@@@@@@@@@ +@.@@@@@@@.@@...@@@@@.@@@@@.@.@.@.....@.@@@@@@.@@@@.@.@@@@@@.@@..@@.@@..@@@@..@@@.@@..@..@@@@@...@@.@@.@@@..@@@.@..@.@@@@@@@@@.@..@.@@@.@ +@@@@.@@@@@@..@@@@.@..@.@@...@@@@@@.@@@.@.@.@@..@@..@...@@@@@..@..@.@...@@@...@@..@@@@@@.@..@.@@@@@@@.@@@@@@.@.@.@.@@.@@.@@.@..@@@@@@@... +.@@@@.@@..@@.@.@@@@@.@@.@@...@@@@@.@.@.@@.@@..@@@@@@@@@@@@@@@.@@.@@.@@@.@@@@@....@@@@@....@@@..@@@@@@..@@...@@.@...@@@@..@@.@.@@@.@@@.@@ +@@@@@@@..@.@@@@@@@@..@@..@...@.@.@@@@.@..@@@@@@@@.@@@.@.@@@@@@@.@@@@@@@@@@.@.@@.@@@@@..@@.@.@@...@@@..@.@@..@@@@@@@@@@@@@@@@..@.@.@...@@ +@@.@@@@@@.@@@...@..@@@.@@@@@@@..@..@@..@.@@@..@@.@@@@@@@@@@@..@.@@@@@@@@@@@.@@@.@..@...@@@@@..@@@@@.@.@@.@..@.@.@@...@@..@@.@@.@@@@.@@.@ +@.@@@.@@@@.@..@...@......@.@@@@@..@.@@@@.@..@.@@@@@@@@@.@.@@@@..@.@....@.@..@.@.@@@@.@...@@@.@.@.@.@@.@@@.@..@@@.@@@@.@.@.@@@....@@@...@ +@@@@@@..@.@.@.@@@@.@.@@.@@@@@.@..@@@@@@@.@@..@@@.@@@..@.@@@@...@@..@.@.@@@..@.@@@..@...@@@@@@@.@..@@@..@@@@@@@@..@@@@@@.@@@@@@..@@@@@@@@ +@@@@@@..@@.@.@@.@@@.@..@@@@@@@@@@@@@@..@@.@@@@@@..@...@@@.@@.@.@.@@@@@...@@@..@...@@.@@@.@@@@@@....@.@@..@@.@.@@.@@@@.@@@@.@@@@@@@@@@@@@ +......@@.@@@.@@.@@@.@..@@@@.@@.@@@@@..@@.@.@.@@@.@.@@@@@@@@@@.@..@.@@.@@@@@@....@@.@@@@@@....@@.@@..@@.@@@.@@@@.@.@.@@@.@@@@@@@@@.@..@@. +@.@@.@@@@@.@@.@@...@.@.@@@@@@@@@@@@@.@@@@.@@@@@@@@.@@@..@.@@@.@@@.@@@..@.@@.@@@@@@..@@....@@@@..@@@@.@@@..@@@....@@...@@@..@@.@.@...@@@. +@@.@@..@@...@@@@@@@@@@.@..@@@.@@@@.@@@@@@@@@@@@..@@@@.@@@@..@@@@@.@@...@@..@@@.@@@.@@.@.@@.@@..@@.@@@@@.@.@@.@@.@.@..@.@..@@@@.@.@@...@@ +@@@@.@@@@...@.@.@@@@....@@@@.@@.@@@@@@...@@@@@@@@.@@@@...@@..@.@@@@@@@.@...@.@.@@@@..@@@@@@..@@@@@@@@.@..@.@@.@..@@@@@....@.......@@.... +.@@@..@..@..@.@@@...@@@@.@..@@.@@.@@...@@...@..@.@@@...@@@@@@..@@@.@@@..@@@@.@@.@@@.@.@@...@@@@@.@@.@@.@.....@@.@@..@..@@.@@@.@@@@.@@@.@ +.@.@.@.@@@@@@@.@.@@....@@..@.@@@@.@.@.@.@@.@@@@@...@.@.@@.@@@@@..@...@@@@.@.@@@@@@@@.@@...@@@@@@.@....@@@....@@@..@.@@@@@@.@.....@@@@@@@ +.@@@@@...@...@@.@@@@.@@...@....@....@@@..@@..@.@@@@@@@@.@.@....@@@.@@@@.@.@@@@.@@..@@@@@.@@@..@@@@.@..@.@@@@@@@..@..@..@@@.@@@.@.@..@@.@ +@@..@.@@.@@..@..@@.@.@@@@@....@.@@@.@@@.@@@@@@@@@@@@@..@.@@@@.@@@@.@.@@@@.@...@@.@@@@@@.@.@@@@.@@@@@.@@....@@@@@@@.@@....@@@@@..@.@@@@@@ +@@.@@@@@@@.@.@@@@@@@@@@@@@@..@@@@.@...@@@@@@.@..@..@.@@@@..@@@@.@@.@.@@@.@@.@.@@@@@@.@.@.@@@.@@..@@@..@.@...@@@@@.@@@@.@@@@@@@@@@@@..@.@ +@.@.@@..@@@@.@.@.@.@@@@@@.@....@@.@@@@@.@@...@@@@@@@@@@@.@@@.@..@.@@.@@@@@..@.@@@@@@@@..@@@@...@.@@.@@@....@@@@@@.@@.@@@@@.@@.@@@@@@.@.@ +@@@.@@@@@@.@@@@...@@.@.@@@.@@@@.@@@@@.@@@.@@@.@@@@@..@@...@..@..@@@.@@..@@.@@@@@@.@..@@.@@.@@@@@@@@@@...@@@@@.@@@.@@@.@.@@.@@@@@@@.@..@@ +@@@@@@@..@.@..@@.@@@@@@@@@@@.@.@..@@@@@@@.@...@@@@.@.@..@@....@@@@@.@@@.@.@@.@@@.@@@@.@@.@@@@@@@@@@@.@.@@@@@...@@.@.@.@.@....@@..@@..@@@ +@@.@...@@.@..@@@.@@@.@@..@@@@@.@@@@@.@.@.@.@@@...@.@@.@@@@....@@@.@@@@..@.@@..@@@..@@@@@..@...@@@@..@..@@@.@@...@..@@@.@@@@@@.@@..@@@@@@ +@@.@@.....@..@@@.@@@@@@@....@.@@@@@@@@@@@@....@@.@@@@@..@@@@@@@@....@@@.@..@@@..@@..@@.@...@@@.@@@@@@.@.@.@..@@@@@@.@@@@@@@@...@.@.@@@.@ +@@@...@@..@@@@.@@@.@@.@@.@@@..@@@.@@@..@@@@..@.@@@@@.@@@.@@@.@....@@@@..@@@.@@@.@@@@..@@...@.@@@.@@@.@@...@.@@@.@@@.@@@....@.@@@@@@.@@.. +@@.@.@.@..@...@@@.@.@.@@@@.@@@@@.@@@@@@..@@..@@@@.@.@@.@@..@@@@..@@@.@.@.@.@@@@.@.@@@.@.@@..@@@@..@@.@@@@.@@@.@.@..@@..@@@@@@@@@@...@..@ +.@@@@.@@@@.@.@@.@@.@@.@@.@@..@...@@..@@..@@@.@..@@@.@.@@@@@..@@@.@@.@.@@@@@.@@.@.@@.@.@@..@@@@.@@@@@@..@@.@.@@.@@.....@@..@@@@@@@@@@@@.@ diff --git a/aoc2025/input/day04_provided.txt b/aoc2025/input/day04_provided.txt new file mode 100644 index 0000000..8209399 --- /dev/null +++ b/aoc2025/input/day04_provided.txt @@ -0,0 +1,10 @@ +..@@.@@@@. +@@@.@.@.@@ +@@@@@.@.@@ +@.@@@@..@. +@@.@@@@.@@ +.@@@@@@@.@ +.@.@.@.@@@ +@.@@@.@@@@ +.@@@@@@@@. +@.@.@@@.@. diff --git a/aoc2025/src/day04.rs b/aoc2025/src/day04.rs new file mode 100644 index 0000000..d91a1ea --- /dev/null +++ b/aoc2025/src/day04.rs @@ -0,0 +1,120 @@ +use std::{fmt::Write, str::FromStr}; + +use anyhow::{bail, Result}; + +const INPUT: &str = include_str!("../input/day04.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + Ok(res) +} + +struct PaperRollsMap(Vec>); + +impl FromStr for PaperRollsMap { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut grid = Vec::new(); + + let mut width = None; + for line in s.lines() { + match width { + Some(size) => assert_eq!(size, line.len()), + None => width = Some(line.len()), + } + + grid.push( + line.chars() + .map(|c| match c { + '@' => Ok(true), + '.' => Ok(false), + _ => bail!("unknown character `{}' while parsing grid", c), + }) + .collect::>>()?, + ); + } + + Ok(Self(grid)) + } +} + +impl PaperRollsMap { + fn width(&self) -> usize { + self.0[0].len() + } + + fn len(&self) -> usize { + self.0.len() + } + + fn count_accessible_rolls(&self) -> usize { + let mut count = 0; + for y in 0..self.len() { + for x in 0..self.width() { + if self.0[y][x] && self.roll_is_accessible(x, y) { + count += 1 + } + } + } + count + } + + fn roll_is_accessible(&self, x: usize, y: usize) -> bool { + let mut count = 0; + for dy in [-1, 0, 1] { + match y.checked_add_signed(dy) { + None => continue, + Some(yval) if yval == self.len() => continue, + Some(yval) => { + for dx in [-1, 0, 1] { + match x.checked_add_signed(dx) { + None => continue, + Some(xval) if xval == self.width() => continue, + Some(xval) => { + if self.0[yval][xval] { + count += 1 + } + } + } + } + } + } + } + count <= 4 + } +} + +fn part1(input: &str) -> Result { + let grid: PaperRollsMap = input.parse()?; + + Ok(grid.count_accessible_rolls()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day04_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 13); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 1393); + } + + //#[test] + //fn part2_provided() { + // assert_eq!(part2(PROVIDED).unwrap(), 3121910778619); + //} + + //#[test] + //fn part2_real() { + // assert_eq!(part2(INPUT).unwrap(), 168798209663590); + //} +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index 89345b1..e051fbd 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -1,3 +1,4 @@ pub mod day01; pub mod day02; pub mod day03; +pub mod day04; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 7719183..8c2e4be 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -5,9 +5,10 @@ use aoc::DayFunc; use aoc2025::day01; use aoc2025::day02; use aoc2025::day03; +use aoc2025::day04; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run]; aoc::run(days) } From 6cf10a0eb56541126ed640280c385731041db04e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 8 Dec 2025 16:24:56 +0100 Subject: [PATCH 127/134] 2025: day04: part 2 --- aoc2025/benches/aoc2025_bench.rs | 2 ++ aoc2025/src/day04.rs | 47 ++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index 4cbc578..8dc0547 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -3,11 +3,13 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2025::day01; use aoc2025::day02; use aoc2025::day03; +use aoc2025::day04; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); + c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); } criterion_group! { diff --git a/aoc2025/src/day04.rs b/aoc2025/src/day04.rs index d91a1ea..7761cf3 100644 --- a/aoc2025/src/day04.rs +++ b/aoc2025/src/day04.rs @@ -7,6 +7,7 @@ const INPUT: &str = include_str!("../input/day04.txt"); pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -84,6 +85,30 @@ impl PaperRollsMap { } count <= 4 } + + fn count_removable_rolls(&mut self) -> usize { + let mut count = 0; + loop { + let mut cur_loop_count = 0; + let mut copy = PaperRollsMap(self.0.clone()); + for y in 0..self.len() { + for x in 0..self.width() { + if self.0[y][x] && self.roll_is_accessible(x, y) { + copy.0[y][x] = false; + cur_loop_count += 1; + } + } + } + + if cur_loop_count == 0 { + break; + } + + *self = copy; + count += cur_loop_count; + } + count + } } fn part1(input: &str) -> Result { @@ -92,6 +117,12 @@ fn part1(input: &str) -> Result { Ok(grid.count_accessible_rolls()) } +fn part2(input: &str) -> Result { + let mut grid: PaperRollsMap = input.parse()?; + + Ok(grid.count_removable_rolls()) +} + #[cfg(test)] mod tests { use super::*; @@ -108,13 +139,13 @@ mod tests { assert_eq!(part1(INPUT).unwrap(), 1393); } - //#[test] - //fn part2_provided() { - // assert_eq!(part2(PROVIDED).unwrap(), 3121910778619); - //} + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 43); + } - //#[test] - //fn part2_real() { - // assert_eq!(part2(INPUT).unwrap(), 168798209663590); - //} + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 8643); + } } From 7433687d696384892fbc1439bebcde80ff16abf9 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 8 Dec 2025 16:39:11 +0100 Subject: [PATCH 128/134] 2025: fix cargo fmt Turns out rustfmt needs a --edition 2024 flag (which cargo fmt adds automatically), otherwise some imports change order. Of course my editor is configured to use rustfmt via apheleia, which does not support cargo fmt. Urgh. --- aoc2025/benches/aoc2025_bench.rs | 2 +- aoc2025/src/day01.rs | 2 +- aoc2025/src/day02.rs | 2 +- aoc2025/src/day04.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index 8dc0547..ee66bd3 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -1,4 +1,4 @@ -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{Criterion, criterion_group, criterion_main}; use aoc2025::day01; use aoc2025::day02; diff --git a/aoc2025/src/day01.rs b/aoc2025/src/day01.rs index 9ee3904..43766af 100644 --- a/aoc2025/src/day01.rs +++ b/aoc2025/src/day01.rs @@ -1,6 +1,6 @@ use std::{fmt::Write, str::FromStr}; -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; const INPUT: &str = include_str!("../input/day01.txt"); const DIAL_SIZE: u16 = 100; diff --git a/aoc2025/src/day02.rs b/aoc2025/src/day02.rs index 6388ad5..60613cf 100644 --- a/aoc2025/src/day02.rs +++ b/aoc2025/src/day02.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Context, Result}; +use anyhow::{Context, Result, anyhow}; use std::{fmt::Write, ops::RangeInclusive, str::FromStr}; const INPUT: &str = include_str!("../input/day02.txt"); diff --git a/aoc2025/src/day04.rs b/aoc2025/src/day04.rs index 7761cf3..91f24ce 100644 --- a/aoc2025/src/day04.rs +++ b/aoc2025/src/day04.rs @@ -1,6 +1,6 @@ use std::{fmt::Write, str::FromStr}; -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; const INPUT: &str = include_str!("../input/day04.txt"); From 82f19b26673628f5d2f911d0b1a9d2e7e3dd3d98 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 8 Dec 2025 18:01:15 +0100 Subject: [PATCH 129/134] 2025: day05 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day05.txt | 1168 ++++++++++++++++++++++++++++++ aoc2025/input/day05_provided.txt | 11 + aoc2025/src/day05.rs | 127 ++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 3 +- 6 files changed, 1311 insertions(+), 1 deletion(-) create mode 100644 aoc2025/input/day05.txt create mode 100644 aoc2025/input/day05_provided.txt create mode 100644 aoc2025/src/day05.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index ee66bd3..e64ba8b 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -4,12 +4,14 @@ use aoc2025::day01; use aoc2025::day02; use aoc2025::day03; use aoc2025::day04; +use aoc2025::day05; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); + c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day05.txt b/aoc2025/input/day05.txt new file mode 100644 index 0000000..0a62223 --- /dev/null +++ b/aoc2025/input/day05.txt @@ -0,0 +1,1168 @@ +335974207908975-335974207908975 +166378971253254-166378971253254 +202256907733789-202256907733789 +21286600651630-24648609504166 +558745805536874-559599518272636 +435394114820892-441719509061826 +174441875641519-175271524124959 +92531249332742-97299413301312 +513484599234147-520481731528370 +173874995893993-174120643897356 +174821166255466-175271524124959 +293613115143021-293613115143021 +425676293461608-427469272423527 +261699778868308-267782959886821 +62792025293181-64427754150033 +213359143863329-216920173874119 +485300942212668-489793905834071 +13378432871871-18518223043577 +175718286653119-176590936466342 +193998237963829-197306069406792 +224922375146937-226805648022207 +485300942212668-487043192651483 +560583161419561-561040752839097 +335974207908976-340360894525194 +173492439912652-173874995893993 +456128568685693-461311211763581 +554853132666292-555060503953561 +345187503361263-351437898258577 +415331359030508-416758070551384 +175718286653119-176131896992802 +559865818114046-559990685160468 +504484787497948-511084091741178 +41812357709935-46323709619503 +400944889652503-401137154895499 +38566586092786-38566586092786 +71063392748694-78768155867248 +88401531130325-90283598868170 +366212386842113-369559574733375 +41812357709935-49638287193527 +80820430981784-82386862701922 +392205177095718-392504737949797 +248578080710452-250780185041297 +473027494433883-479114462366037 +555860029504106-556466347855858 +414519044783763-415742529794645 +233578509446508-236721976075246 +122852185571020-126919155995876 +318807362064738-318807362064738 +559990685160468-560583161419561 +241484697563377-243682180887337 +197306069406793-199659117082727 +132511850415150-138777911998374 +402736436544865-411103997061827 +226805648022208-226805648022208 +393924466477451-394165734508863 +418277983121492-419855611026273 +176388216880188-176590936466342 +115216308429265-115634137713851 +397880740944623-398712454597673 +356534427403335-360529778470432 +244741606128524-246874615680412 +274184272176093-276891099082351 +553786879235470-554225646956219 +441719509061827-441719509061827 +497223143248878-499936465753045 +543649640475870-550684888609470 +375914800960974-380372536476131 +400723725598098-401137154895499 +429547893930521-431760667174505 +400053049630881-400514724465965 +554225646956219-554853132666292 +135239239818335-138777911998374 +182027374246065-189422637659825 +144155552966923-144155552966923 +87392235254912-89213336560437 +283530251930645-285296872972707 +213359143863329-216920173874119 +380372536476131-380372536476131 +156220005513438-158084001614371 +854928928779-854928928779 +82779951437902-84787684996565 +533710125364597-539267469576012 +264489803972606-271074611857554 +854928928779-8566391540121 +119445951907973-120022385782033 +13378432871871-18518223043577 +354155862714865-360529778470432 +455264846030324-456128568685692 +494219560192751-499936465753045 +406873622656898-408148431482032 +468585580330055-471967905222337 +383865841363033-390795142574897 +427014313885862-428814784979861 +559599518272636-559990685160468 +559599518272636-560410632727482 +504484787497947-504484787497947 +64427754150034-67890971713727 +233578509446508-239818719089833 +416411266176555-417812862711511 +24648609504168-29263080242135 +314869508360391-318807362064737 +560583161419561-561040752839097 +111419310349724-112233031390255 +110883288953568-111665610587406 +399209502052219-400053049630881 +561040752839097-561316255371618 +112233031390255-112666262934332 +324828185977870-328086858004231 +324828185977870-328086858004231 +107587576693307-107587576693307 +524080596593938-532342489388312 +417390509854428-419093317118083 +394413024861195-394757137029331 +112666262934332-113317864269805 +446662754943806-450103995140459 +85221235761715-87036012386502 +31473941440477-38566586092786 +412514374136009-413804208813214 +343730583502464-348034601898665 +92531249332741-92531249332741 +383865841363033-386606350017845 +111419310349724-111665610587406 +559246284857000-559990685160468 +165182752983584-166378971253254 +543649640475870-543649640475870 +246083189515790-247908798756856 +420256891645835-421932264678660 +173380777142810-174120643897356 +144155552966924-147110359740417 +101753444912368-107587576693306 +119091563626635-119445951907973 +285296872972708-289812470209470 +400288079402009-400723725598098 +113008816697274-113662773409190 +424135858939915-425998486358274 +174975048817048-175271524124959 +428496401741058-430734630493823 +464500784968198-468585580330053 +303866335136566-307890118348895 +202256907733789-210125636959977 +124455006477459-129196124218540 +394413024861195-395118980044980 +413587981094322-414864801923854 +419335851296203-420942147944880 +86107799660651-87988102400429 +526807835244889-528743093879030 +446662754943806-450103995140459 +253843593355425-258292954265193 +84158911770863-85542009864131 +422677329720344-424462640002629 +152176426627367-158084001614371 +113878761125354-114156526358922 +247249187230399-249243372682639 +276891099082353-280656369807064 +539267469576012-539267469576012 +395905589789358-396469906815526 +172496676347961-173001774144952 +476653069393498-481331058855155 +81957654709794-83295826585653 +242969727811069-244959373538347 +74394496875907-76781648657372 +363577973505683-366212386842111 +293613115143021-298938356609908 +118225058422162-118558339178687 +395118980044980-395905589789358 +52883578495993-56916924366480 +183815199442521-188204070048092 + +95421034754432 +187179043703356 +518586140516029 +286087724210976 +171547521407314 +118796582870366 +80700451913997 +521304944811388 +497468960146556 +120606342021435 +260394049436757 +200596862923178 +188589752480046 +197064627901683 +360568655614345 +331520423406200 +237943558918272 +282775400579729 +480634058235661 +387123238330877 +407311889566058 +276576032963344 +108810466370754 +212436708456393 +378152926139933 +9539258390456 +281625824028267 +539618529896649 +256138651620246 +359014620151679 +253880903370040 +184624512447647 +82311226354056 +516734033336448 +357403910169806 +303119157923575 +543161445154172 +264618797247246 +466707387250480 +88011917280175 +95476869924856 +383715343175304 +473642625792138 +178333505393210 +318686646529518 +62714303498196 +38712704045944 +240698891130918 +435248429254210 +227025814289600 +33915893072946 +62526691936577 +248790560032824 +453661476529089 +462227344128986 +555662229460224 +473624561372123 +276377583721064 +558508284289223 +203299005563602 +396993851834484 +137896622349447 +346865373468445 +373506787536335 +288467334194362 +347997654929570 +146607305666440 +447601507813676 +51495128381982 +231637467929814 +299606936878056 +557626860612469 +354054394144975 +150627318630636 +278880679271512 +477587880734738 +193400650974752 +393435084719475 +55283577724959 +211152190911931 +3925818696675 +135681614102409 +362212511935836 +15245439499461 +469268230455889 +280306907226699 +13108165441170 +450961761646095 +493135537724534 +543513801509751 +412257224038 +394071927077474 +521079984516881 +492359630059532 +366412387640018 +177699407790013 +414487427672158 +529846119496680 +137301446715144 +512053011848440 +432979864636899 +161350530359498 +112854252365641 +533458423746447 +318632973652408 +314944771805149 +174334343800494 +455121110191088 +345947433453361 +323714520499482 +179443839376817 +548082988887097 +18267001378267 +283608421420521 +520321056536851 +234263961645426 +8190929262671 +538828046340449 +33254683016337 +425572185983473 +488557445980242 +11951846999189 +521283998853305 +561659516040865 +329313844231447 +368466415820673 +540149017603243 +280695472377801 +152121629837146 +114305019133387 +406714162273808 +232201283017301 +140506397608555 +9248763541481 +124445354405428 +137657422393595 +280192423076119 +146692574387499 +211306199762647 +319809016642867 +84012182209918 +169899064816585 +364799307008810 +483304088820862 +385494390424332 +327981529459437 +31394677952634 +245372471891013 +438327981906171 +74927526680816 +261818081429269 +144334098124209 +31758233428411 +52710106266718 +238166478887568 +169562321358767 +330654407646253 +493962129811822 +504551302357996 +453228700142237 +60661783473372 +304618837615069 +314419727746404 +507901124142683 +366928218804813 +71077994649221 +143312746817111 +208864183320714 +158669774376852 +38415894633069 +426285938708603 +173732342198265 +381596583122544 +139333902849444 +562930746320361 +299153278548982 +258702673209260 +461207679800758 +515482702223393 +77893020634835 +332006390167407 +392880606704720 +227442635091447 +391106972192016 +157112754399357 +250958689609784 +557099760724962 +324128042383584 +448495819564965 +68622143164569 +132156875443396 +429978653437826 +542601391784931 +164667455575880 +385308998578707 +303568535743369 +397956049210214 +509095691945333 +167697561181675 +315445489488298 +349657346264055 +380672309472065 +316812211996017 +458179549034732 +233848958077938 +200255966676269 +255123710170889 +408264438219290 +499465274034481 +59184775106056 +115754353359652 +45436745326892 +529343025925307 +60987202120266 +355171194124646 +59334813063361 +218271963649499 +81798752961535 +382613802205632 +81164643446055 +192263130358918 +14950842718816 +561625591981174 +95560028634521 +451339980674243 +273556597459920 +75832351369826 +267462302692896 +498818218165393 +370132175272712 +480380307767814 +354994148632894 +320403156490950 +455081389885802 +455069242867452 +141663717234570 +50398520399781 +550026750664252 +456070589691856 +441784144333129 +506677145361245 +441655718359854 +290827731264154 +460018451485172 +548902559600377 +398495694436003 +4803494865017 +482772676466232 +551605955871700 +175425566524033 +276396995779074 +19885198042189 +520871233429048 +319047176585574 +548704188271087 +159773928469700 +261969546702883 +458920737300731 +551481293707 +223222988760505 +57120960533451 +253888547194942 +390943257567901 +369759578840532 +322499433638314 +381466669710836 +47508010730741 +98385139440756 +61220160510811 +22082641517702 +75725980493680 +202197220498977 +495388824624335 +556029079944015 +343105576135909 +226547101746838 +221291764485430 +122160416023622 +10407162470410 +300553098166486 +124918384122246 +439622208725188 +70161758138109 +130132511023479 +211815660014820 +173731351552218 +84879638458890 +347442089561375 +381193659045772 +376365628500085 +109371947052760 +260704799640162 +505291657065252 +7979499160298 +141939784233605 +396359642039323 +381223416637207 +403742798792521 +41875944940582 +286832825547004 +418521937962215 +468364877455071 +397405547685448 +302986613091056 +53570221215055 +137947070089911 +494320748922078 +278495605713418 +356583765894996 +166096544430923 +462961652181124 +178728098109514 +27465208031789 +457594112275071 +306343677134663 +80913003939829 +165744304257405 +484195292627758 +41127402258904 +457233114196134 +542937220417300 +77002920969070 +401450824164946 +121166679631716 +272769445220787 +451015965504175 +421966175139574 +12458477947374 +382119036417204 +451053055860974 +309791497558758 +423426748752492 +12122329348700 +185447302912028 +66052691280574 +465635908582021 +113545299950352 +532311736607203 +270085319988406 +104442614627868 +301656913331806 +249141122093886 +415591144012947 +334103228980608 +336535426596669 +411997402766609 +114456852432120 +131331849015344 +186480502336660 +154403871216046 +304183379436527 +352925086311243 +185872055326627 +15839530743895 +181510405374135 +374796393472737 +103765041706181 +148244694839096 +181373724702688 +201729373985416 +113554788206222 +225516678903365 +69244219558408 +356560178686019 +124989349975293 +195066814362826 +334490858380620 +82162929539730 +223419421588339 +398128563330487 +458196454433780 +150089126753276 +69405508222389 +159514596618637 +521648241238531 +255172259034208 +171389847853039 +182837229449722 +288389808294500 +553680446954477 +322822311673700 +330336577305119 +286309285024163 +40516696906700 +247527149720990 +429589296140858 +357016505064933 +170200616025067 +499813712174605 +517107049325407 +69063148554856 +48476243865555 +443305960626541 +429832460423833 +49739807098888 +227669926768160 +423193948126066 +65192185454036 +41470571839975 +522386153384224 +232829721412542 +150150633348933 +101191218688765 +75293107589941 +537984532351798 +103907120888053 +557922541520927 +489537649785016 +446442275945984 +345847605313075 +306212088830421 +208558642425658 +311860396978414 +392987506091906 +22955118182998 +527255806516331 +314274955991567 +296208433749607 +252809667953039 +483408440522500 +172623897731241 +53242341360513 +201500807021580 +390163998578841 +176815282150252 +447532216209997 +487690188770716 +262931147359511 +170988511893621 +496229042271059 +316060892128770 +214613795356459 +225605271366387 +94549602951308 +275959508605998 +8284604692648 +64053360408335 +539432357242415 +435222374800551 +414672972555117 +128233252869997 +102272351347327 +116522193401692 +201857337030305 +347590540484565 +123112797328761 +221115412681745 +149631199034761 +344107701572476 +531412855412105 +542257392327843 +216830528547531 +257656367851810 +193547003521438 +331634211891451 +403987187284510 +533644872886638 +160098661575060 +60403330318185 +536064917422223 +99448496001858 +448081211272760 +373821644035517 +231082300675709 +149284086893486 +372325828224406 +229703679694849 +483711790988476 +552131322755803 +72265630766658 +491735328313862 +533092924843969 +193514382668152 +23797480452068 +186371363154517 +93331650325380 +337103192206080 +134115079574231 +256853142206226 +433789348045944 +481386698088705 +90687339442155 +404644194188888 +430613124564471 +84194472837243 +544089520572005 +100792883404662 +450785412879140 +343703884994314 +147420335837520 +33661533334802 +242887372440726 +289825013209262 +550038599399527 +541853958674420 +39332775480172 +191415476771788 +400091896779043 +382358141380220 +202766845674265 +233522322989061 +44850699798379 +373489511039324 +282966142248632 +423726525714994 +31537933715736 +55789409663904 +354282688323879 +92231368452235 +538632572952411 +310180431981757 +253214402336065 +142108738355414 +437032300797093 +57397552529102 +452589157777360 +417910168991845 +281521449448197 +281015162964286 +358223196670003 +390785794829198 +216818088555904 +16237398558994 +190951100824182 +253116003033510 +221368855042658 +283771172694190 +221637388508121 +408775986978227 +526424901809270 +559500174409978 +8647376508198 +180828934669520 +308413261737029 +274212982987007 +556598369404348 +130892471937712 +412024269092182 +284619482039589 +449209603648357 +166822994767279 +116193675590975 +288180200805145 +188906357915178 +176615895595748 +534374705282857 +191838606127882 +250287000698286 +201747936389005 +287838443368718 +338077402118203 +163654763724702 +42826889359315 +101985589186349 +520582780271745 +505272525595020 +561860524744086 +205152516681187 +4895971342969 +370056745185454 +76143844870237 +560144953069720 +39305949105169 +209531363573695 +512282084038965 +412134754917120 +344032447488470 +532569461028918 +341353711217851 +289864786824566 +53355779166554 +24687728439462 +400850422940873 +107014940064546 +511805340631895 +317875374582678 +382716792220559 +226097816525508 +354749176148555 +36099849853061 +377169056414991 +348013459262141 +147811778966724 +445429499774647 +433115967693775 +284212097589816 +506326958741273 +287524503348018 +333236257973532 +281062835849571 +380840324852618 +559844062358945 +277027716387511 +519384919578872 +316224943483573 +156784388641315 +505215894238498 +130141984639967 +392793378533943 +13224684055658 +482653875412070 +516527515357501 +230044031292554 +231862395973170 +311438099204190 +259798380873481 +51554643436754 +298526900274115 +507539764682959 +330449204439923 +73165356925665 +551702795313308 +466493894676249 +251473622701408 +107509600028968 +189166696856729 +140671794791830 +74306956796738 +433829982574787 +433723582306720 +391825563346993 +109630305555162 +81395465181618 +157625322363571 +516854323250527 +281504797984592 +400067616910224 +105436697603904 +229699727006957 +132778387932962 +493071858013900 +446500410097013 +178521235148409 +405118884302417 +310964014902516 +283428742056226 +422800666813583 +149012412338622 +234710699299466 +298892335586193 +364173773823456 +87160044977794 +411144543638134 +350160287777301 +245139969993230 +556662202446102 +526990275140446 +314870512949420 +111624080541873 +315204819385145 +222119828246667 +326924513186993 +8659189033900 +20256822965274 +363101794093322 +235814621139851 +296638902350040 +388542083984054 +375122720220590 +352492443920159 +181330892672632 +281889710415904 +22831651642942 +551741327595504 +20700134643062 +227596448425817 +508369334436594 +380817702826230 +25511982575204 +372163508724291 +390244110467746 +341840725411045 +70718166910888 +549649818646187 +513080082829412 +76648058958878 +153099978152043 +551514534373235 +388065115299017 +121579025657971 +471847713053547 +93820229884611 +330826518502790 +64528135513552 +201888768497198 +388995191181410 +426685907757687 +10777532390991 +182495310767794 +503308992744884 +297642026017377 +92208827896039 +321792582347914 +361783248156295 +205065979304128 +126294995441096 +382986098141725 +221686417935066 +483652060660630 +94799586177512 +16474038517879 +414353924759033 +441147596282000 +545522288187641 +227165048219502 +295538877609619 +248008890675937 +350755058302893 +19487978835907 +515683561247901 +234838078160510 +56449555863632 +251553847095049 +338822526308054 +291502159087373 +476165708168989 +536189274049429 +476079748049996 +103227934627942 +454908816407177 +251158099637640 +453658268016572 +134017743020550 +123093789273235 +470419351973539 +3809650037568 +201399871080774 +345345380774778 +71081520975086 +285655232188015 +172428050192722 +495349596357676 +364851486794391 +391018030138335 +274078747963131 +243511701141230 +283238092660637 +278261998579264 +51399287811428 +113874366313686 +91247698099561 +475557908016002 +420575945042145 +500248422741280 +58853699655581 +440743995611400 +119587327466360 +111720822109282 +250953559234761 +383004771425591 +178723941060230 +554429334175803 +323563016584697 +57855805920625 +281371372578578 +98763265875081 +461565306190030 +288900741329413 +363150535290545 +418157891344504 +153825025523759 +485033683854616 +330422880664827 +311757139609034 +80448286387316 +163023276475222 +287173914898269 +343666475225965 +346793280954931 +361263979971885 +561490373869593 +3614002179772 +117399452494110 +363543445412243 +8877262513069 +16883301847154 +390978731290652 +433400770935345 +56985416513890 +267596817518410 +511298927374687 +461462179143054 +446987847643040 +242302061985386 +96661323985 +267316974488682 +375036882005448 +295739770723614 +43765683901849 +101084334057326 +159561485432029 +189947157268058 +15399867702218 +544079607650663 +45059396174813 +288417883227504 +5439119452896 +486142739685112 +13611061315655 +112245074159684 +126429986746827 +542985652811207 +532462153301676 +384346522589209 +491835486960407 +37855686081193 +471525572178769 +114307023636473 +545538255768260 +380887069193431 +352702579425042 +242265279258350 +516910336926260 +100681474935838 +496927172515771 +106697385562092 +67974173849272 +484278733826678 +97682826351151 +278239736846884 +252049875660153 +100065825143746 +375432012816302 +151643205724906 +215590255507510 +513964516321982 +28370576862981 +546240373608981 +254925568847056 +6266651574443 +508368848670820 +112346877356014 +78970060200101 +457050488132862 +542033372141799 +248856247043616 +545524296374306 +532543564069688 +496882529123951 +287908226724540 +503899802459456 +251989974907190 +509292219937076 +272006508695865 +220073222056757 +281839453952112 +392771584363583 +521369229961835 +99184015854510 +538403451393787 +553847015769243 +4097924653470 +78065681016525 +227046892984218 +128171661502493 +376913717090072 +31252442255035 +14144461061554 +119483400515711 +495599704376578 +150339319840037 +553864971279650 +390534079309244 +130970752676272 +130392068898320 +369884820312428 +333985898501743 +543054607457354 +561717181875858 +421233461758509 +370491328439900 +218594764623325 +500426895952749 +25922854607 +369885110878027 +89037537305033 +472828409278784 +46305656364008 +220340956496876 +216921964608246 +544457849832962 +297175572110108 +432397709514668 +552909038059609 +84156995966998 +221170988039583 +143900478110436 +93091530844470 +157007950514667 +425522921444969 +263027491433660 +34249393165417 +241116853605812 +394705658607775 +492487019658364 +562375650620430 +368078010963087 +353493623993357 +5814674762325 +100118303588444 +293319140424835 +7078081833517 +530289173652828 +172106336310292 +55485804997382 +11339491146805 +470998919854599 +74049757677719 +79424614458144 +503859428006781 +142685386196862 +193224325563181 +492414041169026 +251736352602296 +507252544599045 +253143356098888 +551346180162044 +63032009426426 +231866483096537 +281113571420257 +458558158668632 +324880671392348 +68384155807353 +63067268193497 +449050003797863 +193296990626007 +216664257237356 +25213388754786 +71424308686528 +448291335497686 +72039475564748 +561564591649160 +399995127583647 +82465668060024 +352741647416640 +241243864047807 +172653383298080 +49324372278565 +433259557465849 +320458572136013 +329543033251757 +394210785509811 +2910655110622 +357218221458892 +322188948574535 +302964888693601 +281712128724603 +478253463462087 +233492764442868 +427545456324171 +433170864341001 +195090886503403 +117544682732036 +453719938126579 +377530884893577 +251694822050724 +126182477924317 +249995171506842 +390134080778451 +476507244787390 +403455880324958 +244536445564530 +130029742228114 +468029800779647 +6686227056079 +231630419073412 +122659203731415 +258134485519163 +398848772698429 +243040454410648 +7695054461760 +449704059482137 +394530298025519 +530661826187054 +484804492731711 +525672239263451 +44912629375687 +539974255727970 +82548282990712 +401158184218159 +455091251648958 +323201220638987 +396003870153279 +469643904519487 +80557547864924 +355664161323688 +483031479270917 +329950232424461 +454036159410706 +463551341141276 +218754103552578 +549652397885697 +296265383407070 +340425702904394 +212712628297422 +505723926238965 +2864620608008 +462188510540059 +223005744328557 +34360091407176 diff --git a/aoc2025/input/day05_provided.txt b/aoc2025/input/day05_provided.txt new file mode 100644 index 0000000..2e9078d --- /dev/null +++ b/aoc2025/input/day05_provided.txt @@ -0,0 +1,11 @@ +3-5 +10-14 +16-20 +12-18 + +1 +5 +8 +11 +17 +32 diff --git a/aoc2025/src/day05.rs b/aoc2025/src/day05.rs new file mode 100644 index 0000000..9f506ca --- /dev/null +++ b/aoc2025/src/day05.rs @@ -0,0 +1,127 @@ +use std::{ + fmt::Write, + ops::{Bound, RangeBounds}, +}; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day05.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut fresh_id_ranges = Vec::new(); + let mut available_ids = Vec::new(); + + let mut lines = input.lines(); + for line in lines.by_ref() { + if line.is_empty() { + break; + } + let (left, right) = line + .split_once('-') + .with_context(|| format!("failed to split range `{}' on `-'", line))?; + let (left, right) = (left.parse::()?, right.parse::()?); + let range = left..=right; + fresh_id_ranges.push(range); + } + + for line in lines { + available_ids.push(line.parse::()?); + } + + let mut count = 0; + for id in available_ids { + for range in &fresh_id_ranges { + if range.contains(&id) { + count += 1; + break; + } + } + } + + Ok(count) +} + +fn part2(input: &str) -> Result { + let mut fresh_id_ranges = Vec::new(); + + for line in input.lines() { + if line.is_empty() { + break; + } + let (left, right) = line + .split_once('-') + .with_context(|| format!("failed to split range `{}' on `-'", line))?; + let (left, right) = (left.parse::()?, right.parse::()?); + let range = left..=right; + fresh_id_ranges.push(range); + } + + // sort all ranges to prepare for merging of overlapping ranges + let mut new_ranges = Vec::new(); + fresh_id_ranges.sort_by_key(|range| match (range.start_bound(), range.end_bound()) { + (Bound::Included(&beg), Bound::Included(&end)) => (beg, end), + _ => unreachable!("We're only handling inclusive ranges"), + }); + + let mut fresh_id_ranges = fresh_id_ranges.into_iter(); + new_ranges.push( + fresh_id_ranges + .next() + .context("Input did not contain any ranges!")?, + ); + for range in fresh_id_ranges { + let latest = new_ranges + .last_mut() + .expect("new_ranges always contains at least one element"); + let (last_start, last_end) = match (latest.start_bound(), latest.end_bound()) { + (Bound::Included(&beg), Bound::Included(&end)) => (beg, end), + _ => unreachable!("We're only handling inclusive ranges"), + }; + let (cur_start, cur_end) = match (range.start_bound(), range.end_bound()) { + (Bound::Included(&beg), Bound::Included(&end)) => (beg, end), + _ => unreachable!("We're only handling inclusive ranges"), + }; + + if cur_start <= last_end + 1 { + *latest = (last_start)..=(last_end.max(cur_end)); + } else { + new_ranges.push(range); + } + } + + Ok(new_ranges.into_iter().map(|r| r.count()).sum()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day05_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 3); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 509); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 14); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 336790092076620); + } +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index e051fbd..f290640 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -2,3 +2,4 @@ pub mod day01; pub mod day02; pub mod day03; pub mod day04; +pub mod day05; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 8c2e4be..74ed9a0 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -6,9 +6,10 @@ use aoc2025::day01; use aoc2025::day02; use aoc2025::day03; use aoc2025::day04; +use aoc2025::day05; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run, day05::run]; aoc::run(days) } From 47dfb876eb3dd249e1ed2b2a235167b991da7af5 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 10 Dec 2025 10:42:18 +0100 Subject: [PATCH 130/134] 2025: day06 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day06.txt | 5 + aoc2025/input/day06_provided.txt | 4 + aoc2025/src/day06.rs | 199 +++++++++++++++++++++++++++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 10 +- 6 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 aoc2025/input/day06.txt create mode 100644 aoc2025/input/day06_provided.txt create mode 100644 aoc2025/src/day06.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index e64ba8b..d44555a 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -5,6 +5,7 @@ use aoc2025::day02; use aoc2025::day03; use aoc2025::day04; use aoc2025::day05; +use aoc2025::day06; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -12,6 +13,7 @@ fn aoc2025_all(c: &mut Criterion) { c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); + c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day06.txt b/aoc2025/input/day06.txt new file mode 100644 index 0000000..00468a3 --- /dev/null +++ b/aoc2025/input/day06.txt @@ -0,0 +1,5 @@ +366 27 228 617 753 14 146 5 1 83 92 885 64 41 8 952 75 23 26 43 229 478 633 5347 192 64 595 496 644 1 74 119 94 9 1 55 7 2 1269 13 128 368 75 18 32 664 15 4 57 7665 277 2 75 17 722 622 6 91 52 293 23 1 1611 267 1 47 458 469 9521 872 23 2 9 1669 971 77 26 4 17 491 972 354 5 964 438 873 65 432 81 75 71 334 17 6 92 28 888 966 82 98 4 38 5 69 74 754 38 872 349 93 74 12 151 319 332 35 313 8 12 55 295 781 1686 74 997 282 54 382 4881 4655 367 95 7 89 18 23 344 9 53 19 5749 486 72 687 27 29 92 55 15 54 17 85 237 7151 3 2573 6 9 363 623 972 16 9 71 64 741 111 91 3 662 779 65 7 14 23 56 1414 7517 2 41 754 515 32 6326 763 86 2625 83 78 75 9 6159 83 57 25 6989 949 2 2967 1 8 919 45 88 52 74 49 885 41 4 25 7333 185 65 83 327 96 5793 32 457 3 783 244 86 85 18 2 331 52 658 12 85 72 18 42 12 267 33 768 628 78 42 4816 264 17 765 758 9 678 12 45 67 432 447 37 8474 645 2 85 183 79 28 1 96 73 4 572 171 44 59 9787 47 4 46 15 126 3446 459 726 578 9 8 649 144 71 8 6 39 844 554 79 696 58 823 78 51 19 142 64 86 97 1 438 68 8 5746 19 498 323 2 438 3287 649 56 29 79 35 486 361 928 47 51 313 9 7 53 46 76 3 6862 14 24 2 2 44 23 142 28 82 756 2931 643 18 9 12 39 599 43 25 91 29 648 924 81 89 8315 713 88 375 3 894 25 427 938 54 2 967 11 947 97 574 989 215 413 31 59 238 92 24 75 6 966 3 63 252 826 397 9 6223 9957 55 96 89 2 54 589 41 12 327 3 15 295 2 34 366 972 24 89 224 34 68 691 3 5 94 6798 2 2354 891 913 6868 46 53 1 9164 8 6 444 47 5 19 448 5 12 3773 5494 13 76 24 583 4 475 783 951 62 2 44 921 96 251 84 896 58 87 343 75 61 9 661 31 24 6 17 873 163 4 78 45 28 67 42 92 232 3 183 1 879 81 17 98 571 23 7 225 7954 74 82 5 31 949 518 154 67 32 55 1 69 6 95 52 383 216 458 4 482 96 8494 72 275 9 41 52 37 279 51 39 396 57 89 588 32 524 17 6645 9 534 289 9 59 89 1 71 5345 561 3 5 565 93 6389 97 124 3 94 249 86 36 611 9 6299 7329 195 1 389 7 33 988 28 596 84 1 392 9846 364 82 6385 8 5 8482 48 914 4 417 534 59 64 751 7567 129 46 42 25 153 315 988 93 46 336 41 6 91 67 451 426 84 6 8155 3 6 53 4 399 178 53 13 668 4687 76 44 49 673 97 253 41 83 49 853 741 418 3 78 466 896 24 55 15 15 3 195 329 19 78 89 4 6 619 791 62 64 86 89 583 327 752 77 32 2 675 54 78 621 57 5976 18 33 9 441 9 52 828 51 39 2 15 338 4322 2 175 2473 555 69 1 722 28 5 43 59 4 732 656 32 67 147 74 399 1 764 34 69 97 91 46 43 82 85 11 5 376 11 65 2 9371 11 159 463 93 32 263 5 4 2794 1 21 42 199 937 8 168 8 337 17 753 28 46 9 866 4 27 42 144 622 6 9 34 89 73 282 32 14 58 946 91 71 2 8 64 277 18 59 99 4311 5 676 916 773 24 96 24 293 28 5856 227 452 53 5 8 79 5944 357 731 82 56 6787 75 569 8 854 4136 12 95 81 84 6848 2 72 1 86 986 492 13 17 5 32 967 1 27 124 6 82 135 11 73 62 81 3 81 9 61 865 48 5 62 16 963 8 52 71 93 4 529 7291 2 84 8 86 56 3727 14 157 64 74 377 694 275 21 2615 18 9 59 577 7811 839 67 24 3558 246 528 89 368 924 752 685 49 522 61 75 5735 8 4 37 745 56 815 38 9 247 53 6 1844 3 1 531 971 735 9 21 99 9413 89 8657 39 514 565 42 6724 2 23 443 37 85 117 63 14 35 3466 934 57 79 2 116 63 95 2 51 46 47 5535 28 6 38 81 898 93 3 871 3 9468 432 224 91 24 85 891 2 78 568 26 45 23 8 85 57 8 51 82 859 929 65 5 458 5456 752 96 47 264 86 76 24 67 87 8 622 9912 357 38 62 1 17 53 899 3 3977 97 6135 1 33 44 153 37 435 63 674 27 394 86 7696 119 1 77 94 69 417 7 917 53 831 4 62 314 794 17 78 268 8 58 465 6 969 59 39 44 +2893 23 156 756 335 46 8446 45 5 83 57 16 641 43 1 275 56 3517 44 68 386 955 412 2855 155 64 641 489 199 4 17 589 99 99 15 25 73 62 1746 32 643 215 58 38 74 849 89 9 48 6538 178 735 13 26 719 991 714 85 43 956 44 4 6637 833 86 38 144 948 2943 786 21 2 829 8547 846 21 723 325 35 561 965 569 8 954 571 174 621 5163 93 42 66 953 52 24 59 13 487 778 26 789 74 84 34 98 97 836 944 218 11 98 32 727 731 258 269 18 798 14 15 94 773 227 2385 994 888 528 24 928 6311 9789 678 95 7 415 81 8 864 3 75 14 6375 756 17 589 82 9 99 15 47 94 631 99 254 1682 1 4196 32 8 7344 225 517 97 1 37 68 372 424 94 3 791 446 32 67 79 36 91 2515 7279 8 32 418 597 869 184 797 624 1492 44 83 73 2 1567 95 662 27 9258 798 2 8517 6 7 893 63 33 44 82 16 389 28 2 37 7143 697 69 33 744 44 9763 28 532 5 546 785 96 74 438 34 246 49 887 47 9635 148 33 99 83 361 38 643 363 69 58 93 459 164 548 659 3 388 62 493 89 478 431 11 587 298 99 39 168 573 856 56 51 772 35 938 639 61 59 4897 92 5 825 81 668 6531 241 168 252 88 27 65 381 86 39 54 23 7696 169 927 452 14 732 48 67 97 119 45 67 18 3 728 392 727 6797 36 613 357 4 197 9565 229 17 8 98 263 938 677 524 33 82 745 62 8 17 26 711 3 7725 37 37 92 9 68 37 233 18 66 63 1272 984 99 7 57 68 462 91 31 165 45 533 667 885 52 7378 81 28 923 11 975 62 945 367 23 96 381 51 249 66 833 669 8538 243 633 96 22 894 71 62 61 7369 26 271 718 41 269 5 5175 1161 15 39 888 7 98 593 52 46 423 68 33 981 27 47 3555 386 15 72 825 47 73 527 3 51 621 7416 11 8976 59 695 899 63 43 8 7564 78 22 285 92 57 2947 616 3 193 387 3633 241 573 74 182 33 694 589 728 53 3 249 62 58 579 26 576 58 38 422 65 24 89 411 59 67 61 1981 681 3767 14 67 33 725 523 83 878 713 2 716 26 16 287 982 65 648 96 47 731 1426 86 72 64 4369 99 757 8748 197 57 968 799 73 7 251 21 626 742 114 9 645 26 7211 5 345 9 95 445 73 584 19 39 175 58 63 592 49 979 469 1887 68 335 846 3 69 67 89 21 2186 435 734 4 483 84 1574 787 598 89 9 556 44 61 52 38 8941 4321 369 3 942 87 46 256 22 642 5 23 883 6479 965 14 216 4 88 214 59 173 57 937 912 63 18 654 7595 743 62 277 24 661 739 632 875 5164 829 56 637 38 839 56 75 4 8 1369 5 8 41 53 642 773 89 37 526 2696 67 65 57 37 476 85 14 94 6 853 8839 639 8 73 53 448 38 29 39 32 45 254 443 75 26 795 26 982 71 658 41 39 97 989 19 272 749 68 751 22 159 29 789 918 69 4287 83 18 859 518 31 74 449 418 96 495 56 854 8471 9 551 728 84 67 2 894 339 64 44 88 68 646 3232 493 72 353 11 833 72 711 97 147 67 22 56 412 11 46 86 47 249 976 55 3 7253 15 51 532 32 34 65 51 415 4241 53 344 182 165 389 58 377 6 398 231 311 26 56 6 568 95 23 78 434 392 71 76 697 5 125 486 5 23 3918 819 84 86 8 283 98 654 49 987 42 9794 7 72 569 143 742 4594 182 565 25 9658 546 4 27 831 25 68 8848 137 4321 2572 927 8545 99 923 52 424 6371 89 86 47 93 8895 1 49 1 99 9281 172 18 69 77 83 221 47 863 938 73 77 34 311 617 94 79 876 68 322 22 931 22 2 32 1787 828 1 75 52 25 8 632 5567 12 62 7 44 69 5892 81 812 32 317 726 1196 927 21 8555 39 3 62 559 1835 9679 31 58 446 931 858 61 247 917 161 4457 88 798 27 84 52 453 32 728 691 499 887 68 95 742 17 39 7951 51 16 823 664 483 1 4 51 754 313 9495 77 132 421 766 3315 176 93 58 37 86 433 42 66 15 9322 551 49 914 96 3215 11 88 2 22 11 13 7469 219 37 19 39 667 14 79 453 31 63 548 421 96 53 39 719 6 4 85 67 834 63 64 12 15 86 669 16 43 125 99 39 547 1666 372 11 74 875 59 381 89 86 99 68 176 452 537 3 34 886 49 87 621 32 236 64 6154 26 46 16 797 141 465 19 233 16 443 89 1322 37 42 47 25 715 613 188 236 78 592 485 67 699 919 39 37 583 728 64 373 5 156 388 76 29 +5447 89 387 842 49 388 8423 814 93 2 17 2 288 92 5 45 77 9841 28 58 463 91 657 8732 899 525 1 74 928 74 27 186 72 78 386 51 853 34 6447 553 9 397 29 95 77 654 6 94 4 3949 985 873 6 8 57 732 438 81 6 98 72 14 136 864 73 17 948 128 2574 819 14 43 467 316 965 67 594 436 11 697 1 285 39 267 285 99 436 5384 28 83 11 568 45 41 67 94 664 775 53 644 69 75 51 347 7 62 556 415 2 41 71 718 58 299 194 34 5 52 56 6 63 46 95 569 922 25 36 643 6557 1685 85 87 566 161 92 1 25 332 43 239 53 418 675 98 87 9 76 67 57 22 687 38 291 4964 46 1211 658 163 6126 837 149 12 1 21 18 271 48 5 85 577 48 6 16 59 92 853 335 7311 22 87 879 567 165 762 843 765 9163 65 39 86 147 9749 84 614 95 649 743 68 9515 85 98 263 49 67 1 82 77 8 33 72 98 8562 38 56 46 165 627 532 27 131 1 85 519 99 463 284 18 265 99 88 69 9716 259 18 1 6 71 73 944 555 51 18 3 845 145 229 47 6 419 45 953 38 234 451 28 62 6937 592 71 267 998 895 21 4 634 188 15 758 78 79 946 38 46 219 67 735 56 836 784 824 45 55 16 791 29 853 73 83 4867 5254 6523 75 74 266 18 1 99 268 19 76 4 58 747 2392 521 398 22 887 131 3 379 855 527 75 5 24 882 69 938 257 1 1 98 44 7 72 12 3282 74 8446 37 7 84 12 58 61 866 3 83 1 74 513 59 2 76 62 667 53 74 587 55 626 7 768 14 1984 2 46 22 789 142 39 775 711 86 44 162 35 369 86 795 235 7833 172 543 82 59 381 18 31 33 3758 35 7626 1 46 82 77 575 4442 73 79 332 137 14 88 984 72 528 87 11 4 32 77 8142 32 28 9 4 293 22 979 8 72 495 1319 39 999 81 715 982 87 65 86 6563 693 25 952 54 86 8537 892 7 3145 337 991 882 256 97 13 293 42 249 533 68 91 733 74 41 167 295 222 2 976 252 42 9 69 134 3 761 9391 7723 515 1836 524 16 32 912 3775 74 391 177 135 8141 92 77 8335 139 72 21 39 94 66 4944 3 14 894 3411 17 75 4368 499 496 724 7259 6 27 317 18 182 574 84 3 758 18 574 4 78 78 69 831 87 331 17 464 112 19 11 354 93 9481 428 4432 15 476 67 7 6 83 13 31 6637 216 149 31 24 93 622 438 755 41 6 44 66 35 78 97 8919 3559 641 4 469 54 84 249 3 136 4 81 393 6263 149 5 838 71 83 78 22 813 41 95 245 61 17 27 619 835 25 891 72 863 7639 922 521 2126 437 58 8567 64 375 92 8 4 8 665 2 44 8 44 782 614 71 81 626 632 17 85 45 5 615 38 11 51 5 862 2717 4776 96 47 17 171 83 33 9385 597 92 585 653 825 99 3724 92 727 1 77 75 26 93 666 24 81 77 21 236 5938 422 66 113 66 43 8992 23 58 193 148 95 85 44 2252 22 336 2 793 2935 51 716 685 71 66 7 595 942 5755 56 62 43 732 3911 169 64 5 18 71 16 634 71 149 173 77 98 227 67 456 8 37 3287 832 65 1 8536 88 95 53 27 517 8 39 512 1264 81 496 886 76 846 17 456 71 529 358 958 95 86 41 217 372 83 67 58 24 95 229 167 3 611 6666 6 26 6394 44 37 97 15 693 53 159 31 273 86 6282 53 43 881 518 265 7965 7358 762 87 866 76 5 49 793 499 87 5339 779 6527 3278 517 6474 97 773 49 236 6713 67 54 55 15 152 6 89 2 41 4163 224 71 48 93 99 51 366 351 892 78 6 53 238 282 92 76 532 11 194 6 64 73 93 86 7588 815 25 13 949 97 7 76 3581 56 82 66 88 7 2413 74 41 26 997 5763 6164 51 93 185 469 86 38 793 7966 9935 7 31 997 7 283 85 674 295 955 9349 59 78 74 85 21 185 975 325 81 715 269 58 44 986 66 77 8718 261 821 684 963 211 61 4 63 212 691 2275 57 765 264 149 856 686 58 33 1 44 258 17 2 24 274 266 6 954 41 4924 14 3156 54 52 45 649 4247 583 99 65 68 449 66 358 664 41 14 789 625 17 11 55 174 67 8 37 34 1815 74 58 96 3 18 792 91 62 99 95 66 82 659 271 56 69 264 6 861 56 6 54 5579 336 566 5 8 5 417 21 76 256 76 726 6 3455 69 79 21 75 522 974 75 687 5 649 53 8932 84 33 78 75 814 52 412 7132 72 268 667 69 498 991 14 61 13 624 97 396 98 787 693 96 15 +6541 525 919 57 35 465 2588 525 73 9 69 1 767 5 223 2 55 4553 5 26 26 31 29 57 999 9419 9 4 764 81 84 435 49 48 414 52 214 96 3372 128 8 748 51 7 99 89 3 83 6 13 887 219 1 8 7 589 139 3 8 15 3 42 57 329 58 41 13 12 2 56 458 651 783 99 558 34 395 843 74 3 7 65 46 4 3 3 613 8815 53 77 56 372 4 44 85 88 762 79 3 797 33 55 99 746 2 4 321 959 5 77 79 461 39 434 72 3 2 72 3 9 1 9 21 625 221 88 67 18 222 428 4 99 723 774 12 8 14 249 13 685 7 619 246 25 57 5 88 15 22 93 335 69 7 597 54 5 239 367 4373 85 72 4 37 5 59 172 53 1 46 136 85 6 61 8 21 166 9 99 927 95 71 162 227 698 9 684 2936 6 5 14 232 3271 11 118 67 713 16 78 946 754 51 5 98 8 4 65 73 1 66 22 48 4298 97 5 49 1 511 67 68 63 35 4 99 38 767 7295 74 535 42 9 44 2266 167 6 9 6 1 75 469 573 43 2 4 288 369 45 92 33 34 65 7323 66 84 339 86 8 3418 912 95 65 534 571 55 7 347 916 98 525 79 76 53 179 868 641 62 46 21 328 96 569 59 74 31 748 75 4226 23 33 4956 5484 8379 67 3 2 24 2 274 595 3 23 8 941 98 9326 931 17 27 31 854 47 293 667 22 18 6 32 225 1 982 196 4 4 4 33 583 46 4 6614 17 37 11 7 727 65 15 23 39 7 81 9 89 55 27 29 9 85 18 19 4 532 855 4 4 432 7 627 2 82 15 779 428 25 49 4 94 771 8 24 71 31 1 124 8544 878 924 32 45 793 2 92 11 4697 536 8998 9 88 78 16 93 95 55 56 685 4663 16 8 989 475 181 97 97 2 925 28 7439 7 19 5 9 383 81 339 39 27 995 381 86 68 2 861 13 87 16 91 4 671 36 54 24 72 9474 3 65 5712 95 393 581 978 35 68 356 28 154 99 39 51 8787 6 16 98 491 595 8 635 8 3 5 45 12 6 697 8141 4634 734 1189 639 75 95 127 4166 3 188 559 9214 3794 28 32 2436 283 5 11 12 637 75 818 5 27 226 2653 37 18 5517 262 583 843 1692 2 78 748 5 3 529 9 47 23 4 71 2 72 83 22 774 58 297 55 443 853 43 836 43 8 4633 796 4457 58 749 19 88 2 99 55 57 84 89 959 787 55 43 14 292 62 789 3 79 35 94 84 19 1445 1399 364 66 6 532 22 818 9 717 9 42 562 282 225 9 25 29 58 59 6 392 345 71 42 44 93 74 4 131 58 454 62 327 3564 675 638 4942 29 72 6424 3 545 7 7 9 59 951 65 18 3 49 364 1 71 77 627 7 77 15 87 3 198 4 65 18 4 837 3535 4837 11 38 32 185 87 8 5348 3612 51 83 33 725 99 6495 393 537 7 28 24 88 5 399 33 84 32 19 544 1192 723 7 496 7 96 62 52 92 962 863 835 96 94 8555 929 478 2 26 6582 67 497 47 9 87 36 52 169 4924 79 9 92 886 8948 722 8 2 6 16 79 56 58 558 256 93 49 351 62 996 1 54 4473 556 11 74 8835 42 33 4 6 978 6 25 8128 54 73 988 7983 73 864 23 132 64 688 747 183 58 24 21 631 469 92 95 47 11 85 195 714 8 786 7177 3 49 5727 41 474 19 66 261 74 26 45 194 91 9331 31 8 95 792 323 5649 9529 32 39 37 46 9 9 119 582 8 868 2893 7217 3284 576 1669 68 773 13 6 6739 91 4 22 45 61 71 1 98 63 7212 767 5 93 34 96 49 396 186 53 24 3 66 449 626 5 9 689 53 932 4 81 9 59 19 6946 25 74 97 767 68 97 21 3754 19 46 47 7 4 617 681 12 5 235 5543 2688 2 92 14 974 53 19 839 4444 8543 2 53 78 3 5 3 26 96 712 9234 86 11 65 22 15 594 636 922 12 466 992 12 69 74 31 14 3378 225 359 11 77 598 12 1 36 32 255 382 38 19 747 979 824 455 676 2 3 71 51 87 1 26 12 273 2 863 65 8761 2 4543 42 64 82 226 8952 639 62 81 15 367 87 872 173 46 5 43 84 68 34 59 38 93 5 15 96 3882 33 77 12 3 28 426 48 16 1 9 749 6 81 73 45 33 24 6 987 68 9 6 8677 7 38 5 6 9 544 9 21 39 61 512 6 615 68 8 2 72 871 625 91 242 1 223 6 72 5 73 1 14 5328 38 718 1348 17 799 282 99 81 283 27 539 1 523 2 7 89 21 876 3 55 ++ * + * + * + + * * * + * * + * * + + * * + * + * + * + * * * + * + + + * + + + * * * * * + * * * + + * * * * * * + * * * * + * * + + * + + * * * + + * * * * * + + * * * * * + + * + + * * * * + * + + + * * * + + * * * * * + * * * + * + * + + * + * * * + * + + * * + * * * + * * * + + * * + * + * * * * * + + * + + * + * * * * + + * * * * * + * * + * * + + * + + * + + + + + * + + * + * + + + * * + + + * * + * * + * + * * + + * * + + + + * + + * + * + + * + + * + * + * * * + + * * * + * + * * + * + + * * * + + + * * * + * + * * * * + * * + * * * * * + * + * + * + * + + + * + + + * + * + + * + * * * * + + * + + * * * + + + + * + * * * + + + * * + * * + * + * * * + + * + * * * + * + + + + + * * + + + + * * + * * * + * + * * * + + + * * * * + + * * * + * + + + * + + * + * + + * + * + * + * + * * + * * * + * * * + + * * + + + + * + * * + * + * + * + * + * + * * + + + + * + * * * + * * + + * + + + + + * + * + * + * * + + + + + + + * + + + * + + * * + * + * * + + + + * * + * * + * + * + * + * * * + * * + + + * + * * * * * + + + * * * * + * + + * + * * * + * + + + * * * + * + + + * * * * + + + + * * + * * * + + * * + + + + + + + * + + + * * + * + * * + * + + * + + * * + + * * + * * + * * * * * + * * * + * * * + * + * + * * + + * + + + * * + + * * * + * + * * * * + * * + + * + * * + * + * + * + * * + * + * * + + + + + + * * + * + * * * + * * * + + * * * * + + + * + * * * + + + * + + + * * + * * * * * * * + + + * + * * * + + + + + * * * + * + * + + + + + * * + * + + * * + + * + * + * + + + * * * * + + + + + * * * * + * + + + + * + * + * * + + * * * + * + + + + * * + + + * * * + + * + * + * + * + + + * + * * + * * + * + + * + * * * * + + * * * * + + * + + + * + + + + * + + + * * + * * + * + + + + + * + + * * * * + + + + * + * * * * * + + * + * * * * + * * * + * * + + + + * + * + + * + + + + * + + * + + * * * * + + * * * + + * * + + * + + * * + + * * * * * + * + + + * + + * + + * + + + * * * * + * * + + + + * * * + * + * * + * + + + + * + + * * + + * + + * + * * * * + * + * + + + diff --git a/aoc2025/input/day06_provided.txt b/aoc2025/input/day06_provided.txt new file mode 100644 index 0000000..337b837 --- /dev/null +++ b/aoc2025/input/day06_provided.txt @@ -0,0 +1,4 @@ +123 328 51 64 + 45 64 387 23 + 6 98 215 314 +* + * + diff --git a/aoc2025/src/day06.rs b/aoc2025/src/day06.rs new file mode 100644 index 0000000..86077d4 --- /dev/null +++ b/aoc2025/src/day06.rs @@ -0,0 +1,199 @@ +use std::{fmt::Write, str::FromStr}; + +use anyhow::{Context, Result, bail}; + +const INPUT: &str = include_str!("../input/day06.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + Ok(res) +} + +#[derive(Debug, Clone, Copy)] +enum MathOp { + Add, + Mult, +} + +impl FromStr for MathOp { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "+" => Ok(MathOp::Add), + "*" => Ok(MathOp::Mult), + _ => bail!("cannot parse `{}' as MathOp", s), + } + } +} + +#[derive(Debug, Clone)] +struct MathProblem { + numbers: Vec, + op: MathOp, +} + +impl MathProblem { + fn compute(&self) -> u64 { + match self.op { + MathOp::Add => self.numbers.iter().sum(), + MathOp::Mult => self.numbers.iter().product(), + } + } +} + +fn part1(input: &str) -> Result { + let mut numbers: Vec> = Vec::new(); + let mut ops = Vec::new(); + + for line in input.lines() { + let line = line.trim(); + if line + .chars() + .next() + .context("got an empty line")? + .is_ascii_punctuation() + { + ops = line + .split_ascii_whitespace() + .map(|c| c.parse::()) + .collect::>()?; + break; + } + + let split_line = line.trim().split_ascii_whitespace(); + let width = split_line.clone().count(); + if !numbers.is_empty() && numbers.len() != width { + bail!( + "all input lines should have the same number of columns: current line has {}, previous lines had {}", + width, + numbers.len() + ); + } + if numbers.is_empty() { + for _ in 0..width { + numbers.push(Vec::new()); + } + } + + for (idx, num) in split_line.enumerate() { + numbers[idx].push(num.parse::()?); + } + } + + Ok(ops + .into_iter() + .zip(numbers) + .map(|(op, numbers)| MathProblem { numbers, op }) + .map(|problem| problem.compute()) + .sum()) +} + +fn part2(input: &str) -> Result { + let mut numbers: Vec> = Vec::new(); + let mut ops = Vec::new(); + + for line in input.lines() { + if line + .chars() + .next() + .context("got an empty line")? + .is_ascii_punctuation() + { + ops = line + .split_ascii_whitespace() + .map(|c| c.parse::()) + .collect::>()?; + break; + } + + let line = line.as_bytes().to_vec(); + if !numbers.is_empty() && numbers[0].len() != line.len() { + bail!( + "all input lines should have the same number of columns: current line has {}, previous lines had {}", + line.len(), + numbers[0].len(), + ); + } + numbers.push(line); + } + + if numbers.is_empty() { + bail!("input had no numbers"); + } + + let mut parsed_numbers = Vec::new(); + let mut cur_problem_numbers = Vec::new(); + for col in 0..numbers[0].len() { + fn col_is_empty(col: usize, numbers: &[Vec]) -> bool { + (0..numbers.len()).all(|line| numbers[line][col].is_ascii_whitespace()) + } + + if col_is_empty(col, &numbers) { + parsed_numbers.push(cur_problem_numbers); + cur_problem_numbers = Vec::new(); + continue; + } + + let mut num = 0; + for line in &numbers { + let chr = line[col]; + if chr.is_ascii_whitespace() { + continue; + } + if !chr.is_ascii_digit() { + bail!("input contained non-digit ascii character: `{}'", chr) + } + let digit = (chr - b'0') as u64; + num *= 10; + num += digit; + } + cur_problem_numbers.push(num); + } + if !cur_problem_numbers.is_empty() { + parsed_numbers.push(cur_problem_numbers); + } + if parsed_numbers.len() != ops.len() { + bail!( + "got a different number of number sets ({}) and operators ({})", + parsed_numbers.len(), + ops.len() + ); + } + + Ok(ops + .into_iter() + .zip(parsed_numbers) + .map(|(op, numbers)| MathProblem { numbers, op }) + .map(|problem| problem.compute()) + .sum()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day06_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 4277556); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 5316572080628); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 3263827); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 11299263623062); + } +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index f290640..d945a75 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -3,3 +3,4 @@ pub mod day02; pub mod day03; pub mod day04; pub mod day05; +pub mod day06; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 74ed9a0..e9dc172 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -7,9 +7,17 @@ use aoc2025::day02; use aoc2025::day03; use aoc2025::day04; use aoc2025::day05; +use aoc2025::day06; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run, day05::run]; + let days: &[DayFunc] = &[ + day01::run, + day02::run, + day03::run, + day04::run, + day05::run, + day06::run, + ]; aoc::run(days) } From b91aad3b146d70afc99947ec91af74d44116f3db Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 10 Dec 2025 13:55:53 +0100 Subject: [PATCH 131/134] 2025: day07 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day07.txt | 142 +++++++++++++++++++++ aoc2025/input/day07_provided.txt | 16 +++ aoc2025/src/day07.rs | 206 +++++++++++++++++++++++++++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 2 + 6 files changed, 369 insertions(+) create mode 100644 aoc2025/input/day07.txt create mode 100644 aoc2025/input/day07_provided.txt create mode 100644 aoc2025/src/day07.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index d44555a..e548cf8 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -6,6 +6,7 @@ use aoc2025::day03; use aoc2025::day04; use aoc2025::day05; use aoc2025::day06; +use aoc2025::day07; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -14,6 +15,7 @@ fn aoc2025_all(c: &mut Criterion) { c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); + c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day07.txt b/aoc2025/input/day07.txt new file mode 100644 index 0000000..95f51c6 --- /dev/null +++ b/aoc2025/input/day07.txt @@ -0,0 +1,142 @@ +......................................................................S...................................................................... +............................................................................................................................................. +......................................................................^...................................................................... +............................................................................................................................................. +.....................................................................^.^..................................................................... +............................................................................................................................................. +....................................................................^...^.................................................................... +............................................................................................................................................. +...................................................................^.^.^.^................................................................... +............................................................................................................................................. +..................................................................^.^.....^.................................................................. +............................................................................................................................................. +.................................................................^.^.^.^...^................................................................. +............................................................................................................................................. +................................................................^.^.^...^...^................................................................ +............................................................................................................................................. +...............................................................^.^.^.^...^.^.^............................................................... +............................................................................................................................................. +..............................................................^.^.^...^.^.^.^.^.............................................................. +............................................................................................................................................. +.............................................................^.^.^...^...^...^.^............................................................. +............................................................................................................................................. +............................................................^...^.^.^.^.^.^.....^............................................................ +............................................................................................................................................. +...........................................................^.......^...^.^.^...^.^........................................................... +............................................................................................................................................. +..........................................................^.^.^.^.......^.^.^.^.^.^.......................................................... +............................................................................................................................................. +.........................................................^.^.^.^.^.^.........^.^.^.^......................................................... +............................................................................................................................................. +........................................................^.^.^.^.^...^.^.^.^.^.^.^.^.^........................................................ +............................................................................................................................................. +.......................................................^.^.^.....^...^.....^.........^....................................................... +............................................................................................................................................. +......................................................^.^.^.^.^...^...^.^...^.^.^...^.^...................................................... +............................................................................................................................................. +.....................................................^...^.^.^.^.^.^...^...^...^.^.^.^.^..................................................... +............................................................................................................................................. +....................................................^.^...^.^...^.^.^.^.^.^.....^.^.^.^.^.................................................... +............................................................................................................................................. +...................................................^.^...^.^...^...^.^.....^.....^...^.^.^................................................... +............................................................................................................................................. +..................................................^.^.....^...^.^...^.^.^.^.^.^.^.^.^...^.^.................................................. +............................................................................................................................................. +.................................................^...^.^...^...^.^.....^.....^.........^.^.^................................................. +............................................................................................................................................. +................................................^.^.^...^.^.^.^.^.......^...^.^.^.^.^.^...^.^................................................ +............................................................................................................................................. +...............................................^.........^.^.^.^.........^...^.^.^...^...^.^.^............................................... +............................................................................................................................................. +..............................................^...^.^.^.^...^.^.^.^...^.^.^...^.....^.....^.^.^.............................................. +............................................................................................................................................. +.............................................^.....^.^.......^.^...^.^.^.^.......^.^.^.^...^...^............................................. +............................................................................................................................................. +............................................^...^...^.^.^.^.^...^.^.^.^...........^.^...^...^.^.^............................................ +............................................................................................................................................. +...........................................^.^.^.^...^...^...^.^.^.....^.^.^.^.....^...^.^.^.^.^.^........................................... +............................................................................................................................................. +..........................................^...^...^.^.^.....^.^...^.^.^.^.^.^.......^.^.^...^.^...^.......................................... +............................................................................................................................................. +.........................................^...^.^...^.^.....^.^.^.^.^.^.^.^...^.^.^.^.^.^.^...^.....^......................................... +............................................................................................................................................. +........................................^.^...^.^.^.^.^.^.^.^.......^...^.^.^.^.......^.^.^.^.^...^.^........................................ +............................................................................................................................................. +.......................................^.^...^.^.^.^.^.^.^.^.^.^...^.^.....^...^...^...^.^.^.^.^.^...^....................................... +............................................................................................................................................. +......................................^.^.^...^.^.^.^.^.^...........^.^.^.^.^.^...^.^.....^.^.^.^.^.^.^...................................... +............................................................................................................................................. +.....................................^.^.^.......^.^.^.......^...^.....^.^.^...^.^.^...^.^.^...^.^.^...^..................................... +............................................................................................................................................. +....................................^.^...^.^.....^.^.^...^.^.^.^.^.....^.......^.^.^...^...........^.^.^.................................... +............................................................................................................................................. +...................................^.^.^...^.^.^.^...^...^.......^.^.^.^.^...^.^.^.^.^.^.^...^.^.....^...^................................... +............................................................................................................................................. +..................................^.^.....^.........^...^.^.^.^.......^.^.^...^.....^.........^.^.........^.................................. +............................................................................................................................................. +.................................^.^.^.^.^.^.^.^.^...^.^...^.^.......^.^.^...^.......^.^.....^...^.^.^.....^................................. +............................................................................................................................................. +................................^.^...^...^.^.^.^...^.^.......^.^.^.^.^.^.^.^...^.^.^.....^.^.....^...^.....^................................ +............................................................................................................................................. +...............................^...^.^.^.^...^.^.^.^.^...^.^...^.^.^.....^.^.^.^.^.^.^...^.......^.^.^...^.^.^............................... +............................................................................................................................................. +..............................^...^.^...^.^.^.^.^.^.^.^.......^.^.^.^.^.^...^.........^.^.....^.^.^.^...^.^...^.............................. +............................................................................................................................................. +.............................^...^.^.^...^.^...^.^.^...^.^...^...^.^.^.^.......^.^...^.^...^...^.^.^...^.^.^.^.^............................. +............................................................................................................................................. +............................^.........^...........^.........^.^.^...^.^.^.^.......^...^.^.^...^.^...^.^.^.^...^.^............................ +............................................................................................................................................. +...........................^.....^.^.^.^.^...^...^.^.....^.^.^...^...^.^.^.^.^...^.^...^...^.^.^.^.^...^.^.^...^.^........................... +............................................................................................................................................. +..........................^.^.^.^.^...^.....^.^.....^.^.^.^.^.^.^.^...^.^.^.^.^.^.^...^.^.^.......^.......^.^.^.^.^.......................... +............................................................................................................................................. +.........................^.^.^.....^.^.^.^.^.^.....^...^.^.^.^.......^.^.^.^.^.^.^.^.^...^.^...^.^.^...^.^...^.^.^.^......................... +............................................................................................................................................. +........................^.^.^.....^.^.^...^.^.^.^.^.^...^.....^.....^.....^.^.^...^...^.^.....^...^.^.^.^.^.^.^...^.^........................ +............................................................................................................................................. +.......................^.^.......^.^...^.^.^.^.^...^...^.^.^.......^.^.......^...^.....^.^...^.^.^...^.^...^.^.^.^.^.^....................... +............................................................................................................................................. +......................^...^.^.^.^.^...^.^.^.....^.^...^.^...^.....^.^.^.^.^.^.^.^.......^.^.....^...^.^.^.^.^.^.^.....^...................... +............................................................................................................................................. +.....................^...^.....^.^.^.^.......^.^.^.......^...........^...^.^...^.^.^.^...^.^...^.^...^.^.^.^.^...^...^.^..................... +............................................................................................................................................. +....................^.^.^...^.^.....^...^...^.^.^.^.^.^.^.^.^.^.^.^...^.^...^.^.^.^.^...^.^.^...^.^...^.^.....^...^.^.^.^.................... +............................................................................................................................................. +...................^.....^...^.^.^.^...^.......^.^...^.^.^.^...^.^...^.^.^...^.^.^...^.^.^...^.....^.^.^.^.^.^.^.^.^.^.^.^................... +............................................................................................................................................. +..................^.^.^.^.^...^.^.^.^...^.^.^.^.^...^.^.^.^...^...^...^.^.......^.^.^.^.....^.^...^.^.^...^...^.^.....^.^.^.................. +............................................................................................................................................. +.................^.^.^.^.^...^.^.......^.^.^...^.^...^...^...^.^.^.^...^.^...^.^.^.^.^.^.^...^.^.^.^.^.^...^...^.^...^...^.^................. +............................................................................................................................................. +................^.^...^...........^.^.^.......^.^...^.^.^.......^...^.^.^...^...^.^...^...^.^.^.^.^.^.^.....^.^.^.^.^...^.^.^................ +............................................................................................................................................. +...............^.^.....^.^...^.^...^...^.^.^.^.^.^.^.^.^...^.^...^...^.^.^.^.^.^.^.^.^.^.^.^.^.^...^.^...^.........^.^.^.^.^.^............... +............................................................................................................................................. +..............^...^...^.^.^.^.^.^...^.^.^...^.^.....^.^.^.......^...^.^...^.^.^...^...^.^.^.^.^...^.^...^.^...........^.....^.^.............. +............................................................................................................................................. +.............^.......^...^...^.^...^.^.^.....^.......^.^.^...^.^.^.^.^.^.^.^.......^...^.^.^.^.^.^.^.....^.^.......^.....^.^.^.^............. +............................................................................................................................................. +............^...^.^.^.^.^.....^.^.^.^.^.^.^.^.^.^.^...^.^.^.^...^.^...^.^.....^.^...^.......^...^...........^.^.^...^.^...^.^.^.^............ +............................................................................................................................................. +...........^.....^.^.^...^.^.^.^.^.....^...^...^...^.^.^.......^.....^.^.^.^.....^.^.^.^.^.^.^.^...^.^.^.^.^.^.^...^.^...^.^...^.^........... +............................................................................................................................................. +..........^.^.^.^.^.^.^...^...^...^.....^.^.........^...^.^.....^...^...^.^.....^.^.^.^.^...^.^.^...^.^.^...^.....^.....^.^...^.^.^.......... +............................................................................................................................................. +.........^.^...^.^...^...^.....^...^.^.........^...^.^.^.....^.^...........^.^...^.^.^...^.^.......^.^.^.^.^...^.^.^.^...^.^.^.....^......... +............................................................................................................................................. +........^.^.^.^.^...^...^.....^...^.^.^.^.........^...^.^.^.....^...^.^...^.^.^.....^.^.^.^.^.....^...^.^...^.^.^.^...^.^...^.^.^.^.^........ +............................................................................................................................................. +.......^...^.^.^...^.......^.....^.^...^.^.^.^.^.^.^.^...^...^.^.^.^.^.^.^.^.^...^.^.^.^.^.^.^.^.^...^.^.^.^.^.^...^.^.^.^.^.....^.^.^....... +............................................................................................................................................. +......^...^.^.^...^...^.^...^.^.....^.^.....^.^.^.^...^.^...^...^.....^.^...^.^.^.^.^.^.^...^.^.^.^.^...^.^.^.^.^.^.^...^.^.^...^.....^...... +............................................................................................................................................. +.....^.....^...^.^.^...^...^.^.^.^.^...^.^.^.^.^...^.^...^.^.^.....^...^.^.^.^.....^...^.........^.....^.^...^.^.^.....^.^.^.^.^.^.....^..... +............................................................................................................................................. +....^.....^.^.^.......^.^.....^.^.^.^.....^.^.^.^...^.^.^.^.^.^.....^.^...^...^.^.^.^.^.^.........^.^.^.^.^...^.^.^...^.^.^...^.^...^.^.^.... +............................................................................................................................................. +...^.........^.^.^...^...^.^.^.^.....^.^...^.^.....^.^.^...^.^.^.....^.^.^...^.^.^.^.^.^.^.^.....^.^.^.^...^.....^.^.^.^.^...^.......^.^.^... +............................................................................................................................................. +..^.^...^.^...^.^.^.^.....^.^.....^...^.^.....^.^.^.^.^...^.....^.^.^...^.^.........^.^.^.........^.........^.^.^.^.^.^...^.^.^.^.^.^...^.^.. +............................................................................................................................................. +.^.....^...^.^.^...^.^.^.^.^.^.^.^.^.^...^.^.^.^.^.^.^.^...^.^...^.^.^.^.^...^.^.....^.^...^.^.^.^.^...^...^...^...^.^.^...^.........^.^.^.^. +............................................................................................................................................. diff --git a/aoc2025/input/day07_provided.txt b/aoc2025/input/day07_provided.txt new file mode 100644 index 0000000..57a2466 --- /dev/null +++ b/aoc2025/input/day07_provided.txt @@ -0,0 +1,16 @@ +.......S....... +............... +.......^....... +............... +......^.^...... +............... +.....^.^.^..... +............... +....^.^...^.... +............... +...^.^...^.^... +............... +..^...^.....^.. +............... +.^.^.^.^.^...^. +............... diff --git a/aoc2025/src/day07.rs b/aoc2025/src/day07.rs new file mode 100644 index 0000000..ad3ac30 --- /dev/null +++ b/aoc2025/src/day07.rs @@ -0,0 +1,206 @@ +use anyhow::{Result, anyhow, bail}; +use std::{ + collections::{HashMap, hash_map::Entry}, + fmt::Write, + str::FromStr, +}; + +const INPUT: &str = include_str!("../input/day07.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + Ok(res) +} + +#[derive(Debug, Copy, Clone)] +enum DiagramCell { + Source, + EmptySpace, + Splitter, +} + +impl FromStr for DiagramCell { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "S" => Ok(DiagramCell::Source), + "." => Ok(DiagramCell::EmptySpace), + "^" => Ok(DiagramCell::Splitter), + _ => Err(anyhow!( + "cannot parse unexpected string `{}' as DiagramCell", + s + )), + } + } +} + +#[derive(Debug, Clone)] +struct ManifoldDiagram { + grid: Vec>, + source_coords: (usize, usize), +} + +impl FromStr for ManifoldDiagram { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut grid = Vec::new(); + let mut source_coords = None; + for (line_idx, line) in s.lines().enumerate() { + let mut grid_line = Vec::new(); + for cell_idx in 0..line.len() { + let cell = line[cell_idx..=cell_idx].parse()?; + if let DiagramCell::Source = cell { + match source_coords { + None => source_coords = Some((cell_idx, line_idx)), + Some(_) => bail!("found two different sources in diagram"), + } + } + grid_line.push(cell); + } + grid.push(grid_line); + } + + source_coords + .ok_or(anyhow!("couldn't find source in diagram")) + .map(|source_coords| Self { + grid, + source_coords, + }) + } +} + +impl ManifoldDiagram { + fn count_ray_splits(&self) -> usize { + let mut ray_sources = vec![self.source_coords]; + // TODO: we use a HashMap<(usize, usize), ()> because a HashSet doesn't have `entry` methods in stable: + // https://github.com/rust-lang/rust/issues/60896 + let mut used_splitters = HashMap::new(); + + let mut count = 0; + while let Some(ray_source) = ray_sources.pop() { + let (x, mut y) = ray_source; + y += 1; + while y < self.grid.len() + && let DiagramCell::EmptySpace = self.grid[y][x] + { + y += 1; + } + + if y == self.grid.len() { + // We've reached the end of the diagram, we can stop computing this ray + continue; + } + // otherwise, we've hit a splitter (unless there are multiple sources, which shouldn't happen) + if let DiagramCell::Splitter = self.grid[y][x] { + // make sure we don't exit the grid when splitting, shouldn't happen + assert!(x > 0 && x < (self.grid[0].len() - 1)); + + if let Entry::Vacant(e) = used_splitters.entry((x, y)) { + e.insert(()); + } else { + continue; + } + ray_sources.push((x - 1, y)); + ray_sources.push((x + 1, y)); + count += 1; + } + } + + count + } + + // This is an iterative implementation of the obvious recursive algorithm for Part 2. It's + // probably unnecessarily complex written this way, it ended up that way because I reused the + // Part 1 code and felt it was faster to adapt it rather than rewrite the recursive version :) + fn count_timelines(&self) -> usize { + let mut ray_sources = vec![self.source_coords]; + let mut timelines_from: HashMap<(usize, usize), usize> = HashMap::new(); + + while let Some(ray_source) = ray_sources.pop() { + let (x, mut y) = ray_source; + y += 1; + while y < self.grid.len() + && let DiagramCell::EmptySpace = self.grid[y][x] + { + y += 1; + } + + if y == self.grid.len() { + // We've reached the end of the diagram, this ray is a single timeline + timelines_from.insert(ray_source, 1); + continue; + } + + // Otherwise, we've hit a splitter (unless there are multiple sources, which shouldn't happen) + if let DiagramCell::Splitter = self.grid[y][x] { + // Make sure we don't exit the grid when splitting, shouldn't happen + assert!(x > 0 && x < (self.grid[0].len() - 1)); + let (ray_left, ray_right) = ((x - 1, y), (x + 1, y)); + + let left = timelines_from.get(&ray_left); + let right = timelines_from.get(&ray_right); + match (left, right) { + (Some(res_left), Some(res_right)) => { + timelines_from.insert(ray_source, res_left + res_right); + } + (None, Some(_)) => { + ray_sources.push(ray_source); + ray_sources.push(ray_left); + } + (Some(_), None) => { + ray_sources.push(ray_source); + ray_sources.push(ray_right); + } + (None, None) => { + ray_sources.push(ray_source); + ray_sources.push(ray_left); + ray_sources.push(ray_right); + } + } + } + } + + *timelines_from.get(&self.source_coords).unwrap() + } +} + +fn part1(input: &str) -> Result { + let diagram = input.parse::()?; + Ok(diagram.count_ray_splits()) +} + +fn part2(input: &str) -> Result { + let diagram = input.parse::()?; + Ok(diagram.count_timelines()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day07_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 21); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 1537); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 40); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 18818811755665); + } +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index d945a75..58e7837 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -4,3 +4,4 @@ pub mod day03; pub mod day04; pub mod day05; pub mod day06; +pub mod day07; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index e9dc172..def4397 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -8,6 +8,7 @@ use aoc2025::day03; use aoc2025::day04; use aoc2025::day05; use aoc2025::day06; +use aoc2025::day07; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -17,6 +18,7 @@ fn main() -> Result<()> { day04::run, day05::run, day06::run, + day07::run, ]; aoc::run(days) From 63ffe8794b633026dea46da28f3edf747c16f6db Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 10 Dec 2025 18:17:03 +0100 Subject: [PATCH 132/134] 2025: day08: part 1 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day08.txt | 1000 ++++++++++++++++++++++++++++++ aoc2025/input/day08_provided.txt | 20 + aoc2025/src/day08.rs | 188 ++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 2 + 6 files changed, 1213 insertions(+) create mode 100644 aoc2025/input/day08.txt create mode 100644 aoc2025/input/day08_provided.txt create mode 100644 aoc2025/src/day08.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index e548cf8..094eb7f 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -7,6 +7,7 @@ use aoc2025::day04; use aoc2025::day05; use aoc2025::day06; use aoc2025::day07; +use aoc2025::day08; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -16,6 +17,7 @@ fn aoc2025_all(c: &mut Criterion) { c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); + c.bench_function("day08", |b| b.iter(|| day08::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day08.txt b/aoc2025/input/day08.txt new file mode 100644 index 0000000..9df6b93 --- /dev/null +++ b/aoc2025/input/day08.txt @@ -0,0 +1,1000 @@ +96616,810,75978 +47,21512,72240 +37204,32405,96978 +29869,39703,17245 +85469,86947,73441 +30718,17071,51096 +41362,30138,67009 +598,13948,14379 +76389,15190,48555 +49893,73440,15307 +29849,31150,65844 +43789,38501,72225 +1289,51970,81957 +94777,88446,92003 +67115,73782,47139 +34918,73782,76791 +10226,21601,9106 +25255,34515,55484 +15907,71527,29965 +81513,47000,15653 +80059,88130,47907 +38982,78390,65861 +52404,53380,32169 +57890,49601,15440 +124,21347,33712 +34031,15726,61115 +74713,70099,55008 +5651,21087,42325 +7646,22850,56910 +77521,99356,56389 +21748,86110,49763 +33638,70698,70272 +72192,16208,6392 +44081,77872,46151 +77812,33943,16761 +73761,81089,45679 +8774,27775,53496 +7575,13375,22609 +58036,91575,80779 +59110,66473,56545 +86077,10459,63254 +66197,87350,40327 +81411,92072,72676 +49748,9698,89965 +78439,17433,63349 +21784,15350,87174 +20127,8208,29553 +68687,89811,29134 +37359,84624,5746 +16185,94710,97793 +18231,95999,20306 +46807,93766,75186 +66175,64946,13827 +2379,85923,41962 +49923,83393,61215 +49402,16213,59895 +16578,1185,60394 +26992,44142,77991 +11815,61668,19454 +49157,21692,51961 +70475,72818,83517 +60133,50809,14515 +36769,65052,9338 +68358,29041,16515 +68765,91605,30936 +93634,60030,23295 +75141,909,75737 +77063,82141,8421 +29230,5618,66027 +60311,44944,84379 +6727,40525,76384 +60892,71273,13434 +99336,47605,54010 +4854,66583,83047 +41024,75773,25856 +61313,40857,75555 +92580,94652,34432 +66175,63087,68137 +862,46037,40611 +9364,61053,96965 +96197,97478,31849 +46012,78260,93076 +4284,3783,29454 +79377,111,81121 +36895,62273,40991 +28332,83678,6091 +124,6836,46015 +58191,32091,27558 +83664,90573,74440 +47684,52380,13614 +35120,46095,58900 +75844,70060,25294 +22872,85463,81740 +55383,79835,82127 +44744,64274,86800 +60852,70621,32428 +91516,39702,39626 +3688,20727,56814 +49311,23987,86560 +44548,2875,53676 +16841,24697,97455 +17788,80255,91151 +83290,1708,4577 +39021,78132,21442 +12009,82267,12399 +91035,14375,97595 +94085,31799,99374 +88944,58929,65104 +82345,84761,71280 +62780,13633,35806 +70571,95978,95108 +52888,93487,88078 +29130,16331,14409 +92304,65168,58557 +28472,46629,22552 +832,89716,12881 +8947,49372,18917 +53393,62848,85813 +14570,95609,71932 +34906,59313,55734 +37689,47610,81231 +48410,8422,91050 +43870,76541,8153 +5427,34304,38621 +76919,40838,49838 +89295,69748,69369 +50411,60493,56509 +26826,15701,77344 +24956,47561,88427 +56537,24378,40188 +84314,39970,40106 +13090,35301,17852 +60153,99913,7345 +21147,67767,86352 +94054,90953,58835 +81837,49253,53459 +64686,71238,47767 +74230,40836,81723 +86599,29209,24915 +94641,86178,95813 +45007,59187,71572 +33557,77915,37965 +10,26480,78523 +49998,17424,383 +72243,16533,32163 +96153,76105,53137 +67890,80555,76817 +58274,24705,50617 +90297,95948,32697 +44469,83877,56552 +15831,6265,94385 +55836,6873,75895 +90337,23678,21982 +35012,30025,70177 +42902,52640,67628 +51436,86883,38944 +72763,97457,11606 +50955,3969,92867 +91443,54845,20378 +2133,70178,55310 +17613,15558,96325 +62436,31322,23281 +53947,2865,94764 +40898,32429,56964 +53537,52879,22200 +42871,1669,76000 +63615,86744,87542 +93336,17798,45244 +56804,65416,20724 +49294,21904,85931 +45336,49650,26151 +38314,46233,85923 +64085,1875,33253 +6740,22204,3436 +94916,13931,65156 +65933,21535,26507 +45670,48945,7381 +88012,2945,38942 +8597,15275,7742 +37182,10617,88064 +44966,19938,98403 +52444,10373,45375 +2510,89230,59817 +41311,12069,30872 +42173,92528,45714 +81874,83719,21053 +66914,60637,68318 +9977,30378,74103 +77500,5036,80383 +14977,54324,58522 +64913,27528,28552 +79234,26215,79253 +65555,68595,19347 +48129,62152,56907 +55931,49134,27039 +81533,76718,78435 +27041,48960,99966 +12471,11450,99887 +44614,14647,11244 +7064,79634,40939 +47042,12530,41088 +2893,25877,88592 +93696,12076,1871 +46418,97089,52542 +67033,30021,91392 +80133,5826,11001 +10958,41254,28841 +31153,7589,15039 +17780,43539,49617 +76429,94380,46400 +15092,32751,31607 +34046,15838,20784 +75419,51308,44185 +47445,41839,7061 +91239,85946,6742 +2606,30107,86190 +57460,64139,20675 +47311,26384,38310 +75437,20187,60579 +45740,25222,35810 +89165,70723,56270 +83116,55684,54082 +18207,17844,67662 +9674,58573,66797 +44733,89585,51527 +83277,92121,15913 +4249,7080,93485 +92675,37985,23278 +68824,25339,15228 +98817,25303,50014 +79441,94633,94983 +3538,68284,7729 +90071,19613,80286 +35338,57531,87102 +13284,79098,7934 +52860,41073,17367 +63008,43331,63254 +78540,80209,43105 +8114,96893,96242 +33065,15885,38404 +93180,10260,1406 +49667,46625,92829 +33003,24911,14339 +38778,55485,59791 +72543,61880,87071 +85741,95244,22418 +85620,63879,96866 +67367,81893,85550 +50325,33325,35215 +39346,39396,46554 +68496,87768,76749 +25295,69389,65559 +95779,28875,6542 +95024,16913,1461 +54393,79624,66654 +22568,66655,17707 +42154,25195,2845 +94777,25624,50767 +29674,369,53974 +29667,70763,48673 +90169,60090,15118 +99124,57348,86302 +63913,1301,25716 +81174,63073,69642 +59620,25265,48206 +7818,69808,55040 +1176,94990,88053 +62167,61746,50297 +10710,51779,51561 +55335,99261,74317 +94526,24185,92724 +98776,71390,17390 +74558,87154,35918 +40211,49179,4540 +74967,488,56683 +76881,89746,20583 +83194,11163,55480 +58293,85409,68879 +22119,39436,26300 +33552,10044,448 +32230,13128,38117 +81887,5361,46790 +72993,66761,17603 +47638,80029,73438 +39481,64315,79268 +58135,18165,18841 +2042,62057,70204 +9114,12242,22985 +35882,13857,4096 +18964,762,17683 +38511,95699,6284 +73814,1119,60942 +83070,32272,95920 +84551,68696,99564 +62889,86971,44801 +30741,80485,10486 +7872,31662,84503 +65006,93089,15350 +72897,5321,3410 +84915,37773,941 +66303,31900,55969 +88175,91065,44552 +9797,71120,30801 +18859,592,52302 +48347,85770,56567 +2175,35684,92455 +39724,11001,65710 +61391,86663,37548 +45330,58198,7425 +70936,54231,13355 +42914,38762,66826 +1884,93081,23928 +70788,2959,68377 +31287,77424,53853 +49782,74150,12616 +22011,27058,19827 +35744,39142,141 +46698,44490,42526 +99503,65888,29700 +23109,2935,55599 +73873,86052,88730 +41705,73980,37236 +79535,44606,82017 +45461,52915,48898 +20403,23037,50390 +52469,52324,71746 +27849,17692,85574 +63316,98722,95925 +11186,46337,14356 +83076,32036,79529 +61105,8234,11086 +95435,83738,68003 +61421,61582,42741 +18857,40910,67067 +97733,90507,91159 +62126,69029,10771 +51588,89853,31246 +14402,45890,62651 +4576,99380,53771 +40711,89434,94430 +6203,98731,77355 +45700,46430,87272 +36822,67855,58488 +9902,41517,24442 +93293,91156,74863 +71444,13876,4077 +42980,68701,9986 +97660,73023,2494 +19956,5786,58572 +43631,25027,61813 +47487,71311,92859 +1627,86846,1636 +76397,34793,31510 +69137,69406,53854 +51824,63534,67604 +48669,7752,35759 +35347,91796,83425 +66421,72114,65991 +41769,65462,64707 +52154,83731,18679 +93093,80021,2843 +59961,87369,41338 +61774,67916,56576 +61238,83388,22624 +87301,35647,21220 +18563,40513,46270 +31431,89556,22191 +18400,15064,32441 +19586,56478,91982 +10018,46780,77058 +39406,7841,36230 +15191,12600,21150 +16792,47932,24378 +60440,92024,4940 +6052,10147,48120 +1230,94468,22896 +90393,69014,78693 +20778,6823,5014 +12785,38994,51536 +15309,27025,40538 +9455,93063,94175 +52963,63538,24640 +76876,99767,20424 +88675,70704,84876 +29837,572,89758 +24665,43287,4124 +19596,39044,22506 +23320,89139,12457 +16298,43802,18588 +13863,53279,86359 +65756,38823,39017 +87980,76503,68792 +29808,1133,5547 +65225,76422,23690 +97926,56995,73309 +52631,46378,86930 +9699,19378,79988 +50576,35602,76568 +10475,51282,28809 +10841,6595,69501 +68477,7514,78298 +80172,90885,77294 +794,74931,66380 +16579,66603,50677 +677,38561,19559 +3076,24613,17121 +48482,23484,4486 +96978,26894,96599 +29550,67389,6448 +59980,27451,80958 +60956,37227,24831 +40202,40948,35792 +25500,21049,18829 +95357,78024,61424 +66165,41073,67961 +3900,18562,90386 +5993,41426,12575 +55978,14534,4710 +62310,98833,3965 +36662,21431,3535 +1247,94520,16658 +56495,63277,82136 +60227,11533,3984 +55190,46612,75533 +55832,29751,10128 +60037,5341,11856 +88331,37751,9479 +12410,76462,51822 +50775,10467,22268 +31249,97861,29215 +51633,19235,43441 +26172,13202,69249 +20710,13243,16076 +72953,93560,87352 +16585,67087,56128 +78,97449,5581 +7850,39585,11593 +56185,25107,62693 +20769,86165,77245 +54030,10493,82291 +20323,16227,72965 +20539,97065,5529 +11191,69352,16214 +24808,74182,6714 +32750,7109,5245 +30078,95393,61862 +95086,84632,26437 +89669,27166,69617 +97663,85156,84583 +65200,24901,58281 +32476,59684,22183 +88333,75537,24786 +97754,39828,21801 +57090,90810,81819 +17456,68293,6317 +60663,86154,2830 +11207,37715,44558 +96412,78170,57495 +34637,65683,61943 +5630,25259,60799 +40213,29880,79917 +87800,58721,69438 +54801,54714,63846 +88524,99139,48762 +50727,68520,46641 +66039,79990,40004 +58332,89351,39201 +51305,50160,14617 +28711,75570,86916 +26603,6518,63794 +72342,6476,18513 +99389,15571,47630 +93384,1223,9329 +63826,83729,39849 +45497,91340,64174 +67149,76,31547 +44954,36510,44 +14335,56031,90974 +98817,18441,97055 +84815,20683,90130 +16029,52282,25647 +4673,72115,50859 +8478,9303,92507 +48363,95236,35571 +50476,39311,79493 +32214,61642,19903 +42575,26360,22095 +9005,97980,95725 +38370,19056,61572 +22433,32537,82787 +74722,90590,41988 +63986,47474,95387 +83201,90859,69588 +7211,61064,74448 +87248,6356,93720 +20158,17109,94009 +89712,24089,73478 +35006,76016,16268 +1824,84875,87901 +76893,26724,55166 +14099,98873,46158 +29978,52099,97563 +98961,36113,91465 +6965,37774,7694 +69426,38603,96398 +62390,58816,85791 +15607,4487,68388 +10489,3819,94356 +88826,63999,54207 +24275,72347,35567 +14595,36746,21829 +46424,34568,29156 +8091,71151,70584 +43115,66533,65697 +66238,19311,21142 +62809,94372,60354 +83256,94129,30351 +31516,1932,54914 +52641,9316,43683 +16236,46067,72858 +32497,42313,23951 +5145,30764,1848 +23996,9112,22069 +94277,56791,44035 +15141,99918,59303 +95687,11722,19938 +94496,21896,20355 +93225,72983,12458 +4839,68108,21219 +47380,48890,5259 +12663,60051,41363 +76954,60657,52851 +52305,41381,47981 +24778,91820,73082 +35675,9601,80940 +28456,92478,39358 +51958,60200,63049 +51650,52676,11650 +48081,33850,64276 +87064,1720,63296 +40433,12725,18266 +94348,43418,45799 +20470,21702,94090 +12004,23132,27411 +89986,31923,8502 +85648,47680,41230 +51972,45075,30931 +97869,98693,51228 +68981,64466,42538 +79201,4048,35804 +59814,65659,33387 +67253,20434,5822 +99162,32642,40954 +88951,94213,70431 +66956,10283,79203 +50472,19167,19814 +77595,34367,9152 +52200,30637,98911 +9572,56961,51688 +21728,42000,95581 +34644,82476,46113 +49920,7112,42564 +99372,53953,7932 +25640,30738,4419 +38390,14097,87763 +62913,35208,1032 +78886,46674,34610 +29481,84778,33270 +4136,12091,60037 +18100,71599,44697 +83013,56763,57956 +10506,43444,67437 +47624,60852,29131 +33347,1017,60890 +11269,30794,19962 +298,67872,64086 +28053,403,93977 +41764,80623,49348 +51190,6989,99367 +79404,16174,93582 +56124,67785,13804 +24384,50933,10733 +14984,83175,28379 +45916,48239,59985 +10967,99826,7620 +2997,51633,23639 +34753,71335,92675 +75660,39969,10715 +83824,72792,94541 +9061,46619,93357 +43832,99088,59806 +84001,38257,78243 +85568,33320,66853 +8783,8617,92299 +76061,39130,39721 +78880,16258,75417 +57278,21997,40354 +4559,60796,14693 +75173,78782,69586 +30588,47763,69657 +69813,51508,8619 +66973,39919,83925 +93116,65750,35214 +49428,75151,61072 +99304,453,24846 +64857,75563,81408 +99758,7054,93834 +60990,98648,73787 +4153,51510,43699 +30768,63940,92372 +44204,47525,71638 +58279,27840,69103 +87149,98184,8365 +20501,17223,72651 +27456,95880,46643 +27906,57479,1243 +8916,81885,58480 +34538,53272,46977 +31376,1084,39050 +36311,17922,51330 +79624,94586,41997 +70740,42495,24029 +24404,52571,61354 +93458,825,3 +21917,90222,28768 +67330,83159,6462 +40946,95176,96946 +12360,29184,83047 +94636,18556,71984 +86584,42247,40325 +30412,15684,94710 +59413,69110,34094 +43275,11397,32663 +38312,82394,71991 +50954,92538,77890 +53986,21917,62472 +96368,75398,45486 +70828,27018,1180 +60612,65119,56177 +28171,45411,45312 +80693,73816,54751 +39115,3128,11970 +78907,6226,32605 +26051,24623,12847 +43169,3632,81127 +72407,61325,65026 +80694,39461,55748 +28953,33984,16018 +17340,97547,32755 +298,28373,37454 +68428,19166,26358 +81883,45188,87649 +74802,44106,71842 +77704,1463,75014 +87334,7436,48879 +95479,14681,67734 +72300,12948,90266 +29920,88606,86139 +86951,52647,24937 +22086,36572,63814 +87668,86806,70369 +1200,97676,40547 +83998,79586,44813 +97007,10381,20433 +57917,74956,51309 +48901,72861,1907 +93789,81139,93024 +30414,75217,98870 +58580,95454,82328 +28177,84260,29178 +80996,2150,52258 +30211,259,23066 +96922,77069,96152 +36905,31544,67887 +24998,62122,12193 +45677,76513,54279 +27945,34130,83745 +49823,46546,13147 +7112,85252,26375 +26021,16210,84105 +53145,46690,86495 +3610,48225,81447 +23818,28027,76288 +15867,2347,37266 +6657,95764,89140 +484,34773,97330 +58783,86276,79156 +63051,15779,17616 +42935,68871,21255 +62612,76887,26788 +8593,56089,39178 +93484,3650,14149 +2940,47948,86899 +89602,80937,62602 +34040,33292,82330 +37219,99156,70790 +82351,1733,439 +79284,15436,52520 +86629,92093,16274 +41450,95994,62484 +53514,32949,25695 +61243,75842,22016 +54266,48744,20085 +25976,63680,69662 +92436,30860,89517 +42543,5132,65960 +51498,15404,36682 +68737,34406,98600 +40474,78936,67870 +66152,87039,2599 +98037,93472,24095 +21175,24538,12389 +36564,91001,51018 +60963,98829,7138 +39623,65980,22582 +61402,80958,58207 +6536,46233,67184 +5251,6313,77704 +51855,82850,32709 +87166,75005,54035 +99871,61178,43781 +6037,28496,63688 +69792,9256,36639 +18169,45582,20739 +47133,46218,79206 +99231,7619,83999 +22531,30483,60079 +30053,13538,63244 +41213,14032,83358 +19612,24452,32798 +46331,91809,86738 +40064,26655,52982 +57841,31154,72898 +56635,73059,63085 +55312,50346,39193 +40347,28418,89452 +52846,71841,9491 +68673,95159,28260 +73176,39675,10294 +60776,83560,4247 +50158,60720,81557 +52300,5490,70598 +60491,95648,15378 +94407,3440,59489 +52223,90064,18409 +68582,67041,69493 +2010,71946,77616 +38521,38306,13975 +17469,5414,10282 +89535,91811,95346 +69364,31928,13834 +70031,90204,24476 +3797,54613,88896 +5812,8985,75003 +22793,45011,55540 +61147,27621,93151 +36269,48287,5527 +2649,10723,27605 +17791,32979,86074 +48507,84122,1818 +26671,41278,61634 +72879,25592,15274 +99759,7284,58489 +44039,10648,13272 +25317,94599,90036 +61642,92926,9170 +92451,51251,55900 +39169,42097,2939 +86180,44776,21256 +81870,97141,59508 +59849,30747,84612 +25083,80413,80812 +57339,93998,73598 +67947,40278,88085 +71103,49165,35603 +73164,90129,5035 +94186,40896,79885 +48358,72402,76865 +53985,93911,89396 +82555,29679,91328 +24284,21738,66560 +78977,93294,88178 +43656,84564,67611 +70657,88671,14706 +53874,98002,69623 +34961,83067,26014 +34355,20976,88292 +20243,83630,45228 +97840,54203,48912 +70094,3728,87602 +15885,22135,65573 +90065,52616,82741 +80262,3897,19480 +12949,45545,86824 +22964,34014,3490 +79424,33014,67174 +2004,9673,83023 +35263,20547,81573 +71872,93083,82170 +19235,61149,62626 +41483,47173,54942 +88241,48949,77808 +49569,81928,2796 +23992,7742,2713 +42194,33740,82279 +4985,47773,18486 +66575,40452,60523 +57640,23071,63549 +77021,79670,33706 +97362,41882,71030 +58685,64389,69989 +33625,30256,65375 +94237,40730,83689 +20251,40207,11770 +55200,59388,1538 +95924,18294,1616 +10295,82720,18580 +72200,30002,30603 +59517,42844,17238 +9554,4993,90531 +63439,49409,94765 +15016,44792,35985 +26963,78156,51701 +85011,95060,76739 +46454,50866,89711 +96060,82846,91659 +83037,59319,94577 +8290,65634,79205 +43973,80688,10500 +6481,98859,30186 +7909,53917,69252 +81053,79295,78868 +496,85261,91125 +55593,87845,28416 +57944,1184,65874 +537,30202,23691 +89984,99697,91522 +95379,86410,29013 +52840,70782,10030 +45392,89876,41492 +65937,12179,84915 +44975,21436,11367 +91749,40933,81747 +4394,33870,72074 +30503,54402,41910 +90388,29049,99214 +73084,9468,2846 +43703,86295,80347 +66369,25581,37351 +68141,46918,95767 +80843,29490,95476 +55487,50085,90603 +6519,62962,64539 +11129,5495,18000 +79627,21265,69007 +47555,41141,56667 +35418,33436,32838 +92217,41311,18613 +87607,78095,7303 +12374,17570,64957 +59264,30016,93434 +82306,73860,63935 +19314,1277,72635 +98737,45817,73515 +599,82828,95784 +28168,33778,27577 +36334,23307,87450 +67557,75339,63636 +91325,21865,36016 +97705,59880,7858 +30360,12961,92047 +62707,80663,85148 +28282,23753,39358 +20484,28395,71223 +10840,9341,48297 +90035,3390,96894 +56994,93652,85405 +42510,99407,93703 +39446,36668,65599 +76602,58135,93364 +44819,19878,85464 +35839,26022,40879 +45179,57834,13928 +52043,98603,39397 +50845,68890,91754 +4333,30718,24748 +85718,44038,82496 +36811,84974,81632 +86975,15165,50972 +82208,84572,34824 +98514,15014,73770 +91731,46928,81094 +69747,92990,78259 +68183,42665,77481 +19611,75932,19865 +91689,10370,21722 +49668,40708,74950 +94405,93768,35688 +1023,458,13922 +53258,1329,35183 +89336,19276,61280 +99141,48439,642 +99347,35502,7385 +34396,61785,21270 +67865,33068,456 +77457,61399,46096 +74406,42306,31269 +36090,99467,76063 +7026,41996,80380 +85809,60651,59086 +64441,913,93940 +17508,79886,22233 +19798,163,74563 +65879,87452,9465 +87573,10666,29235 +19440,71454,64779 +80368,81746,42378 +37497,82571,6031 +17805,40743,51561 +99430,54794,72102 +71081,12906,49982 +29729,30666,30274 +57623,28424,80051 +58177,19137,2554 +96505,7588,34090 +71558,6884,85993 +73899,36484,70026 +94708,2893,89823 +97027,81418,7995 +61130,83329,25406 +18626,51289,69051 +1429,29676,69214 +88701,99619,69548 +13765,16487,43486 +12314,21972,37452 +35899,89588,30736 +72539,74685,45191 +58884,92790,49418 +63125,17196,26531 +60646,30082,6629 +42734,66619,99223 +45935,91192,51495 +63356,98654,60871 +88030,11109,17034 +95560,3923,57626 +89105,12290,13002 +92937,14797,41207 +53584,91001,6559 +274,18596,41925 +42345,94771,1754 +54611,9066,71752 +91105,96036,42456 +39235,30011,31715 +20747,12314,73330 +15122,61490,7637 +733,11696,42854 +35153,12422,94022 +70000,44092,48455 +81860,14081,58066 +9514,35503,3768 +72622,53367,19479 +68031,4916,31380 +767,42546,48127 +38350,69122,98407 +88119,35828,60076 +28315,60103,29161 +19170,68838,38067 +15589,56043,16922 +34957,94254,17877 +70527,77168,35752 +74229,34735,33462 +90067,82557,76853 +24472,47475,5789 +33669,84848,31096 +99008,47931,80792 +35028,37251,66246 +91743,14312,48414 +50456,18764,20102 +92576,36976,88684 +69341,84968,60432 +45576,58907,58240 +39931,5153,21603 +59648,98603,47109 +69689,59695,53475 +21397,51003,35263 +16441,91456,25256 +77545,95209,57368 +52314,53248,71775 +29646,20210,27412 +75484,27781,55025 +93626,7439,81898 +75820,78773,26176 +29572,40252,16137 +73749,38852,76768 +54913,22959,2008 +38918,43540,38659 +63895,14206,21558 +39549,83596,5315 +90015,38967,79682 +98057,39297,15666 diff --git a/aoc2025/input/day08_provided.txt b/aoc2025/input/day08_provided.txt new file mode 100644 index 0000000..e98a3b6 --- /dev/null +++ b/aoc2025/input/day08_provided.txt @@ -0,0 +1,20 @@ +162,817,812 +57,618,57 +906,360,560 +592,479,940 +352,342,300 +466,668,158 +542,29,236 +431,825,988 +739,650,466 +52,470,668 +216,146,977 +819,987,18 +117,168,530 +805,96,715 +346,949,466 +970,615,88 +941,993,340 +862,61,35 +984,92,344 +425,690,689 diff --git a/aoc2025/src/day08.rs b/aoc2025/src/day08.rs new file mode 100644 index 0000000..a8349a3 --- /dev/null +++ b/aoc2025/src/day08.rs @@ -0,0 +1,188 @@ +use anyhow::{Context, Result, bail}; +use std::{collections::HashMap, fmt::Write, hash::Hash, str::FromStr}; + +const INPUT: &str = include_str!("../input/day08.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT, 1000)?)?; + Ok(res) +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +struct JunctionBox { + x: usize, + y: usize, + z: usize, +} + +impl FromStr for JunctionBox { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (x, rest) = s + .split_once(',') + .context("couldn't split JunctionBox coordinates on comma")?; + let (y, z) = rest + .split_once(',') + .context("couldn't split JunctionBox coordinates on second comma")?; + + let x = x.parse()?; + let y = y.parse()?; + let z = z.parse()?; + + Ok(Self { x, y, z }) + } +} + +impl JunctionBox { + fn distance_to(&self, other: &JunctionBox) -> f64 { + ((self.x as f64 - other.x as f64).powi(2) + + (self.y as f64 - other.y as f64).powi(2) + + (self.z as f64 - other.z as f64).powi(2)) + .sqrt() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct UnionFindKey(usize); + +/// UnionFind implementation that maintains a circular linked list in addition to the usual tree for +/// each disjoint subset, allowing easy iteration on a subset's members. +struct UnionFind { + members_to_keys: HashMap, + parent: Vec, + #[allow(unused)] + next: Vec, + size: Vec, +} + +impl UnionFind { + fn from(members: Vec) -> Self { + let keys: Vec = (0..members.len()).map(UnionFindKey).collect(); + Self { + parent: keys.clone(), + next: keys.clone(), + size: (0..members.len()).map(|_| 1).collect(), + members_to_keys: members.into_iter().zip(keys).collect(), + } + } + + fn get_key(&self, member: &T) -> Result { + self.members_to_keys + .get(member) + .context("unknown member") + .copied() + } + + fn union(&mut self, left: &T, right: &T) -> Result { + let left = self.get_key(left)?; + let right = self.get_key(right)?; + Ok(self.union_by_key(left, right)) + } + + fn union_by_key(&mut self, left: UnionFindKey, right: UnionFindKey) -> UnionFindKey { + let mut left_root = self.find_by_key(left); + let mut right_root = self.find_by_key(right); + + if left_root == right_root { + return left_root; + } + + if self.size[left_root.0] < self.size[right_root.0] { + (left_root, right_root) = (right_root, left_root) + } + + self.parent[right_root.0] = left_root; + let new_size = self.size[left_root.0] + self.size[right_root.0]; + self.size[left_root.0] = new_size; + + left_root + } + + #[allow(unused)] + fn find(&mut self, member: &T) -> Result { + let key = self.get_key(member)?; + Ok(self.find_by_key(key)) + } + + // This could be implemented with &self using interior mutability... + fn find_by_key(&mut self, key: UnionFindKey) -> UnionFindKey { + if key != self.parent[key.0] { + self.parent[key.0] = self.find_by_key(self.parent[key.0]); + } + + self.parent[key.0] + } + + fn roots(&self) -> impl Iterator { + self.parent + .iter() + .enumerate() + .filter_map(|(idx, &key)| if idx == key.0 { Some(key) } else { None }) + } + + fn get_size(&mut self, key: UnionFindKey) -> usize { + let root = self.find_by_key(key); + self.size[root.0] + } +} + +fn part1(input: &str, connections: usize) -> Result { + let points = input + .lines() + .map(JunctionBox::from_str) + .collect::>>()?; + + let mut distances = Vec::new(); + for (i, &pi) in points.iter().enumerate() { + for &pj in points.iter().skip(i + 1) { + distances.push((pi.distance_to(&pj), (pi, pj))); + } + } + distances.sort_by(|(dist1, _), (dist2, _)| dist1.total_cmp(dist2)); + if connections > distances.len() { + bail!( + "There are less possible matchings than the required number of connections: {} matchings", + distances.len() + ); + } + + let mut uf = UnionFind::from(points); + for (_, (p1, p2)) in distances.into_iter().take(connections) { + uf.union(&p1, &p2)?; + } + + let roots = uf.roots().collect::>(); + let mut sizes = roots.iter().map(|r| uf.get_size(*r)).collect::>(); + sizes.sort_by_key(|v| std::cmp::Reverse(*v)); + + Ok(sizes[0] * sizes[1] * sizes[2]) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day08_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED, 10).unwrap(), 40); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT, 1000).unwrap(), 127551); + } + + //#[test] + //fn part2_provided() { + // assert_eq!(part2(PROVIDED).unwrap(), 40); + //} + + //#[test] + //fn part2_real() { + // assert_eq!(part2(INPUT).unwrap(), 18818811755665); + //} +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index 58e7837..9ac735a 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -5,3 +5,4 @@ pub mod day04; pub mod day05; pub mod day06; pub mod day07; +pub mod day08; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index def4397..5997649 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -9,6 +9,7 @@ use aoc2025::day04; use aoc2025::day05; use aoc2025::day06; use aoc2025::day07; +use aoc2025::day08; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -19,6 +20,7 @@ fn main() -> Result<()> { day05::run, day06::run, day07::run, + day08::run, ]; aoc::run(days) From 22350a3c689461e9e618f6f46522ff3a346247ce Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 10 Dec 2025 18:38:46 +0100 Subject: [PATCH 133/134] 2025: day08: part 2 --- aoc2025/src/day08.rs | 58 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/aoc2025/src/day08.rs b/aoc2025/src/day08.rs index a8349a3..a6aaa89 100644 --- a/aoc2025/src/day08.rs +++ b/aoc2025/src/day08.rs @@ -6,6 +6,7 @@ const INPUT: &str = include_str!("../input/day08.txt"); pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT, 1000)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -68,6 +69,10 @@ impl UnionFind { } } + fn size(&self) -> usize { + self.parent.len() + } + fn get_key(&self, member: &T) -> Result { self.members_to_keys .get(member) @@ -160,6 +165,43 @@ fn part1(input: &str, connections: usize) -> Result { Ok(sizes[0] * sizes[1] * sizes[2]) } +fn part2(input: &str) -> Result { + let points = input + .lines() + .map(JunctionBox::from_str) + .collect::>>()?; + + let mut distances = Vec::new(); + for (i, &pi) in points.iter().enumerate() { + for &pj in points.iter().skip(i + 1) { + distances.push((pi.distance_to(&pj), (pi, pj))); + } + } + distances.sort_by(|(dist1, _), (dist2, _)| dist1.total_cmp(dist2)); + + let mut uf = UnionFind::from(points); + let mut unions = 0; + let mut last_pair = None; + for (_, (p1, p2)) in distances { + if unions >= (uf.size() - 1) { + break; + } + last_pair = Some((p1, p2)); + + if uf.find(&p1)? == uf.find(&p2)? { + continue; + } + + uf.union(&p1, &p2)?; + unions += 1; + } + + Ok(match last_pair { + Some((p1, p2)) => p1.x * p2.x, + None => bail!("points was empty?"), + }) +} + #[cfg(test)] mod tests { use super::*; @@ -176,13 +218,13 @@ mod tests { assert_eq!(part1(INPUT, 1000).unwrap(), 127551); } - //#[test] - //fn part2_provided() { - // assert_eq!(part2(PROVIDED).unwrap(), 40); - //} + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 25272); + } - //#[test] - //fn part2_real() { - // assert_eq!(part2(INPUT).unwrap(), 18818811755665); - //} + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2347225200); + } } From 8c9d675964b85f45bc2d1d88cb9aad97e54f8fdb Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 12 Dec 2025 19:53:08 +0100 Subject: [PATCH 134/134] 2025: day09: part 1 and 2 --- aoc2025/benches/aoc2025_bench.rs | 2 + aoc2025/input/day09.txt | 496 +++++++++++++++++++++++++++++++ aoc2025/input/day09_provided.txt | 8 + aoc2025/src/day09.rs | 164 ++++++++++ aoc2025/src/lib.rs | 1 + aoc2025/src/main.rs | 2 + 6 files changed, 673 insertions(+) create mode 100644 aoc2025/input/day09.txt create mode 100644 aoc2025/input/day09_provided.txt create mode 100644 aoc2025/src/day09.rs diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index 094eb7f..54497a0 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -8,6 +8,7 @@ use aoc2025::day05; use aoc2025::day06; use aoc2025::day07; use aoc2025::day08; +use aoc2025::day09; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -18,6 +19,7 @@ fn aoc2025_all(c: &mut Criterion) { c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); c.bench_function("day07", |b| b.iter(|| day07::run().unwrap())); c.bench_function("day08", |b| b.iter(|| day08::run().unwrap())); + c.bench_function("day09", |b| b.iter(|| day09::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day09.txt b/aoc2025/input/day09.txt new file mode 100644 index 0000000..9c9aa1a --- /dev/null +++ b/aoc2025/input/day09.txt @@ -0,0 +1,496 @@ +97997,50117 +97997,51346 +98453,51346 +98453,52549 +97943,52549 +97943,53788 +98190,53788 +98190,54948 +97502,54948 +97502,56154 +97395,56154 +97395,57433 +97739,57433 +97739,58596 +97292,58596 +97292,59837 +97281,59837 +97281,61017 +96953,61017 +96953,62054 +96089,62054 +96089,63409 +96430,63409 +96430,64384 +95454,64384 +95454,65751 +95714,65751 +95714,66804 +95033,66804 +95033,67976 +94684,67976 +94684,69011 +94003,69011 +94003,70198 +93676,70198 +93676,71390 +93338,71390 +93338,72348 +92529,72348 +92529,73408 +91931,73408 +91931,74257 +90977,74257 +90977,75371 +90482,75371 +90482,76290 +89678,76290 +89678,77659 +89532,77659 +89532,78647 +88813,78647 +88813,79559 +87993,79559 +87993,80678 +87436,80678 +87436,81480 +86488,81480 +86488,82509 +85805,82509 +85805,83363 +84926,83363 +84926,84016 +83849,84016 +83849,84837 +82952,84837 +82952,85751 +82141,85751 +82141,86148 +80878,86148 +80878,86955 +79982,86955 +79982,87912 +79198,87912 +79198,88620 +78213,88620 +78213,89781 +77544,89781 +77544,90134 +76309,90134 +76309,90879 +75341,90879 +75341,91649 +74380,91649 +74380,92207 +73291,92207 +73291,92361 +71995,92361 +71995,93245 +71081,93245 +71081,93967 +70071,93967 +70071,94524 +68977,94524 +68977,94943 +67824,94943 +67824,95146 +66594,95146 +66594,95498 +65427,95498 +65427,95782 +64240,95782 +64240,95918 +63017,95918 +63017,96932 +62028,96932 +62028,96751 +60727,96751 +60727,96832 +59504,96832 +59504,97447 +58383,97447 +58383,97339 +57133,97339 +57133,97862 +55976,97862 +55976,97522 +54714,97522 +54714,98341 +53561,98341 +53561,98159 +52323,98159 +52323,97865 +51095,97865 +51095,98319 +49881,98319 +49881,97497 +48679,97497 +48679,97646 +47466,97646 +47466,97937 +46230,97937 +46230,97396 +45062,97396 +45062,97403 +43844,97403 +43844,97029 +42677,97029 +42677,97668 +41335,97668 +41335,96999 +40221,96999 +40221,96413 +39109,96413 +39109,96133 +37934,96133 +37934,95950 +36729,95950 +36729,95917 +35469,95917 +35469,94917 +34523,94917 +34523,95102 +33169,95102 +33169,94246 +32199,94246 +32199,94503 +30772,94503 +30772,93436 +29912,93436 +29912,92610 +28968,92610 +28968,92121 +27865,92121 +27865,92036 +26532,92036 +26532,91010 +25722,91010 +25722,90374 +24696,90374 +24696,90327 +23279,90327 +23279,88941 +22753,88941 +22753,88221 +21788,88221 +21788,87580 +20762,87580 +20762,87110 +19588,87110 +19588,86306 +18676,86306 +18676,85743 +17547,85743 +17547,84602 +16945,84602 +16945,83641 +16193,83641 +16193,83283 +14813,83283 +14813,81918 +14496,81918 +14496,80918 +13804,80918 +13804,80292 +12662,80292 +12662,79115 +12195,79115 +12195,78440 +11068,78440 +11068,77149 +10787,77149 +10787,76199 +10033,76199 +10033,75155 +9420,75155 +9420,74315 +8460,74315 +8460,73226 +7910,73226 +7910,72194 +7255,72194 +7255,71018 +6882,71018 +6882,69749 +6736,69749 +6736,68882 +5698,68882 +5698,67727 +5301,67727 +5301,66585 +4877,66585 +4877,65281 +4930,65281 +4930,64395 +3722,64395 +3722,63224 +3347,63224 +3347,61827 +3853,61827 +3853,60651 +3581,60651 +3581,59463 +3371,59463 +3371,58378 +2585,58378 +2585,57101 +2870,57101 +2870,55946 +2377,55946 +2377,54727 +2352,54727 +2352,53560 +1681,53560 +1681,52313 +2044,52313 +2044,51094 +2172,51094 +2172,50110 +94865,50110 +94865,48656 +1652,48656 +1652,47426 +1613,47426 +1613,46276 +2643,46276 +2643,44990 +1915,44990 +1915,43812 +2348,43812 +2348,42565 +2253,42565 +2253,41451 +2971,41451 +2971,40208 +2941,40208 +2941,39037 +3278,39037 +3278,37906 +3762,37906 +3762,36793 +4270,36793 +4270,35611 +4530,35611 +4530,34328 +4516,34328 +4516,33171 +4901,33171 +4901,32169 +5679,32169 +5679,31086 +6224,31086 +6224,29900 +6537,29900 +6537,28819 +7087,28819 +7087,27837 +7824,27837 +7824,26571 +8032,26571 +8032,25560 +8716,25560 +8716,24305 +9002,24305 +9002,23228 +9595,23228 +9595,22755 +11060,22755 +11060,21499 +11387,21499 +11387,20615 +12230,20615 +12230,19629 +12940,19629 +12940,18363 +13330,18363 +13330,17822 +14559,17822 +14559,16593 +15028,16593 +15028,16138 +16304,16138 +16304,15078 +16967,15078 +16967,14567 +18145,14567 +18145,13691 +18985,13691 +18985,12725 +19758,12725 +19758,11618 +20440,11618 +20440,11285 +21717,11285 +21717,10537 +22677,10537 +22677,9996 +23776,9996 +23776,9085 +24636,9085 +24636,8807 +25887,8807 +25887,7954 +26797,7954 +26797,7299 +27828,7299 +27828,6560 +28824,6560 +28824,6675 +30222,6675 +30222,6188 +31326,6188 +31326,5665 +32416,5665 +32416,5269 +33558,5269 +33558,4558 +34592,4558 +34592,4297 +35783,4297 +35783,4096 +36987,4096 +36987,3676 +38127,3676 +38127,3093 +39236,3093 +39236,2965 +40454,2965 +40454,2678 +41638,2678 +41638,2319 +42815,2319 +42815,2781 +44104,2781 +44104,2245 +45262,2245 +45262,2218 +46479,2218 +46479,1829 +47675,1829 +47675,1732 +48895,1732 +48895,1948 +50118,1948 +50118,2255 +51327,2255 +51327,1730 +52566,1730 +52566,1670 +53799,1670 +53799,2521 +54945,2521 +54945,1990 +56234,1990 +56234,2955 +57325,2955 +57325,2820 +58575,2820 +58575,3321 +59712,3321 +59712,3024 +61022,3024 +61022,3906 +62055,3906 +62055,3723 +63364,3723 +63364,4203 +64492,4203 +64492,4440 +65697,4440 +65697,4855 +66845,4855 +66845,5402 +67941,5402 +67941,5922 +69043,5922 +69043,6713 +70017,6713 +70017,7102 +71172,7102 +71172,7317 +72429,7317 +72429,7869 +73519,7869 +73519,8752 +74417,8752 +74417,9149 +75601,9149 +75601,10303 +76301,10303 +76301,10274 +77794,10274 +77794,11384 +78502,11384 +78502,12252 +79367,12252 +79367,12863 +80432,12863 +80432,14015 +81045,14015 +81045,14153 +82546,14153 +82546,15277 +83169,15277 +83169,16371 +83794,16371 +83794,17100 +84780,17100 +84780,18019 +85572,18019 +85572,18602 +86755,18602 +86755,19867 +87140,19867 +87140,20414 +88416,20414 +88416,21566 +88920,21566 +88920,22438 +89807,22438 +89807,23692 +90131,23692 +90131,24638 +90912,24638 +90912,25875 +91212,25875 +91212,26672 +92272,26672 +92272,28023 +92324,28023 +92324,29101 +92870,29101 +92870,30144 +93494,30144 +93494,31085 +94375,31085 +94375,32167 +94962,32167 +94962,33582 +94664,33582 +94664,34550 +95563,34550 +95563,35684 +96022,35684 +96022,36879 +96285,36879 +96285,38051 +96621,38051 +96621,39161 +97232,39161 +97232,40476 +96926,40476 +96926,41698 +96982,41698 +96982,42794 +97820,42794 +97820,44053 +97627,44053 +97627,45302 +97346,45302 +97346,46459 +98049,46459 +98049,47710 +97453,47710 +97453,48890 +98462,48890 +98462,50117 diff --git a/aoc2025/input/day09_provided.txt b/aoc2025/input/day09_provided.txt new file mode 100644 index 0000000..c8563ea --- /dev/null +++ b/aoc2025/input/day09_provided.txt @@ -0,0 +1,8 @@ +7,1 +11,1 +11,7 +9,7 +9,5 +2,5 +2,3 +7,3 diff --git a/aoc2025/src/day09.rs b/aoc2025/src/day09.rs new file mode 100644 index 0000000..90ff1af --- /dev/null +++ b/aoc2025/src/day09.rs @@ -0,0 +1,164 @@ +use anyhow::{Context, Result, anyhow}; +use std::{fmt::Write, str::FromStr}; + +const INPUT: &str = include_str!("../input/day09.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + Ok(res) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Point { + x: usize, + y: usize, +} + +impl FromStr for Point { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let (x, y) = s + .split_once(',') + .with_context(|| format!("couldn't parse point `{}'", s))?; + let (x, y) = (x.parse()?, y.parse()?); + + Ok(Self { x, y }) + } +} + +fn rectangle_area(p1: &Point, p2: &Point) -> usize { + (p1.x.max(p2.x) - p1.x.min(p2.x) + 1) * (p1.y.max(p2.y) - p1.y.min(p2.y) + 1) +} + +fn part1(input: &str) -> Result { + let points = input + .lines() + .map(|line| line.parse::()) + .collect::>>()?; + + let mut max = None; + for (idx, p1) in points.iter().enumerate() { + for p2 in points.iter().skip(idx + 1) { + let area = rectangle_area(p1, p2); + match max { + Some(m) => max = Some(area.max(m)), + None => max = Some(area), + } + } + } + + max.ok_or_else(|| anyhow!("input was empty")) +} + +// Computes whether a segment crosses through our rectangle. +// +// Since edges are always parallel to axes, this is easier than in the general case +fn edge_intersects(&(e1, e2): &(Point, Point), (r1, r2): (&Point, &Point)) -> bool { + let (rect_xmin, rect_xmax) = (r1.x.min(r2.x), r1.x.max(r2.x)); + let (rect_ymin, rect_ymax) = (r1.y.min(r2.y), r1.y.max(r2.y)); + + #[allow(clippy::nonminimal_bool)] + if e1.x == e2.x { + // segment is vertical + let edge_ymin = e1.y.min(e2.y); + let edge_ymax = e1.y.max(e2.y); + (rect_xmin < e1.x && e1.x < rect_xmax ) // we're in the right X range to cross + && ((edge_ymin <= rect_ymin && edge_ymax >= rect_ymax) // segment crosses through both sides + || (edge_ymin <= rect_ymin && rect_ymin < edge_ymax) // segment crosses through bottom edge + || (edge_ymin < rect_ymax && edge_ymax >= rect_ymax) // segment crosses through top edge + ) + } else { + // segment is horizontal + let edge_xmin = e1.x.min(e2.x); + let edge_xmax = e1.x.max(e2.x); + (rect_ymin < e1.y && e1.y < rect_ymax ) // we're in the right X range to cross + && ((edge_xmin <= rect_xmin && edge_xmax >= rect_xmax) // segment crosses through both sides + || (edge_xmin <= rect_xmin && rect_xmin < edge_xmax) // segment crosses through bottom edge + || (edge_xmin < rect_xmax && edge_xmax >= rect_xmax) // segment crosses through top edge + ) + } +} + +fn part2(input: &str) -> Result { + let points = input + .lines() + .map(|line| line.parse::()) + .collect::>>()?; + + let mut edges = points.windows(2).map(|w| (w[0], w[1])).collect::>(); + edges.push(( + *points.last().context("input was empty")?, + *points.first().context("input was empty")?, + )); + + let mut max = None; + for (idx, p1) in points.iter().enumerate() { + for p2 in points.iter().skip(idx + 1) { + if edges.iter().any(|e| edge_intersects(e, (p1, p2))) { + // If an edge crosses through our rectangle then one side of the edge is obviously + // outside our polygon. + // + // Generally, this isn't sufficient to guarantee that a rectangle is "valid". + // Consider the following polygon: + // + // .......... + // .#X1..#X#. + // .XXX..XXX. + // .XX#XX2XX. + // .#XXXXXX#. + // .......... + // + // The rectangle between 1 and 2 isn't crossed by any edge, yet it is outside the + // polygon. However looking at the shape of my input (which more or less looks like + // a rasterized circle), it's obvious that this kind of edge case will never happen + // for rectangles large enough to be of maximal area. + continue; + } + let area = rectangle_area(p1, p2); + match max { + Some(m) => max = Some(area.max(m)), + None => max = Some(area), + } + } + } + + max.ok_or_else(|| anyhow!("input was empty")) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day09_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 50); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 4758121828); + } + + #[test] + fn part2_provided() { + assert!(edge_intersects( + &(Point { x: 7, y: 3 }, Point { x: 7, y: 1 }), + (&Point { x: 2, y: 5 }, &Point { x: 11, y: 1 }) + )); + assert!(edge_intersects( + &(Point { x: 9, y: 5 }, Point { x: 2, y: 5 }), + (&Point { x: 9, y: 7 }, &Point { x: 2, y: 3 }) + )); + assert_eq!(part2(PROVIDED).unwrap(), 24); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 1577956170); + } +} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index 9ac735a..a8fc1a9 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -6,3 +6,4 @@ pub mod day05; pub mod day06; pub mod day07; pub mod day08; +pub mod day09; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 5997649..daa8ec3 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -10,6 +10,7 @@ use aoc2025::day05; use aoc2025::day06; use aoc2025::day07; use aoc2025::day08; +use aoc2025::day09; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -21,6 +22,7 @@ fn main() -> Result<()> { day06::run, day07::run, day08::run, + day09::run, ]; aoc::run(days)