From b29deec7e756c65b8e7ad4486e41b18b182f6d2d Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Thu, 29 Aug 2024 19:27:55 +0200 Subject: [PATCH 1/5] Refacture: Moved solutions into lib crate for better reuse --- Cargo.lock | 33 +- Cargo.toml | 18 +- crates/cli/Cargo.lock | 439 ++++++++++++++++++ crates/cli/Cargo.toml | 14 + {src => crates/cli/src}/cli.rs | 0 {src => crates/cli/src}/cli/given_day.rs | 0 {src => crates/cli/src}/cli/given_task.rs | 0 {src => crates/cli/src}/constants.rs | 0 crates/cli/src/lib.rs | 3 + {src => crates/cli/src}/main.rs | 0 {src => crates/cli/src}/solutions.rs | 6 +- crates/solutions/Cargo.toml | 15 + .../solutions/src}/day5.rs | 2 +- .../solutions/src}/day5/day_example_input.txt | 0 .../solutions/src}/day5/item_mapping.rs | 2 +- .../solutions/src}/day5/parsing.rs | 4 +- .../solutions/src}/day5/seed_range.rs | 0 ..._day5__parsing__testing__should_parse.snap | 0 ..._day5__parsing__testing__should_parse.snap | 172 +++++++ .../solutions/src}/day6.rs | 2 +- .../solutions/src}/day6/day_example_input.txt | 0 .../solutions/src}/day6/parsing.rs | 2 +- .../solutions/src}/day6/race_record.rs | 0 .../solutions/src}/day7.rs | 6 +- .../solutions/src}/day7/categorized_hand.rs | 20 +- .../day7/categorized_hand/joker_ordered.rs | 4 +- ...g__example_sort_with_joker_as_weakest.snap | 0 ...g__example_sort_with_joker_as_weakest.snap | 51 ++ .../solutions/src}/day7/dealt_hand.rs | 2 +- .../solutions/src}/day7/hand_kind.rs | 5 +- .../src}/day7/hand_kind/non_zero_count.rs | 0 .../solutions/src}/day7/hello.rs | 0 .../solutions/src}/day7/parsing.rs | 2 +- .../solutions/src}/day7/second_ordering.rs | 7 - ...hand__testing__sort_example_correctly.snap | 0 ...esting__check_label_with_joker_orders.snap | 0 ...hand__testing__sort_example_correctly.snap | 41 ++ ...esting__check_label_with_joker_orders.snap | 66 +++ crates/solutions/src/lib.rs | 4 + crates/solutions/src/utils.rs | 1 + .../solutions/src/utils/parsing.rs | 0 src/iterations.rs | 70 --- src/lib.rs | 6 - src/sequences.rs | 26 -- 44 files changed, 864 insertions(+), 159 deletions(-) create mode 100644 crates/cli/Cargo.lock create mode 100644 crates/cli/Cargo.toml rename {src => crates/cli/src}/cli.rs (100%) rename {src => crates/cli/src}/cli/given_day.rs (100%) rename {src => crates/cli/src}/cli/given_task.rs (100%) rename {src => crates/cli/src}/constants.rs (100%) create mode 100644 crates/cli/src/lib.rs rename {src => crates/cli/src}/main.rs (100%) rename {src => crates/cli/src}/solutions.rs (92%) create mode 100644 crates/solutions/Cargo.toml rename {src/solutions => crates/solutions/src}/day5.rs (99%) rename {src/solutions => crates/solutions/src}/day5/day_example_input.txt (100%) rename {src/solutions => crates/solutions/src}/day5/item_mapping.rs (99%) rename {src/solutions => crates/solutions/src}/day5/parsing.rs (89%) rename {src/solutions => crates/solutions/src}/day5/seed_range.rs (100%) rename {src/solutions => crates/solutions/src}/day5/snapshots/advent_of_code_2023__solutions__day5__parsing__testing__should_parse.snap (100%) create mode 100644 crates/solutions/src/day5/snapshots/solutions_advent_of_code_2023__day5__parsing__testing__should_parse.snap rename {src/solutions => crates/solutions/src}/day6.rs (96%) rename {src/solutions => crates/solutions/src}/day6/day_example_input.txt (100%) rename {src/solutions => crates/solutions/src}/day6/parsing.rs (97%) rename {src/solutions => crates/solutions/src}/day6/race_record.rs (100%) rename {src/solutions => crates/solutions/src}/day7.rs (94%) rename {src/solutions => crates/solutions/src}/day7/categorized_hand.rs (88%) rename {src/solutions => crates/solutions/src}/day7/categorized_hand/joker_ordered.rs (96%) rename {src/solutions => crates/solutions/src}/day7/categorized_hand/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap (100%) create mode 100644 crates/solutions/src/day7/categorized_hand/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap rename {src/solutions => crates/solutions/src}/day7/dealt_hand.rs (97%) rename {src/solutions => crates/solutions/src}/day7/hand_kind.rs (97%) rename {src/solutions => crates/solutions/src}/day7/hand_kind/non_zero_count.rs (100%) rename {src/solutions => crates/solutions/src}/day7/hello.rs (100%) rename {src/solutions => crates/solutions/src}/day7/parsing.rs (88%) rename {src/solutions => crates/solutions/src}/day7/second_ordering.rs (92%) rename {src/solutions => crates/solutions/src}/day7/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__testing__sort_example_correctly.snap (100%) rename {src/solutions => crates/solutions/src}/day7/snapshots/advent_of_code_2023__solutions__day7__second_ordering__testing__check_label_with_joker_orders.snap (100%) create mode 100644 crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__testing__sort_example_correctly.snap create mode 100644 crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__second_ordering__testing__check_label_with_joker_orders.snap create mode 100644 crates/solutions/src/lib.rs create mode 100644 crates/solutions/src/utils.rs rename src/parsing_utils.rs => crates/solutions/src/utils/parsing.rs (100%) delete mode 100644 src/iterations.rs delete mode 100644 src/lib.rs delete mode 100644 src/sequences.rs diff --git a/Cargo.lock b/Cargo.lock index 2843f2f..464cfcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,9 +9,8 @@ dependencies = [ "clap", "derive_more", "env_logger", - "insta", "log", - "regex", + "solutions_advent_of_code_2023", "thiserror", ] @@ -75,9 +74,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.15" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -229,9 +228,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.156" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linked-hash-map" @@ -262,9 +261,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -304,6 +303,16 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +[[package]] +name = "solutions_advent_of_code_2023" +version = "0.1.0" +dependencies = [ + "derive_more", + "insta", + "regex", + "thiserror", +] + [[package]] name = "strsim" version = "0.11.1" @@ -312,9 +321,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.74" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", @@ -355,9 +364,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "utf8parse" diff --git a/Cargo.toml b/Cargo.toml index 8c75ded..870ac71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,9 @@ -[package] -name = "advent_of_code_2023" -version = "0.1.0" -edition = "2021" +[workspace] +resolver = "2" +members = ["crates/cli", "crates/solutions"] -[dependencies] +default-members = ["crates/cli"] + +[workspace.dependencies] derive_more = { version = "1", features = ["full"] } -regex = "1.10.6" -clap = { version = "4.5.15", features = ["derive"] } -env_logger = "0.11.5" -log = "0.4.22" thiserror = "1.0.63" - -[dev-dependencies] -insta = "1.39.0" diff --git a/crates/cli/Cargo.lock b/crates/cli/Cargo.lock new file mode 100644 index 0000000..2843f2f --- /dev/null +++ b/crates/cli/Cargo.lock @@ -0,0 +1,439 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "advent_of_code_2023" +version = "0.1.0" +dependencies = [ + "clap", + "derive_more", + "env_logger", + "insta", + "log", + "regex", + "thiserror", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "insta" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "similar", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "similar" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml new file mode 100644 index 0000000..bbcf323 --- /dev/null +++ b/crates/cli/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "advent_of_code_2023" +version = "0.1.0" +edition = "2021" + +[dependencies] +solutions_advent_of_code_2023 = { path = "../solutions" } + +derive_more = { workspace = true } +thiserror = { workspace = true } + +clap = { version = "4.5.15", features = ["derive"] } +env_logger = "0.11.5" +log = "0.4.22" diff --git a/src/cli.rs b/crates/cli/src/cli.rs similarity index 100% rename from src/cli.rs rename to crates/cli/src/cli.rs diff --git a/src/cli/given_day.rs b/crates/cli/src/cli/given_day.rs similarity index 100% rename from src/cli/given_day.rs rename to crates/cli/src/cli/given_day.rs diff --git a/src/cli/given_task.rs b/crates/cli/src/cli/given_task.rs similarity index 100% rename from src/cli/given_task.rs rename to crates/cli/src/cli/given_task.rs diff --git a/src/constants.rs b/crates/cli/src/constants.rs similarity index 100% rename from src/constants.rs rename to crates/cli/src/constants.rs diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs new file mode 100644 index 0000000..5551262 --- /dev/null +++ b/crates/cli/src/lib.rs @@ -0,0 +1,3 @@ +pub mod cli; +pub mod constants; +pub mod solutions; diff --git a/src/main.rs b/crates/cli/src/main.rs similarity index 100% rename from src/main.rs rename to crates/cli/src/main.rs diff --git a/src/solutions.rs b/crates/cli/src/solutions.rs similarity index 92% rename from src/solutions.rs rename to crates/cli/src/solutions.rs index 6677dd3..ca1a777 100644 --- a/src/solutions.rs +++ b/crates/cli/src/solutions.rs @@ -1,6 +1,6 @@ -pub mod day5; -pub mod day6; -pub mod day7; +use solutions_advent_of_code_2023::day5; +use solutions_advent_of_code_2023::day6; +use solutions_advent_of_code_2023::day7; pub fn create_solutions() -> Vec String>> { vec![ diff --git a/crates/solutions/Cargo.toml b/crates/solutions/Cargo.toml new file mode 100644 index 0000000..a127a94 --- /dev/null +++ b/crates/solutions/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "solutions_advent_of_code_2023" + +version = "0.1.0" +edition = "2021" + +[dependencies] + +derive_more = { workspace = true } +thiserror = { workspace = true } + +regex = "1.10.6" + +[dev-dependencies] +insta = "1.39.0" diff --git a/src/solutions/day5.rs b/crates/solutions/src/day5.rs similarity index 99% rename from src/solutions/day5.rs rename to crates/solutions/src/day5.rs index 76e507d..562282d 100644 --- a/src/solutions/day5.rs +++ b/crates/solutions/src/day5.rs @@ -136,7 +136,7 @@ fn combine_single_to_ranges_for_seeds(single_seeds: &[UnsignedNumber]) -> Vec (Vec, Vec>) { - let mut blocks = parsing_utils::blocks_of_lines_seperated_by_empty_lines(input); + let mut blocks = parsing::blocks_of_lines_seperated_by_empty_lines(input); let seeds = { let first_block = blocks.next().unwrap(); let first_line = first_block.first().unwrap(); diff --git a/src/solutions/day5/seed_range.rs b/crates/solutions/src/day5/seed_range.rs similarity index 100% rename from src/solutions/day5/seed_range.rs rename to crates/solutions/src/day5/seed_range.rs diff --git a/src/solutions/day5/snapshots/advent_of_code_2023__solutions__day5__parsing__testing__should_parse.snap b/crates/solutions/src/day5/snapshots/advent_of_code_2023__solutions__day5__parsing__testing__should_parse.snap similarity index 100% rename from src/solutions/day5/snapshots/advent_of_code_2023__solutions__day5__parsing__testing__should_parse.snap rename to crates/solutions/src/day5/snapshots/advent_of_code_2023__solutions__day5__parsing__testing__should_parse.snap diff --git a/crates/solutions/src/day5/snapshots/solutions_advent_of_code_2023__day5__parsing__testing__should_parse.snap b/crates/solutions/src/day5/snapshots/solutions_advent_of_code_2023__day5__parsing__testing__should_parse.snap new file mode 100644 index 0000000..cc549c7 --- /dev/null +++ b/crates/solutions/src/day5/snapshots/solutions_advent_of_code_2023__day5__parsing__testing__should_parse.snap @@ -0,0 +1,172 @@ +--- +source: crates/solutions/src/day5/parsing.rs +expression: actual +--- +( + [ + 79, + 14, + 55, + 13, + ], + [ + [ + ItemMapping { + source_range: SeedRange { + start: 98, + end: 99, + }, + target: 50, + range: 2, + }, + ItemMapping { + source_range: SeedRange { + start: 50, + end: 97, + }, + target: 52, + range: 48, + }, + ], + [ + ItemMapping { + source_range: SeedRange { + start: 15, + end: 51, + }, + target: 0, + range: 37, + }, + ItemMapping { + source_range: SeedRange { + start: 52, + end: 53, + }, + target: 37, + range: 2, + }, + ItemMapping { + source_range: SeedRange { + start: 0, + end: 14, + }, + target: 39, + range: 15, + }, + ], + [ + ItemMapping { + source_range: SeedRange { + start: 53, + end: 60, + }, + target: 49, + range: 8, + }, + ItemMapping { + source_range: SeedRange { + start: 11, + end: 52, + }, + target: 0, + range: 42, + }, + ItemMapping { + source_range: SeedRange { + start: 0, + end: 6, + }, + target: 42, + range: 7, + }, + ItemMapping { + source_range: SeedRange { + start: 7, + end: 10, + }, + target: 57, + range: 4, + }, + ], + [ + ItemMapping { + source_range: SeedRange { + start: 18, + end: 24, + }, + target: 88, + range: 7, + }, + ItemMapping { + source_range: SeedRange { + start: 25, + end: 94, + }, + target: 18, + range: 70, + }, + ], + [ + ItemMapping { + source_range: SeedRange { + start: 77, + end: 99, + }, + target: 45, + range: 23, + }, + ItemMapping { + source_range: SeedRange { + start: 45, + end: 63, + }, + target: 81, + range: 19, + }, + ItemMapping { + source_range: SeedRange { + start: 64, + end: 76, + }, + target: 68, + range: 13, + }, + ], + [ + ItemMapping { + source_range: SeedRange { + start: 69, + end: 69, + }, + target: 0, + range: 1, + }, + ItemMapping { + source_range: SeedRange { + start: 0, + end: 68, + }, + target: 1, + range: 69, + }, + ], + [ + ItemMapping { + source_range: SeedRange { + start: 56, + end: 92, + }, + target: 60, + range: 37, + }, + ItemMapping { + source_range: SeedRange { + start: 93, + end: 96, + }, + target: 56, + range: 4, + }, + ], + ], +) diff --git a/src/solutions/day6.rs b/crates/solutions/src/day6.rs similarity index 96% rename from src/solutions/day6.rs rename to crates/solutions/src/day6.rs index 14d5df1..bd51482 100644 --- a/src/solutions/day6.rs +++ b/crates/solutions/src/day6.rs @@ -44,7 +44,7 @@ fn simuluate_reached_distance_at( #[cfg(test)] mod testing { - use crate::solutions::day6::{simuluate_reached_distance_at, solve_task_2, NumericValue}; + use crate::day6::{simuluate_reached_distance_at, solve_task_2, NumericValue}; use super::solve_task_1; diff --git a/src/solutions/day6/day_example_input.txt b/crates/solutions/src/day6/day_example_input.txt similarity index 100% rename from src/solutions/day6/day_example_input.txt rename to crates/solutions/src/day6/day_example_input.txt diff --git a/src/solutions/day6/parsing.rs b/crates/solutions/src/day6/parsing.rs similarity index 97% rename from src/solutions/day6/parsing.rs rename to crates/solutions/src/day6/parsing.rs index 1a84b85..5d1b2c3 100644 --- a/src/solutions/day6/parsing.rs +++ b/crates/solutions/src/day6/parsing.rs @@ -41,7 +41,7 @@ pub fn parsing_part_2(input: &str) -> RaceRecord { #[cfg(test)] mod testing { - use crate::solutions::day6::race_record::RaceRecord; + use crate::day6::race_record::RaceRecord; #[test] fn should_parse() { diff --git a/src/solutions/day6/race_record.rs b/crates/solutions/src/day6/race_record.rs similarity index 100% rename from src/solutions/day6/race_record.rs rename to crates/solutions/src/day6/race_record.rs diff --git a/src/solutions/day7.rs b/crates/solutions/src/day7.rs similarity index 94% rename from src/solutions/day7.rs rename to crates/solutions/src/day7.rs index 429dfda..806b182 100644 --- a/src/solutions/day7.rs +++ b/crates/solutions/src/day7.rs @@ -1,12 +1,12 @@ +use crate::day7::dealt_hand::DealtHand; use categorized_hand::{CategorizedHand, JokerOrdered}; -use crate::solutions::day7::dealt_hand::DealtHand; mod categorized_hand; mod dealt_hand; mod hand_kind; +mod hello; mod parsing; mod second_ordering; -mod hello; pub fn solve_task_1(input: &str) -> String { let parsed = parsing::parse_input(input); @@ -22,7 +22,7 @@ pub fn solve_task_1(input: &str) -> String { pub fn solve_task_2(input: &str) -> String { const JOKER: char = 'J'; let parsed = parsing::parse_input(input); - let sorted_and_categorized= categorize_and_sort_with_a_joker(parsed, JOKER); + let sorted_and_categorized = categorize_and_sort_with_a_joker(parsed, JOKER); let total_winning = calc_total_winning(&sorted_and_categorized); total_winning.to_string() } diff --git a/src/solutions/day7/categorized_hand.rs b/crates/solutions/src/day7/categorized_hand.rs similarity index 88% rename from src/solutions/day7/categorized_hand.rs rename to crates/solutions/src/day7/categorized_hand.rs index c9d378a..1cfe782 100644 --- a/src/solutions/day7/categorized_hand.rs +++ b/crates/solutions/src/day7/categorized_hand.rs @@ -1,7 +1,7 @@ mod joker_ordered; pub use joker_ordered::JokerOrdered; -use crate::solutions::day7::second_ordering; +use crate::day7::second_ordering; use std::usize; use super::{dealt_hand::DealtHand, hand_kind::HandKind, second_ordering::StrengthOfSymbols}; @@ -39,8 +39,12 @@ fn hand_cmp( ) -> std::cmp::Ordering { match left.kind.cmp(&right.kind) { std::cmp::Ordering::Equal => { - assert_eq!(left.kind, right.kind, "If ordering is equal then the hand kind must be the same too\n\ - left kind: ({:?}) and right kind: ({:?})", left.kind, right.kind); + assert_eq!( + left.kind, right.kind, + "If ordering is equal then the hand kind must be the same too\n\ + left kind: ({:?}) and right kind: ({:?})", + left.kind, right.kind + ); second_ordering::compare_along_str( left.rest().hand(), right.rest().hand(), @@ -48,8 +52,12 @@ fn hand_cmp( ) } not_equal_ordering => { - assert_ne!(left.kind, right.kind, "If ordering is not equal then the hand kind must not be the same either\n\ - left kind: ({:?}) and right kind: ({:?})", left.kind, right.kind); + assert_ne!( + left.kind, right.kind, + "If ordering is not equal then the hand kind must not be the same either\n\ + left kind: ({:?}) and right kind: ({:?})", + left.kind, right.kind + ); not_equal_ordering } } @@ -78,7 +86,7 @@ impl From<(DealtHand, char)> for CategorizedHand { mod testing { use std::cmp::Ordering; - use crate::solutions::day7::{categorized_hand::CategorizedHand, dealt_hand::DealtHand}; + use crate::day7::{categorized_hand::CategorizedHand, dealt_hand::DealtHand}; #[test] fn compare_correctly_by_kind_and_second_ordering() { diff --git a/src/solutions/day7/categorized_hand/joker_ordered.rs b/crates/solutions/src/day7/categorized_hand/joker_ordered.rs similarity index 96% rename from src/solutions/day7/categorized_hand/joker_ordered.rs rename to crates/solutions/src/day7/categorized_hand/joker_ordered.rs index bda9704..8ede82e 100644 --- a/src/solutions/day7/categorized_hand/joker_ordered.rs +++ b/crates/solutions/src/day7/categorized_hand/joker_ordered.rs @@ -1,6 +1,6 @@ use derive_more::derive::Into; -use crate::solutions::day7::second_ordering; +use crate::day7::second_ordering; use super::{hand_cmp, CategorizedHand}; @@ -32,7 +32,7 @@ impl PartialOrd for JokerOrdered { mod testing { use std::cmp::Ordering; - use crate::solutions::day7::{ + use crate::day7::{ categorized_hand::{CategorizedHand, JokerOrdered}, dealt_hand::DealtHand, second_ordering::{self, JOKER}, diff --git a/src/solutions/day7/categorized_hand/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap b/crates/solutions/src/day7/categorized_hand/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap similarity index 100% rename from src/solutions/day7/categorized_hand/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap rename to crates/solutions/src/day7/categorized_hand/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap diff --git a/crates/solutions/src/day7/categorized_hand/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap b/crates/solutions/src/day7/categorized_hand/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap new file mode 100644 index 0000000..3678497 --- /dev/null +++ b/crates/solutions/src/day7/categorized_hand/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__joker_ordered__testing__example_sort_with_joker_as_weakest.snap @@ -0,0 +1,51 @@ +--- +source: crates/solutions/src/day7/categorized_hand/joker_ordered.rs +expression: input +--- +[ + JokerOrdered( + CategorizedHand { + kind: OnePair, + rest: DealtHand { + hand: "32T3K", + bid: 765, + }, + }, + ), + JokerOrdered( + CategorizedHand { + kind: TwoPair, + rest: DealtHand { + hand: "KK677", + bid: 28, + }, + }, + ), + JokerOrdered( + CategorizedHand { + kind: Four, + rest: DealtHand { + hand: "T55J5", + bid: 684, + }, + }, + ), + JokerOrdered( + CategorizedHand { + kind: Four, + rest: DealtHand { + hand: "QQQJA", + bid: 483, + }, + }, + ), + JokerOrdered( + CategorizedHand { + kind: Four, + rest: DealtHand { + hand: "KTJJT", + bid: 220, + }, + }, + ), +] diff --git a/src/solutions/day7/dealt_hand.rs b/crates/solutions/src/day7/dealt_hand.rs similarity index 97% rename from src/solutions/day7/dealt_hand.rs rename to crates/solutions/src/day7/dealt_hand.rs index 904a913..a21d7ca 100644 --- a/src/solutions/day7/dealt_hand.rs +++ b/crates/solutions/src/day7/dealt_hand.rs @@ -58,7 +58,7 @@ impl FromStr for DealtHand { #[cfg(test)] mod testing { - use crate::solutions::day7::dealt_hand::{DealtHand, InvalidStrDealtHand}; + use crate::day7::dealt_hand::{DealtHand, InvalidStrDealtHand}; #[test] fn parse_str() { diff --git a/src/solutions/day7/hand_kind.rs b/crates/solutions/src/day7/hand_kind.rs similarity index 97% rename from src/solutions/day7/hand_kind.rs rename to crates/solutions/src/day7/hand_kind.rs index 4f4cbd0..f627743 100644 --- a/src/solutions/day7/hand_kind.rs +++ b/crates/solutions/src/day7/hand_kind.rs @@ -1,6 +1,5 @@ use std::{cmp::Reverse, collections::HashMap}; -use log::warn; use non_zero_count::NonZeroCount; mod non_zero_count; @@ -121,16 +120,14 @@ fn choose_kind_from(to_choose_from: &[usize]) -> HandKind { } calc_kind(&to_choose_from).unwrap_or_else(|| { - warn!("Got hand ({:?}) with less than 2 cards", &to_choose_from); let default_value = HandKind::default(); - warn!("Default kind ({:?}) is assumed", default_value); default_value }) } #[cfg(test)] mod testing { - use crate::solutions::day7::{ + use crate::day7::{ categorized_hand::CategorizedHand, dealt_hand::DealtHand, hand_kind::HandKind, }; diff --git a/src/solutions/day7/hand_kind/non_zero_count.rs b/crates/solutions/src/day7/hand_kind/non_zero_count.rs similarity index 100% rename from src/solutions/day7/hand_kind/non_zero_count.rs rename to crates/solutions/src/day7/hand_kind/non_zero_count.rs diff --git a/src/solutions/day7/hello.rs b/crates/solutions/src/day7/hello.rs similarity index 100% rename from src/solutions/day7/hello.rs rename to crates/solutions/src/day7/hello.rs diff --git a/src/solutions/day7/parsing.rs b/crates/solutions/src/day7/parsing.rs similarity index 88% rename from src/solutions/day7/parsing.rs rename to crates/solutions/src/day7/parsing.rs index 5adad52..aca31a9 100644 --- a/src/solutions/day7/parsing.rs +++ b/crates/solutions/src/day7/parsing.rs @@ -6,7 +6,7 @@ pub fn parse_input(input: &str) -> Vec { #[cfg(test)] mod testing { - use crate::solutions::day7::{dealt_hand::DealtHand, TEST_INPUT}; + use crate::day7::{dealt_hand::DealtHand, TEST_INPUT}; #[test] fn parse() { diff --git a/src/solutions/day7/second_ordering.rs b/crates/solutions/src/day7/second_ordering.rs similarity index 92% rename from src/solutions/day7/second_ordering.rs rename to crates/solutions/src/day7/second_ordering.rs index 1d852b6..7274835 100644 --- a/src/solutions/day7/second_ordering.rs +++ b/crates/solutions/src/day7/second_ordering.rs @@ -1,7 +1,5 @@ use std::{cmp::Ordering, collections::HashMap, ops::RangeInclusive, sync::LazyLock, usize}; -use log::warn; - pub const JOKER: char = 'J'; static LETTERS_WITHOUT_JOKER: &[char] = &['T', 'Q', 'K', 'A']; static LETTERS: &[char] = &['T', 'J', 'Q', 'K', 'A']; @@ -57,11 +55,6 @@ pub fn compare_along_str( } } let (left_len, right_len) = (left.len(), right.len()); - warn!( - "Left and right seem to have no difference in strength\n\ - Now comparing via lenght ({}) ({}). By same length, lefte wins !", - left_len, right_len - ); left_len.cmp(&right_len) } diff --git a/src/solutions/day7/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__testing__sort_example_correctly.snap b/crates/solutions/src/day7/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__testing__sort_example_correctly.snap similarity index 100% rename from src/solutions/day7/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__testing__sort_example_correctly.snap rename to crates/solutions/src/day7/snapshots/advent_of_code_2023__solutions__day7__categorized_hand__testing__sort_example_correctly.snap diff --git a/src/solutions/day7/snapshots/advent_of_code_2023__solutions__day7__second_ordering__testing__check_label_with_joker_orders.snap b/crates/solutions/src/day7/snapshots/advent_of_code_2023__solutions__day7__second_ordering__testing__check_label_with_joker_orders.snap similarity index 100% rename from src/solutions/day7/snapshots/advent_of_code_2023__solutions__day7__second_ordering__testing__check_label_with_joker_orders.snap rename to crates/solutions/src/day7/snapshots/advent_of_code_2023__solutions__day7__second_ordering__testing__check_label_with_joker_orders.snap diff --git a/crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__testing__sort_example_correctly.snap b/crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__testing__sort_example_correctly.snap new file mode 100644 index 0000000..4bb86f1 --- /dev/null +++ b/crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__categorized_hand__testing__sort_example_correctly.snap @@ -0,0 +1,41 @@ +--- +source: crates/solutions/src/day7/categorized_hand.rs +expression: input +--- +[ + CategorizedHand { + kind: OnePair, + rest: DealtHand { + hand: "32T3K", + bid: 765, + }, + }, + CategorizedHand { + kind: TwoPair, + rest: DealtHand { + hand: "KTJJT", + bid: 220, + }, + }, + CategorizedHand { + kind: TwoPair, + rest: DealtHand { + hand: "KK677", + bid: 28, + }, + }, + CategorizedHand { + kind: Three, + rest: DealtHand { + hand: "T55J5", + bid: 684, + }, + }, + CategorizedHand { + kind: Three, + rest: DealtHand { + hand: "QQQJA", + bid: 483, + }, + }, +] diff --git a/crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__second_ordering__testing__check_label_with_joker_orders.snap b/crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__second_ordering__testing__check_label_with_joker_orders.snap new file mode 100644 index 0000000..dc2ff50 --- /dev/null +++ b/crates/solutions/src/day7/snapshots/solutions_advent_of_code_2023__day7__second_ordering__testing__check_label_with_joker_orders.snap @@ -0,0 +1,66 @@ +--- +source: crates/solutions/src/day7/second_ordering.rs +expression: ordered +--- +[ + ( + 'J', + 0, + ), + ( + '0', + 1, + ), + ( + '1', + 2, + ), + ( + '2', + 3, + ), + ( + '3', + 4, + ), + ( + '4', + 5, + ), + ( + '5', + 6, + ), + ( + '6', + 7, + ), + ( + '7', + 8, + ), + ( + '8', + 9, + ), + ( + '9', + 10, + ), + ( + 'T', + 11, + ), + ( + 'Q', + 12, + ), + ( + 'K', + 13, + ), + ( + 'A', + 14, + ), +] diff --git a/crates/solutions/src/lib.rs b/crates/solutions/src/lib.rs new file mode 100644 index 0000000..cdac89d --- /dev/null +++ b/crates/solutions/src/lib.rs @@ -0,0 +1,4 @@ +pub mod day5; +pub mod day6; +pub mod day7; +mod utils; diff --git a/crates/solutions/src/utils.rs b/crates/solutions/src/utils.rs new file mode 100644 index 0000000..dd9e1b8 --- /dev/null +++ b/crates/solutions/src/utils.rs @@ -0,0 +1 @@ +pub(crate) mod parsing; diff --git a/src/parsing_utils.rs b/crates/solutions/src/utils/parsing.rs similarity index 100% rename from src/parsing_utils.rs rename to crates/solutions/src/utils/parsing.rs diff --git a/src/iterations.rs b/src/iterations.rs deleted file mode 100644 index d255b0d..0000000 --- a/src/iterations.rs +++ /dev/null @@ -1,70 +0,0 @@ -pub trait AdventIterator: Iterator { - fn into_chunks(self) -> impl Iterator> - where - Self: Sized, - { - in_chunks::(self) - } -} - -impl AdventIterator for I where I: Iterator {} - -#[derive(Debug, PartialEq, Eq)] -pub enum Chunk { - Next([T; N]), - Rest(Vec), -} - -pub fn in_chunks( - mut iterator: impl Iterator, -) -> impl Iterator> { - let mut buffer = Vec::new(); - let mut done = false; - std::iter::from_fn(move || { - if done { - return None; - } - for _ in 0..N { - match iterator.next() { - Some(to_push) => buffer.push(to_push), - None => { - done = true; - return if buffer.is_empty() { - None - } else { - Some(Chunk::Rest(std::mem::take(&mut buffer))) - }; - } - } - } - let array: [T; N] = std::mem::take(&mut buffer) - .try_into() - .unwrap_or_else(|_| panic!("Buffer must have the same size as the N ({})", N)); - Some(Chunk::Next(array)) - }) -} - -#[cfg(test)] -mod testing { - use crate::iterations::{in_chunks, Chunk}; - - #[test] - fn should_split_chunks() { - fn assert_case(input: Vec, expected: Vec>) { - let actual: Vec> = in_chunks::(input.into_iter()).collect(); - assert_eq!(expected, actual); - } - - assert_case::<2>(vec![2], vec![Chunk::Rest(vec![2])]); - assert_case::<2>(vec![], vec![]); - assert_case::<2>(vec![2, 2], vec![Chunk::Next([2, 2])]); - assert_case::<2>( - vec![1, 2, 3], - vec![Chunk::Next([1, 2]), Chunk::Rest(vec![3])], - ); - assert_case::<1>( - vec![1, 2, 3], - vec![Chunk::Next([1]), Chunk::Next([2]), Chunk::Next([3])], - ); - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index fa2c6aa..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod cli; -pub mod constants; -pub mod iterations; -pub mod parsing_utils; -pub mod sequences; -pub mod solutions; diff --git a/src/sequences.rs b/src/sequences.rs deleted file mode 100644 index 681d449..0000000 --- a/src/sequences.rs +++ /dev/null @@ -1,26 +0,0 @@ -pub fn is_sorted(shoube_be_sorted: &[T]) -> bool -where - T: PartialOrd + Ord + Clone + PartialEq + Eq, -{ - let mut sorted: Vec = shoube_be_sorted.into_iter().cloned().collect(); - sorted.sort(); - sorted.as_slice().eq(shoube_be_sorted) -} - -#[cfg(test)] -mod testing { - - #[test] - fn should_detect_if_is_sorted() { - fn assert_case(input: &[u32], expected: bool) { - let actual = super::is_sorted(input); - assert_eq!(expected, actual, "Input {:#?}", input); - } - - assert_case(&[1, 2], true); - assert_case(&[2, 1, 2], false); - assert_case(&[2, 1], false); - assert_case(&[1], true); - assert_case(&[], true); - } -} -- 2.45.3 From 5a98c0541b939a8b36f91f6533c9074aeef50ba8 Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Thu, 29 Aug 2024 19:31:01 +0200 Subject: [PATCH 2/5] Added License --- LICENSE | 17 +++++++++++++++++ TODO.md | 2 -- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9328f9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ +Copyright 2024 BoolPurist + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the “Software”), to deal in the Software without restriction, +including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/TODO.md b/TODO.md index 658a20b..2f2f002 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,3 @@ # TODO -- Add MIT license -- Seperate solution into own library crate - Implment subcommand to execute puzzle input files and print out how every long every one takes -- 2.45.3 From 854f1f1334fbaf883ee28ca4b8107dbef55f18f6 Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Fri, 30 Aug 2024 02:18:02 +0200 Subject: [PATCH 3/5] Implemented benchmark framework --- Cargo.lock | 96 +++++++++++++++++++ TODO.md | 3 - crates/cli/Cargo.toml | 4 + crates/cli/src/benchmarking.rs | 96 +++++++++++++++++++ .../cli/src/benchmarking/benchmark_result.rs | 66 +++++++++++++ .../cli/src/benchmarking/file_to_benchmark.rs | 71 ++++++++++++++ crates/cli/src/benchmarking/row_building.rs | 55 +++++++++++ crates/cli/src/cli.rs | 48 ++++------ crates/cli/src/cli/benchmark_cli.rs | 14 +++ crates/cli/src/cli/cli_solution_to_solve.rs | 32 +++++++ crates/cli/src/cli/given_day.rs | 5 +- crates/cli/src/cli/given_task.rs | 5 +- crates/cli/src/lib.rs | 5 + crates/cli/src/main.rs | 58 +++-------- crates/cli/src/solutions.rs | 6 +- crates/cli/src/solving_given.rs | 51 ++++++++++ ...ay5_example_input.txt => day5_example.txt} | 0 ...ay6_example_input.txt => day6_example.txt} | 0 file_input/example_benchmarks.ron | 38 ++++++++ real_benchmark.ron | 38 ++++++++ 20 files changed, 612 insertions(+), 79 deletions(-) delete mode 100644 TODO.md create mode 100644 crates/cli/src/benchmarking.rs create mode 100644 crates/cli/src/benchmarking/benchmark_result.rs create mode 100644 crates/cli/src/benchmarking/file_to_benchmark.rs create mode 100644 crates/cli/src/benchmarking/row_building.rs create mode 100644 crates/cli/src/cli/benchmark_cli.rs create mode 100644 crates/cli/src/cli/cli_solution_to_solve.rs create mode 100644 crates/cli/src/solving_given.rs rename file_input/{day5_example_input.txt => day5_example.txt} (100%) rename file_input/{day6_example_input.txt => day6_example.txt} (100%) create mode 100644 file_input/example_benchmarks.ron create mode 100644 real_benchmark.ron diff --git a/Cargo.lock b/Cargo.lock index 464cfcb..e7a3585 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,10 +6,14 @@ version = 3 name = "advent_of_code_2023" version = "0.1.0" dependencies = [ + "anyhow", "clap", + "colonnade", "derive_more", "env_logger", "log", + "ron", + "serde", "solutions_advent_of_code_2023", "thiserror", ] @@ -72,6 +76,27 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + [[package]] name = "clap" version = "4.5.16" @@ -112,6 +137,16 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +[[package]] +name = "colonnade" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833230a1f610c0f3418a80b03c387be9de15b1172b3785b702961ead07e3e475" +dependencies = [ + "strip-ansi-escapes", + "unicode-segmentation", +] + [[package]] name = "colorchoice" version = "1.0.2" @@ -297,6 +332,38 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64", + "bitflags", + "serde", + "serde_derive", +] + +[[package]] +name = "serde" +version = "1.0.209" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.209" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "similar" version = "2.6.0" @@ -313,6 +380,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.1" @@ -374,6 +450,26 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 2f2f002..0000000 --- a/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -# TODO -- Implment subcommand to execute puzzle input files and print out how every long every one takes - diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index bbcf323..74454c5 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -8,7 +8,11 @@ solutions_advent_of_code_2023 = { path = "../solutions" } derive_more = { workspace = true } thiserror = { workspace = true } +serde = { version = "1.0.209", features = ["derive"] } clap = { version = "4.5.15", features = ["derive"] } env_logger = "0.11.5" log = "0.4.22" +anyhow = "1.0.86" +ron = "0.8.1" +colonnade = "1.3.3" diff --git a/crates/cli/src/benchmarking.rs b/crates/cli/src/benchmarking.rs new file mode 100644 index 0000000..49a4e49 --- /dev/null +++ b/crates/cli/src/benchmarking.rs @@ -0,0 +1,96 @@ +pub use benchmark_result::BenchmarkResult; +pub use file_to_benchmark::FileToBenchmark; + +mod benchmark_result; +mod file_to_benchmark; +mod row_building; + +use crate::{cli::BenchmarkCli, solving_given::solve_given, AppResult}; +use anyhow::anyhow; +use colonnade::Colonnade; +use std::time::{Duration, Instant}; + +fn calc_average(sum: Duration, nanos_count: u64) -> Duration { + let average_raw = sum.div_duration_f64(Duration::from_nanos(nanos_count)); + Duration::from_nanos(average_raw.round() as u64) +} +pub fn execute_benchmark(args: &BenchmarkCli) -> AppResult { + let loaded = load_benchmarks(args)?; + let benchmarked = loaded + .into_iter() + .map(solve_and_keep_track_of_runtime) + .collect::>>()?; + let sum: Duration = benchmarked.iter().map(|result| result.how_long()).sum(); + let average = calc_average(sum, benchmarked.len() as u64); + let header = row_building::create_header(); + let after_header = row_building::create_rows_for_every_solutions(benchmarked); + let table: Vec> = after_header + .into_iter() + .chain(row_building::create_sum_row(sum)) + .chain(row_building::create_average_row(average)) + .chain(header) + .collect(); + let lines = Colonnade::new(5, 100).unwrap().tabulate(table)?; + + Ok(lines.join("\n")) +} + +fn solve_and_keep_track_of_runtime( + (benchmark, content): (FileToBenchmark, String), +) -> AppResult { + let (day, task) = (benchmark.given_day(), benchmark.given_task()); + let before = Instant::now(); + let actual_ouput = solve_given(day, task, &content)?; + let after = Instant::now(); + + let how_long = after - before; + + let result = BenchmarkResult::new(benchmark, actual_ouput, how_long); + Ok(result) +} + +fn load_benchmarks(args: &BenchmarkCli) -> AppResult> { + let benchmarks = args + .files() + .iter() + .map(|path| { + let content = std::fs::read_to_string(path).map_err(|error| { + anyhow!( + "Could not read benchmark file at {:?}\n\ + Details: {}", + path, + error + ) + })?; + let parsed: Vec = ron::from_str(&content).map_err(|error| { + anyhow!( + "Content of benchmark file at ({:?}) is in an invalid ron format\n\ + Details of invalid format: {}", + path, + error + ) + })?; + Ok(parsed) + }) + .collect::>>>()? + .into_iter() + .flatten(); + + benchmarks + .into_iter() + .map(|benchmark| { + let where_to_look = benchmark.where_to_look(); + let content = std::fs::read_to_string(where_to_look).map_err(|error| { + anyhow!( + "Could not read puzzle input file at {:?} for day {} and task {}\n\ + Details: {}", + where_to_look, + benchmark.given_day(), + benchmark.given_task(), + error + ) + })?; + Ok((benchmark, content)) + }) + .collect::>>() +} diff --git a/crates/cli/src/benchmarking/benchmark_result.rs b/crates/cli/src/benchmarking/benchmark_result.rs new file mode 100644 index 0000000..15d5d17 --- /dev/null +++ b/crates/cli/src/benchmarking/benchmark_result.rs @@ -0,0 +1,66 @@ +use std::time::Duration; + +use crate::cli::{GivenDay, GivenTask}; + +use super::FileToBenchmark; + +#[derive(Debug)] +pub struct BenchmarkResult { + task: GivenTask, + day: GivenDay, + how_long: Duration, + maybe_different_actual_output: Option, + expected_output: String, +} + +impl BenchmarkResult { + pub fn new(benchmarking: FileToBenchmark, actual_ouput: String, how_long: Duration) -> Self { + let (day, task, expected_output) = benchmarking.into(); + let maybe_different_actual_output = if actual_ouput == expected_output { + None + } else { + Some(actual_ouput) + }; + Self { + task, + day, + how_long, + maybe_different_actual_output, + expected_output, + } + } + + pub fn matched_with_expected_output(&self) -> bool { + self.maybe_different_actual_output().is_none() + } + + pub fn task(&self) -> GivenTask { + self.task + } + + pub fn day(&self) -> GivenDay { + self.day + } + + pub fn how_long_as_string(&self) -> String { + Self::convert_duration_to_secs_and_mili_txt(self.how_long) + } + + pub fn maybe_different_actual_output(&self) -> Option<&str> { + self.maybe_different_actual_output.as_deref() + } + + pub fn expected_output(&self) -> &str { + &self.expected_output + } + + pub fn how_long(&self) -> Duration { + self.how_long + } + + pub fn convert_duration_to_secs_and_mili_txt(how_long: Duration) -> String { + let secs = how_long.as_secs(); + let mili_secs = how_long.as_nanos() % 1_000_000_000; + format!("{}:{}", secs, mili_secs) + } +} diff --git a/crates/cli/src/benchmarking/file_to_benchmark.rs b/crates/cli/src/benchmarking/file_to_benchmark.rs new file mode 100644 index 0000000..7208ae9 --- /dev/null +++ b/crates/cli/src/benchmarking/file_to_benchmark.rs @@ -0,0 +1,71 @@ +use std::{ + io, + path::{Path, PathBuf}, + str::FromStr, +}; + +use derive_more::derive::Debug; +use ron::de::SpannedError; +use serde::{Deserialize, Serialize}; + +use crate::cli::{GivenDay, GivenTask}; +use thiserror::Error; + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub struct FileToBenchmark { + given_day: GivenDay, + given_task: GivenTask, + where_to_look: PathBuf, + expected_output: String, +} + +impl Into<(GivenDay, GivenTask, String)> for FileToBenchmark { + fn into(self) -> (GivenDay, GivenTask, String) { + (self.given_day, self.given_task, self.expected_output) + } +} + +impl FromStr for FileToBenchmark { + type Err = CouldNotReadFileToBenchmark; + + fn from_str(s: &str) -> Result { + let path = PathBuf::from(s); + let content = std::fs::read_to_string(&path).map_err(|error| { + if error.kind() == io::ErrorKind::NotFound { + CouldNotReadFileToBenchmark::NotFound(s.to_owned()) + } else { + error.into() + } + })?; + let parsed_content = ron::from_str(&content)?; + Ok(parsed_content) + } +} + +#[derive(Debug, Error)] +pub enum CouldNotReadFileToBenchmark { + #[error("There is not file at {0:?}")] + NotFound(String), + #[error("Coud not read file at.\nDetails: {0}")] + IoError(#[from] io::Error), + #[error("File content is not in the correct format. Details: {0}")] + InvalidRon(#[from] SpannedError), +} + +impl FileToBenchmark { + pub fn given_day(&self) -> GivenDay { + self.given_day + } + + pub fn given_task(&self) -> GivenTask { + self.given_task + } + + pub fn where_to_look(&self) -> &Path { + &self.where_to_look + } + + pub fn expected_output(&self) -> &str { + &self.expected_output + } +} diff --git a/crates/cli/src/benchmarking/row_building.rs b/crates/cli/src/benchmarking/row_building.rs new file mode 100644 index 0000000..ecaef11 --- /dev/null +++ b/crates/cli/src/benchmarking/row_building.rs @@ -0,0 +1,55 @@ +use std::time::Duration; + +use super::BenchmarkResult; +type MatrixReport = Vec>; + +pub fn create_header() -> std::iter::Once> { + std::iter::once(vec![ + "Day".to_string(), + "Task".to_string(), + "How long (Seconds:Mili)".to_string(), + "Expected".to_string(), + "Actual".to_string(), + ]) +} + +pub fn create_sum_row(sum: Duration) -> std::iter::Once> { + let passed_txt = BenchmarkResult::convert_duration_to_secs_and_mili_txt(sum); + std::iter::once(vec![ + "Total".to_string(), + "Total".to_string(), + passed_txt, + "-".to_string(), + "-".to_string(), + ]) +} + +pub fn create_average_row(average: Duration) -> std::iter::Once> { + let passed_txt = BenchmarkResult::convert_duration_to_secs_and_mili_txt(average); + std::iter::once(vec![ + "Average".to_string(), + "Average".to_string(), + passed_txt, + "-".to_string(), + "-".to_string(), + ]) +} + +pub fn create_rows_for_every_solutions(loaded: Vec) -> MatrixReport { + let after_header = loaded + .into_iter() + .map(|result| { + vec![ + result.day().to_string(), + result.task().to_string(), + result.how_long_as_string(), + result.expected_output().to_string(), + result + .maybe_different_actual_output() + .map(|unowned| unowned.to_string()) + .unwrap_or_else(|| result.expected_output().to_string()), + ] + }) + .collect(); + after_header +} diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index 0d067d5..ecafe94 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -1,35 +1,29 @@ -use clap::Parser; -mod given_day; -mod given_task; - +pub use benchmark_cli::BenchmarkCli; +use clap::{Parser, Subcommand}; +pub use cli_solution_to_solve::CliSolutionToSolve; pub use given_day::GivenDay; pub use given_task::GivenTask; +mod benchmark_cli; +mod cli_solution_to_solve; +mod given_day; + +mod given_task; + +#[derive(Debug, Subcommand)] +pub enum AppCliSubcommands { + Solve(CliSolutionToSolve), + Benchmark(BenchmarkCli), +} + #[derive(Debug, Parser)] -pub struct AppCliArguments { - #[arg(short, long)] - day: GivenDay, - #[arg(short, long)] - task: GivenTask, - #[arg(short, long)] - read_as_file: bool, - input: String, +pub struct AppCliArgs { + #[command(subcommand)] + sub_command: AppCliSubcommands, } -impl AppCliArguments { - pub fn day(&self) -> GivenDay { - self.day - } - - pub fn task(&self) -> GivenTask { - self.task - } - - pub fn input(&self) -> &str { - &self.input - } - - pub fn read_as_file(&self) -> bool { - self.read_as_file +impl AppCliArgs { + pub fn sub_command(&self) -> &AppCliSubcommands { + &self.sub_command } } diff --git a/crates/cli/src/cli/benchmark_cli.rs b/crates/cli/src/cli/benchmark_cli.rs new file mode 100644 index 0000000..fd851b0 --- /dev/null +++ b/crates/cli/src/cli/benchmark_cli.rs @@ -0,0 +1,14 @@ +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Debug, Parser)] +pub struct BenchmarkCli { + files: Vec, +} + +impl BenchmarkCli { + pub fn files(&self) -> &[PathBuf] { + &self.files + } +} diff --git a/crates/cli/src/cli/cli_solution_to_solve.rs b/crates/cli/src/cli/cli_solution_to_solve.rs new file mode 100644 index 0000000..a62d17d --- /dev/null +++ b/crates/cli/src/cli/cli_solution_to_solve.rs @@ -0,0 +1,32 @@ +use clap::Parser; + +use super::{GivenDay, GivenTask}; + +#[derive(Debug, Parser)] +pub struct CliSolutionToSolve { + #[arg(short, long)] + day: GivenDay, + #[arg(short, long)] + task: GivenTask, + #[arg(short, long)] + read_as_file: bool, + input: String, +} + +impl CliSolutionToSolve { + pub fn day(&self) -> GivenDay { + self.day + } + + pub fn task(&self) -> GivenTask { + self.task + } + + pub fn input(&self) -> &str { + &self.input + } + + pub fn read_as_file(&self) -> bool { + self.read_as_file + } +} diff --git a/crates/cli/src/cli/given_day.rs b/crates/cli/src/cli/given_day.rs index 7575ca6..26c8556 100644 --- a/crates/cli/src/cli/given_day.rs +++ b/crates/cli/src/cli/given_day.rs @@ -1,6 +1,7 @@ use std::{str::FromStr, sync::Arc}; -use derive_more::derive::Into; +use derive_more::derive::{Display, Into}; +use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::constants; @@ -16,7 +17,7 @@ pub enum InvalidGivenDayError { InvalidRange(u32), } -#[derive(Debug, Copy, Clone, Into, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Into, PartialEq, Eq, Serialize, Deserialize, Display)] pub struct GivenDay(u32); impl GivenDay { diff --git a/crates/cli/src/cli/given_task.rs b/crates/cli/src/cli/given_task.rs index 0b58ae3..3e5a43b 100644 --- a/crates/cli/src/cli/given_task.rs +++ b/crates/cli/src/cli/given_task.rs @@ -1,6 +1,7 @@ use std::{str::FromStr, sync::Arc}; -use derive_more::derive::Into; +use derive_more::derive::{Display, Into}; +use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::constants; @@ -18,7 +19,7 @@ pub enum InvalidGivenTaskError { InvalidRange(u32), } -#[derive(Debug, Copy, Into, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Into, Clone, PartialEq, Eq, Serialize, Deserialize, Display)] pub struct GivenTask(u32); impl GivenTask { diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 5551262..4752be4 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,3 +1,8 @@ +pub mod benchmarking; pub mod cli; pub mod constants; pub mod solutions; +pub mod solving_given; + +pub type AppError = anyhow::Error; +pub type AppResult = anyhow::Result; diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 2eb2275..2a589c4 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,14 +1,17 @@ -use std::{fs, io, path::Path, process::ExitCode}; +use std::process::ExitCode; -use advent_of_code_2023::{cli::AppCliArguments, solutions}; +use advent_of_code_2023::{ + benchmarking::execute_benchmark, + cli::{AppCliArgs, AppCliSubcommands}, + solving_given::solve_given_from_cli, + AppResult, +}; use clap::Parser; -use thiserror::Error; - fn main() -> ExitCode { - let args = AppCliArguments::parse(); + let args = AppCliArgs::parse(); env_logger::init(); - let solution = solve_given(&args); + let solution = handle_command(&args); match solution { Ok(found_solution) => { println!("{}", found_solution); @@ -21,42 +24,9 @@ fn main() -> ExitCode { } } -fn solve_given(args: &AppCliArguments) -> Result { - let all_solutions = solutions::create_solutions(); - - let found_task = { - let day: u32 = args.day().into(); - let task: u32 = args.task().into(); - let found_day = all_solutions - .get(day.saturating_sub(1) as usize) - .ok_or_else(|| CouldNotSolveError::DayNotFound(day))?; - found_day - .get(task.saturating_sub(1) as usize) - .ok_or_else(|| CouldNotSolveError::TaskNotFound { day, task }) - }?; - - let puzzel_input = try_read_from_file_if_demanded(args)?; - let solved = (found_task)(&puzzel_input); - Ok(solved) -} - -fn try_read_from_file_if_demanded(args: &AppCliArguments) -> io::Result { - let content = if args.read_as_file() { - let path = Path::new(args.input()); - let input_as_file = fs::read_to_string(path)?; - input_as_file - } else { - args.input().to_string() - }; - Ok(content) -} - -#[derive(Debug, Error)] -enum CouldNotSolveError { - #[error("There is no solution for the day {0}")] - DayNotFound(u32), - #[error("There is not solution for task {task} under the day {day}")] - TaskNotFound { day: u32, task: u32 }, - #[error("Could not read puzzel input from the given file\n {0}")] - CouldNotReadFromFile(#[from] io::Error), +fn handle_command(args: &AppCliArgs) -> AppResult { + match args.sub_command() { + AppCliSubcommands::Solve(to_solve) => solve_given_from_cli(to_solve), + AppCliSubcommands::Benchmark(benchmark) => execute_benchmark(benchmark), + } } diff --git a/crates/cli/src/solutions.rs b/crates/cli/src/solutions.rs index ca1a777..a508ebd 100644 --- a/crates/cli/src/solutions.rs +++ b/crates/cli/src/solutions.rs @@ -1,8 +1,12 @@ +use std::sync::LazyLock; + use solutions_advent_of_code_2023::day5; use solutions_advent_of_code_2023::day6; use solutions_advent_of_code_2023::day7; -pub fn create_solutions() -> Vec String>> { +pub type SolutionMatrix = Vec String>>; +pub static ALL_SOLUTIONS: LazyLock = LazyLock::new(|| create_solutions()); +fn create_solutions() -> SolutionMatrix { vec![ vec![not_implemented_yet, not_implemented_yet], vec![not_implemented_yet, not_implemented_yet], diff --git a/crates/cli/src/solving_given.rs b/crates/cli/src/solving_given.rs new file mode 100644 index 0000000..575abdb --- /dev/null +++ b/crates/cli/src/solving_given.rs @@ -0,0 +1,51 @@ +use std::{fs, io, path::Path}; +use thiserror::Error; + +use crate::{ + cli::{CliSolutionToSolve, GivenDay, GivenTask}, + solutions::ALL_SOLUTIONS, + AppResult, +}; + +pub fn solve_given(given_day: GivenDay, given_task: GivenTask, content: &str) -> AppResult { + let found_task = { + let day: u32 = given_day.into(); + let task: u32 = given_task.into(); + let found_day = ALL_SOLUTIONS + .get(day.saturating_sub(1) as usize) + .ok_or_else(|| CouldNotSolveError::DayNotFound(day))?; + found_day + .get(task.saturating_sub(1) as usize) + .ok_or_else(|| CouldNotSolveError::TaskNotFound { day, task }) + }?; + + let solved = (found_task)(content); + Ok(solved) +} + +pub fn solve_given_from_cli(args: &CliSolutionToSolve) -> AppResult { + let puzzel_input = try_read_from_file_if_demanded(args)?; + let output = solve_given(args.day(), args.task(), &puzzel_input)?; + Ok(output) +} + +fn try_read_from_file_if_demanded(args: &CliSolutionToSolve) -> io::Result { + let content = if args.read_as_file() { + let path = Path::new(args.input()); + let input_as_file = fs::read_to_string(path)?; + input_as_file + } else { + args.input().to_string() + }; + Ok(content) +} + +#[derive(Debug, Error)] +enum CouldNotSolveError { + #[error("There is no solution for the day {0}")] + DayNotFound(u32), + #[error("There is not solution for task {task} under the day {day}")] + TaskNotFound { day: u32, task: u32 }, + #[error("Could not read puzzel input from the given file\n {0}")] + CouldNotReadFromFile(#[from] io::Error), +} diff --git a/file_input/day5_example_input.txt b/file_input/day5_example.txt similarity index 100% rename from file_input/day5_example_input.txt rename to file_input/day5_example.txt diff --git a/file_input/day6_example_input.txt b/file_input/day6_example.txt similarity index 100% rename from file_input/day6_example_input.txt rename to file_input/day6_example.txt diff --git a/file_input/example_benchmarks.ron b/file_input/example_benchmarks.ron new file mode 100644 index 0000000..f2f53f4 --- /dev/null +++ b/file_input/example_benchmarks.ron @@ -0,0 +1,38 @@ +[ + ( + given_day: GivenDay(5), + given_task: GivenTask(2), + where_to_look: "file_input/day5_example.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(5), + given_task: GivenTask(1), + where_to_look: "file_input/day5_example.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(6), + given_task: GivenTask(1), + where_to_look: "file_input/day6_example.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(6), + given_task: GivenTask(2), + where_to_look: "file_input/day6_example.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(7), + given_task: GivenTask(1), + where_to_look: "file_input/day7_example.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(7), + given_task: GivenTask(2), + where_to_look: "file_input/day7_example.txt", + expected_output: "42", + ), +] diff --git a/real_benchmark.ron b/real_benchmark.ron new file mode 100644 index 0000000..fa7408f --- /dev/null +++ b/real_benchmark.ron @@ -0,0 +1,38 @@ +[ + ( + given_day: GivenDay(5), + given_task: GivenTask(2), + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(5), + given_task: GivenTask(1), + where_to_look: "real_puzzel_input/day5_real.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(6), + given_task: GivenTask(1), + where_to_look: "real_puzzel_input/day6_real.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(6), + given_task: GivenTask(2), + where_to_look: "real_puzzel_input/day6_real.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(7), + given_task: GivenTask(1), + where_to_look: "real_puzzel_input/day7_real.txt", + expected_output: "42", + ), + ( + given_day: GivenDay(7), + given_task: GivenTask(2), + where_to_look: "real_puzzel_input/day7_real.txt", + expected_output: "42", + ), +] -- 2.45.3 From c449b002f8821cb9f6d81ff2051914beb72bf541 Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Fri, 30 Aug 2024 03:06:53 +0200 Subject: [PATCH 4/5] Made solution for day 6 faster --- crates/solutions/src/day6.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/solutions/src/day6.rs b/crates/solutions/src/day6.rs index bd51482..089bf95 100644 --- a/crates/solutions/src/day6.rs +++ b/crates/solutions/src/day6.rs @@ -1,3 +1,5 @@ +use std::usize; + mod parsing; mod race_record; @@ -16,11 +18,34 @@ pub fn solve_task_1(input: &str) -> String { } pub fn solve_task_2(input: &str) -> String { let parsed = parsing::parsing_part_2(input); - let how_many_times_won = all_rounds_of_durations(parsed.time()) + + let time_to_beat = parsed.time(); + assert!(time_to_beat > 1, "Race time must be at least 2"); + const FIRST_AND_LAST_CYCLE_DO_NOT_MOVE: NumericValue = 2; + const HALF_AT_OR_OVER_PEAK: NumericValue = 2; + let range: NumericValue = + (parsed.time() - FIRST_AND_LAST_CYCLE_DO_NOT_MOVE) / HALF_AT_OR_OVER_PEAK; + + const FIRST_CYCLE_NO_DISTANCE: usize = 1; + for (index, next_distance) in all_rounds_of_durations(parsed.time()) .into_iter() - .filter(|&distance| distance > parsed.reached_distance()) - .count() as NumericValue; - how_many_times_won.to_string() + .enumerate() + .skip(FIRST_CYCLE_NO_DISTANCE) + { + if next_distance > parsed.reached_distance() { + const EVEN_TIME_TO_BEAT_LEADS_UNEVEN_PICK: NumericValue = 1; + let one_offset = if time_to_beat % 2 == 0 { + EVEN_TIME_TO_BEAT_LEADS_UNEVEN_PICK + } else { + 0 + }; + let lower_than_distance_over_pick = (index as NumericValue) - 1; + let both_halves = (range - lower_than_distance_over_pick) * 2; + let how_many_times_won = both_halves + one_offset; + return how_many_times_won.to_string(); + } + } + unreachable!(); } fn all_rounds_of_durations(duration: NumericValue) -> Vec { -- 2.45.3 From 331faaa44d69da6b3156ad1cd2eb2f9787f9f2b7 Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Fri, 30 Aug 2024 03:17:49 +0200 Subject: [PATCH 5/5] Fixed clippy warnings --- crates/cli/src/benchmarking/file_to_benchmark.rs | 6 +++--- crates/cli/src/benchmarking/row_building.rs | 5 ++--- crates/cli/src/cli/given_day.rs | 6 +++--- crates/cli/src/cli/given_task.rs | 6 +++--- crates/cli/src/solving_given.rs | 3 +-- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/crates/cli/src/benchmarking/file_to_benchmark.rs b/crates/cli/src/benchmarking/file_to_benchmark.rs index 7208ae9..c365093 100644 --- a/crates/cli/src/benchmarking/file_to_benchmark.rs +++ b/crates/cli/src/benchmarking/file_to_benchmark.rs @@ -19,9 +19,9 @@ pub struct FileToBenchmark { expected_output: String, } -impl Into<(GivenDay, GivenTask, String)> for FileToBenchmark { - fn into(self) -> (GivenDay, GivenTask, String) { - (self.given_day, self.given_task, self.expected_output) +impl From for (GivenDay, GivenTask, String) { + fn from(val: FileToBenchmark) -> Self { + (val.given_day, val.given_task, val.expected_output) } } diff --git a/crates/cli/src/benchmarking/row_building.rs b/crates/cli/src/benchmarking/row_building.rs index ecaef11..d068981 100644 --- a/crates/cli/src/benchmarking/row_building.rs +++ b/crates/cli/src/benchmarking/row_building.rs @@ -36,7 +36,7 @@ pub fn create_average_row(average: Duration) -> std::iter::Once> { } pub fn create_rows_for_every_solutions(loaded: Vec) -> MatrixReport { - let after_header = loaded + loaded .into_iter() .map(|result| { vec![ @@ -50,6 +50,5 @@ pub fn create_rows_for_every_solutions(loaded: Vec) -> MatrixRe .unwrap_or_else(|| result.expected_output().to_string()), ] }) - .collect(); - after_header + .collect() } diff --git a/crates/cli/src/cli/given_day.rs b/crates/cli/src/cli/given_day.rs index 26c8556..9fa8ac4 100644 --- a/crates/cli/src/cli/given_day.rs +++ b/crates/cli/src/cli/given_day.rs @@ -22,10 +22,10 @@ pub struct GivenDay(u32); impl GivenDay { pub fn new(value: u32) -> Result { - if value < 1 || value > constants::MAX_DAY { - Err(InvalidGivenDayError::InvalidRange(value)) - } else { + if (1..=constants::MAX_DAY).contains(&value) { Ok(Self(value)) + } else { + Err(InvalidGivenDayError::InvalidRange(value)) } } } diff --git a/crates/cli/src/cli/given_task.rs b/crates/cli/src/cli/given_task.rs index 3e5a43b..2a4fe59 100644 --- a/crates/cli/src/cli/given_task.rs +++ b/crates/cli/src/cli/given_task.rs @@ -24,10 +24,10 @@ pub struct GivenTask(u32); impl GivenTask { pub fn new(value: u32) -> Result { - if value < 1 || value > constants::MAX_TASK { - Err(InvalidGivenTaskError::InvalidRange(value)) - } else { + if (1..=constants::MAX_TASK).contains(&value) { Ok(Self(value)) + } else { + Err(InvalidGivenTaskError::InvalidRange(value)) } } } diff --git a/crates/cli/src/solving_given.rs b/crates/cli/src/solving_given.rs index 575abdb..24f7a28 100644 --- a/crates/cli/src/solving_given.rs +++ b/crates/cli/src/solving_given.rs @@ -32,8 +32,7 @@ pub fn solve_given_from_cli(args: &CliSolutionToSolve) -> AppResult { fn try_read_from_file_if_demanded(args: &CliSolutionToSolve) -> io::Result { let content = if args.read_as_file() { let path = Path::new(args.input()); - let input_as_file = fs::read_to_string(path)?; - input_as_file + fs::read_to_string(path)? } else { args.input().to_string() }; -- 2.45.3