From 74f46dcbf5a2944ff439b1d9633b9bff9c2717ac Mon Sep 17 00:00:00 2001 From: Vest Date: Wed, 25 Jan 2023 02:31:25 -0800 Subject: [PATCH] Updated Cargo dependencies Formatted code Corrected errors after new changes --- Cargo.lock | 475 ++++++++++++++++-------------- adv2015/Cargo.toml | 8 +- adv2015/src/day1.rs | 1 - adv2015/src/day10.rs | 1 - adv2015/src/day11.rs | 44 ++- adv2015/src/day12.rs | 32 +- adv2015/src/day13.rs | 445 ++++++++++++++-------------- adv2015/src/day14.rs | 72 +++-- adv2015/src/day15.rs | 18 +- adv2015/src/day16.rs | 140 ++++++--- adv2015/src/day17.rs | 60 ++-- adv2015/src/day18.rs | 28 +- adv2015/src/day19.rs | 499 ++++++++++++++++--------------- adv2015/src/day2.rs | 10 +- adv2015/src/day20.rs | 29 +- adv2015/src/day21.rs | 169 +++++++++-- adv2015/src/day22.rs | 176 ++++++++--- adv2015/src/day23.rs | 79 +++-- adv2015/src/day24.rs | 34 ++- adv2015/src/day25.rs | 278 +++++++++--------- adv2015/src/day3.rs | 22 +- adv2015/src/day4.rs | 27 +- adv2015/src/day5.rs | 90 +++--- adv2015/src/day6.rs | 331 +++++++++++++++------ adv2015/src/day7.rs | 584 ++++++++++++++++++++++++++++--------- adv2015/src/day8.rs | 54 ++-- adv2015/src/day9.rs | 48 +-- adv2015/src/lib.rs | 296 +++++++++++++------ adv2020/Cargo.toml | 4 +- adv2020/src/day1.rs | 21 +- adv2020/src/day10.rs | 68 +++-- adv2020/src/day11.rs | 96 +++--- adv2020/src/day12.rs | 146 +++++----- adv2020/src/day13.rs | 68 +++-- adv2020/src/day14.rs | 173 ++++++----- adv2020/src/day15.rs | 26 +- adv2020/src/day16.rs | 89 +++--- adv2020/src/day17.rs | 51 ++-- adv2020/src/day2.rs | 61 ++-- adv2020/src/day3.rs | 24 +- adv2020/src/day4.rs | 134 ++++++--- adv2020/src/day5.rs | 66 ++--- adv2020/src/day6.rs | 44 ++- adv2020/src/day7.rs | 69 +++-- adv2020/src/day8.rs | 9 +- adv2020/src/day9.rs | 59 ++-- adv2020/src/lib.rs | 142 +++++++-- adventofcode/Cargo.toml | 4 +- adventofcode/src/advent.rs | 14 +- adventofcode/src/main.rs | 57 ++-- 50 files changed, 3368 insertions(+), 2107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d31c168..4763a92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "adv2015" -version = "0.25.1" +version = "0.25.2" dependencies = [ "combinations", "divisors", @@ -16,7 +16,7 @@ dependencies = [ [[package]] name = "adv2020" -version = "0.17.0" +version = "0.17.1" dependencies = [ "combinations", "itertools", @@ -24,7 +24,7 @@ dependencies = [ [[package]] name = "adventofcode" -version = "0.2.17" +version = "0.2.18" dependencies = [ "adv2015", "adv2020", @@ -34,24 +34,13 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -60,9 +49,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bitflags" @@ -72,21 +61,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytes" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cfg-if" @@ -96,24 +85,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.18" +version = "4.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" dependencies = [ - "atty", "bitflags", "clap_lex", - "indexmap", + "is-terminal", "strsim", "termcolor", - "textwrap", ] [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" dependencies = [ "os_str_bytes", ] @@ -151,9 +138,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 = "encoding_rs" @@ -164,11 +151,32 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -196,52 +204,51 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-io", @@ -254,20 +261,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "h2" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -284,15 +291,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "libc", ] @@ -321,9 +328,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -333,9 +340,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.19" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", @@ -370,20 +377,19 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -398,32 +404,54 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "ipnet" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + +[[package]] +name = "is-terminal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] [[package]] name = "itertools" -version = "0.9.0" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -436,9 +464,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "log" @@ -449,12 +483,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "md5" version = "0.7.0" @@ -475,21 +503,21 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -582,9 +610,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ "hermit-abi", "libc", @@ -592,15 +620,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if", @@ -630,9 +658,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg", "cc", @@ -643,21 +671,21 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "permute" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add5cf6a6a9e572d398fc2e73500305c18b6eb66c46cc730ee3737025a4e9209" +checksum = "4fddb8f2cf68c74002bde337a2472e18c870e3464b1f637cc9718f51687e88ca" [[package]] name = "pin-project-lite" @@ -673,52 +701,50 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom", "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -726,36 +752,27 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.5.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.6" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -764,9 +781,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -779,9 +796,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "base64", "bytes", @@ -795,10 +812,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "serde", @@ -806,6 +823,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -813,27 +831,40 @@ dependencies = [ "winreg", ] +[[package]] +name = "rustix" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", "windows-sys", ] [[package]] name = "security-framework" -version = "2.6.1" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721" dependencies = [ "bitflags", "core-foundation", @@ -844,9 +875,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -854,15 +885,15 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.137" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -883,15 +914,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -905,9 +939,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -930,19 +964,13 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - [[package]] name = "tinyvec" version = "1.6.0" @@ -960,19 +988,19 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", - "once_cell", "pin-project-lite", "socket2", - "winapi", + "windows-sys", ] [[package]] @@ -987,9 +1015,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -1001,15 +1029,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", @@ -1018,49 +1046,48 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -1080,12 +1107,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1094,9 +1115,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1104,13 +1125,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1119,9 +1140,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if", "js-sys", @@ -1131,9 +1152,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1141,9 +1162,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -1154,15 +1175,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -1201,46 +1222,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "winreg" diff --git a/adv2015/Cargo.toml b/adv2015/Cargo.toml index 0d927bc..c8c0c69 100644 --- a/adv2015/Cargo.toml +++ b/adv2015/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adv2015" -version = "0.25.1" +version = "0.25.2" authors = ["Vest "] edition = "2018" @@ -13,8 +13,8 @@ doc = false [dependencies] md5 = "0.7.0" -permute = "0.1.0" +permute = "0.2.1" combinations = "0.1.0" -regex = "1.4.2" -rand = "0.7.3" +regex = "1.7.1" +rand = "0.8.5" divisors = "0.2.1" diff --git a/adv2015/src/day1.rs b/adv2015/src/day1.rs index b92b127..9113a78 100644 --- a/adv2015/src/day1.rs +++ b/adv2015/src/day1.rs @@ -67,4 +67,3 @@ mod tests { assert_eq!(count_position("()()("), None); } } - diff --git a/adv2015/src/day10.rs b/adv2015/src/day10.rs index a49ca0a..1224b45 100644 --- a/adv2015/src/day10.rs +++ b/adv2015/src/day10.rs @@ -69,4 +69,3 @@ mod tests { assert_eq!(calc_length(&"1".to_string(), 5), 6, "Length of 312211 is 6"); } } - diff --git a/adv2015/src/day11.rs b/adv2015/src/day11.rs index f4cf410..387027c 100644 --- a/adv2015/src/day11.rs +++ b/adv2015/src/day11.rs @@ -18,14 +18,14 @@ struct Password { impl Password { fn new_str(input: &str) -> Password { Password { - state: String::from(input) + state: String::from(input), } } #[allow(dead_code)] fn new() -> Password { let mut pwd = Password { - state: String::with_capacity(MAX_LENGTH) + state: String::with_capacity(MAX_LENGTH), }; for _ in 0..MAX_LENGTH { @@ -86,7 +86,11 @@ fn is_increased(input: &str) -> bool { let prev_ascii = prev_char.unwrap() as u8; let c_ascii = c as u8; - count = if c_ascii.checked_sub(prev_ascii) == Some(1) { count + 1 } else { 1 }; + count = if c_ascii.checked_sub(prev_ascii) == Some(1) { + count + 1 + } else { + 1 + }; if count == 3 { return true; @@ -99,9 +103,7 @@ fn is_increased(input: &str) -> bool { } fn is_not_confusing(input: &str) -> bool { - !input.contains(|c| { - c == 'i' || c == 'o' || c == 'l' - }) + !input.contains(|c| c == 'i' || c == 'o' || c == 'l') } fn has_pairs(input: &str) -> bool { @@ -159,7 +161,10 @@ mod tests { let pwd = Password::new(); let pwd_str = pwd.get_password(); - assert_eq!(pwd_str, "aaaaaaaa", "Expected a string with eight 'a' chars"); + assert_eq!( + pwd_str, "aaaaaaaa", + "Expected a string with eight 'a' chars" + ); } #[test] @@ -169,7 +174,10 @@ mod tests { { let pwd_str = pwd.get_password(); - assert_eq!(pwd_str, "aaaaaaab", "Expected a string with seven 'a' chars and one 'b'"); + assert_eq!( + pwd_str, "aaaaaaab", + "Expected a string with seven 'a' chars and one 'b'" + ); } pwd.inc(); pwd.inc(); @@ -178,7 +186,10 @@ mod tests { { let pwd_str = pwd.get_password(); - assert_eq!(pwd_str, "aaaaaaaf", "Expected a string with seven 'a' chars and one 'f'"); + assert_eq!( + pwd_str, "aaaaaaaf", + "Expected a string with seven 'a' chars and one 'f'" + ); } } @@ -188,7 +199,10 @@ mod tests { pwd.inc(); let pwd_str = pwd.get_password(); - assert_eq!(pwd_str, "zzzzzzzz", "Expected a string with eight 'z' chars"); + assert_eq!( + pwd_str, "zzzzzzzz", + "Expected a string with eight 'z' chars" + ); } #[test] @@ -197,14 +211,20 @@ mod tests { pwd.inc(); let pwd_str = pwd.get_password(); - assert_eq!(pwd_str, "aaaaaaaa", "Expected a string with eight 'a' chars"); + assert_eq!( + pwd_str, "aaaaaaaa", + "Expected a string with eight 'a' chars" + ); } #[test] fn test_password_iter() { let mut pwd = Password::new(); while let Some(pass) = pwd.next() { - assert_eq!(pass, "aaaaaaab", "Expected a string with seven 'a' chars and one 'b'"); + assert_eq!( + pass, "aaaaaaab", + "Expected a string with seven 'a' chars and one 'b'" + ); break; } } diff --git a/adv2015/src/day12.rs b/adv2015/src/day12.rs index ac2b2ce..30da9ee 100644 --- a/adv2015/src/day12.rs +++ b/adv2015/src/day12.rs @@ -12,9 +12,10 @@ pub fn get_answer_without_red(input: &str) -> i32 { } fn extract_numbers(input: &str) -> Vec { - input.split_terminator(|c| { - c == '[' || c == ']' || c == ',' || c == '"' || c == ':' || c == '{' || c == '}' - }) + input + .split_terminator(|c| { + c == '[' || c == ']' || c == ',' || c == '"' || c == ':' || c == '{' || c == '}' + }) .filter(|s| !s.is_empty()) .map(|s| s.parse::()) .filter(|p| p.is_ok()) @@ -23,8 +24,7 @@ fn extract_numbers(input: &str) -> Vec { } fn sum_numbers(input: &Vec) -> i32 { - input.iter() - .sum() + input.iter().sum() } fn find_first_json_object(input: &str) -> &str { @@ -57,7 +57,11 @@ fn scan_deep(input: &str) -> i32 { let res = find_first_json_object(input); if res == "" { - return if input.contains(r#":"red""#) { 0 } else { get_answer(input) }; + return if input.contains(r#":"red""#) { + 0 + } else { + get_answer(input) + }; } if let Some(i) = input.find(res) { @@ -142,7 +146,6 @@ mod tests { assert_eq!(sum, 6); } - #[test] fn test_sum_numbers_2() { let res = extract_numbers(r#"[]"#); @@ -152,10 +155,19 @@ mod tests { #[test] fn test_find_json_object() { - assert_eq!(find_first_json_object(r#"[1,{"c":"red","b":2},3]"#), r#"{"c":"red","b":2}"#); - assert_eq!(find_first_json_object(r#"[1,{"c":"red",{"a":1},"b":2},3]"#), r#"{"c":"red",{"a":1},"b":2}"#); + assert_eq!( + find_first_json_object(r#"[1,{"c":"red","b":2},3]"#), + r#"{"c":"red","b":2}"# + ); + assert_eq!( + find_first_json_object(r#"[1,{"c":"red",{"a":1},"b":2},3]"#), + r#"{"c":"red",{"a":1},"b":2}"# + ); assert_eq!(find_first_json_object(r#"[1,3]"#), r#""#); - assert_eq!(find_first_json_object(r#"{"d":"red","e":[1,2,3,4],"f":5}"#), r#"{"d":"red","e":[1,2,3,4],"f":5}"#); + assert_eq!( + find_first_json_object(r#"{"d":"red","e":[1,2,3,4],"f":5}"#), + r#"{"d":"red","e":[1,2,3,4],"f":5}"# + ); } #[test] diff --git a/adv2015/src/day13.rs b/adv2015/src/day13.rs index 4d6a833..e22689b 100644 --- a/adv2015/src/day13.rs +++ b/adv2015/src/day13.rs @@ -1,215 +1,230 @@ -use std::collections::{HashMap, HashSet}; -use permute::permutations_of; -use std::cmp::max; - -pub fn get_answer(input: &str) -> i32 { - calculate_everyone(input) -} - -pub fn get_answer_with_me(input: &str) -> i32 { - calculate_everyone_and_me(input) -} - -struct PersonToPerson { - who: String, - next: String, - attitude: i32, -} - -fn parse_line(input: &str) -> PersonToPerson { - let mut split = input.split_whitespace(); - let who = split.next().unwrap(); // name - split.next(); // would - let verb = split.next().unwrap(); // gain/lose - let attitude = split.next().unwrap().parse::().unwrap() * if verb == "lose" { -1 } else { 1 }; // amount * verb - split.next(); // happiness - split.next(); // units - split.next(); // by - split.next(); // sitting - split.next(); // next - split.next(); // to - let mut next = String::from(split.next().unwrap()); // name, with . at the end. - next.pop(); - - PersonToPerson { - who: String::from(who), - next, - attitude, - } -} - -fn parse_input(input: &str) -> Vec { - let vec: Vec = input.lines() - .map(|line| parse_line(line)) - .collect(); - - vec -} - -fn build_relationships(input: &Vec) -> HashMap<(String, String), i32> { - let mut hash_map: HashMap<(String, String), i32> = HashMap::with_capacity(10); - - for person in input { - hash_map.insert((person.who.clone(), person.next.clone()), person.attitude); - } - - hash_map -} - -fn extract_names(input: &Vec) -> HashSet { - let mut hash_set: HashSet = HashSet::with_capacity(5); - - input.iter().for_each(|person| { hash_set.insert(person.who.clone()); }); - - hash_set -} - -fn calculate_happiness(people: &Vec, relationship: &HashMap<(String, String), i32>) -> i32 { - let mut result = 0i32; - let mut previous = String::from(people.last().unwrap()); - - for current in people.iter() { - result += relationship[&(previous.clone(), current.clone())]; - result += relationship[&(current.clone(), previous.clone())]; - previous = current.clone(); - } - - result -} - -fn calculate_happiness_with_me(people: &Vec, relationship: &HashMap<(String, String), i32>) -> i32 { - let mut result = 0i32; - let mut previous = String::from(people.last().unwrap()); - - for current in people.iter() { - if current.eq("Me") || previous.eq("Me") { - previous = current.clone(); - continue; - } - - result += relationship[&(previous.clone(), current.clone())]; - result += relationship[&(current.clone(), previous.clone())]; - previous = current.clone(); - } - - result -} - -fn calculate_everyone(input: &str) -> i32 { - let people = parse_input(input); - let relationship = build_relationships(&people); - let table: Vec = extract_names(&people).iter().map(|n| (*n).clone()).collect(); - - let mut result = 0i32; - - for permutation in permutations_of(&table) { - let guessed_table: Vec = permutation.map(|n| (*n).clone()).collect(); - - let current_happiness = calculate_happiness(&guessed_table, &relationship); - result = max(result, current_happiness); - } - - result -} - -fn calculate_everyone_and_me(input: &str) -> i32 { - let people = parse_input(input); - let relationship = build_relationships(&people); - let mut table: Vec = extract_names(&people).iter().map(|n| (*n).clone()).collect(); - table.push("Me".to_string()); - - let mut result = 0i32; - - for permutation in permutations_of(&table) { - let guessed_table: Vec = permutation.map(|n| (*n).clone()).collect(); - - let current_happiness = calculate_happiness_with_me(&guessed_table, &relationship); - result = max(result, current_happiness); - } - - result -} - -#[cfg(test)] -mod tests { - use super::*; - - const INPUT: &'static str = r#"Alice would gain 54 happiness units by sitting next to Bob. - Alice would lose 79 happiness units by sitting next to Carol. - Alice would lose 2 happiness units by sitting next to David. - Bob would gain 83 happiness units by sitting next to Alice. - Bob would lose 7 happiness units by sitting next to Carol. - Bob would lose 63 happiness units by sitting next to David. - Carol would lose 62 happiness units by sitting next to Alice. - Carol would gain 60 happiness units by sitting next to Bob. - Carol would gain 55 happiness units by sitting next to David. - David would gain 46 happiness units by sitting next to Alice. - David would lose 7 happiness units by sitting next to Bob. - David would gain 41 happiness units by sitting next to Carol."#; - - #[test] - fn test_parse_line_1() { - let result = parse_line("Alice would gain 54 happiness units by sitting next to Bob."); - assert_eq!(result.who, "Alice"); - assert_eq!(result.next, "Bob"); - assert_eq!(result.attitude, 54); - } - - #[test] - fn test_parse_line_2() { - let result = parse_line("Alice would lose 79 happiness units by sitting next to Carol."); - assert_eq!(result.who, "Alice"); - assert_eq!(result.next, "Carol"); - assert_eq!(result.attitude, -79); - } - - #[test] - fn test_parse_input() { - let result = parse_input(INPUT); - let single_line = result.get(10).unwrap(); - - assert_eq!(result.len(), 12); - assert_eq!(single_line.who, "David"); - assert_eq!(single_line.next, "Bob"); - assert_eq!(single_line.attitude, -7); - } - - #[test] - fn test_build_relationships() { - let result = parse_input(INPUT); - let hash_map = build_relationships(&result); - - let key = (String::from("David"), String::from("Bob")); // David -> Bob - - assert_eq!(hash_map.len(), 12); - assert_eq!(hash_map[&key], -7); - } - - #[test] - fn test_extract_names() { - let result = parse_input(INPUT); - let people = extract_names(&result); - - assert_eq!(people.len(), 4); - assert!(people.contains("Alice")); - assert!(people.contains("Bob")); - assert!(people.contains("Carol")); - assert!(people.contains("David")); - } - - #[test] - fn test_calculate_happiness() { - let people = parse_input(INPUT); - let hash_map = build_relationships(&people); - let table: Vec = vec!["Alice".to_string(), "Bob".to_string(), "Carol".to_string(), "David".to_string()]; - - let result = calculate_happiness(&table, &hash_map); - assert_eq!(result, 330); - } - - #[test] - fn test_calculate_everyone() { - let result = calculate_everyone(INPUT); - assert_eq!(result, 330); - } -} \ No newline at end of file +use permute::permutations_of; +use std::cmp::max; +use std::collections::{HashMap, HashSet}; + +pub fn get_answer(input: &str) -> i32 { + calculate_everyone(input) +} + +pub fn get_answer_with_me(input: &str) -> i32 { + calculate_everyone_and_me(input) +} + +struct PersonToPerson { + who: String, + next: String, + attitude: i32, +} + +fn parse_line(input: &str) -> PersonToPerson { + let mut split = input.split_whitespace(); + let who = split.next().unwrap(); // name + split.next(); // would + let verb = split.next().unwrap(); // gain/lose + let attitude = + split.next().unwrap().parse::().unwrap() * if verb == "lose" { -1 } else { 1 }; // amount * verb + split.next(); // happiness + split.next(); // units + split.next(); // by + split.next(); // sitting + split.next(); // next + split.next(); // to + let mut next = String::from(split.next().unwrap()); // name, with . at the end. + next.pop(); + + PersonToPerson { + who: String::from(who), + next, + attitude, + } +} + +fn parse_input(input: &str) -> Vec { + let vec: Vec = input.lines().map(|line| parse_line(line)).collect(); + + vec +} + +fn build_relationships(input: &Vec) -> HashMap<(String, String), i32> { + let mut hash_map: HashMap<(String, String), i32> = HashMap::with_capacity(10); + + for person in input { + hash_map.insert((person.who.clone(), person.next.clone()), person.attitude); + } + + hash_map +} + +fn extract_names(input: &Vec) -> HashSet { + let mut hash_set: HashSet = HashSet::with_capacity(5); + + input.iter().for_each(|person| { + hash_set.insert(person.who.clone()); + }); + + hash_set +} + +fn calculate_happiness(people: &Vec, relationship: &HashMap<(String, String), i32>) -> i32 { + let mut result = 0i32; + let mut previous = String::from(people.last().unwrap()); + + for current in people.iter() { + result += relationship[&(previous.clone(), current.clone())]; + result += relationship[&(current.clone(), previous.clone())]; + previous = current.clone(); + } + + result +} + +fn calculate_happiness_with_me( + people: &Vec, + relationship: &HashMap<(String, String), i32>, +) -> i32 { + let mut result = 0i32; + let mut previous = String::from(people.last().unwrap()); + + for current in people.iter() { + if current.eq("Me") || previous.eq("Me") { + previous = current.clone(); + continue; + } + + result += relationship[&(previous.clone(), current.clone())]; + result += relationship[&(current.clone(), previous.clone())]; + previous = current.clone(); + } + + result +} + +fn calculate_everyone(input: &str) -> i32 { + let people = parse_input(input); + let relationship = build_relationships(&people); + let table: Vec = extract_names(&people) + .iter() + .map(|n| (*n).clone()) + .collect(); + + let mut result = 0i32; + + for permutation in permutations_of(&table) { + let guessed_table: Vec = permutation.map(|n| (*n).clone()).collect(); + + let current_happiness = calculate_happiness(&guessed_table, &relationship); + result = max(result, current_happiness); + } + + result +} + +fn calculate_everyone_and_me(input: &str) -> i32 { + let people = parse_input(input); + let relationship = build_relationships(&people); + let mut table: Vec = extract_names(&people) + .iter() + .map(|n| (*n).clone()) + .collect(); + table.push("Me".to_string()); + + let mut result = 0i32; + + for permutation in permutations_of(&table) { + let guessed_table: Vec = permutation.map(|n| (*n).clone()).collect(); + + let current_happiness = calculate_happiness_with_me(&guessed_table, &relationship); + result = max(result, current_happiness); + } + + result +} + +#[cfg(test)] +mod tests { + use super::*; + + const INPUT: &'static str = r#"Alice would gain 54 happiness units by sitting next to Bob. + Alice would lose 79 happiness units by sitting next to Carol. + Alice would lose 2 happiness units by sitting next to David. + Bob would gain 83 happiness units by sitting next to Alice. + Bob would lose 7 happiness units by sitting next to Carol. + Bob would lose 63 happiness units by sitting next to David. + Carol would lose 62 happiness units by sitting next to Alice. + Carol would gain 60 happiness units by sitting next to Bob. + Carol would gain 55 happiness units by sitting next to David. + David would gain 46 happiness units by sitting next to Alice. + David would lose 7 happiness units by sitting next to Bob. + David would gain 41 happiness units by sitting next to Carol."#; + + #[test] + fn test_parse_line_1() { + let result = parse_line("Alice would gain 54 happiness units by sitting next to Bob."); + assert_eq!(result.who, "Alice"); + assert_eq!(result.next, "Bob"); + assert_eq!(result.attitude, 54); + } + + #[test] + fn test_parse_line_2() { + let result = parse_line("Alice would lose 79 happiness units by sitting next to Carol."); + assert_eq!(result.who, "Alice"); + assert_eq!(result.next, "Carol"); + assert_eq!(result.attitude, -79); + } + + #[test] + fn test_parse_input() { + let result = parse_input(INPUT); + let single_line = result.get(10).unwrap(); + + assert_eq!(result.len(), 12); + assert_eq!(single_line.who, "David"); + assert_eq!(single_line.next, "Bob"); + assert_eq!(single_line.attitude, -7); + } + + #[test] + fn test_build_relationships() { + let result = parse_input(INPUT); + let hash_map = build_relationships(&result); + + let key = (String::from("David"), String::from("Bob")); // David -> Bob + + assert_eq!(hash_map.len(), 12); + assert_eq!(hash_map[&key], -7); + } + + #[test] + fn test_extract_names() { + let result = parse_input(INPUT); + let people = extract_names(&result); + + assert_eq!(people.len(), 4); + assert!(people.contains("Alice")); + assert!(people.contains("Bob")); + assert!(people.contains("Carol")); + assert!(people.contains("David")); + } + + #[test] + fn test_calculate_happiness() { + let people = parse_input(INPUT); + let hash_map = build_relationships(&people); + let table: Vec = vec![ + "Alice".to_string(), + "Bob".to_string(), + "Carol".to_string(), + "David".to_string(), + ]; + + let result = calculate_happiness(&table, &hash_map); + assert_eq!(result, 330); + } + + #[test] + fn test_calculate_everyone() { + let result = calculate_everyone(INPUT); + assert_eq!(result, 330); + } +} diff --git a/adv2015/src/day14.rs b/adv2015/src/day14.rs index eec72ec..a018b08 100644 --- a/adv2015/src/day14.rs +++ b/adv2015/src/day14.rs @@ -26,8 +26,7 @@ struct RangiferTarandus { fn parse_line(input: &str) -> RangiferTarandus { let mut split = input.split_whitespace(); let name = String::from(split.next().unwrap()); - let numbers: Vec = split.filter_map(|s| s.parse().ok()) - .collect(); + let numbers: Vec = split.filter_map(|s| s.parse().ok()).collect(); RangiferTarandus { _name: name, @@ -55,7 +54,8 @@ fn calculate_deer(deer: &RangiferTarandus, time: usize) -> usize { } fn find_fastest_deer(input: &str, total: usize) -> usize { - input.lines() + input + .lines() .map(|l| parse_line(l)) .map(|d| calculate_deer(&d, total)) .max() @@ -63,48 +63,43 @@ fn find_fastest_deer(input: &str, total: usize) -> usize { } fn deer_race(input: &str, duration: usize) -> usize { - let mut deers: Vec = input.lines() - .map(|l| parse_line(l)) - .collect(); + let mut deers: Vec = input.lines().map(|l| parse_line(l)).collect(); for _ in 0..duration + 1 { - deers.iter_mut() - .for_each(|d| { - if d.running_time == d.endurance { - d.is_running = false; - d.sleeping_time = 0; - d.running_time = 0; - } - - if d.sleeping_time == d.sleep { - d.is_running = true; - d.sleeping_time = 0; - d.running_time = 0; - } - - if d.is_running { - d.distance += d.speed; - d.running_time += 1; - } else { - d.sleeping_time += 1; - } - }); - - if let Some(max_distance) = deers.iter() - .map(|d| d.distance) - .max() { - deers.iter_mut() + deers.iter_mut().for_each(|d| { + if d.running_time == d.endurance { + d.is_running = false; + d.sleeping_time = 0; + d.running_time = 0; + } + + if d.sleeping_time == d.sleep { + d.is_running = true; + d.sleeping_time = 0; + d.running_time = 0; + } + + if d.is_running { + d.distance += d.speed; + d.running_time += 1; + } else { + d.sleeping_time += 1; + } + }); + + if let Some(max_distance) = deers.iter().map(|d| d.distance).max() { + deers + .iter_mut() .filter(|d| d.distance == max_distance) .for_each(|d| d.points += 1); } } - return if let Some(deer) = deers.iter() - .max_by_key(|d| d.points) { + return if let Some(deer) = deers.iter().max_by_key(|d| d.points) { deer.points } else { 0 - } + }; } #[cfg(test)] @@ -124,8 +119,11 @@ mod tests { #[test] fn test_calculate_deer() { - let input1 = parse_line("Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds."); - let input2 = parse_line("Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds."); + let input1 = + parse_line("Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds."); + let input2 = parse_line( + "Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds.", + ); let result1 = calculate_deer(&input1, 1000); let result2 = calculate_deer(&input2, 1000); diff --git a/adv2015/src/day15.rs b/adv2015/src/day15.rs index 4f328c8..63fd1f0 100644 --- a/adv2015/src/day15.rs +++ b/adv2015/src/day15.rs @@ -25,7 +25,8 @@ struct Ingredient { } fn parse_line(input: &str) -> Ingredient { - let everything: Vec<&str> = input.split(|c: char| c == ':' || c == ',' || c.is_whitespace()) + let everything: Vec<&str> = input + .split(|c: char| c == ':' || c == ',' || c.is_whitespace()) .filter(|s| !s.is_empty()) // remove empty results, we don't need them .collect(); let name = everything[0]; @@ -46,9 +47,7 @@ fn parse_line(input: &str) -> Ingredient { } fn parse_lines(input: &str) -> Vec { - input.lines() - .map(|line| parse_line(line)) - .collect() + input.lines().map(|line| parse_line(line)).collect() } fn calc_spoons(ingredients: &Vec, spoons: &Vec) -> usize { @@ -141,7 +140,8 @@ fn find_spoons_with_calories(ingredients: &Vec) -> Vec { spoons[spoons_count - 1] = 100 - total; - let calories: i32 = spoons.iter() + let calories: i32 = spoons + .iter() .enumerate() .map(|(i, s)| ingredients[i].calories * s) .sum(); @@ -158,14 +158,14 @@ fn find_spoons_with_calories(ingredients: &Vec) -> Vec { result } - #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_line() { - let result = parse_line("Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8"); + let result = + parse_line("Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8"); assert_eq!(result.name, String::from("Butterscotch")); assert_eq!(result.capacity, -1); @@ -185,7 +185,7 @@ mod tests { #[test] fn test_calc_spoons() { let ingredients = parse_lines("Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8\nCinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3"); - let spoons = vec!(44, 56); + let spoons = vec![44, 56]; let result = calc_spoons(&ingredients, &spoons); assert_eq!(result, 62842880); @@ -222,4 +222,4 @@ mod tests { let result = get_answer_with_calories("Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8\nCinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3"); assert_eq!(result, 57600000); } -} \ No newline at end of file +} diff --git a/adv2015/src/day16.rs b/adv2015/src/day16.rs index 2ed698b..ed22d35 100644 --- a/adv2015/src/day16.rs +++ b/adv2015/src/day16.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use std::str::FromStr; use std::fmt; +use std::str::FromStr; const IDEAL_AUNT: &str = r#"Sue 0: children: 3, cats: 7, samoyeds: 2, pomeranians: 3, akitas: 0, vizslas: 0, goldfish: 5, trees: 3, cars: 2, perfumes: 1"#; @@ -8,16 +8,14 @@ pub fn get_answer(input: &str) -> usize { let aunts = parse_aunts(input); let ideal_aunt = Aunt::from_str(IDEAL_AUNT).unwrap(); - find_ideal_aunt(&aunts, &ideal_aunt) - .unwrap_or(0) + find_ideal_aunt(&aunts, &ideal_aunt).unwrap_or(0) } pub fn get_answer_from_retroencabulator(input: &str) -> usize { let aunts = parse_aunts(input); let ideal_aunt = Aunt::from_str(IDEAL_AUNT).unwrap(); - find_ideal_retro_aunt(&aunts, &ideal_aunt) - .unwrap_or(0) + find_ideal_retro_aunt(&aunts, &ideal_aunt).unwrap_or(0) } #[derive(Debug)] @@ -25,7 +23,10 @@ struct ParseThingsError(String); impl fmt::Display for ParseThingsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!("ParseThingsError: couldn't parse '{}' to Things", self.0)) + f.write_fmt(format_args!( + "ParseThingsError: couldn't parse '{}' to Things", + self.0 + )) } } @@ -34,7 +35,10 @@ struct ParseAuntError(String); impl fmt::Display for ParseAuntError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!("ParseAuntError: couldn't parse '{}' to Aunt", self.0)) + f.write_fmt(format_args!( + "ParseAuntError: couldn't parse '{}' to Aunt", + self.0 + )) } } @@ -67,7 +71,7 @@ impl FromStr for Things { "trees" => Ok(Things::Trees), "cars" => Ok(Things::Cars), "perfumes" => Ok(Things::Perfumes), - _ => Err(ParseThingsError(String::from(s))) + _ => Err(ParseThingsError(String::from(s))), } } } @@ -79,14 +83,17 @@ struct Aunt { impl Aunt { fn get_thing(&self, thing: &Things) -> Option { - self.things.get(thing) - .copied() + self.things.get(thing).copied() } } impl fmt::Debug for Aunt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!("Sue {}: # of things {}", self.number, self.things.len())) + f.write_fmt(format_args!( + "Sue {}: # of things {}", + self.number, + self.things.len() + )) } } @@ -138,7 +145,8 @@ impl FromStr for Aunt { } fn parse_aunts(input: &str) -> Vec { - input.lines() + input + .lines() .map(|l| Aunt::from_str(l)) .filter(|a| a.is_ok()) .map(|a| a.unwrap()) @@ -146,37 +154,53 @@ fn parse_aunts(input: &str) -> Vec { } fn find_ideal_aunt(input_aunts: &Vec, aunt_sample: &Aunt) -> Option { - input_aunts.iter() + input_aunts + .iter() .find(|&input_aunt| { - aunt_sample.things + aunt_sample + .things .iter() .filter(|sample_aunt_thing| { - if let Some(input_aunt_thing_value) = input_aunt.get_thing(sample_aunt_thing.0) { + if let Some(input_aunt_thing_value) = input_aunt.get_thing(sample_aunt_thing.0) + { *sample_aunt_thing.1 == input_aunt_thing_value } else { false } - }).count() == input_aunt.things.len() - }).map(|found_aunt| found_aunt.number) + }) + .count() + == input_aunt.things.len() + }) + .map(|found_aunt| found_aunt.number) } fn find_ideal_retro_aunt(input_aunts: &Vec, aunt_sample: &Aunt) -> Option { - input_aunts.iter() + input_aunts + .iter() .find(|&input_aunt| { - aunt_sample.things.iter() + aunt_sample + .things + .iter() .filter(|sample_aunt_thing| { - if let Some(input_aunt_thing_value) = input_aunt.get_thing(sample_aunt_thing.0) { + if let Some(input_aunt_thing_value) = input_aunt.get_thing(sample_aunt_thing.0) + { match sample_aunt_thing.0 { - Things::Cats | Things::Trees => *sample_aunt_thing.1 < input_aunt_thing_value, - Things::Pomeranians | Things::Goldfish => *sample_aunt_thing.1 > input_aunt_thing_value, + Things::Cats | Things::Trees => { + *sample_aunt_thing.1 < input_aunt_thing_value + } + Things::Pomeranians | Things::Goldfish => { + *sample_aunt_thing.1 > input_aunt_thing_value + } _ => *sample_aunt_thing.1 == input_aunt_thing_value, } } else { false } }) - .count() == input_aunt.things.len() - }).map(|found_aunt| found_aunt.number) + .count() + == input_aunt.things.len() + }) + .map(|found_aunt| found_aunt.number) } #[cfg(test)] @@ -185,8 +209,7 @@ mod tests { #[test] fn test_aunt_from_str() { - let aunt = Aunt::from_str("Sue 30: vizslas: 3, perfumes: 8, akitas: 2") - .unwrap(); + let aunt = Aunt::from_str("Sue 30: vizslas: 3, perfumes: 8, akitas: 2").unwrap(); assert_eq!(aunt.number, 30); assert_eq!(aunt.get_thing(&Things::Vizslas), Some(3usize)); assert_eq!(aunt.get_thing(&Things::Perfumes), Some(8usize)); @@ -197,8 +220,7 @@ mod tests { #[test] fn test_aunt_from_str_error_token() { - let aunt = Aunt::from_str("Sue 32: perfumes: 8, children: -3, akitas: 2") - .unwrap(); + let aunt = Aunt::from_str("Sue 32: perfumes: 8, children: -3, akitas: 2").unwrap(); assert_eq!(aunt.number, 32); assert_eq!(aunt.things.len(), 1); assert_eq!(aunt.get_thing(&Things::Children), None); @@ -208,8 +230,14 @@ mod tests { fn test_aunt_from_str_error_aunt() { let err = Aunt::from_str("Marry 32: children: 13, perfumes: 8, akitas: 2"); let aunt_error = err.unwrap_err(); - assert_eq!(format!("{:?}", aunt_error), r#"ParseAuntError("Marry 32: children: 13, perfumes: 8, akitas: 2")"#); - assert_eq!(format!("{}", aunt_error), r#"ParseAuntError: couldn't parse 'Marry 32: children: 13, perfumes: 8, akitas: 2' to Aunt"#); + assert_eq!( + format!("{:?}", aunt_error), + r#"ParseAuntError("Marry 32: children: 13, perfumes: 8, akitas: 2")"# + ); + assert_eq!( + format!("{}", aunt_error), + r#"ParseAuntError: couldn't parse 'Marry 32: children: 13, perfumes: 8, akitas: 2' to Aunt"# + ); } #[test] @@ -217,7 +245,10 @@ mod tests { assert_eq!(Things::from_str("children").unwrap(), Things::Children); assert_eq!(Things::from_str("cats").unwrap(), Things::Cats); assert_eq!(Things::from_str("samoyeds").unwrap(), Things::Samoyeds); - assert_eq!(Things::from_str("pomeranians").unwrap(), Things::Pomeranians); + assert_eq!( + Things::from_str("pomeranians").unwrap(), + Things::Pomeranians + ); assert_eq!(Things::from_str("akitas").unwrap(), Things::Akitas); assert_eq!(Things::from_str("vizslas").unwrap(), Things::Vizslas); assert_eq!(Things::from_str("goldfish").unwrap(), Things::Goldfish); @@ -229,18 +260,23 @@ mod tests { assert!(things_result.is_err()); let things_error = things_result.unwrap_err(); assert_eq!(format!("{:?}", things_error), r#"ParseThingsError("Vest")"#); - assert_eq!(format!("{}", things_error), r#"ParseThingsError: couldn't parse 'Vest' to Things"#); + assert_eq!( + format!("{}", things_error), + r#"ParseThingsError: couldn't parse 'Vest' to Things"# + ); } #[test] fn test_parse_aunts() { - let aunts = parse_aunts(r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 + let aunts = parse_aunts( + r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 Sue 2: akitas: 9, children: 3, samoyeds: 9 Sue 3: trees: 6, cars: 6, children: 4 Sue 4: trees: 4, vizslas: 4, goldfish: 9 Vest Sue 5: akitas: 9, vizslas: 7, cars: 5 - Sue 6: vizslas: 6, goldfish: 6, akitas: 3"#); + Sue 6: vizslas: 6, goldfish: 6, akitas: 3"#, + ); assert_eq!(aunts.len(), 6); } @@ -253,8 +289,10 @@ mod tests { #[test] fn test_find_ideal_aunt() { - let aunts = parse_aunts(r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 - Sue 2: children: 3, cats: 7, pomeranians: 3"#); + let aunts = parse_aunts( + r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 + Sue 2: children: 3, cats: 7, pomeranians: 3"#, + ); let ideal_aunt = Aunt::from_str(IDEAL_AUNT).unwrap(); let aunt = find_ideal_aunt(&aunts, &ideal_aunt); assert!(aunt.is_some()); @@ -263,8 +301,10 @@ mod tests { #[test] fn test_cannot_find_ideal_aunt() { - let aunts = parse_aunts(r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 - Sue 2: children: 4, cats: 7, pomeranians: 3"#); // this aunt doesn't exist + let aunts = parse_aunts( + r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 + Sue 2: children: 4, cats: 7, pomeranians: 3"#, + ); // this aunt doesn't exist let ideal_aunt = Aunt::from_str(IDEAL_AUNT).unwrap(); let aunt = find_ideal_aunt(&aunts, &ideal_aunt); assert!(aunt.is_none()); @@ -272,8 +312,10 @@ mod tests { #[test] fn test_get_answer() { - let answer = get_answer(r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 - Sue 2: children: 3, cats: 7, pomeranians: 3"#); + let answer = get_answer( + r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 + Sue 2: children: 3, cats: 7, pomeranians: 3"#, + ); assert_eq!(answer, 2); } @@ -285,22 +327,28 @@ mod tests { #[test] fn test_cannot_get_answer() { - let answer = get_answer(r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 - Sue 2: children: 4, cats: 7, pomeranians: 3"#); // this aunt doesn't exist + let answer = get_answer( + r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 + Sue 2: children: 4, cats: 7, pomeranians: 3"#, + ); // this aunt doesn't exist assert_eq!(answer, 0); } #[test] fn test_cannot_get_answer_from_retroencabulator() { - let answer = get_answer_from_retroencabulator(r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 - Sue 2: children: 3, cats: 7, pomeranians: 3"#); + let answer = get_answer_from_retroencabulator( + r#"Sue 1: cars: 9, akitas: 3, goldfish: 0 + Sue 2: children: 3, cats: 7, pomeranians: 3"#, + ); assert_eq!(answer, 0); } #[test] fn test_get_answer_from_retroencabulator() { - let answer = get_answer_from_retroencabulator(r#"Sue 1: cats: 9, akitas: 0, goldfish: 4 - Sue 2: children: 4, cats: 7, pomeranians: 3"#); + let answer = get_answer_from_retroencabulator( + r#"Sue 1: cats: 9, akitas: 0, goldfish: 4 + Sue 2: children: 4, cats: 7, pomeranians: 3"#, + ); assert_eq!(answer, 1); } } diff --git a/adv2015/src/day17.rs b/adv2015/src/day17.rs index dfcb28a..4c26a93 100644 --- a/adv2015/src/day17.rs +++ b/adv2015/src/day17.rs @@ -17,7 +17,8 @@ pub fn get_minimal_count_of_cans(input: &str) -> usize { } fn parse_to_available_cans(input: &str) -> Vec { - input.lines() + input + .lines() .map(|l| l.trim()) .map(|l| l.parse::()) .filter(|c| c.is_ok()) @@ -36,16 +37,12 @@ fn find_cans_combination_total_count(vec: &Vec, required_volume: usize) - if k_tuple.0 > 0 { for k in k_tuple.0..=k_tuple.1 { - let cloned_vec: Vec<(usize, usize)> = vec.iter() - .enumerate() - .map(|e| (e.0, *e.1)) - .collect(); + let cloned_vec: Vec<(usize, usize)> = + vec.iter().enumerate().map(|e| (e.0, *e.1)).collect(); let computed = Combinations::new(cloned_vec, k); - answer += computed.map(|c| { - c.iter().map(|can| can.1) - .sum() - }) + answer += computed + .map(|c| c.iter().map(|can| can.1).sum()) .filter(|&volume: &usize| volume == required_volume) .count(); } @@ -63,15 +60,12 @@ fn find_cans_combination_minimal_count(vec: &Vec, required_volume: usize) if k_tuple.0 > 0 { for k in k_tuple.0..=k_tuple.1 { - let cloned_vec: Vec<(usize, usize)> = vec.iter().enumerate() - .map(|e| (e.0, *e.1)) - .collect(); + let cloned_vec: Vec<(usize, usize)> = + vec.iter().enumerate().map(|e| (e.0, *e.1)).collect(); let computed = Combinations::new(cloned_vec, k); - let answer = computed.map(|c| { - c.iter().map(|can| can.1) - .sum() - }) + let answer = computed + .map(|c| c.iter().map(|can| can.1).sum()) .filter(|&volume: &usize| volume == required_volume) .count(); if answer > 0 { @@ -119,27 +113,39 @@ mod tests { #[test] fn test_get_total_count_of_combinations() { - assert_eq!(get_total_count_of_combinations(r#"50 + assert_eq!( + get_total_count_of_combinations( + r#"50 50 - 100"#), 2); + 100"# + ), + 2 + ); } #[test] fn test_get_minimal_count_of_cans() { - assert_eq!(get_minimal_count_of_cans(r#"10 + assert_eq!( + get_minimal_count_of_cans( + r#"10 140 50 50 - 50"#), 1); + 50"# + ), + 1 + ); } #[test] fn test_parse_to_available_cans() { - let cans = parse_to_available_cans(r#"20 + let cans = parse_to_available_cans( + r#"20 15 10 5 - 5"#); + 5"#, + ); assert_eq!(cans.len(), 5); @@ -149,8 +155,14 @@ mod tests { #[test] fn test_find_cans_combination_count() { - assert_eq!(find_cans_combination_total_count(&vec![1, 2, 3, 4, 5], 5), 3); - assert_eq!(find_cans_combination_total_count(&vec![20, 15, 10, 5, 5], 25), 4); + assert_eq!( + find_cans_combination_total_count(&vec![1, 2, 3, 4, 5], 5), + 3 + ); + assert_eq!( + find_cans_combination_total_count(&vec![20, 15, 10, 5, 5], 25), + 4 + ); } #[test] diff --git a/adv2015/src/day18.rs b/adv2015/src/day18.rs index 6820275..87346ad 100644 --- a/adv2015/src/day18.rs +++ b/adv2015/src/day18.rs @@ -32,7 +32,6 @@ struct Grid { grid: Vec>, } - impl Grid { fn new(size: usize) -> Grid { Grid { @@ -87,7 +86,8 @@ impl Grid { results.push(self.is_on(row3, col3)); } - results.iter() + results + .iter() .filter(|&r| r.is_some()) .map(|r| r.unwrap()) .filter(|&r| *r) @@ -95,16 +95,11 @@ impl Grid { } fn parse_grid(&mut self, lines: &str) { - lines.lines() - .enumerate() - .for_each(|(row, line)| { - line.trim() - .chars() - .enumerate() - .for_each(|(col, light)| { - self.grid[row][col] = light == '#'; - }) - }); + lines.lines().enumerate().for_each(|(row, line)| { + line.trim().chars().enumerate().for_each(|(col, light)| { + self.grid[row][col] = light == '#'; + }) + }); } fn evolve(&mut self) { @@ -125,12 +120,9 @@ impl Grid { } fn count_lights(&self) -> usize { - self.grid.iter() - .map(|line| - line.iter() - .filter(|&light| *light) - .count() - ) + self.grid + .iter() + .map(|line| line.iter().filter(|&light| *light).count()) .sum() } diff --git a/adv2015/src/day19.rs b/adv2015/src/day19.rs index 7e12de4..cce3d97 100644 --- a/adv2015/src/day19.rs +++ b/adv2015/src/day19.rs @@ -1,254 +1,245 @@ -use regex::Regex; -use std::collections::{HashSet}; -use rand::seq::SliceRandom; - -pub fn count_unique_molecules(input: &str) -> usize { - let (replacements, sample_molecule) = parse_all(input); - let molecules = build_molecules(sample_molecule, &replacements); - - molecules.len() -} - -pub fn count_molecules_from_electron(input: &str) -> usize { - let (replacements, sample_molecule) = parse_all(input); - let count = build_molecule_from_e(sample_molecule, &replacements); - - count -} - -struct Replace<'a> { - from: &'a str, - to: &'a str, -} - -fn parse_single_replace(line: &str) -> Replace { - let atoms: Vec<&str> = line.trim() - .split(" => ") - .collect(); - Replace { - from: atoms[0], - to: atoms[1], - } -} - -fn parse_all(input: &str) -> (Vec, &str) { - let mut result = Vec::with_capacity(5); - let mut is_molecule = false; - let mut molecule: &str = ""; - - input.lines() - .into_iter() - .map(&str::trim) - .for_each(|line| { - if line.is_empty() { - is_molecule = true; - } - - if !is_molecule { - result.push(parse_single_replace(line)); - } else { - molecule = line; - } - }); - - (result, molecule) -} - -fn split_molecule(input: &str) -> Vec<&str> { - let mol_reg = Regex::new("(e)|([A-Z][a-d,f-z]?)").unwrap(); // everything but not "Xe". Xa, Xb - - mol_reg.captures_iter(input) - .map(|c| c.get(0).unwrap().as_str()) - .collect() -} - -fn build_molecules(molecule: &str, replacements: &Vec) -> HashSet { - let mut molecules = HashSet::with_capacity(replacements.capacity()); - let atoms = split_molecule(molecule); - - replacements.iter() - .for_each(|replace| { - for top in 0..atoms.len() { - let mut molecule: Vec<&str> = Vec::with_capacity(atoms.len()); - if atoms[top] == replace.from { - if top > 0 { - molecule.extend(atoms.iter() - .take(top)); - } - molecule.push(replace.to); - if top < atoms.len() - 1 { - molecule.extend(atoms.iter() - .skip(top + 1)); - } - - let result_molecule = String::from(molecule.concat()); - molecules.insert(result_molecule); - - continue; - } - } - }); - - molecules -} - -fn build_molecule_from_e(molecule: &str, replacements: &Vec) -> usize { - let mut thread_rng = rand::thread_rng(); - let mut finished = false; - let mut iter = 0usize; - - // brute force, if the answer is not obtained - repeat. - while !finished { - iter = 0usize; - - // it is a potential 'e' result, but not always - let mut potential_e = String::from(molecule); - - while potential_e != "e" { - if let Some(replacement) = replacements.choose(&mut thread_rng) { - if potential_e.find(replacement.to).is_some() { - potential_e = potential_e.replacen(replacement.to, replacement.from, 1); - iter += 1; - } - - // couldn't find the solution - if potential_e.chars().filter(|c| *c == 'e') - .count() > 1 { - break; - } - } else { - return iter; - } - } - - finished = potential_e == "e"; - } - - iter -} - -#[cfg(test)] -mod tests { - use super::*; - - const SAMPLE: &str = r#"H => HO - H => OH - O => HH - - HOH"#; - const SANTA_SAMPLE: &str = r#"H => HO - H => OH - O => HH - - HOHOHO"#; - - const E_SAMPLE: &str = r#"e => H - e => O - H => HO - H => OH - O => HH - - HOH"#; - - const E_SANTA_SAMPLE: &str = r#"e => H - e => O - H => HO - H => OH - O => HH - - HOHOHO"#; - - #[test] - fn test_split_molecule() { - let atoms = split_molecule("CRnSiRneOe"); - assert_eq!(atoms[0], "C"); - assert_eq!(atoms[1], "Rn"); - assert_eq!(atoms[2], "Si"); - assert_eq!(atoms[3], "Rn"); - assert_eq!(atoms[4], "e"); - assert_eq!(atoms[5], "O"); - assert_eq!(atoms[6], "e"); - } - - #[test] - fn test_parse_single_replace() { - let replace_atoms = parse_single_replace("O => HH"); - assert_eq!(replace_atoms.from, "O"); - assert_eq!(replace_atoms.to, "HH"); - } - - #[test] - fn test_parse_all() { - let (replacements, molecule) = parse_all(SAMPLE); - - assert_eq!(replacements.len(), 3); - - assert_eq!(replacements[0].from, "H"); - assert_eq!(replacements[0].to, "HO"); - - assert_eq!(replacements[1].from, "H"); - assert_eq!(replacements[1].to, "OH"); - - assert_eq!(replacements[2].from, "O"); - assert_eq!(replacements[2].to, "HH"); - - assert_eq!(molecule, "HOH"); - } - - #[test] - fn test_build_molecules() { - let (replacements, sample_molecule) = parse_all(SAMPLE); - - - let molecules = build_molecules(sample_molecule, &replacements); - - assert_eq!(molecules.len(), 4); - assert!(molecules.contains("HOOH")); - assert!(molecules.contains("HOHO")); - assert!(molecules.contains("OHOH")); - assert!(molecules.contains("HHHH")); - } - - #[test] - fn test_build_molecules_santa() { - let (replacements, sample_molecule) = parse_all(SANTA_SAMPLE); - - let molecules = build_molecules(sample_molecule, &replacements); - println!("{:?}", molecules); - assert_eq!(molecules.len(), 7); - } - - #[test] - fn test_count_unique_molecules() { - let answer = count_unique_molecules(SANTA_SAMPLE); - - assert_eq!(answer, 7); - } - - #[test] - fn test_count_unique_molecules_empty() { - let answer = count_unique_molecules(""); - - assert_eq!(answer, 0); - } - - #[test] - fn test_build_molecule_from_e() { - let (replacements, molecule) = parse_all(E_SAMPLE); - let number_steps = build_molecule_from_e(molecule, &replacements); - assert_eq!(number_steps, 3); - } - - #[test] - fn test_build_santa_molecule_from_e() { - let (replacements, molecule) = parse_all(E_SANTA_SAMPLE); - let number_steps = build_molecule_from_e(molecule, &replacements); - assert_eq!(number_steps, 6); - } - - #[test] - fn test_count_molecules_from_electron() { - let answer = count_molecules_from_electron(E_SANTA_SAMPLE); - assert_eq!(answer, 6); - } -} +use rand::seq::SliceRandom; +use regex::Regex; +use std::collections::HashSet; + +pub fn count_unique_molecules(input: &str) -> usize { + let (replacements, sample_molecule) = parse_all(input); + let molecules = build_molecules(sample_molecule, &replacements); + + molecules.len() +} + +pub fn count_molecules_from_electron(input: &str) -> usize { + let (replacements, sample_molecule) = parse_all(input); + let count = build_molecule_from_e(sample_molecule, &replacements); + + count +} + +struct Replace<'a> { + from: &'a str, + to: &'a str, +} + +fn parse_single_replace(line: &str) -> Replace { + let atoms: Vec<&str> = line.trim().split(" => ").collect(); + Replace { + from: atoms[0], + to: atoms[1], + } +} + +fn parse_all(input: &str) -> (Vec, &str) { + let mut result = Vec::with_capacity(5); + let mut is_molecule = false; + let mut molecule: &str = ""; + + input.lines().into_iter().map(&str::trim).for_each(|line| { + if line.is_empty() { + is_molecule = true; + } + + if !is_molecule { + result.push(parse_single_replace(line)); + } else { + molecule = line; + } + }); + + (result, molecule) +} + +fn split_molecule(input: &str) -> Vec<&str> { + let mol_reg = Regex::new("(e)|([A-Z][a-d,f-z]?)").unwrap(); // everything but not "Xe". Xa, Xb + + mol_reg + .captures_iter(input) + .map(|c| c.get(0).unwrap().as_str()) + .collect() +} + +fn build_molecules(molecule: &str, replacements: &Vec) -> HashSet { + let mut molecules = HashSet::with_capacity(replacements.capacity()); + let atoms = split_molecule(molecule); + + replacements.iter().for_each(|replace| { + for top in 0..atoms.len() { + let mut molecule: Vec<&str> = Vec::with_capacity(atoms.len()); + if atoms[top] == replace.from { + if top > 0 { + molecule.extend(atoms.iter().take(top)); + } + molecule.push(replace.to); + if top < atoms.len() - 1 { + molecule.extend(atoms.iter().skip(top + 1)); + } + + let result_molecule = String::from(molecule.concat()); + molecules.insert(result_molecule); + + continue; + } + } + }); + + molecules +} + +fn build_molecule_from_e(molecule: &str, replacements: &Vec) -> usize { + let mut thread_rng = rand::thread_rng(); + let mut finished = false; + let mut iter = 0usize; + + // brute force, if the answer is not obtained - repeat. + while !finished { + iter = 0usize; + + // it is a potential 'e' result, but not always + let mut potential_e = String::from(molecule); + + while potential_e != "e" { + if let Some(replacement) = replacements.choose(&mut thread_rng) { + if potential_e.find(replacement.to).is_some() { + potential_e = potential_e.replacen(replacement.to, replacement.from, 1); + iter += 1; + } + + // couldn't find the solution + if potential_e.chars().filter(|c| *c == 'e').count() > 1 { + break; + } + } else { + return iter; + } + } + + finished = potential_e == "e"; + } + + iter +} + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLE: &str = r#"H => HO + H => OH + O => HH + + HOH"#; + const SANTA_SAMPLE: &str = r#"H => HO + H => OH + O => HH + + HOHOHO"#; + + const E_SAMPLE: &str = r#"e => H + e => O + H => HO + H => OH + O => HH + + HOH"#; + + const E_SANTA_SAMPLE: &str = r#"e => H + e => O + H => HO + H => OH + O => HH + + HOHOHO"#; + + #[test] + fn test_split_molecule() { + let atoms = split_molecule("CRnSiRneOe"); + assert_eq!(atoms[0], "C"); + assert_eq!(atoms[1], "Rn"); + assert_eq!(atoms[2], "Si"); + assert_eq!(atoms[3], "Rn"); + assert_eq!(atoms[4], "e"); + assert_eq!(atoms[5], "O"); + assert_eq!(atoms[6], "e"); + } + + #[test] + fn test_parse_single_replace() { + let replace_atoms = parse_single_replace("O => HH"); + assert_eq!(replace_atoms.from, "O"); + assert_eq!(replace_atoms.to, "HH"); + } + + #[test] + fn test_parse_all() { + let (replacements, molecule) = parse_all(SAMPLE); + + assert_eq!(replacements.len(), 3); + + assert_eq!(replacements[0].from, "H"); + assert_eq!(replacements[0].to, "HO"); + + assert_eq!(replacements[1].from, "H"); + assert_eq!(replacements[1].to, "OH"); + + assert_eq!(replacements[2].from, "O"); + assert_eq!(replacements[2].to, "HH"); + + assert_eq!(molecule, "HOH"); + } + + #[test] + fn test_build_molecules() { + let (replacements, sample_molecule) = parse_all(SAMPLE); + + let molecules = build_molecules(sample_molecule, &replacements); + + assert_eq!(molecules.len(), 4); + assert!(molecules.contains("HOOH")); + assert!(molecules.contains("HOHO")); + assert!(molecules.contains("OHOH")); + assert!(molecules.contains("HHHH")); + } + + #[test] + fn test_build_molecules_santa() { + let (replacements, sample_molecule) = parse_all(SANTA_SAMPLE); + + let molecules = build_molecules(sample_molecule, &replacements); + println!("{:?}", molecules); + assert_eq!(molecules.len(), 7); + } + + #[test] + fn test_count_unique_molecules() { + let answer = count_unique_molecules(SANTA_SAMPLE); + + assert_eq!(answer, 7); + } + + #[test] + fn test_count_unique_molecules_empty() { + let answer = count_unique_molecules(""); + + assert_eq!(answer, 0); + } + + #[test] + fn test_build_molecule_from_e() { + let (replacements, molecule) = parse_all(E_SAMPLE); + let number_steps = build_molecule_from_e(molecule, &replacements); + assert_eq!(number_steps, 3); + } + + #[test] + fn test_build_santa_molecule_from_e() { + let (replacements, molecule) = parse_all(E_SANTA_SAMPLE); + let number_steps = build_molecule_from_e(molecule, &replacements); + assert_eq!(number_steps, 6); + } + + #[test] + fn test_count_molecules_from_electron() { + let answer = count_molecules_from_electron(E_SANTA_SAMPLE); + assert_eq!(answer, 6); + } +} diff --git a/adv2015/src/day2.rs b/adv2015/src/day2.rs index aa3cc87..2631831 100644 --- a/adv2015/src/day2.rs +++ b/adv2015/src/day2.rs @@ -1,8 +1,10 @@ pub fn calc_packs(s: &str) -> u32 { - s.lines().map(|line| { - let (l, w, h) = parse_line(line); - calc_paper(l, w, h) - }).sum() + s.lines() + .map(|line| { + let (l, w, h) = parse_line(line); + calc_paper(l, w, h) + }) + .sum() } pub fn calc_ribbons(s: &str) -> u32 { diff --git a/adv2015/src/day20.rs b/adv2015/src/day20.rs index a75d853..f273f87 100644 --- a/adv2015/src/day20.rs +++ b/adv2015/src/day20.rs @@ -3,19 +3,22 @@ use std::ops::*; pub fn get_richest_house_before_strike(input: &str) -> usize { if let Ok(desired_number) = input.parse::() { find_house(desired_number, count_presents) - } else { 0 } + } else { + 0 + } } pub fn get_richest_house_after_strike(input: &str) -> usize { if let Ok(desired_number) = input.parse::() { find_house(desired_number, count_strike_presents) - } else { 0 } + } else { + 0 + } } fn find_house(desired_number: usize, algorithm: fn(usize) -> usize) -> usize { - RangeFrom { - start: 1usize - }.find(|&house_number| algorithm(house_number) >= desired_number) + RangeFrom { start: 1usize } + .find(|&house_number| algorithm(house_number) >= desired_number) .unwrap_or(0) } @@ -24,12 +27,8 @@ fn count_presents(house: usize) -> usize { return 0; } - (divisors::get_divisors(house) - .iter() - .sum::() - + 1 - + if house > 2 { house } else { 0 } - ) * 10 + (divisors::get_divisors(house).iter().sum::() + 1 + if house > 2 { house } else { 0 }) + * 10 } fn count_strike_presents(house: usize) -> usize { @@ -40,13 +39,13 @@ fn count_strike_presents(house: usize) -> usize { (divisors::get_divisors(house) .iter() .filter(|elf| house / *elf <= 50) - .sum::() + - match house { + .sum::() + + match house { 1..=2 => 1, 3..=50 => house + 1, _ => house, - } - ) * 11 + }) + * 11 } #[cfg(test)] diff --git a/adv2015/src/day21.rs b/adv2015/src/day21.rs index f245444..2dee798 100644 --- a/adv2015/src/day21.rs +++ b/adv2015/src/day21.rs @@ -78,30 +78,102 @@ impl Generator { } const WEAPONS: [Item; 5] = [ - Item { cost: 8, damage: 4, armor: 0 }, - Item { cost: 10, damage: 5, armor: 0 }, - Item { cost: 25, damage: 6, armor: 0 }, - Item { cost: 40, damage: 7, armor: 0 }, - Item { cost: 74, damage: 8, armor: 0 }, + Item { + cost: 8, + damage: 4, + armor: 0, + }, + Item { + cost: 10, + damage: 5, + armor: 0, + }, + Item { + cost: 25, + damage: 6, + armor: 0, + }, + Item { + cost: 40, + damage: 7, + armor: 0, + }, + Item { + cost: 74, + damage: 8, + armor: 0, + }, ]; const ARMORS: [Item; 6] = [ - Item { cost: 0, damage: 0, armor: 0 }, - Item { cost: 13, damage: 0, armor: 1 }, - Item { cost: 31, damage: 0, armor: 2 }, - Item { cost: 53, damage: 0, armor: 3 }, - Item { cost: 75, damage: 0, armor: 4 }, - Item { cost: 102, damage: 0, armor: 5 }, + Item { + cost: 0, + damage: 0, + armor: 0, + }, + Item { + cost: 13, + damage: 0, + armor: 1, + }, + Item { + cost: 31, + damage: 0, + armor: 2, + }, + Item { + cost: 53, + damage: 0, + armor: 3, + }, + Item { + cost: 75, + damage: 0, + armor: 4, + }, + Item { + cost: 102, + damage: 0, + armor: 5, + }, ]; const RINGS: [Item; 7] = [ - Item { cost: 0, damage: 0, armor: 0 }, //no ring - Item { cost: 20, damage: 0, armor: 1 }, // defense +1 - Item { cost: 25, damage: 1, armor: 0 }, // offense +1 - Item { cost: 40, damage: 0, armor: 2 }, // defense +2 - Item { cost: 50, damage: 2, armor: 0 }, // offense +2 - Item { cost: 80, damage: 0, armor: 3 }, // defense +3 - Item { cost: 100, damage: 3, armor: 0 }, // offense +3 + Item { + cost: 0, + damage: 0, + armor: 0, + }, //no ring + Item { + cost: 20, + damage: 0, + armor: 1, + }, // defense +1 + Item { + cost: 25, + damage: 1, + armor: 0, + }, // offense +1 + Item { + cost: 40, + damage: 0, + armor: 2, + }, // defense +2 + Item { + cost: 50, + damage: 2, + armor: 0, + }, // offense +2 + Item { + cost: 80, + damage: 0, + armor: 3, + }, // defense +3 + Item { + cost: 100, + damage: 3, + armor: 0, + }, // offense +3 ]; impl Default for Human { @@ -142,7 +214,8 @@ impl Iterator for Generator { } // Check to see if we've finished counting or not. - if self.counter > 0x4556 { // max digits, e.g. 5 weapons, 6 armors, 7 rings + if self.counter > 0x4556 { + // max digits, e.g. 5 weapons, 6 armors, 7 rings return None; } @@ -167,7 +240,8 @@ impl Iterator for Generator { } fn parse_enemy(input: &str) -> Human { - input.to_lowercase() + input + .to_lowercase() .lines() .map(|line| line.trim()) .fold(Human::default(), |mut res, line| { @@ -207,7 +281,9 @@ fn fight_to_death(human_sample: &Human, enemy_sample: &Human) -> Battle { fn attack(attacker: &Human, defender: &mut Human) { let damage = attacker.damage.saturating_sub(defender.armor); - defender.health = defender.health.saturating_sub(if damage == 0 { 1 } else { damage }); + defender.health = defender + .health + .saturating_sub(if damage == 0 { 1 } else { damage }); } #[cfg(test)] @@ -229,7 +305,8 @@ mod tests { r#"Hit Points: 100 Damage: 8 Armor: 2 - Name: Tester"#); + Name: Tester"#, + ); assert_eq!(enemy.health, 100); assert_eq!(enemy.damage, 8); @@ -245,8 +322,18 @@ mod tests { #[test] fn test_fight_to_death() { - let human = Human { health: 8, damage: 5, armor: 5, wealth: 0 }; - let enemy = Human { health: 12, damage: 7, armor: 2, wealth: 0 }; + let human = Human { + health: 8, + damage: 5, + armor: 5, + wealth: 0, + }; + let enemy = Human { + health: 12, + damage: 7, + armor: 2, + wealth: 0, + }; let result = fight_to_death(&human, &enemy); assert_eq!(result, Battle::Won, "The battle should be won"); @@ -255,8 +342,18 @@ mod tests { #[test] fn test_fight_with_uber_boss() { - let human = Human { health: 8, damage: 5, armor: 5, wealth: 0 }; - let enemy = Human { health: 12, damage: 20, armor: 2, wealth: 0 }; + let human = Human { + health: 8, + damage: 5, + armor: 5, + wealth: 0, + }; + let enemy = Human { + health: 12, + damage: 20, + armor: 2, + wealth: 0, + }; let result = fight_to_death(&human, &enemy); assert_eq!(result, Battle::Lost, "The battle should be lost"); @@ -264,8 +361,18 @@ mod tests { #[test] fn test_attack() { - let human = Human { health: 8, damage: 5, armor: 5, wealth: 0 }; - let mut enemy = Human { health: 12, damage: 7, armor: 2, wealth: 0 }; + let human = Human { + health: 8, + damage: 5, + armor: 5, + wealth: 0, + }; + let mut enemy = Human { + health: 12, + damage: 7, + armor: 2, + wealth: 0, + }; attack(&human, &mut enemy); assert_eq!(enemy.health, 12 - (5 - 2)); // 9 left @@ -280,7 +387,8 @@ mod tests { let wealth = find_cheapest_warrior( r#"Hit Points: 100 Damage: 8 - Armor: 2"#); + Armor: 2"#, + ); assert_eq!(wealth, 91); } @@ -290,7 +398,8 @@ mod tests { let wealth = find_expensive_loser( r#"Hit Points: 100 Damage: 8 - Armor: 2"#); + Armor: 2"#, + ); assert_eq!(wealth, 158); } diff --git a/adv2015/src/day22.rs b/adv2015/src/day22.rs index ab8c66d..515f143 100644 --- a/adv2015/src/day22.rs +++ b/adv2015/src/day22.rs @@ -46,8 +46,8 @@ struct GameState { impl GameState { fn find_possible_actions(&self) -> Vec { - let mut possible_actions: Vec = vec![Action::from_u8(1).unwrap(), - Action::from_u8(2).unwrap()]; + let mut possible_actions: Vec = + vec![Action::from_u8(1).unwrap(), Action::from_u8(2).unwrap()]; let mut queue_clone = self.queue.to_vec(); for action_idx in 3..=5 { if let Some(action) = Action::from_u8(action_idx) { @@ -180,11 +180,30 @@ impl Enemy { impl Action { fn from_u8(n: u8) -> Option { match n { - 1 => Some(Action::MagickMissile { cost: 53, damage: 4 }), - 2 => Some(Action::Drain { cost: 73, damage: 2, heal: 2 }), - 3 => Some(Action::Shield { cost: 113, duration: 6, armor: 7 }), - 4 => Some(Action::Poison { cost: 173, duration: 6, damage: 3 }), - 5 => Some(Action::Recharge { cost: 229, duration: 5, mana: 101 }), + 1 => Some(Action::MagickMissile { + cost: 53, + damage: 4, + }), + 2 => Some(Action::Drain { + cost: 73, + damage: 2, + heal: 2, + }), + 3 => Some(Action::Shield { + cost: 113, + duration: 6, + armor: 7, + }), + 4 => Some(Action::Poison { + cost: 173, + duration: 6, + damage: 3, + }), + 5 => Some(Action::Recharge { + cost: 229, + duration: 5, + mana: 101, + }), _ => None, } } @@ -200,7 +219,8 @@ impl Default for Enemy { } fn parse_enemy(input: &str) -> Enemy { - input.to_lowercase() + input + .to_lowercase() .lines() .map(|line| line.trim()) .fold(Enemy::default(), |mut res, line| { @@ -255,7 +275,12 @@ fn is_queue_valid(queue: &Vec) -> bool { true } -fn simulate_battle(player: &Player, enemy: &Enemy, actions: &Vec, hard: bool) -> (Battle, usize) { +fn simulate_battle( + player: &Player, + enemy: &Enemy, + actions: &Vec, + hard: bool, +) -> (Battle, usize) { let mut cost = 0usize; let mut player_clone = (*player).clone(); let mut enemy_clone = (*enemy).clone(); @@ -307,10 +332,14 @@ fn simulate_battle(player: &Player, enemy: &Enemy, actions: &Vec, hard: enemy_clone.health = enemy_clone.health.saturating_sub(*damage); player_clone.health = player_clone.health.saturating_add(*heal); } - Action::Shield { duration, armor, .. } => { + Action::Shield { + duration, armor, .. + } => { shield_status = (*duration, *armor); } - Action::Poison { duration, damage, .. } => { + Action::Poison { + duration, damage, .. + } => { poison_status = (*duration, *damage); } Action::Recharge { duration, mana, .. } => { @@ -327,7 +356,10 @@ fn simulate_battle(player: &Player, enemy: &Enemy, actions: &Vec, hard: } let damage = enemy_clone.damage.saturating_sub(player_clone.armor); - player_clone.health = player_clone.health.saturating_sub(if damage == 0 { 1 } else { damage }); + player_clone.health = + player_clone + .health + .saturating_sub(if damage == 0 { 1 } else { damage }); if player_clone.dead() { return (Battle::Lost, cost); @@ -358,16 +390,16 @@ mod tests { impl PartialEq for Battle { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Battle::Won, Battle::Won) | (Battle::Lost, Battle::Lost) | (Battle::Draw, Battle::Draw) => true, + (Battle::Won, Battle::Won) + | (Battle::Lost, Battle::Lost) + | (Battle::Draw, Battle::Draw) => true, _ => false, } } } fn count_queue_cost(queue: &Vec) -> usize { - queue.iter() - .map(|a| a.cost()) - .sum() + queue.iter().map(|a| a.cost()).sum() } #[test] @@ -381,7 +413,8 @@ mod tests { let enemy = parse_enemy( r#"Hit Points: 71 Damage: 10 - Name: Tester"#); + Name: Tester"#, + ); assert_eq!(enemy.health, 71); assert_eq!(enemy.damage, 10); @@ -408,19 +441,34 @@ mod tests { assert_eq!(heal, 2); } - if let Action::Shield { cost, duration, armor } = Action::from_u8(3).unwrap() { + if let Action::Shield { + cost, + duration, + armor, + } = Action::from_u8(3).unwrap() + { assert_eq!(cost, 113); assert_eq!(duration, 6); assert_eq!(armor, 7); } - if let Action::Poison { cost, duration, damage } = Action::from_u8(4).unwrap() { + if let Action::Poison { + cost, + duration, + damage, + } = Action::from_u8(4).unwrap() + { assert_eq!(cost, 173); assert_eq!(duration, 6); assert_eq!(damage, 3); } - if let Action::Recharge { cost, duration, mana } = Action::from_u8(5).unwrap() { + if let Action::Recharge { + cost, + duration, + mana, + } = Action::from_u8(5).unwrap() + { assert_eq!(cost, 229); assert_eq!(duration, 5); assert_eq!(mana, 101); @@ -429,15 +477,45 @@ mod tests { #[test] fn test_is_queue_valid() { - assert!(is_queue_valid(&vec![Action::from_u8(1).unwrap(), Action::from_u8(2).unwrap()])); - assert!(is_queue_valid(&vec![Action::from_u8(2).unwrap(), Action::from_u8(3).unwrap()])); - assert!(!is_queue_valid(&vec![Action::from_u8(3).unwrap(), Action::from_u8(3).unwrap()])); - assert!(is_queue_valid(&vec![Action::from_u8(3).unwrap(), Action::from_u8(4).unwrap()])); - assert!(is_queue_valid(&vec![Action::from_u8(4).unwrap(), Action::from_u8(3).unwrap()])); - assert!(!is_queue_valid(&vec![Action::from_u8(4).unwrap(), Action::from_u8(4).unwrap()])); - assert!(!is_queue_valid(&vec![Action::from_u8(5).unwrap(), Action::from_u8(5).unwrap()])); - assert!(is_queue_valid(&vec![Action::from_u8(3).unwrap(), Action::from_u8(4).unwrap(), Action::from_u8(5).unwrap()])); - assert!(is_queue_valid(&vec![Action::from_u8(5).unwrap(), Action::from_u8(1).unwrap(), Action::from_u8(1).unwrap(), Action::from_u8(5).unwrap()])); + assert!(is_queue_valid(&vec![ + Action::from_u8(1).unwrap(), + Action::from_u8(2).unwrap() + ])); + assert!(is_queue_valid(&vec![ + Action::from_u8(2).unwrap(), + Action::from_u8(3).unwrap() + ])); + assert!(!is_queue_valid(&vec![ + Action::from_u8(3).unwrap(), + Action::from_u8(3).unwrap() + ])); + assert!(is_queue_valid(&vec![ + Action::from_u8(3).unwrap(), + Action::from_u8(4).unwrap() + ])); + assert!(is_queue_valid(&vec![ + Action::from_u8(4).unwrap(), + Action::from_u8(3).unwrap() + ])); + assert!(!is_queue_valid(&vec![ + Action::from_u8(4).unwrap(), + Action::from_u8(4).unwrap() + ])); + assert!(!is_queue_valid(&vec![ + Action::from_u8(5).unwrap(), + Action::from_u8(5).unwrap() + ])); + assert!(is_queue_valid(&vec![ + Action::from_u8(3).unwrap(), + Action::from_u8(4).unwrap(), + Action::from_u8(5).unwrap() + ])); + assert!(is_queue_valid(&vec![ + Action::from_u8(5).unwrap(), + Action::from_u8(1).unwrap(), + Action::from_u8(1).unwrap(), + Action::from_u8(5).unwrap() + ])); } #[test] @@ -456,7 +534,10 @@ mod tests { let actions = vec![Action::from_u8(4).unwrap(), Action::from_u8(1).unwrap()]; let cost = count_queue_cost(&actions); - assert_eq!(simulate_battle(&player, &enemy, &actions, false), (Battle::Won, cost)); + assert_eq!( + simulate_battle(&player, &enemy, &actions, false), + (Battle::Won, cost) + ); } #[test] @@ -477,11 +558,14 @@ mod tests { Action::from_u8(3).unwrap(), Action::from_u8(2).unwrap(), Action::from_u8(4).unwrap(), - Action::from_u8(1).unwrap() + Action::from_u8(1).unwrap(), ]; let cost = count_queue_cost(&actions); - assert_eq!(simulate_battle(&player, &enemy, &actions, false), (Battle::Won, cost)); + assert_eq!( + simulate_battle(&player, &enemy, &actions, false), + (Battle::Won, cost) + ); } #[test] @@ -499,7 +583,10 @@ mod tests { let actions = vec![Action::from_u8(1).unwrap()]; - assert_eq!(simulate_battle(&player, &enemy, &actions, false).0, Battle::Lost); + assert_eq!( + simulate_battle(&player, &enemy, &actions, false).0, + Battle::Lost + ); } #[test] @@ -515,9 +602,18 @@ mod tests { damage: 15, }; - let actions = vec![Action::from_u8(1).unwrap(), Action::from_u8(1).unwrap(), Action::from_u8(1).unwrap(), Action::from_u8(1).unwrap(), Action::from_u8(1).unwrap()]; + let actions = vec![ + Action::from_u8(1).unwrap(), + Action::from_u8(1).unwrap(), + Action::from_u8(1).unwrap(), + Action::from_u8(1).unwrap(), + Action::from_u8(1).unwrap(), + ]; - assert_eq!(simulate_battle(&player, &enemy, &actions, false).0, Battle::Lost); + assert_eq!( + simulate_battle(&player, &enemy, &actions, false).0, + Battle::Lost + ); } #[test] @@ -534,7 +630,10 @@ mod tests { }; let actions = vec![Action::from_u8(4).unwrap(), Action::from_u8(1).unwrap()]; - assert_eq!(simulate_battle(&player, &enemy, &actions, true), (Battle::Lost, 173)); + assert_eq!( + simulate_battle(&player, &enemy, &actions, true), + (Battle::Lost, 173) + ); } #[test] @@ -551,7 +650,10 @@ mod tests { }; let actions = vec![Action::from_u8(1).unwrap()]; - assert_eq!(simulate_battle(&player, &enemy, &actions, true), (Battle::Draw, 53)); + assert_eq!( + simulate_battle(&player, &enemy, &actions, true), + (Battle::Draw, 53) + ); } #[test] diff --git a/adv2015/src/day23.rs b/adv2015/src/day23.rs index 1bb15d1..15dd218 100644 --- a/adv2015/src/day23.rs +++ b/adv2015/src/day23.rs @@ -1,11 +1,11 @@ -use std::str::FromStr; use std::collections::HashMap; +use std::str::FromStr; pub fn get_answer_b(input: &str) -> i32 { let instructions = parse_code(input); let mut machine = Machine::new(instructions); - while machine.do_evaluate() {}; + while machine.do_evaluate() {} Machine::get_register(&mut machine.registers, &'b') } @@ -15,7 +15,7 @@ pub fn get_answer_b_after_a(input: &str) -> i32 { let mut machine = Machine::new(instructions); Machine::set_register(&mut machine.registers, &'a', 1); - while machine.do_evaluate() {}; + while machine.do_evaluate() {} Machine::get_register(&mut machine.registers, &'b') } @@ -85,7 +85,10 @@ impl Machine { if let Instruction::jie(_, _) = inst { // Is even - Self::jump(&mut self.position, if register_value & 1 == 0 { *o } else { 1 }) + Self::jump( + &mut self.position, + if register_value & 1 == 0 { *o } else { 1 }, + ) } else { Self::jump(&mut self.position, if register_value == 1 { *o } else { 1 }) } @@ -108,9 +111,7 @@ impl Machine { } fn get_register(registers: &mut HashMap, r: &Register) -> i32 { - registers.entry(*r) - .or_insert(0) - .clone() + registers.entry(*r).or_insert(0).clone() } fn set_register(registers: &mut HashMap, r: &Register, v: i32) { @@ -125,7 +126,8 @@ impl FromStr for Instruction { type Err = ParseInstructionError; fn from_str(s: &str) -> Result { - let split: Vec<&str> = s.trim() + let split: Vec<&str> = s + .trim() .split(|c: char| c == ' ' || c == ',') .filter(|s| !s.is_empty()) .collect(); @@ -168,13 +170,14 @@ impl FromStr for Instruction { .map(|o| Instruction::jio(r, o)) }), - _ => Err(ParseInstructionError(String::from(s))) + _ => Err(ParseInstructionError(String::from(s))), } } } fn parse_code(input: &str) -> Vec { - input.lines() + input + .lines() .map(|l| Instruction::from_str(l)) .filter_map(|r| r.ok()) .collect() @@ -200,7 +203,7 @@ mod tests { (jmp(o1), jmp(o2)) => o1 == o2, (jie(r1, o1), jie(r2, o2)) => r1 == r2 && o1 == o2, (jio(r1, o1), jio(r2, o2)) => r1 == r2 && o1 == o2, - (_, _) => false + (_, _) => false, } } } @@ -226,24 +229,54 @@ mod tests { assert_ne!(Instruction::from_str("jio c, -2").unwrap(), inc('c')); // PartialEq for ParseInstructionError - assert_eq!(Instruction::from_str("jio err, -2").unwrap_err(), ParseInstructionError(String::from("jio err, -2"))); + assert_eq!( + Instruction::from_str("jio err, -2").unwrap_err(), + ParseInstructionError(String::from("jio err, -2")) + ); // only xxx y or xxx y, z - assert_eq!(Instruction::from_str("jio a, b, c, d").unwrap_err(), ParseInstructionError(String::from("jio a, b, c, d"))); + assert_eq!( + Instruction::from_str("jio a, b, c, d").unwrap_err(), + ParseInstructionError(String::from("jio a, b, c, d")) + ); } #[test] fn test_debug() { - assert_eq!(format!("{:?}", Instruction::from_str("hlf a").unwrap()), "hlf('a')"); - assert_eq!(format!("{:?}", Instruction::from_str("tpl b").unwrap()), "tpl('b')"); - assert_eq!(format!("{:?}", Instruction::from_str("inc c").unwrap()), "inc('c')"); - assert_eq!(format!("{:?}", Instruction::from_str("jmp 1").unwrap()), "jmp(1)"); - assert_eq!(format!("{:?}", Instruction::from_str("jie b, 3").unwrap()), "jie('b', 3)"); - assert_eq!(format!("{:?}", Instruction::from_str("jio b, 3").unwrap()), "jio('b', 3)"); - - assert_eq!(format!("{:?}", Instruction::from_str("jpa b, 3").unwrap_err()), "ParseInstructionError(\"jpa b, 3\")"); - - assert_eq!(format!("{:?}", Instruction::from_str("jio err, -2").unwrap_err()), "ParseInstructionError(\"jio err, -2\")"); + assert_eq!( + format!("{:?}", Instruction::from_str("hlf a").unwrap()), + "hlf('a')" + ); + assert_eq!( + format!("{:?}", Instruction::from_str("tpl b").unwrap()), + "tpl('b')" + ); + assert_eq!( + format!("{:?}", Instruction::from_str("inc c").unwrap()), + "inc('c')" + ); + assert_eq!( + format!("{:?}", Instruction::from_str("jmp 1").unwrap()), + "jmp(1)" + ); + assert_eq!( + format!("{:?}", Instruction::from_str("jie b, 3").unwrap()), + "jie('b', 3)" + ); + assert_eq!( + format!("{:?}", Instruction::from_str("jio b, 3").unwrap()), + "jio('b', 3)" + ); + + assert_eq!( + format!("{:?}", Instruction::from_str("jpa b, 3").unwrap_err()), + "ParseInstructionError(\"jpa b, 3\")" + ); + + assert_eq!( + format!("{:?}", Instruction::from_str("jio err, -2").unwrap_err()), + "ParseInstructionError(\"jio err, -2\")" + ); } #[test] diff --git a/adv2015/src/day24.rs b/adv2015/src/day24.rs index 689462c..111e405 100644 --- a/adv2015/src/day24.rs +++ b/adv2015/src/day24.rs @@ -27,7 +27,8 @@ fn find_optimal_qe(packages: &Vec, weight: usize) -> usize { let current_count = filtered_group.len(); if (lowest_qe == usize::MAX && lowest_count == usize::MAX) - || (current_count < lowest_count && current_qe < lowest_qe) { + || (current_count < lowest_count && current_qe < lowest_qe) + { let rest_packages = subtract_vectors(packages, &filtered_group); if group_with_weight_exists(&rest_packages, weight) { @@ -46,7 +47,8 @@ fn find_optimal_qe(packages: &Vec, weight: usize) -> usize { } fn parse_packages(input: &str) -> Vec { - input.lines() + input + .lines() .map(|l| l.trim()) .filter(|l| !l.is_empty()) .filter_map(|p| p.parse::().ok()) @@ -72,7 +74,7 @@ impl SleighCombination { } impl Iterator for SleighCombination { - type Item = Box>>; + type Item = Box>>; fn next(&mut self) -> Option { self.size += 1; @@ -83,8 +85,10 @@ impl Iterator for SleighCombination { let copy_packages = self.packages.to_vec(); let copy_weight = self.weight.clone(); - Some(Box::new(Combinations::new(copy_packages, self.size) - .filter(move |group| group.iter().sum::() == copy_weight))) + Some(Box::new( + Combinations::new(copy_packages, self.size) + .filter(move |group| group.iter().sum::() == copy_weight), + )) } } @@ -93,7 +97,8 @@ fn group_with_weight_exists(packages: &Vec, weight: usize) -> bool { let copy_packages = packages.to_vec(); if Combinations::new(copy_packages, size) - .any(|packages| packages.iter().sum::() == weight) { + .any(|packages| packages.iter().sum::() == weight) + { return true; } } @@ -103,15 +108,13 @@ fn group_with_weight_exists(packages: &Vec, weight: usize) -> bool { // quantum entanglement fn calc_qe(group: &Vec) -> usize { - group.iter() - .fold(1, |acc, p| acc * p) + group.iter().fold(1, |acc, p| acc * p) } fn subtract_vectors(from: &Vec, rhs: &Vec) -> Vec { let mut result = Vec::new(); - result.extend(from.iter() - .filter(|i| !rhs.contains(i))); + result.extend(from.iter().filter(|i| !rhs.contains(i))); result } @@ -122,10 +125,12 @@ mod tests { #[test] fn test_parse_packages() { - let packages = parse_packages(r#"1 + let packages = parse_packages( + r#"1 2 - 6"#); + 6"#, + ); assert_eq!(packages.len(), 3); assert_eq!(packages[0], 1); assert_eq!(packages[1], 2); @@ -153,6 +158,9 @@ mod tests { #[test] fn test_find_optimal_qe() { let packages: Vec = vec![1, 2, 3, 4, 5, 7, 8, 9, 10, 11]; - assert_eq!(find_optimal_qe(&packages, packages.iter().sum::() / 3), 99); + assert_eq!( + find_optimal_qe(&packages, packages.iter().sum::() / 3), + 99 + ); } } diff --git a/adv2015/src/day25.rs b/adv2015/src/day25.rs index bf128c1..a728961 100644 --- a/adv2015/src/day25.rs +++ b/adv2015/src/day25.rs @@ -1,134 +1,144 @@ -const FIRST_CODE: usize = 20151125; -const MULTIPLY: usize = 252533; -const DIVIDE: usize = 33554393; - -pub fn find_code(input: &str) -> usize { - let target = parse_input(input); - let list = ListCodes::new(&target); - let mut result = 0usize; - - for code in list { - result = code; - } - - result -} - -fn parse_input(input: &str) -> Coord { - let result: Vec = input.split(|c: char| c.is_whitespace() || c.is_alphabetic() || c.is_ascii_punctuation()) - .filter(|s| !s.is_empty()) - .filter_map(|s| s.parse::().ok()) - .collect(); - - if result.len() != 2 { - return Coord { row: 0, col: 0 }; - } - - Coord { - row: result[0], - col: result[1], - } -} - -#[derive(Clone, PartialEq, Debug)] -struct Coord { - row: usize, - col: usize, -} - -struct ListCodes { - current_pos: Coord, - target_pos: Coord, - current_code: usize, - length: usize, - stop: bool, -} - -impl ListCodes { - fn new(target_pos: &Coord) -> ListCodes { - ListCodes { - current_pos: Coord { row: 0, col: 0 }, - target_pos: target_pos.clone(), - current_code: 0, - length: 0, - stop: false, - } - } -} - -impl Iterator for ListCodes { - type Item = usize; - - fn next(&mut self) -> Option { - self.stop |= self.current_pos == self.target_pos; - - if self.stop { - return None; - } - - // move - if self.current_pos.row <= 1 { - self.length += 1; - self.current_pos.row = self.length; - self.current_pos.col = 1; - } else { - self.current_pos.row -= 1; - self.current_pos.col += 1; - } - - self.current_code = if (self.current_pos == Coord { row: 1, col: 1 }) { - FIRST_CODE - } else { - find_next_code(self.current_code) - }; - - Some(self.current_code) - } -} - -fn find_next_code(code: usize) -> usize { - let temp = code.checked_mul(MULTIPLY).unwrap_or_default(); - temp.checked_rem(DIVIDE).unwrap_or_default() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_input() { - let coord = parse_input("To continue, please consult the code grid in the manual. Enter the code at row 2947, column 3029."); - assert_eq!(coord.row, 2947); - assert_eq!(coord.col, 3029); - - assert_eq!(coord, Coord { row: 2947, col: 3029 }); - } - - #[test] - fn test_parse_bad_input() { - let coord = parse_input("To continue, Test 123 please consult the code grid in the manual. Enter the code at row 2947, column 3029."); - assert_eq!(coord.row, 0); - assert_eq!(coord.col, 0); - } - - #[test] - fn test_find_next_code() { - assert_eq!(find_next_code(FIRST_CODE), 31916031usize); - } - - #[test] - fn test_list_codes() { - let mut list = ListCodes::new(&Coord { row: 2, col: 2 }); - assert_eq!(list.next(), Some(20151125)); - assert_eq!(list.next(), Some(31916031)); - assert_eq!(list.next(), Some(18749137)); - assert_eq!(list.next(), Some(16080970)); - assert_eq!(list.next(), Some(21629792)); - assert_eq!(list.next(), None); - } - - #[test] - fn test_find_code() { - assert_eq!(find_code("Give me bla-bla-bla row 6, bla-bla-bla col 4"), 24659492); - } -} +const FIRST_CODE: usize = 20151125; +const MULTIPLY: usize = 252533; +const DIVIDE: usize = 33554393; + +pub fn find_code(input: &str) -> usize { + let target = parse_input(input); + let list = ListCodes::new(&target); + let mut result = 0usize; + + for code in list { + result = code; + } + + result +} + +fn parse_input(input: &str) -> Coord { + let result: Vec = input + .split(|c: char| c.is_whitespace() || c.is_alphabetic() || c.is_ascii_punctuation()) + .filter(|s| !s.is_empty()) + .filter_map(|s| s.parse::().ok()) + .collect(); + + if result.len() != 2 { + return Coord { row: 0, col: 0 }; + } + + Coord { + row: result[0], + col: result[1], + } +} + +#[derive(Clone, PartialEq, Debug)] +struct Coord { + row: usize, + col: usize, +} + +struct ListCodes { + current_pos: Coord, + target_pos: Coord, + current_code: usize, + length: usize, + stop: bool, +} + +impl ListCodes { + fn new(target_pos: &Coord) -> ListCodes { + ListCodes { + current_pos: Coord { row: 0, col: 0 }, + target_pos: target_pos.clone(), + current_code: 0, + length: 0, + stop: false, + } + } +} + +impl Iterator for ListCodes { + type Item = usize; + + fn next(&mut self) -> Option { + self.stop |= self.current_pos == self.target_pos; + + if self.stop { + return None; + } + + // move + if self.current_pos.row <= 1 { + self.length += 1; + self.current_pos.row = self.length; + self.current_pos.col = 1; + } else { + self.current_pos.row -= 1; + self.current_pos.col += 1; + } + + self.current_code = if (self.current_pos == Coord { row: 1, col: 1 }) { + FIRST_CODE + } else { + find_next_code(self.current_code) + }; + + Some(self.current_code) + } +} + +fn find_next_code(code: usize) -> usize { + let temp = code.checked_mul(MULTIPLY).unwrap_or_default(); + temp.checked_rem(DIVIDE).unwrap_or_default() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_input() { + let coord = parse_input("To continue, please consult the code grid in the manual. Enter the code at row 2947, column 3029."); + assert_eq!(coord.row, 2947); + assert_eq!(coord.col, 3029); + + assert_eq!( + coord, + Coord { + row: 2947, + col: 3029 + } + ); + } + + #[test] + fn test_parse_bad_input() { + let coord = parse_input("To continue, Test 123 please consult the code grid in the manual. Enter the code at row 2947, column 3029."); + assert_eq!(coord.row, 0); + assert_eq!(coord.col, 0); + } + + #[test] + fn test_find_next_code() { + assert_eq!(find_next_code(FIRST_CODE), 31916031usize); + } + + #[test] + fn test_list_codes() { + let mut list = ListCodes::new(&Coord { row: 2, col: 2 }); + assert_eq!(list.next(), Some(20151125)); + assert_eq!(list.next(), Some(31916031)); + assert_eq!(list.next(), Some(18749137)); + assert_eq!(list.next(), Some(16080970)); + assert_eq!(list.next(), Some(21629792)); + assert_eq!(list.next(), None); + } + + #[test] + fn test_find_code() { + assert_eq!( + find_code("Give me bla-bla-bla row 6, bla-bla-bla col 4"), + 24659492 + ); + } +} diff --git a/adv2015/src/day3.rs b/adv2015/src/day3.rs index 961cd81..e7f4987 100644 --- a/adv2015/src/day3.rs +++ b/adv2015/src/day3.rs @@ -67,7 +67,6 @@ pub fn count_houses_together(path: &str) -> usize { houses.len() } - #[cfg(test)] mod tests { use super::*; @@ -80,7 +79,12 @@ mod tests { c.step('o'); c.step('v'); c.step('^'); - assert_eq!(c, Coord { x: 0, y: 0 }, "We should arrive to (0, 0) instead of {:?}", c); + assert_eq!( + c, + Coord { x: 0, y: 0 }, + "We should arrive to (0, 0) instead of {:?}", + c + ); // To increase the coverage level c.x = 1; c.y = 1; @@ -93,7 +97,12 @@ mod tests { let mut c = Coord { x: 0, y: 0 }; c.step('<'); c.step('^'); - assert_eq!(c, Coord { x: -1, y: 1 }, "We should arrive to (-1, 1) instead of {:?}", c); + assert_eq!( + c, + Coord { x: -1, y: 1 }, + "We should arrive to (-1, 1) instead of {:?}", + c + ); } #[test] @@ -106,10 +115,13 @@ mod tests { #[test] fn test_count_houses_together() { - assert_eq!(count_houses_together(""), 1, "We always start with one house"); + assert_eq!( + count_houses_together(""), + 1, + "We always start with one house" + ); assert_eq!(count_houses_together("^v"), 3, "^v - 3"); assert_eq!(count_houses_together("^>v<"), 3, "^>v< - 3"); assert_eq!(count_houses_together("^v^v^v^v^v"), 11, "^v^v^v^v^v - 11"); } } - diff --git a/adv2015/src/day4.rs b/adv2015/src/day4.rs index 96859f0..95be81c 100644 --- a/adv2015/src/day4.rs +++ b/adv2015/src/day4.rs @@ -6,10 +6,7 @@ pub fn mine_suffix(secret: &str, zeroes: u8) -> u32 { pattern.push('0'); } - while !is_adventcoin( - calc_md5(secret, answer).as_str(), - pattern.as_str(), - ) { + while !is_adventcoin(calc_md5(secret, answer).as_str(), pattern.as_str()) { answer += 1; } @@ -33,19 +30,33 @@ mod tests { #[test] fn test_calc_md5() { - assert_eq!(calc_md5("abcdef", 609043), "000001dbbfa3a5c83a2d506429c7b00e") + assert_eq!( + calc_md5("abcdef", 609043), + "000001dbbfa3a5c83a2d506429c7b00e" + ) } #[test] fn test_is_adventcoin() { - assert!(is_adventcoin("000001dbbfa3a5c83a2d506429c7b00e", "00000"), "doesn't have five zeroes"); + assert!( + is_adventcoin("000001dbbfa3a5c83a2d506429c7b00e", "00000"), + "doesn't have five zeroes" + ); } #[test] #[ignore] fn test_mine_suffix_slow() { - assert_eq!(mine_suffix("abcdef", 5), 609043, "Didn't mine suffix properly"); - assert_eq!(mine_suffix("pqrstuv", 5), 1048970, "Didn't mine suffix properly"); + assert_eq!( + mine_suffix("abcdef", 5), + 609043, + "Didn't mine suffix properly" + ); + assert_eq!( + mine_suffix("pqrstuv", 5), + 1048970, + "Didn't mine suffix properly" + ); } #[test] diff --git a/adv2015/src/day5.rs b/adv2015/src/day5.rs index f565aed..539f3df 100644 --- a/adv2015/src/day5.rs +++ b/adv2015/src/day5.rs @@ -1,15 +1,11 @@ use std::collections::HashSet; pub fn count_nice_lines(input: &str) -> usize { - input.lines() - .filter(|&s| is_nice(s)) - .count() + input.lines().filter(|&s| is_nice(s)).count() } pub fn count_nice_lines_advanced(input: &str) -> usize { - input.lines() - .filter(|&s| is_nice_advanced(s)) - .count() + input.lines().filter(|&s| is_nice_advanced(s)).count() } fn is_nice(s: &str) -> bool { @@ -30,10 +26,7 @@ fn is_nice(s: &str) -> bool { pair = (pair.1, c); - if pair == ('a', 'b') || - pair == ('c', 'd') || - pair == ('p', 'q') || - pair == ('x', 'y') { + if pair == ('a', 'b') || pair == ('c', 'd') || pair == ('p', 'q') || pair == ('x', 'y') { return false; } @@ -99,15 +92,15 @@ mod tests { #[test] fn test_nice() { - ["ugknbfddgicrmopn", "aaa"].iter() - .for_each(|s| { - assert!(is_nice(s), "{} is nice, but it wasn't", s); - }); + ["ugknbfddgicrmopn", "aaa"].iter().for_each(|s| { + assert!(is_nice(s), "{} is nice, but it wasn't", s); + }); } #[test] fn test_naughty() { - ["jchzalrnumimnmhp", "haegwjzuvuyypxyu", "dvszwmarrgswjxmb"].iter() + ["jchzalrnumimnmhp", "haegwjzuvuyypxyu", "dvszwmarrgswjxmb"] + .iter() .for_each(|s| { assert!(!is_nice(s), "{} is naughty, but it wasn't", s); }); @@ -115,45 +108,76 @@ mod tests { #[test] fn test_count_nice() { - let input = ["jchzalrnumimnmhp", "ugknbfddgicrmopn", "haegwjzuvuyypxyu", "aaa", "dvszwmarrgswjxmb"] - .join("\n"); - - assert_eq!(count_nice_lines(input.as_str()), 2, "{} has two nice strings", input); + let input = [ + "jchzalrnumimnmhp", + "ugknbfddgicrmopn", + "haegwjzuvuyypxyu", + "aaa", + "dvszwmarrgswjxmb", + ] + .join("\n"); + + assert_eq!( + count_nice_lines(input.as_str()), + 2, + "{} has two nice strings", + input + ); } #[test] fn test_count_nice_lines_advanced() { - let input = ["qjhvhtzxzqqjkmpb", "xxyxx", "dieatyxxxlvhneoj", "xxxx"] - .join("\n"); - - assert_eq!(count_nice_lines_advanced(input.as_str()), 3, "{} has three nice strings", input); + let input = ["qjhvhtzxzqqjkmpb", "xxyxx", "dieatyxxxlvhneoj", "xxxx"].join("\n"); + + assert_eq!( + count_nice_lines_advanced(input.as_str()), + 3, + "{} has three nice strings", + input + ); } #[test] fn test_is_nice_advanced() { - ["qjhvhtzxzqqjkmpb", "xxyxx"].iter() - .for_each(|s| { - assert!(is_nice_advanced(s), "{} is nice (advanced), but it wasn't", s); - }); + ["qjhvhtzxzqqjkmpb", "xxyxx"].iter().for_each(|s| { + assert!( + is_nice_advanced(s), + "{} is nice (advanced), but it wasn't", + s + ); + }); } #[test] fn test_is_naughty_advanced() { - ["uurcxstgmygtbstg", "ieodomkazucvgmuy"].iter() + ["uurcxstgmygtbstg", "ieodomkazucvgmuy"] + .iter() .for_each(|s| { - assert!(!is_nice_advanced(s), "{} is nice (advanced), but it wasn't", s); + assert!( + !is_nice_advanced(s), + "{} is nice (advanced), but it wasn't", + s + ); }); } #[test] fn test_is_naughty_advanced_bugfix() { - assert!(!is_nice_advanced("dieatyxxxlvhneoj"), "dieatyxxxlvhneoj is nice (advanced), but it wasn't"); + assert!( + !is_nice_advanced("dieatyxxxlvhneoj"), + "dieatyxxxlvhneoj is nice (advanced), but it wasn't" + ); } #[test] fn test_is_nice_advanced_bugfix() { - assert!(is_nice_advanced("xxxx"), "xxxx is nice (advanced), but it wasn't"); - assert!(is_nice_advanced("xxaxx"), "xxaxx is nice (advanced), but it wasn't"); + assert!( + is_nice_advanced("xxxx"), + "xxxx is nice (advanced), but it wasn't" + ); + assert!( + is_nice_advanced("xxaxx"), + "xxaxx is nice (advanced), but it wasn't" + ); } } - diff --git a/adv2015/src/day6.rs b/adv2015/src/day6.rs index a29791e..a1db519 100644 --- a/adv2015/src/day6.rs +++ b/adv2015/src/day6.rs @@ -78,16 +78,15 @@ impl Token { "turn off" => return Token::TurnOff, "toggle" => return Token::Toggle, "through" => return Token::Through, - _ if input.contains(',') => return { - let coord_pair: Vec<&str> = input.split(',').collect(); - let res_x = coord_pair[0].parse::(); - let res_y = coord_pair[1].parse::(); - - Token::Coord( - res_x.unwrap_or(0usize), - res_y.unwrap_or(0usize), - ) - }, + _ if input.contains(',') => { + return { + let coord_pair: Vec<&str> = input.split(',').collect(); + let res_x = coord_pair[0].parse::(); + let res_y = coord_pair[1].parse::(); + + Token::Coord(res_x.unwrap_or(0usize), res_y.unwrap_or(0usize)) + } + } _ => Token::EOF, } } @@ -201,7 +200,9 @@ impl SantaInterpreter { }; } } - } else { break; } + } else { + break; + } } } @@ -215,13 +216,11 @@ impl SantaInterpreter { } fn get_state(&self) -> usize { - self.state.iter() - .fold(0usize, |acc1, line| { - acc1 + line.iter() - .fold(0usize, |acc2, &bulb| { - acc2 + if bulb { 1 } else { 0 } - }) - }) + self.state.iter().fold(0usize, |acc1, line| { + acc1 + line + .iter() + .fold(0usize, |acc2, &bulb| acc2 + if bulb { 1 } else { 0 }) + }) } } @@ -247,7 +246,9 @@ impl SantaBetterInterpreter { }; } } - } else { break; } + } else { + break; + } } } @@ -261,11 +262,12 @@ impl SantaBetterInterpreter { } fn get_state(&self) -> usize { - self.state.iter() - .fold(0usize, |acc1, line| { - acc1.saturating_add(line.iter() - .fold(0usize, |acc2, &brightness| acc2.saturating_add(brightness))) - }) + self.state.iter().fold(0usize, |acc1, line| { + acc1.saturating_add( + line.iter() + .fold(0usize, |acc2, &brightness| acc2.saturating_add(brightness)), + ) + }) } } @@ -280,12 +282,10 @@ fn get_token(input: &str, from: usize) -> NextToken { match c { // whitespace, but we have a word in the buffer - _ if c.is_whitespace() && !word.is_empty() => { - match word.as_str() { - "turn" => word.push(' '), - _ => return NextToken(Token::parse_token(word.as_str()), i), - } - } + _ if c.is_whitespace() && !word.is_empty() => match word.as_str() { + "turn" => word.push(' '), + _ => return NextToken(Token::parse_token(word.as_str()), i), + }, // letter _ if c.is_alphabetic() => { @@ -361,7 +361,9 @@ mod tests { fn eq(&self, other: &Self) -> bool { match (self, other) { (Call::EOF, Call::EOF) => true, - (Call::Call(op1, c11, c12), Call::Call(op2, c21, c22)) => op1 == op2 && c11 == c21 && c12 == c22, + (Call::Call(op1, c11, c12), Call::Call(op2, c21, c22)) => { + op1 == op2 && c11 == c21 && c12 == c22 + } _ => false, } } @@ -404,7 +406,7 @@ mod tests { (Token::Through, Token::Through) => true, (Token::EOF, Token::EOF) => true, (Token::Coord(x1, y1), Token::Coord(x2, y2)) if x1 == x2 && y1 == y2 => true, - _ => false + _ => false, } } } @@ -453,9 +455,18 @@ mod tests { assert_ne!(Token::Coord(1, 2), Token::Coord(2, 1)); assert_eq!(Call::EOF, Call::EOF); - assert_eq!(Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)), Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4))); - assert_ne!(Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)), Call::Call(Operation::TurnOff, Coord(3, 4), Coord(1, 2))); - assert_ne!(Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)), Call::EOF); + assert_eq!( + Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)), + Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)) + ); + assert_ne!( + Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)), + Call::Call(Operation::TurnOff, Coord(3, 4), Coord(1, 2)) + ); + assert_ne!( + Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)), + Call::EOF + ); assert_ne!(Operation::TurnOn, Operation::TurnOff); assert_eq!(Operation::TurnOn, Operation::TurnOn); @@ -468,48 +479,103 @@ mod tests { #[test] fn test_get_token_toggle() { let input = "toggle 461,550 through 564,900"; - assert_eq!(get_token(input, 0), NextToken(Token::Toggle, 6), "Unexpected Token"); - assert_eq!(get_token(input, 6), NextToken(Token::Coord(461, 550), 14), "Unexpected Token"); - assert_eq!(get_token(input, 14), NextToken(Token::Through, 22), "Unexpected Token"); - assert_eq!(get_token(input, 23), NextToken(Token::Coord(564, 900), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Toggle, 6), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 6), + NextToken(Token::Coord(461, 550), 14), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 14), + NextToken(Token::Through, 22), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 23), + NextToken(Token::Coord(564, 900), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_turn_off() { let input = "turn off 812,389 through 865,874"; - assert_eq!(get_token(input, 0), NextToken(Token::TurnOff, 8), "Unexpected Token"); - assert_eq!(get_token(input, 8), NextToken(Token::Coord(812, 389), 16), "Unexpected Token"); - assert_eq!(get_token(input, 16), NextToken(Token::Through, 24), "Unexpected Token"); - assert_eq!(get_token(input, 24), NextToken(Token::Coord(865, 874), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::TurnOff, 8), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 8), + NextToken(Token::Coord(812, 389), 16), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 16), + NextToken(Token::Through, 24), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 24), + NextToken(Token::Coord(865, 874), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_turn_on() { let input = "turn on 599,989 through 806,993"; - assert_eq!(get_token(input, 0), NextToken(Token::TurnOn, 7), "Unexpected Token"); - assert_eq!(get_token(input, 8), NextToken(Token::Coord(599, 989), 15), "Unexpected Token"); - assert_eq!(get_token(input, 15), NextToken(Token::Through, 23), "Unexpected Token"); - assert_eq!(get_token(input, 23), NextToken(Token::Coord(806, 993), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::TurnOn, 7), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 8), + NextToken(Token::Coord(599, 989), 15), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 15), + NextToken(Token::Through, 23), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 23), + NextToken(Token::Coord(806, 993), input.len()), + "Unexpected Token" + ); } #[test] fn test_lexer() { let mut lexer = Lexer::new(String::from("turn on 599,989 through 806,993")); assert_eq!(lexer.next_token(), Token::TurnOn, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Coord(599, 989), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Coord(599, 989), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::Through, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Coord(806, 993), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Coord(806, 993), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::EOF, "Unexpected Token"); } #[test] fn test_parser() { let mut parser = Parser::new(String::from("turn on 499,989 through 806,992")); - assert_eq!(parser.next_operation(), Call::Call( - Operation::TurnOn, - Coord(499, 989), - Coord(806, 992), - )); + assert_eq!( + parser.next_operation(), + Call::Call(Operation::TurnOn, Coord(499, 989), Coord(806, 992),) + ); assert!(parser.parsing); assert_eq!(parser.next_operation(), Call::EOF); @@ -539,63 +605,101 @@ mod tests { #[test] fn test_multiline_parser() { - let mut parser = Parser::new(String::from("turn on 59,99 through 806,99\r\nturn off 812,389 through 865,874")); - assert_eq!(parser.next_operation(), Call::Call( - Operation::TurnOn, - Coord(59, 99), - Coord(806, 99), - )); - assert_eq!(parser.next_operation(), Call::Call( - Operation::TurnOff, - Coord(812, 389), - Coord(865, 874), + let mut parser = Parser::new(String::from( + "turn on 59,99 through 806,99\r\nturn off 812,389 through 865,874", )); + assert_eq!( + parser.next_operation(), + Call::Call(Operation::TurnOn, Coord(59, 99), Coord(806, 99),) + ); + assert_eq!( + parser.next_operation(), + Call::Call(Operation::TurnOff, Coord(812, 389), Coord(865, 874),) + ); } #[test] fn test_santa_interpreter_all_on() { - let input = String::from(format!("turn on 0,0 through {},{}", LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1)); + let input = String::from(format!( + "turn on 0,0 through {},{}", + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1 + )); println!("Testing: {}", input); let mut basic = SantaInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); println!("{} bulbs are showing us Christmas", answer); - assert_eq!(answer, LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, "{} bulbs are showing us Christmas, but we see {} only", LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, answer); + assert_eq!( + answer, + LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, + "{} bulbs are showing us Christmas, but we see {} only", + LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, + answer + ); } #[test] fn test_santa_interpreter_all_off() { - let input = String::from(format!("turn on 0,0 through {},{}\r\nturn off 0,0 through {},{}", - LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1)); + let input = String::from(format!( + "turn on 0,0 through {},{}\r\nturn off 0,0 through {},{}", + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1 + )); let mut basic = SantaInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); - assert_eq!(answer, 0, "{} bulbs are showing us Christmas, but we see {} only", 0, answer); + assert_eq!( + answer, 0, + "{} bulbs are showing us Christmas, but we see {} only", + 0, answer + ); } #[test] fn test_santa_interpreter_all_toggle() { - let input = String::from(format!("turn on 0,0 through {},{}\r\ntoggle 0,0 through {},{}", - LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1)); + let input = String::from(format!( + "turn on 0,0 through {},{}\r\ntoggle 0,0 through {},{}", + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1 + )); let mut basic = SantaInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); - assert_eq!(answer, 0, "{} bulbs are showing us Christmas, but we see {} only", 0, answer); + assert_eq!( + answer, 0, + "{} bulbs are showing us Christmas, but we see {} only", + 0, answer + ); } #[test] fn test_santa_interpreter() { let mut basic = SantaInterpreter::new(); - basic.interpret(String::from("turn on 0,0 through 99,99\r\ntoggle 100,100 through 199,199")); + basic.interpret(String::from( + "turn on 0,0 through 99,99\r\ntoggle 100,100 through 199,199", + )); let answer = basic.get_state(); - assert_eq!(answer, 100 * 100 * 2, "{} bulbs are showing us Christmas, but we see {} only", 100 * 100 * 2, answer); + assert_eq!( + answer, + 100 * 100 * 2, + "{} bulbs are showing us Christmas, but we see {} only", + 100 * 100 * 2, + answer + ); } #[test] fn test_santa_reset() { let mut basic = SantaInterpreter::new(); - basic.interpret(String::from("turn on 0,0 through 99,99\r\ntoggle 100,100 through 199,199")); + basic.interpret(String::from( + "turn on 0,0 through 99,99\r\ntoggle 100,100 through 199,199", + )); basic.reset(); let answer = basic.get_state(); @@ -604,34 +708,62 @@ mod tests { #[test] fn test_santa_better_interpreter_all_on() { - let input = String::from(format!("turn on 0,0 through {},{}", LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1)); + let input = String::from(format!( + "turn on 0,0 through {},{}", + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1 + )); println!("Testing: {}", input); let mut basic = SantaBetterInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); println!("{} Christmas brightness", answer); - assert_eq!(answer, LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, "{} is Christmas brightness, but we have {} only", LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, answer); + assert_eq!( + answer, + LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, + "{} is Christmas brightness, but we have {} only", + LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, + answer + ); } #[test] fn test_santa_better_interpreter_all_off() { - let input = String::from(format!("turn on 0,0 through {},{}\r\nturn off 0,0 through {},{}", - LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1)); + let input = String::from(format!( + "turn on 0,0 through {},{}\r\nturn off 0,0 through {},{}", + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1 + )); let mut basic = SantaBetterInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); - assert_eq!(answer, 0, "{} is Christmas brightness, but we have {} only", 0, answer); + assert_eq!( + answer, 0, + "{} is Christmas brightness, but we have {} only", + 0, answer + ); } #[test] fn test_santa_better_interpreter_all_toggle() { - let input = String::from(format!("toggle 0,0 through {},{}", - LIGHT_MAX_SIZE - 1, LIGHT_MAX_SIZE - 1)); + let input = String::from(format!( + "toggle 0,0 through {},{}", + LIGHT_MAX_SIZE - 1, + LIGHT_MAX_SIZE - 1 + )); let mut basic = SantaBetterInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); - assert_eq!(answer, 2 * LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, "{} is Christmas brightness, but we have {} only", 2 * LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, answer); + assert_eq!( + answer, + 2 * LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, + "{} is Christmas brightness, but we have {} only", + 2 * LIGHT_MAX_SIZE * LIGHT_MAX_SIZE, + answer + ); } #[test] @@ -640,13 +772,19 @@ mod tests { let mut basic = SantaBetterInterpreter::new(); basic.interpret(input); let answer = basic.get_state(); - assert_eq!(answer, 2, "{} is Christmas brightness, but we have {} only", 2, answer); + assert_eq!( + answer, 2, + "{} is Christmas brightness, but we have {} only", + 2, answer + ); } #[test] fn test_santa_better_reset() { let mut basic = SantaBetterInterpreter::new(); - basic.interpret(String::from("turn on 0,0 through 99,99\r\ntoggle 100,100 through 199,199")); + basic.interpret(String::from( + "turn on 0,0 through 99,99\r\ntoggle 100,100 through 199,199", + )); basic.reset(); let answer = basic.get_state(); @@ -687,19 +825,34 @@ mod tests { assert_eq!(Operation::TurnOn.to_string(), "on"); assert_eq!(Operation::TurnOff.to_string(), "off"); - assert_eq!(Call::Call(Operation::TurnOn, Coord(1, 2), Coord(3, 4)).to_string(), "on((1,2); (3,4))"); + assert_eq!( + Call::Call(Operation::TurnOn, Coord(1, 2), Coord(3, 4)).to_string(), + "on((1,2); (3,4))" + ); assert_eq!(Call::EOF.to_string(), "End"); } #[test] fn test_debug() { - assert_eq!(format!("{:?}", Operation::Toggle), format!("{}", Operation::Toggle)); + assert_eq!( + format!("{:?}", Operation::Toggle), + format!("{}", Operation::Toggle) + ); assert_eq!(format!("{:?}", Call::EOF), "EOF"); - assert_eq!(format!("{:?}", Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4))), "off: (1,2) and (3,4)"); + assert_eq!( + format!( + "{:?}", + Call::Call(Operation::TurnOff, Coord(1, 2), Coord(3, 4)) + ), + "off: (1,2) and (3,4)" + ); assert_eq!(format!("{:?}", Coord(1, 2)), "(1,2)"); - assert_eq!(format!("{:?}", NextToken(Token::Toggle, 13)), "NextToken(Toggle, 13)"); + assert_eq!( + format!("{:?}", NextToken(Token::Toggle, 13)), + "NextToken(Toggle, 13)" + ); assert_eq!(format!("{:?}", Token::Toggle), "Toggle"); assert_eq!(format!("{:?}", Token::TurnOn), "TurnOn"); diff --git a/adv2015/src/day7.rs b/adv2015/src/day7.rs index ba1741e..8659d63 100644 --- a/adv2015/src/day7.rs +++ b/adv2015/src/day7.rs @@ -1,5 +1,5 @@ -use std::fmt; use std::collections::HashMap; +use std::fmt; use std::fmt::Formatter; pub fn count_input_a(input: &str) -> u16 { @@ -14,7 +14,9 @@ pub fn count_input_a_override(input: &str) -> u16 { bobby.interpret(String::from(input)); let value_for_b = bobby.evaluate(&String::from("a")).unwrap(); - bobby.evaluate_override_signal(&String::from("a"), &String::from("b"), value_for_b).unwrap_or_default() + bobby + .evaluate_override_signal(&String::from("a"), &String::from("b"), value_for_b) + .unwrap_or_default() } struct NextToken(Token, usize); @@ -33,7 +35,6 @@ enum Token { EOF, } - #[derive(Copy, Clone)] enum Operation { And, @@ -88,7 +89,6 @@ struct BobbyInterpreter { cache: HashMap, } - impl Lexer { fn new(input: String) -> Lexer { Lexer { @@ -203,7 +203,10 @@ impl Parser { if let Token::Wire(target) = token { if commands.len() == 1 { if let Some(lvalue) = lvalue_from_one(&commands) { - return Expression::Assign(Command::Result(lvalue), LValue::Var(target)); + return Expression::Assign( + Command::Result(lvalue), + LValue::Var(target), + ); } } else if commands.len() == 2 { if let Some(lvalue) = lvalue_from_two(&commands) { @@ -278,41 +281,65 @@ fn lvalue_from_three(commands: &Vec) -> Option { let lvalue2 = &commands[2]; match op { - Token::And => + Token::And => { if let (Token::Wire(s1), Token::Wire(s2)) = (lvalue1, lvalue2) { - Some(Command::Binary(RValue::Var(s1.clone()), Operation::And, RValue::Var(s2.clone()))) + Some(Command::Binary( + RValue::Var(s1.clone()), + Operation::And, + RValue::Var(s2.clone()), + )) } else if let (Token::Signal(u1), Token::Wire(s2)) = (lvalue1, lvalue2) { - Some(Command::Binary(RValue::Const(u1.clone()), Operation::And, RValue::Var(s2.clone()))) + Some(Command::Binary( + RValue::Const(u1.clone()), + Operation::And, + RValue::Var(s2.clone()), + )) } else { None - }, - Token::Or => + } + } + Token::Or => { if let (Token::Wire(s1), Token::Wire(s2)) = (lvalue1, lvalue2) { - Some(Command::Binary(RValue::Var(s1.clone()), Operation::Or, RValue::Var(s2.clone()))) + Some(Command::Binary( + RValue::Var(s1.clone()), + Operation::Or, + RValue::Var(s2.clone()), + )) } else { None - }, - Token::LeftShift => + } + } + Token::LeftShift => { if let (Token::Wire(ls1), Token::Signal(u1)) = (lvalue1, lvalue2) { - Some(Command::Binary(RValue::Var(ls1.clone()), Operation::LShift, RValue::Const(u1.clone()))) + Some(Command::Binary( + RValue::Var(ls1.clone()), + Operation::LShift, + RValue::Const(u1.clone()), + )) } else { None - }, - Token::RightShift => + } + } + Token::RightShift => { if let (Token::Wire(rs1), Token::Signal(u1)) = (lvalue1, lvalue2) { - Some(Command::Binary(RValue::Var(rs1.clone()), Operation::RShift, RValue::Const(u1.clone()))) + Some(Command::Binary( + RValue::Var(rs1.clone()), + Operation::RShift, + RValue::Const(u1.clone()), + )) } else { None - }, - _ => None + } + } + _ => None, } } impl fmt::Display for Expression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Expression::NOP => { f.write_str("NOP") } - Expression::Assign(_, _) => { f.write_str("Assign") } + Expression::NOP => f.write_str("NOP"), + Expression::Assign(_, _) => f.write_str("Assign"), } } } @@ -349,12 +376,11 @@ impl fmt::Display for Operation { impl fmt::Display for Command { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Command::Result(lvalue) => - f.write_fmt(format_args!("{}", lvalue)), - Command::Binary(lvalue1, op, lvalue2) => - f.write_fmt(format_args!("{} {} {}", lvalue1, op, lvalue2)), - Command::Unary(op, lvalue) => - f.write_fmt(format_args!("{} {}", op, lvalue)), + Command::Result(lvalue) => f.write_fmt(format_args!("{}", lvalue)), + Command::Binary(lvalue1, op, lvalue2) => { + f.write_fmt(format_args!("{} {} {}", lvalue1, op, lvalue2)) + } + Command::Unary(op, lvalue) => f.write_fmt(format_args!("{} {}", op, lvalue)), } } } @@ -405,18 +431,16 @@ impl BobbyInterpreter { } let result = match next_command.unwrap().clone() { - Command::Result(lvalue) => { - match lvalue { - RValue::Const(c) => Some(c.clone()), - RValue::Var(w) => self.evaluate(&w), - } - } + Command::Result(lvalue) => match lvalue { + RValue::Const(c) => Some(c.clone()), + RValue::Var(w) => self.evaluate(&w), + }, Command::Unary(op, lvalue) => { // There is only one Unary operation, for more you can add "match" if let Operation::Not = op { match lvalue { RValue::Const(c) => Some(!c.clone()), - RValue::Var(w) => Some(!self.evaluate(&w).unwrap()) + RValue::Var(w) => Some(!self.evaluate(&w).unwrap()), } } else { None @@ -450,15 +474,22 @@ impl BobbyInterpreter { result } - fn evaluate_override_signal(&mut self, wire: &String, new_wire: &String, new_value: u16) -> Option { + fn evaluate_override_signal( + &mut self, + wire: &String, + new_wire: &String, + new_value: u16, + ) -> Option { self.cache.clear(); - self.tree.insert((*new_wire).clone(), Command::Result(RValue::Const(new_value))); + self.tree.insert( + (*new_wire).clone(), + Command::Result(RValue::Const(new_value)), + ); self.evaluate(wire) } } - #[cfg(test)] mod tests { use super::*; @@ -485,8 +516,10 @@ mod tests { impl fmt::Debug for Expression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Expression::NOP => { f.write_str("NOP") } - Expression::Assign(command, rvalue) => { f.write_fmt(format_args!("{} = {}", rvalue, command)) } + Expression::NOP => f.write_str("NOP"), + Expression::Assign(command, rvalue) => { + f.write_fmt(format_args!("{} = {}", rvalue, command)) + } } } } @@ -505,7 +538,11 @@ mod tests { fn eq(&self, other: &Self) -> bool { match (self, other) { (Expression::NOP, Expression::NOP) => true, - (Expression::Assign(c1, r1), Expression::Assign(c2, r2)) if c1 == c2 && r1 == r2 => true, + (Expression::Assign(c1, r1), Expression::Assign(c2, r2)) + if c1 == c2 && r1 == r2 => + { + true + } _ => false, } } @@ -515,8 +552,14 @@ mod tests { fn eq(&self, other: &Self) -> bool { match (self, other) { (Command::Result(l1), Command::Result(l2)) if l1 == l2 => true, - (Command::Binary(l11, op1, l12), Command::Binary(l21, op2, l22)) if l11 == l21 && op1 == op2 && l12 == l22 => true, - (Command::Unary(op1, l1), Command::Unary(op2, l2)) if op1 == op2 && l1 == l2 => true, + (Command::Binary(l11, op1, l12), Command::Binary(l21, op2, l22)) + if l11 == l21 && op1 == op2 && l12 == l22 => + { + true + } + (Command::Unary(op1, l1), Command::Unary(op2, l2)) if op1 == op2 && l1 == l2 => { + true + } _ => false, } } @@ -570,94 +613,238 @@ mod tests { #[test] fn test_get_token_assign() { let input = "123 -> x"; - assert_eq!(get_token(input, 0), NextToken(Token::Signal(123), 3), "Unexpected Token"); - assert_eq!(get_token(input, 3), NextToken(Token::Assign, 6), "Unexpected Token"); - assert_eq!(get_token(input, 6), NextToken(Token::Wire(String::from("x")), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Signal(123), 3), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 3), + NextToken(Token::Assign, 6), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 6), + NextToken(Token::Wire(String::from("x")), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_and() { let input = "x AND y -> d"; - assert_eq!(get_token(input, 0), NextToken(Token::Wire(String::from("x")), 1), "Unexpected Token"); - assert_eq!(get_token(input, 1), NextToken(Token::And, 5), "Unexpected Token"); - assert_eq!(get_token(input, 5), NextToken(Token::Wire(String::from("y")), 7), "Unexpected Token"); - assert_eq!(get_token(input, 7), NextToken(Token::Assign, 10), "Unexpected Token"); - assert_eq!(get_token(input, 10), NextToken(Token::Wire(String::from("d")), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Wire(String::from("x")), 1), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 1), + NextToken(Token::And, 5), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 5), + NextToken(Token::Wire(String::from("y")), 7), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 7), + NextToken(Token::Assign, 10), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 10), + NextToken(Token::Wire(String::from("d")), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_or() { let input = "x OR y -> e"; - assert_eq!(get_token(input, 0), NextToken(Token::Wire(String::from("x")), 1), "Unexpected Token"); - assert_eq!(get_token(input, 1), NextToken(Token::Or, 4), "Unexpected Token"); - assert_eq!(get_token(input, 4), NextToken(Token::Wire(String::from("y")), 6), "Unexpected Token"); - assert_eq!(get_token(input, 6), NextToken(Token::Assign, 9), "Unexpected Token"); - assert_eq!(get_token(input, 9), NextToken(Token::Wire(String::from("e")), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Wire(String::from("x")), 1), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 1), + NextToken(Token::Or, 4), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 4), + NextToken(Token::Wire(String::from("y")), 6), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 6), + NextToken(Token::Assign, 9), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 9), + NextToken(Token::Wire(String::from("e")), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_lshift() { let input = "x LSHIFT 2 -> f"; - assert_eq!(get_token(input, 0), NextToken(Token::Wire(String::from("x")), 1), "Unexpected Token"); - assert_eq!(get_token(input, 1), NextToken(Token::LeftShift, 8), "Unexpected Token"); - assert_eq!(get_token(input, 8), NextToken(Token::Signal(2), 10), "Unexpected Token"); - assert_eq!(get_token(input, 10), NextToken(Token::Assign, 13), "Unexpected Token"); - assert_eq!(get_token(input, 13), NextToken(Token::Wire(String::from("f")), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Wire(String::from("x")), 1), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 1), + NextToken(Token::LeftShift, 8), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 8), + NextToken(Token::Signal(2), 10), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 10), + NextToken(Token::Assign, 13), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 13), + NextToken(Token::Wire(String::from("f")), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_rshift() { let input = "y RSHIFT 2 -> g"; - assert_eq!(get_token(input, 0), NextToken(Token::Wire(String::from("y")), 1), "Unexpected Token"); - assert_eq!(get_token(input, 1), NextToken(Token::RightShift, 8), "Unexpected Token"); - assert_eq!(get_token(input, 8), NextToken(Token::Signal(2), 10), "Unexpected Token"); - assert_eq!(get_token(input, 10), NextToken(Token::Assign, 13), "Unexpected Token"); - assert_eq!(get_token(input, 13), NextToken(Token::Wire(String::from("g")), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Wire(String::from("y")), 1), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 1), + NextToken(Token::RightShift, 8), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 8), + NextToken(Token::Signal(2), 10), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 10), + NextToken(Token::Assign, 13), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 13), + NextToken(Token::Wire(String::from("g")), input.len()), + "Unexpected Token" + ); } #[test] fn test_get_token_not() { let input = "NOT x -> h"; - assert_eq!(get_token(input, 0), NextToken(Token::Not, 3), "Unexpected Token"); - assert_eq!(get_token(input, 3), NextToken(Token::Wire(String::from("x")), 5), "Unexpected Token"); - assert_eq!(get_token(input, 5), NextToken(Token::Assign, 8), "Unexpected Token"); - assert_eq!(get_token(input, 8), NextToken(Token::Wire(String::from("h")), input.len()), "Unexpected Token"); + assert_eq!( + get_token(input, 0), + NextToken(Token::Not, 3), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 3), + NextToken(Token::Wire(String::from("x")), 5), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 5), + NextToken(Token::Assign, 8), + "Unexpected Token" + ); + assert_eq!( + get_token(input, 8), + NextToken(Token::Wire(String::from("h")), input.len()), + "Unexpected Token" + ); } #[test] fn test_lexer() { - let mut lexer = Lexer::new(String::from("123 -> x\r\n456 -> y\r\nx AND y -> d\r\nx OR y -> e")); + let mut lexer = Lexer::new(String::from( + "123 -> x\r\n456 -> y\r\nx AND y -> d\r\nx OR y -> e", + )); assert_eq!(lexer.next_token(), Token::Signal(123), "Unexpected Token"); assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("x")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("x")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::Signal(456), "Unexpected Token"); assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("y")), "Unexpected Token"); - - assert_eq!(lexer.next_token(), Token::Wire(String::from("x")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("y")), + "Unexpected Token" + ); + + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("x")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::And, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("y")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("y")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("d")), "Unexpected Token"); - - assert_eq!(lexer.next_token(), Token::Wire(String::from("x")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("d")), + "Unexpected Token" + ); + + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("x")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::Or, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("y")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("y")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("e")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("e")), + "Unexpected Token" + ); } #[test] fn test_parser() { - let mut parser = Parser::new(String::from("123 -> x + let mut parser = Parser::new(String::from( + "123 -> x 456 -> y x AND y -> d x OR y -> e x LSHIFT 2 -> f y RSHIFT 2 -> g NOT x -> h - NOT y -> i")); + NOT y -> i", + )); match parser.next_operation() { Expression::Assign(c, v) => { if let Command::Result(RValue::Const(u)) = c { @@ -715,49 +902,95 @@ mod tests { #[test] fn test_bobby_interpreter() { - let input = String::from("123 -> x + let input = String::from( + "123 -> x 456 -> y x AND y -> d x OR y -> e x LSHIFT 2 -> f y RSHIFT 2 -> g NOT x -> h - NOT y -> i"); + NOT y -> i", + ); let mut bobby = BobbyInterpreter::new(); bobby.interpret(input); bobby.print_ast(); let def = 0xffffu16; - assert_eq!(bobby.evaluate(&String::from("x")).unwrap_or(def.clone()), 123, "Unexpected value X"); - assert_eq!(bobby.evaluate(&String::from("y")).unwrap_or(def.clone()), 456, "Unexpected value Y"); - assert_eq!(bobby.evaluate(&String::from("h")).unwrap_or(def.clone()), 65412, "Unexpected value H"); - assert_eq!(bobby.evaluate(&String::from("i")).unwrap_or(def.clone()), 65079, "Unexpected value I"); - assert_eq!(bobby.evaluate(&String::from("d")).unwrap_or(def.clone()), 72, "Unexpected value D"); - assert_eq!(bobby.evaluate(&String::from("e")).unwrap_or(def.clone()), 507, "Unexpected value E"); - assert_eq!(bobby.evaluate(&String::from("f")).unwrap_or(def.clone()), 492, "Unexpected value F"); - assert_eq!(bobby.evaluate(&String::from("g")).unwrap_or(def.clone()), 114, "Unexpected value G"); + assert_eq!( + bobby.evaluate(&String::from("x")).unwrap_or(def.clone()), + 123, + "Unexpected value X" + ); + assert_eq!( + bobby.evaluate(&String::from("y")).unwrap_or(def.clone()), + 456, + "Unexpected value Y" + ); + assert_eq!( + bobby.evaluate(&String::from("h")).unwrap_or(def.clone()), + 65412, + "Unexpected value H" + ); + assert_eq!( + bobby.evaluate(&String::from("i")).unwrap_or(def.clone()), + 65079, + "Unexpected value I" + ); + assert_eq!( + bobby.evaluate(&String::from("d")).unwrap_or(def.clone()), + 72, + "Unexpected value D" + ); + assert_eq!( + bobby.evaluate(&String::from("e")).unwrap_or(def.clone()), + 507, + "Unexpected value E" + ); + assert_eq!( + bobby.evaluate(&String::from("f")).unwrap_or(def.clone()), + 492, + "Unexpected value F" + ); + assert_eq!( + bobby.evaluate(&String::from("g")).unwrap_or(def.clone()), + 114, + "Unexpected value G" + ); } #[test] fn test_lexer_eof() { - let mut lexer = Lexer::new(String::from("123 -> x - 456 -> y")); + let mut lexer = Lexer::new(String::from( + "123 -> x + 456 -> y", + )); assert_eq!(lexer.next_token(), Token::Signal(123), "Unexpected Token"); assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("x")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("x")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::Signal(456), "Unexpected Token"); assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token"); - assert_eq!(lexer.next_token(), Token::Wire(String::from("y")), "Unexpected Token"); + assert_eq!( + lexer.next_token(), + Token::Wire(String::from("y")), + "Unexpected Token" + ); assert_eq!(lexer.next_token(), Token::EOF, "Unexpected Token"); } #[test] fn test_parser_with_const() { - let mut parser = Parser::new(String::from("jp RSHIFT 5 -> js + let mut parser = Parser::new(String::from( + "jp RSHIFT 5 -> js 1 AND io -> ip - eo LSHIFT 15 -> es")); + eo LSHIFT 15 -> es", + )); match parser.next_operation() { Expression::Assign(c, v) => { @@ -804,14 +1037,20 @@ mod tests { #[test] fn test_bobby_interpreter_empty() { - let input = String::from("123 -> x - 456 -> y"); + let input = String::from( + "123 -> x + 456 -> y", + ); let mut bobby = BobbyInterpreter::new(); bobby.interpret(input); bobby.print_ast(); let def = 0xffffu16; - assert_eq!(bobby.evaluate(&String::from("vest")).unwrap_or(def.clone()), 0xffffu16, "We shouldn't find any value"); + assert_eq!( + bobby.evaluate(&String::from("vest")).unwrap_or(def.clone()), + 0xffffu16, + "We shouldn't find any value" + ); } #[test] @@ -826,22 +1065,47 @@ mod tests { assert_eq!(Token::Assign.to_string(), "->"); assert_eq!(Token::EOF.to_string(), "eof"); - assert_eq!(Expression::Assign(Command::Result(RValue::Const(23)), LValue::Var(String::from("abc"))).to_string(), "Assign"); + assert_eq!( + Expression::Assign( + Command::Result(RValue::Const(23)), + LValue::Var(String::from("abc")) + ) + .to_string(), + "Assign" + ); assert_eq!(Expression::NOP.to_string(), "NOP"); } #[test] fn test_debug() { - assert_eq!(format!("{:?}", NextToken(Token::Signal(23), 12)), "NextToken(Signal(23), 12)"); + assert_eq!( + format!("{:?}", NextToken(Token::Signal(23), 12)), + "NextToken(Signal(23), 12)" + ); assert_eq!(format!("{:?}", RValue::Var(String::from("a"))), "a"); assert_eq!(format!("{:?}", RValue::Const(23)), "23"); - assert_eq!(format!("{:?}", Expression::Assign(Command::Result(RValue::Const(23)), LValue::Var(String::from("abc")))), "abc = 23"); - assert_eq!(format!("{:?}", Expression::Assign( - Command::Result(RValue::Var(String::from("a"))), - LValue::Var(String::from("abc"))) - ), "abc = a"); + assert_eq!( + format!( + "{:?}", + Expression::Assign( + Command::Result(RValue::Const(23)), + LValue::Var(String::from("abc")) + ) + ), + "abc = 23" + ); + assert_eq!( + format!( + "{:?}", + Expression::Assign( + Command::Result(RValue::Var(String::from("a"))), + LValue::Var(String::from("abc")) + ) + ), + "abc = a" + ); assert_eq!(format!("{:?}", Expression::NOP), "NOP"); } @@ -850,51 +1114,79 @@ mod tests { fn test_parser_errors() { let mut parser = Parser::new(String::from("2 -> x")); let assign = parser.next_operation(); - assert_eq!(assign, Expression::Assign(Command::Result(RValue::Const(2)), LValue::Var(String::from("x")))); + assert_eq!( + assign, + Expression::Assign( + Command::Result(RValue::Const(2)), + LValue::Var(String::from("x")) + ) + ); let mut parser = Parser::new(String::from("x RSHIFT 2 -> y")); let rshift_good = parser.next_operation(); - assert_eq!(rshift_good, Expression::Assign( - Command::Binary( - RValue::Var(String::from("x")), - Operation::RShift, - RValue::Const(2)), - LValue::Var(String::from("y")))); + assert_eq!( + rshift_good, + Expression::Assign( + Command::Binary( + RValue::Var(String::from("x")), + Operation::RShift, + RValue::Const(2) + ), + LValue::Var(String::from("y")) + ) + ); let mut parser = Parser::new(String::from("x LSHIFT 3 -> ly")); let lshift_good = parser.next_operation(); - assert_eq!(lshift_good, Expression::Assign( - Command::Binary( - RValue::Var(String::from("x")), - Operation::LShift, - RValue::Const(3)), - LValue::Var(String::from("ly")))); + assert_eq!( + lshift_good, + Expression::Assign( + Command::Binary( + RValue::Var(String::from("x")), + Operation::LShift, + RValue::Const(3) + ), + LValue::Var(String::from("ly")) + ) + ); let mut parser = Parser::new(String::from("x AND y -> ay")); let and_good = parser.next_operation(); - assert_eq!(and_good, Expression::Assign( - Command::Binary( - RValue::Var(String::from("x")), - Operation::And, - RValue::Var(String::from("y"))), - LValue::Var(String::from("ay")))); + assert_eq!( + and_good, + Expression::Assign( + Command::Binary( + RValue::Var(String::from("x")), + Operation::And, + RValue::Var(String::from("y")) + ), + LValue::Var(String::from("ay")) + ) + ); let mut parser = Parser::new(String::from("y OR x -> oy")); let or_good = parser.next_operation(); - assert_eq!(or_good, Expression::Assign( - Command::Binary( - RValue::Var(String::from("y")), - Operation::Or, - RValue::Var(String::from("x"))), - LValue::Var(String::from("oy")))); + assert_eq!( + or_good, + Expression::Assign( + Command::Binary( + RValue::Var(String::from("y")), + Operation::Or, + RValue::Var(String::from("x")) + ), + LValue::Var(String::from("oy")) + ) + ); let mut parser = Parser::new(String::from("NOT y -> ny")); let not_good = parser.next_operation(); - assert_eq!(not_good, Expression::Assign( - Command::Unary( - Operation::Not, - RValue::Var(String::from("y"))), - LValue::Var(String::from("ny")))); + assert_eq!( + not_good, + Expression::Assign( + Command::Unary(Operation::Not, RValue::Var(String::from("y"))), + LValue::Var(String::from("ny")) + ) + ); let mut parser = Parser::new(String::from("2 LSHIFT 1 -> z")); let lshift = parser.next_operation(); @@ -914,9 +1206,13 @@ mod tests { let mut parser = Parser::new(String::from("x -> t")); let assign_bad = parser.next_operation(); - assert_eq!(assign_bad, Expression::Assign( - Command::Result(RValue::Var(String::from("x"))), - LValue::Var(String::from("t")))); + assert_eq!( + assign_bad, + Expression::Assign( + Command::Result(RValue::Var(String::from("x"))), + LValue::Var(String::from("t")) + ) + ); let mut parser = Parser::new(String::from("8 RSHIFT x -> t")); let rshift_x = parser.next_operation(); @@ -958,10 +1254,12 @@ mod tests { #[test] fn test_interpreter() { let mut bobby = BobbyInterpreter::new(); - bobby.interpret(String::from(r#"NOT a -> b + bobby.interpret(String::from( + r#"NOT a -> b b AND d -> e 1 -> a - a -> d"#)); + a -> d"#, + )); let answer = bobby.evaluate(&String::from("e")); assert_eq!(answer.unwrap(), 0); } diff --git a/adv2015/src/day8.rs b/adv2015/src/day8.rs index 140a471..265c981 100644 --- a/adv2015/src/day8.rs +++ b/adv2015/src/day8.rs @@ -1,46 +1,37 @@ use std::char; pub fn calc_difference(input: &str) -> usize { - let literals = input.lines() - .fold(0, |acc, line| { - acc + count_literals(line) - }); + let literals = input + .lines() + .fold(0, |acc, line| acc + count_literals(line)); - let chars = input.lines() - .fold(0, |acc, line| { - acc + count_chars(line) - }); + let chars = input.lines().fold(0, |acc, line| acc + count_chars(line)); literals - chars } pub fn calc_new_difference(input: &str) -> usize { - let literals = input.lines() - .fold(0, |acc, line| { - acc + count_literals(line) - }); + let literals = input + .lines() + .fold(0, |acc, line| acc + count_literals(line)); - let chars = input.lines() - .fold(0, |acc, line| { - acc + count_escaped_chars(line) - }); + let chars = input + .lines() + .fold(0, |acc, line| acc + count_escaped_chars(line)); chars - literals } fn count_literals(input: &str) -> usize { - input.chars() - .count() + input.chars().count() } fn count_chars(input: &str) -> usize { - unescape(input).chars() - .count() + unescape(input).chars().count() } fn count_escaped_chars(input: &str) -> usize { - escape(input).chars() - .count() + escape(input).chars().count() } // Info: this code was taken from the crate "snailquote". It wasn't stolen for sale, but for @@ -116,8 +107,9 @@ fn escape(input: &str) -> String { } fn parse_unicode(chars: &mut I) -> char - where - I: Iterator { +where + I: Iterator, +{ let c1 = chars.next().unwrap(); let c2 = chars.next().unwrap(); @@ -159,11 +151,21 @@ mod tests { #[test] fn test_escape() { - println!("Debug: input={} result={} escape(input)={}", r#""""#, r#""\"\"""#, escape(r#""""#)); + println!( + "Debug: input={} result={} escape(input)={}", + r#""""#, + r#""\"\"""#, + escape(r#""""#) + ); assert_eq!(escape(r#""""#), r#""\"\"""#); assert_eq!(escape(r#""abc""#), r#""\"abc\"""#); - println!("Debug: input={} result={} escape(input)={}", r#""aaa\"aaa""#, r#""\"aaa\\\"aaa\"""#, escape(r#""aaa\"aaa""#)); + println!( + "Debug: input={} result={} escape(input)={}", + r#""aaa\"aaa""#, + r#""\"aaa\\\"aaa\"""#, + escape(r#""aaa\"aaa""#) + ); assert_eq!(escape(r#""aaa\"aaa""#), r#""\"aaa\\\"aaa\"""#); assert_eq!(escape(r#""\x27""#), r#""\"\\x27\"""#); } diff --git a/adv2015/src/day9.rs b/adv2015/src/day9.rs index 4c9615d..67c8796 100644 --- a/adv2015/src/day9.rs +++ b/adv2015/src/day9.rs @@ -1,16 +1,15 @@ -use std::collections::{HashMap, HashSet}; use permute::permutations_of; -use std::iter::FromIterator; use std::cmp; +use std::collections::{HashMap, HashSet}; +use std::iter::FromIterator; pub fn calc_shortest(input: &str) -> usize { let mut santa = Santa::new(); - input.lines() - .for_each(|line| { - let path = parse_to_path(line); - santa.add_path(&path); - }); + input.lines().for_each(|line| { + let path = parse_to_path(line); + santa.add_path(&path); + }); santa.find_path().0 } @@ -18,11 +17,10 @@ pub fn calc_shortest(input: &str) -> usize { pub fn calc_longest(input: &str) -> usize { let mut santa = Santa::new(); - input.lines() - .for_each(|line| { - let path = parse_to_path(line); - santa.add_path(&path); - }); + input.lines().for_each(|line| { + let path = parse_to_path(line); + santa.add_path(&path); + }); santa.find_path().1 } @@ -47,8 +45,10 @@ impl Santa { self.cities.insert(city1.clone()); self.cities.insert(city2.clone()); - self.distances.insert((city1.clone(), city2.clone()), *distance); - self.distances.insert((city2.clone(), city1.clone()), *distance); + self.distances + .insert((city1.clone(), city2.clone()), *distance); + self.distances + .insert((city2.clone(), city1.clone()), *distance); } fn find_path(&self) -> (usize, usize) { @@ -65,7 +65,10 @@ impl Santa { continue; } - let path = *self.distances.get(&(prev_city.clone(), (*city).clone())).unwrap(); + let path = *self + .distances + .get(&(prev_city.clone(), (*city).clone())) + .unwrap(); prev_city = (*city).clone(); current_distance += path; @@ -82,7 +85,11 @@ impl Santa { fn parse_to_path(input: &str) -> Path { let split: Vec<&str> = input.split_whitespace().collect(); - Path(split[0].to_string(), split[2].to_string(), split[4].parse::().unwrap()) + Path( + split[0].to_string(), + split[2].to_string(), + split[4].parse::().unwrap(), + ) } #[cfg(test)] @@ -104,10 +111,11 @@ mod tests { "London to Dublin = 464 London to Belfast = 518 Dublin to Belfast = 141" - .lines().for_each(|line| { - let path = parse_to_path(line); - santa.add_path(&path); - }); + .lines() + .for_each(|line| { + let path = parse_to_path(line); + santa.add_path(&path); + }); assert_eq!(santa.cities.len(), 3); assert_eq!(santa.distances.len(), 6); diff --git a/adv2015/src/lib.rs b/adv2015/src/lib.rs index e8e12e8..4528c92 100644 --- a/adv2015/src/lib.rs +++ b/adv2015/src/lib.rs @@ -1,86 +1,210 @@ -/* */ -mod day1; -mod day2; -mod day3; -mod day4; -mod day5; -mod day6; -mod day7; -mod day8; -mod day9; -mod day10; -mod day11; -mod day12; -mod day13; -mod day14; -mod day15; -mod day16; -mod day17; -mod day18; -mod day19; -mod day20; -mod day21; -mod day22; -mod day23; -mod day24; -mod day25; -/* */ - -pub fn print_answers(day: u8, input: String) { - // Trim is mandatory for one-line inputs - let input = input.as_str().trim(); - let prefix = format!("Day {} / 2015:", day); - match day { - 1 => println!("{} {} and {}", prefix, day1::count_brackets(input), day1::count_position(input).unwrap_or(-1)), - 2 => println!("{} {} and {}", prefix, day2::calc_packs(input), day2::calc_ribbons(input)), - 3 => println!("{} {} and {}", prefix, day3::count_houses(input), day3::count_houses_together(input)), - 4 => println!("{} {} and {}", prefix, day4::mine_suffix(input, 5), day4::mine_suffix(input, 6)), - 5 => println!("{} {} and {}", prefix, day5::count_nice_lines(input), day5::count_nice_lines_advanced(input)), - 6 => println!("{} {} and {}", prefix, day6::count_bulbs(input), day6::count_brightness(input)), - 7 => println!("{} {} and {}", prefix, day7::count_input_a(input), day7::count_input_a_override(input)), - 8 => println!("{} {} and {}", prefix, day8::calc_difference(input), day8::calc_new_difference(input)), - 9 => println!("{} {} and {}", prefix, day9::calc_shortest(input), day9::calc_longest(input)), - 10 => println!("{} {} and {}", prefix, day10::calc_first(input), day10::calc_second(input)), - 11 => println!("{} {} and {}", prefix, day11::get_expired_once(input), day11::get_expired_twice(input)), - 12 => println!("{} {} and {}", prefix, day12::get_answer(input), day12::get_answer_without_red(input)), - 13 => println!("{} {} and {}", prefix, day13::get_answer(input), day13::get_answer_with_me(input)), - 14 => println!("{} {} and {}", prefix, day14::get_answer(input), day14::get_answer_points(input)), - 15 => println!("{} {} and {}", prefix, day15::get_answer(input), day15::get_answer_with_calories(input)), - 16 => println!("{} {} and {}", prefix, day16::get_answer(input), day16::get_answer_from_retroencabulator(input)), - 17 => println!("{} {} and {}", prefix, day17::get_total_count_of_combinations(input), day17::get_minimal_count_of_cans(input)), - 18 => println!("{} {} and {}", prefix, day18::get_answer_normal(input), day18::get_answer_broken(input)), - 19 => println!("{} {} and {}", prefix, day19::count_unique_molecules(input), day19::count_molecules_from_electron(input)), - 20 => println!("{} {} and {}", prefix, day20::get_richest_house_before_strike(input), day20::get_richest_house_after_strike(input)), - 21 => println!("{} {} and {}", prefix, day21::find_cheapest_warrior(input), day21::find_expensive_loser(input)), - 22 => println!("{} {} and {}", prefix, day22::find_easy_result(input), day22::find_hard_result(input)), - 23 => println!("{} {} and {}", prefix, day23::get_answer_b(input), day23::get_answer_b_after_a(input)), - 24 => println!("{} {} and {}", prefix, day24::find_answer(input), day24::find_answer_better(input)), - 25 => println!("{} {}", prefix, day25::find_code(input)), - _ => { eprintln!("2015: I don't know the answer for day {} :(", day) } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_print_answers() { - for i in 0..26 { - let mut input = String::new(); - - // Required to speed-up tests & increase the coverage - if i == 4 { - input = String::from("abcdef"); - } else if i == 7 { - input = String::from("123 -> a"); - } else if i == 13 { - input = String::from("Vest would gain 1 happiness units by sitting next to Vest."); - } else if i == 15 { - input = String::from("Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8"); - } - - print_answers(i, input); - } - } -} +/* */ +mod day1; +mod day10; +mod day11; +mod day12; +mod day13; +mod day14; +mod day15; +mod day16; +mod day17; +mod day18; +mod day19; +mod day2; +mod day20; +mod day21; +mod day22; +mod day23; +mod day24; +mod day25; +mod day3; +mod day4; +mod day5; +mod day6; +mod day7; +mod day8; +mod day9; +/* */ + +pub fn print_answers(day: u8, input: String) { + // Trim is mandatory for one-line inputs + let input = input.as_str().trim(); + let prefix = format!("Day {} / 2015:", day); + match day { + 1 => println!( + "{} {} and {}", + prefix, + day1::count_brackets(input), + day1::count_position(input).unwrap_or(-1) + ), + 2 => println!( + "{} {} and {}", + prefix, + day2::calc_packs(input), + day2::calc_ribbons(input) + ), + 3 => println!( + "{} {} and {}", + prefix, + day3::count_houses(input), + day3::count_houses_together(input) + ), + 4 => println!( + "{} {} and {}", + prefix, + day4::mine_suffix(input, 5), + day4::mine_suffix(input, 6) + ), + 5 => println!( + "{} {} and {}", + prefix, + day5::count_nice_lines(input), + day5::count_nice_lines_advanced(input) + ), + 6 => println!( + "{} {} and {}", + prefix, + day6::count_bulbs(input), + day6::count_brightness(input) + ), + 7 => println!( + "{} {} and {}", + prefix, + day7::count_input_a(input), + day7::count_input_a_override(input) + ), + 8 => println!( + "{} {} and {}", + prefix, + day8::calc_difference(input), + day8::calc_new_difference(input) + ), + 9 => println!( + "{} {} and {}", + prefix, + day9::calc_shortest(input), + day9::calc_longest(input) + ), + 10 => println!( + "{} {} and {}", + prefix, + day10::calc_first(input), + day10::calc_second(input) + ), + 11 => println!( + "{} {} and {}", + prefix, + day11::get_expired_once(input), + day11::get_expired_twice(input) + ), + 12 => println!( + "{} {} and {}", + prefix, + day12::get_answer(input), + day12::get_answer_without_red(input) + ), + 13 => println!( + "{} {} and {}", + prefix, + day13::get_answer(input), + day13::get_answer_with_me(input) + ), + 14 => println!( + "{} {} and {}", + prefix, + day14::get_answer(input), + day14::get_answer_points(input) + ), + 15 => println!( + "{} {} and {}", + prefix, + day15::get_answer(input), + day15::get_answer_with_calories(input) + ), + 16 => println!( + "{} {} and {}", + prefix, + day16::get_answer(input), + day16::get_answer_from_retroencabulator(input) + ), + 17 => println!( + "{} {} and {}", + prefix, + day17::get_total_count_of_combinations(input), + day17::get_minimal_count_of_cans(input) + ), + 18 => println!( + "{} {} and {}", + prefix, + day18::get_answer_normal(input), + day18::get_answer_broken(input) + ), + 19 => println!( + "{} {} and {}", + prefix, + day19::count_unique_molecules(input), + day19::count_molecules_from_electron(input) + ), + 20 => println!( + "{} {} and {}", + prefix, + day20::get_richest_house_before_strike(input), + day20::get_richest_house_after_strike(input) + ), + 21 => println!( + "{} {} and {}", + prefix, + day21::find_cheapest_warrior(input), + day21::find_expensive_loser(input) + ), + 22 => println!( + "{} {} and {}", + prefix, + day22::find_easy_result(input), + day22::find_hard_result(input) + ), + 23 => println!( + "{} {} and {}", + prefix, + day23::get_answer_b(input), + day23::get_answer_b_after_a(input) + ), + 24 => println!( + "{} {} and {}", + prefix, + day24::find_answer(input), + day24::find_answer_better(input) + ), + 25 => println!("{} {}", prefix, day25::find_code(input)), + _ => { + eprintln!("2015: I don't know the answer for day {} :(", day) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_print_answers() { + for i in 0..26 { + let mut input = String::new(); + + // Required to speed-up tests & increase the coverage + if i == 4 { + input = String::from("abcdef"); + } else if i == 7 { + input = String::from("123 -> a"); + } else if i == 13 { + input = String::from("Vest would gain 1 happiness units by sitting next to Vest."); + } else if i == 15 { + input = String::from( + "Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8", + ); + } + + print_answers(i, input); + } + } +} diff --git a/adv2020/Cargo.toml b/adv2020/Cargo.toml index e537460..b7f1189 100644 --- a/adv2020/Cargo.toml +++ b/adv2020/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adv2020" -version = "0.17.0" +version = "0.17.1" authors = ["Vest "] edition = "2018" @@ -13,4 +13,4 @@ doc = false [dependencies] combinations = "0.1.0" -itertools = "0.9.0" +itertools = "0.10.5" diff --git a/adv2020/src/day1.rs b/adv2020/src/day1.rs index f775d74..d048eb2 100644 --- a/adv2020/src/day1.rs +++ b/adv2020/src/day1.rs @@ -17,7 +17,8 @@ pub fn find_more_expenses(input: &str) -> usize { } fn parse_input(input: &str) -> Vec { - input.lines() + input + .lines() .map(|l| l.trim()) .filter_map(|n| n.parse::().ok()) .collect() @@ -90,21 +91,31 @@ mod tests { #[test] fn test_find_expenses() { - assert_eq!(find_expenses(r#"1721 + assert_eq!( + find_expenses( + r#"1721 979 366 299 675 - 1456"#), 514579); + 1456"# + ), + 514579 + ); } #[test] fn test_find_more_expenses() { - assert_eq!(find_more_expenses(r#"1721 + assert_eq!( + find_more_expenses( + r#"1721 979 366 299 675 - 1456"#), 241861950); + 1456"# + ), + 241861950 + ); } } diff --git a/adv2020/src/day10.rs b/adv2020/src/day10.rs index a30390e..0aea773 100644 --- a/adv2020/src/day10.rs +++ b/adv2020/src/day10.rs @@ -13,7 +13,8 @@ pub fn find_all_combinations(input: &str) -> usize { } fn parse_as_sorted(input: &str) -> Vec { - let mut result: Vec = input.lines() + let mut result: Vec = input + .lines() .map(&str::trim) .map(&str::parse::) .filter_map(Result::ok) @@ -35,9 +36,9 @@ impl Default for OneTwo { } } - fn group_by_difference(input: &[usize]) -> OneTwo { - input.windows(2) + input + .windows(2) .filter(check_jolt) .fold(OneTwo::default(), |mut acc, pair| { match pair[1].saturating_sub(pair[0]) { @@ -57,7 +58,7 @@ fn check_jolt(pair: &&[usize]) -> bool { match pair[1].saturating_sub(pair[0]) { 1 | 2 | 3 => true, - _ => false + _ => false, } } @@ -66,9 +67,7 @@ fn is_chain_valid(chain: &[usize]) -> bool { return false; } - chain.windows(2) - .find(|pair| !check_jolt(pair)) - .is_none() + chain.windows(2).find(|pair| !check_jolt(pair)).is_none() } fn count_possible_valid_chains(chain: &[usize]) -> usize { @@ -76,18 +75,18 @@ fn count_possible_valid_chains(chain: &[usize]) -> usize { // creates a vector with jolts, with the difference equal to 1: // one_diffs: [[0, 1], [4, 5, 6, 7], [10, 11, 12], [15, 16], [19], [22]] - chain.windows(2) - .for_each(|window| { - let diff = window[1] - window[0]; - let last = one_diffs.last_mut().unwrap(); - last.push(window[0]); - if diff == 3 { - one_diffs.push(vec![]); - } - }); + chain.windows(2).for_each(|window| { + let diff = window[1] - window[0]; + let last = one_diffs.last_mut().unwrap(); + last.push(window[0]); + if diff == 3 { + one_diffs.push(vec![]); + } + }); one_diffs.last_mut().unwrap().push(*chain.last().unwrap()); - one_diffs.iter() + one_diffs + .iter() .map(|joins| { let length = joins.len(); if length == 1 || length == 2 { @@ -107,7 +106,8 @@ fn count_one_diff_joints(adapters: &[usize]) -> usize { (1..length - 1) .map(|k| { // all possible combinations. E.g. [4, 5, 6, 7] gives [4, 5, 7], [4, 6, 7], [4, 5, 6, 7] - adapters[1..length - 1].iter() + adapters[1..length - 1] + .iter() .combinations(k) .filter(|joint_combination| { let mut tmp_joint = vec![adapters[0]]; @@ -115,9 +115,11 @@ fn count_one_diff_joints(adapters: &[usize]) -> usize { tmp_joint.push(*adapters.last().unwrap()); is_chain_valid(&tmp_joint) - }).count() - }).sum::() + - { + }) + .count() + }) + .sum::() + + { // Situation, when we check: [4, 5, 6, 7] -> [4, 7] if is_chain_valid(&vec![adapters[0], adapters[length - 1]]) { 1 @@ -166,8 +168,12 @@ mod tests { #[test] fn test_is_chain_valid() { - assert!(is_chain_valid(&vec![0, 1, 4, 5, 6, 7, 10, 11, 12, 15, 16, 19, 22])); - assert!(is_chain_valid(&vec![0, 1, 4, 5, 6, 7, 10, 12, 15, 16, 19, 22])); + assert!(is_chain_valid(&vec![ + 0, 1, 4, 5, 6, 7, 10, 11, 12, 15, 16, 19, 22 + ])); + assert!(is_chain_valid(&vec![ + 0, 1, 4, 5, 6, 7, 10, 12, 15, 16, 19, 22 + ])); assert!(is_chain_valid(&vec![0, 1, 4, 6, 7, 10, 12, 15, 16, 19, 22])); assert!(!is_chain_valid(&vec![0, 1, 5, 8])); @@ -176,11 +182,17 @@ mod tests { #[test] fn test_count_possible_valid_chains() { - assert_eq!(count_possible_valid_chains(&vec![0, 1, 4, 5, 6, 7, 10, 11, - 12, 15, 16, 19, 22]), 8); - assert_eq!(count_possible_valid_chains(&vec![0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 14, 17, - 18, 19, 20, 23, 24, 25, 28, 31, 32, 33, 34, 35, - 38, 39, 42, 45, 46, 47, 48, 49, 52]), 19208); + assert_eq!( + count_possible_valid_chains(&vec![0, 1, 4, 5, 6, 7, 10, 11, 12, 15, 16, 19, 22]), + 8 + ); + assert_eq!( + count_possible_valid_chains(&vec![ + 0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 14, 17, 18, 19, 20, 23, 24, 25, 28, 31, 32, 33, 34, + 35, 38, 39, 42, 45, 46, 47, 48, 49, 52 + ]), + 19208 + ); } #[test] diff --git a/adv2020/src/day11.rs b/adv2020/src/day11.rs index fe4fdc4..443f842 100644 --- a/adv2020/src/day11.rs +++ b/adv2020/src/day11.rs @@ -1,5 +1,5 @@ -use std::convert::TryFrom; use itertools::iproduct; +use std::convert::TryFrom; pub fn find_places_direct(input: &str) -> usize { let mut plane = Plane::new(input); @@ -9,7 +9,6 @@ pub fn find_places_direct(input: &str) -> usize { plane.count_all() } - pub fn find_seats_visible_only(input: &str) -> usize { let mut plane = Plane::new(input); let iter = plane.evo_visible_iter(); @@ -42,31 +41,26 @@ struct PlaneIter<'a> { impl Plane { fn new(input: &str) -> Plane { - let seats: Vec> = input.lines() + let seats: Vec> = input + .lines() .map(&str::trim) - .map(|line| line.chars() - .map(Seat::from) - .collect()) + .map(|line| line.chars().map(Seat::from).collect()) .collect(); let rows = seats.len(); let cols = seats.get(0).unwrap_or(&Vec::new()).len(); - Plane { - seats, - - rows, - cols, - } + Plane { seats, rows, cols } } fn get_seat(&self, row: i32, col: i32) -> &Seat { match (usize::try_from(row), usize::try_from(col)) { - (Ok(row), Ok(col)) => self.seats + (Ok(row), Ok(col)) => self + .seats .get(row) .and_then(|row| row.get(col)) .unwrap_or(&Seat::NoSeat), - _ => &Seat::NoSeat + _ => &Seat::NoSeat, } } @@ -74,22 +68,24 @@ impl Plane { fn print(&self) { for row in 0..(self.rows as i32) { for col in 0..(self.cols as i32) { - print!("{}", match self.get_seat(row, col) { - Seat::Vacant => 'L', - Seat::Occupied => '#', - Seat::NoSeat => '.', - }); + print!( + "{}", + match self.get_seat(row, col) { + Seat::Vacant => 'L', + Seat::Occupied => '#', + Seat::NoSeat => '.', + } + ); } println!(); } } fn count_all(&self) -> usize { - self.seats.iter() - .map(|row| row.iter() - .filter(|&seat| seat == &Seat::Occupied) - .count() - ).sum() + self.seats + .iter() + .map(|row| row.iter().filter(|&seat| seat == &Seat::Occupied).count()) + .sum() } fn evo_direct_iter(&mut self) -> PlaneIter { @@ -114,9 +110,7 @@ impl Plane { fn count_direct_neighbours(plane: &Plane, row: usize, col: usize) -> usize { iproduct!(-1..=1, -1..=1) .filter(|&(dr, dc)| !(dr == 0 && dc == 0)) // exclude center - .filter(|&(dr, dc)| { - plane.get_seat(row as i32 + dr, col as i32 + dc) == &Seat::Occupied - }) + .filter(|&(dr, dc)| plane.get_seat(row as i32 + dr, col as i32 + dc) == &Seat::Occupied) .count() } @@ -168,18 +162,20 @@ impl<'a> Iterator for PlaneIter<'a> { let mut state = Vec::>::with_capacity(self.plane.rows); (0..self.plane.rows).for_each(|_| state.push(vec![Seat::NoSeat; self.plane.cols])); - iproduct!(0..self.plane.rows, 0..self.plane.cols) - .for_each(|(row, col)| { - let neighbours = (self.count_fn)(self.plane, row, col); - let ¤t_seat = self.plane.get_seat(row as i32, col as i32); + iproduct!(0..self.plane.rows, 0..self.plane.cols).for_each(|(row, col)| { + let neighbours = (self.count_fn)(self.plane, row, col); + let ¤t_seat = self.plane.get_seat(row as i32, col as i32); - state[row][col] = (self.should_seat_fn)(current_seat, neighbours); - }); + state[row][col] = (self.should_seat_fn)(current_seat, neighbours); + }); - if state.iter().zip(self.plane.seats.iter()) - .filter(|(r1, r2)| - r1.eq(r2) - ).count() == self.plane.rows { + if state + .iter() + .zip(self.plane.seats.iter()) + .filter(|(r1, r2)| r1.eq(r2)) + .count() + == self.plane.rows + { return None; } @@ -199,11 +195,10 @@ impl From for Seat { } } - #[cfg(test)] mod tests { use super::*; - use std::fmt::{Debug, Formatter, Write, Result}; + use std::fmt::{Debug, Formatter, Result, Write}; const INPUT: &str = r#"L.LL.LL.LL LLLLLLL.LL @@ -262,7 +257,8 @@ mod tests { #[test] fn test_count_visible_neighbours() { - let plane1 = Plane::new(r#".......#. + let plane1 = Plane::new( + r#".......#. ...#..... .#....... ......... @@ -270,26 +266,34 @@ mod tests { ....#.... ......... #........ - ...#....."#); + ...#....."#, + ); assert_eq!(count_visible_neighbours(&plane1, 4, 3), 8); - let plane2 = Plane::new(r#"............. + let plane2 = Plane::new( + r#"............. .L.L.#.#.#.#. - ............."#); + ............."#, + ); assert_eq!(count_visible_neighbours(&plane2, 1, 1), 0); - let plane3 = Plane::new(r#".##.##. + let plane3 = Plane::new( + r#".##.##. #.#.#.# ##...## ...L... ##...## #.#.#.# - .##.##."#); + .##.##."#, + ); assert_eq!(count_visible_neighbours(&plane3, 3, 3), 0); } #[test] fn test_seat_debug() { - assert_eq!(format!("{:?}{:?}{:?}", Seat::Vacant, Seat::NoSeat, Seat::Occupied),"L.#"); + assert_eq!( + format!("{:?}{:?}{:?}", Seat::Vacant, Seat::NoSeat, Seat::Occupied), + "L.#" + ); } } diff --git a/adv2020/src/day12.rs b/adv2020/src/day12.rs index 40756f8..de23a3d 100644 --- a/adv2020/src/day12.rs +++ b/adv2020/src/day12.rs @@ -4,34 +4,31 @@ pub fn find_answer1(input: &str) -> i32 { direction: 0, }; - input.lines() - .for_each(|line| { - let mut chars = line.chars(); - let direction = chars.next().unwrap(); - let value_str = chars.collect::(); - let value = value_str.parse::().unwrap(); - - match direction { - 'N' => ship.position.1 += value, - 'S' => ship.position.1 -= value, - 'E' => ship.position.0 += value, - 'W' => ship.position.0 -= value, - 'L' => ship.direction += value, - 'R' => ship.direction -= value, - 'F' if ship.direction == 0 => ship.position.0 += value, - 'F' if ship.direction == 90 => ship.position.1 += value, - 'F' if ship.direction == 180 => ship.position.0 -= value, - 'F' if ship.direction == 270 => ship.position.1 -= value, - 'F' if ship.direction == -90 => ship.position.1 -= value, - 'F' if ship.direction == -180 => ship.position.0 -= value, - 'F' if ship.direction == -270 => ship.position.1 += value, - _ => ( - println!("pfffffff") - ), - } - - ship.direction %= 360; - }); + input.lines().for_each(|line| { + let mut chars = line.chars(); + let direction = chars.next().unwrap(); + let value_str = chars.collect::(); + let value = value_str.parse::().unwrap(); + + match direction { + 'N' => ship.position.1 += value, + 'S' => ship.position.1 -= value, + 'E' => ship.position.0 += value, + 'W' => ship.position.0 -= value, + 'L' => ship.direction += value, + 'R' => ship.direction -= value, + 'F' if ship.direction == 0 => ship.position.0 += value, + 'F' if ship.direction == 90 => ship.position.1 += value, + 'F' if ship.direction == 180 => ship.position.0 -= value, + 'F' if ship.direction == 270 => ship.position.1 -= value, + 'F' if ship.direction == -90 => ship.position.1 -= value, + 'F' if ship.direction == -180 => ship.position.0 -= value, + 'F' if ship.direction == -270 => ship.position.1 += value, + _ => println!("pfffffff"), + } + + ship.direction %= 360; + }); ship.position.0.abs() + ship.position.1.abs() } @@ -41,7 +38,6 @@ struct Ship { direction: i32, } - struct Titanic { position: (i32, i32), waypoint: (i32, i32), @@ -53,41 +49,48 @@ pub fn find_answer2(input: &str) -> i32 { waypoint: (10, 1), }; - input.lines() - .for_each(|line| { - let mut chars = line.chars(); - let direction = chars.next().unwrap(); - let value_str = chars.collect::(); - let value = value_str.parse::().unwrap(); - let value_neg = -value; - - let ca = (value as f64).to_radians().cos() as i32; - let sa = (value as f64).to_radians().sin() as i32; - - let cra = (value_neg as f64).to_radians().cos() as i32; - let sra = (value_neg as f64).to_radians().sin() as i32; - - match direction { - 'N' => titanic.waypoint.1 += value, - 'S' => titanic.waypoint.1 -= value, - 'E' => titanic.waypoint.0 += value, - 'W' => titanic.waypoint.0 -= value, - - 'L' => titanic.waypoint = (ca * titanic.waypoint.0 - sa * titanic.waypoint.1, sa * titanic.waypoint.0 + ca * titanic.waypoint.1), - 'R' => titanic.waypoint = (cra * titanic.waypoint.0 - sra * titanic.waypoint.1, sra * titanic.waypoint.0 + cra * titanic.waypoint.1), - - 'F' => { - titanic.position.0 += value * titanic.waypoint.0; - titanic.position.1 += value * titanic.waypoint.1; - } - - _ => ( - println!("pfffffff") - ), + input.lines().for_each(|line| { + let mut chars = line.chars(); + let direction = chars.next().unwrap(); + let value_str = chars.collect::(); + let value = value_str.parse::().unwrap(); + let value_neg = -value; + + let ca = (value as f64).to_radians().cos() as i32; + let sa = (value as f64).to_radians().sin() as i32; + + let cra = (value_neg as f64).to_radians().cos() as i32; + let sra = (value_neg as f64).to_radians().sin() as i32; + + match direction { + 'N' => titanic.waypoint.1 += value, + 'S' => titanic.waypoint.1 -= value, + 'E' => titanic.waypoint.0 += value, + 'W' => titanic.waypoint.0 -= value, + + 'L' => { + titanic.waypoint = ( + ca * titanic.waypoint.0 - sa * titanic.waypoint.1, + sa * titanic.waypoint.0 + ca * titanic.waypoint.1, + ) + } + 'R' => { + titanic.waypoint = ( + cra * titanic.waypoint.0 - sra * titanic.waypoint.1, + sra * titanic.waypoint.0 + cra * titanic.waypoint.1, + ) + } + + 'F' => { + titanic.position.0 += value * titanic.waypoint.0; + titanic.position.1 += value * titanic.waypoint.1; } - println!("{} - {:?} {:?}", line, titanic.position, titanic.waypoint); - }); + _ => println!("pfffffff"), + } + + println!("{} - {:?} {:?}", line, titanic.position, titanic.waypoint); + }); titanic.position.0.abs() + titanic.position.1.abs() } @@ -103,18 +106,27 @@ fn parse_input<'a>(input: &'a str) -> impl Iterator + 'a { mod tests { use super::*; - #[test] fn test_empty_answers() { - assert_eq!(find_answer1(r#"F10 + assert_eq!( + find_answer1( + r#"F10 N3 F7 R90 -F11"#), 25); - assert_eq!(find_answer2(r#"F10 +F11"# + ), + 25 + ); + assert_eq!( + find_answer2( + r#"F10 N3 F7 R90 -F11"#), 286); +F11"# + ), + 286 + ); } } diff --git a/adv2020/src/day13.rs b/adv2020/src/day13.rs index cb284d5..77cfdd4 100644 --- a/adv2020/src/day13.rs +++ b/adv2020/src/day13.rs @@ -4,9 +4,10 @@ pub fn find_earliest_bus(input: &str) -> usize { } let mut lines = input.lines(); - let time = lines.next().unwrap() - .parse::().unwrap(); - let bus = lines.next().unwrap() + let time = lines.next().unwrap().parse::().unwrap(); + let bus = lines + .next() + .unwrap() .split(|c| c == ',') .map(str::parse::) .filter_map(Result::ok) @@ -22,29 +23,33 @@ pub fn find_earliest_timestamp(input: &str) -> usize { return 0; } - let buses: Vec<(usize, usize)> = input.lines() + let buses: Vec<(usize, usize)> = input + .lines() .skip(1) - .next().unwrap() + .next() + .unwrap() .split(|c| c == ',') .enumerate() - .filter_map(|(pos, str)| + .filter_map(|(pos, str)| { if let Ok(num) = str.parse::() { Some((pos, num)) } else { None } - ) - .map(|(pos, num)| if pos != 0 { - let mut checked_sub = None; - let mut i = 1usize; - while checked_sub.is_none() { - checked_sub = (num * i).checked_sub(pos); - i += 1; + }) + .map(|(pos, num)| { + if pos != 0 { + let mut checked_sub = None; + let mut i = 1usize; + while checked_sub.is_none() { + checked_sub = (num * i).checked_sub(pos); + i += 1; + } + + (checked_sub.unwrap(), num) + } else { + (pos, num) } - - (checked_sub.unwrap(), num) - } else { - (pos, num) }) .collect(); @@ -52,27 +57,24 @@ pub fn find_earliest_timestamp(input: &str) -> usize { } fn chinese_remainder_theorem(nums: &[(usize, usize)]) -> (usize, usize) { - let m_product: usize = nums.iter() - .map(|(_, modulo)| modulo) - .product(); + let m_product: usize = nums.iter().map(|(_, modulo)| modulo).product(); - let mi = nums.iter() + let mi = nums + .iter() .map(|(_, modulo)| m_product / modulo) .collect::>(); - let yi = nums.iter() + let yi = nums + .iter() .map(|(_, modulo)| *modulo) .zip(mi.iter()) - .map(|(modulo, &mi)| { - (1..mi).find(|&rem| - (rem * mi) % modulo == 1 - ).unwrap() - }) + .map(|(modulo, &mi)| (1..mi).find(|&rem| (rem * mi) % modulo == 1).unwrap()) .collect::>(); let x = (0..nums.len()) .map(|i| nums[i].0 * mi[i] * yi[i]) - .sum::() % m_product; + .sum::() + % m_product; (x, m_product) } @@ -123,7 +125,13 @@ mod tests { #[test] fn test_chinese_remainder_theorem() { - assert_eq!(chinese_remainder_theorem(&[(2, 3), (3, 5), (1, 7)]), (8, 105)); - assert_eq!(chinese_remainder_theorem(&[(0, 7), (12, 13), (55, 59), (25, 31), (12, 19)]), (1068781, 7 * 13 * 59 * 31 * 19)); + assert_eq!( + chinese_remainder_theorem(&[(2, 3), (3, 5), (1, 7)]), + (8, 105) + ); + assert_eq!( + chinese_remainder_theorem(&[(0, 7), (12, 13), (55, 59), (25, 31), (12, 19)]), + (1068781, 7 * 13 * 59 * 31 * 19) + ); } } diff --git a/adv2020/src/day14.rs b/adv2020/src/day14.rs index 1786999..f11ccfb 100644 --- a/adv2020/src/day14.rs +++ b/adv2020/src/day14.rs @@ -4,20 +4,17 @@ pub fn find_answer1(input: &str) -> usize { let mut mem: HashMap = HashMap::new(); let mut current_mask = String::new(); - input.lines() - .map(&str::trim) - .for_each(|line: &str| { - if line.starts_with("mask") { - current_mask = extract_mask(line); - } else { - let (address, mut value) = extract_address_value(line); - value = apply_mask(value, current_mask.as_str()); - mem.insert(address, value); - } - }); - - mem.values() - .sum() + input.lines().map(&str::trim).for_each(|line: &str| { + if line.starts_with("mask") { + current_mask = extract_mask(line); + } else { + let (address, mut value) = extract_address_value(line); + value = apply_mask(value, current_mask.as_str()); + mem.insert(address, value); + } + }); + + mem.values().sum() } fn extract_mask(input: &str) -> String { @@ -33,39 +30,35 @@ fn extract_address_value(input: &str) -> (usize, usize) { } fn apply_mask(mut value: usize, bitmask: &str) -> usize { - bitmask.chars() + bitmask + .chars() .rev() .enumerate() - .for_each(|(position, bit)| { - match bit { - '0' => { - value &= !(1 << position); - } - '1' => { - value |= 1 << position; - } - _ => (), + .for_each(|(position, bit)| match bit { + '0' => { + value &= !(1 << position); } + '1' => { + value |= 1 << position; + } + _ => (), }); value } fn create_mask(address: usize, bitmask: &str) -> String { - bitmask.chars() + bitmask + .chars() .rev() .enumerate() - .map(|(position, bit)| { - match bit { - '0' => { - match (address >> position) & 1 { - 0 => '0', - _ => '1', - } - } - '1' => '1', - _ => 'X', - } + .map(|(position, bit)| match bit { + '0' => match (address >> position) & 1 { + 0 => '0', + _ => '1', + }, + '1' => '1', + _ => 'X', }) .collect::() .chars() @@ -76,47 +69,52 @@ fn create_mask(address: usize, bitmask: &str) -> String { fn generate_addresses(bitmask: &str) -> Vec { let total = bitmask.chars().filter(|c| *c == 'X').count(); - (0..2usize.pow(total as u32)).map(|i| { - let mut j = 0usize; - - bitmask.chars() - .map(|c| match c { - 'X' => { - let bit = (i & 1 << j) >> j; - j += 1; - if bit == 0 { '0' } else { '1' } - } - _ => c, - }).collect() - }).collect() + (0..2usize.pow(total as u32)) + .map(|i| { + let mut j = 0usize; + + bitmask + .chars() + .map(|c| match c { + 'X' => { + let bit = (i & 1 << j) >> j; + j += 1; + if bit == 0 { + '0' + } else { + '1' + } + } + _ => c, + }) + .collect() + }) + .collect() } pub fn find_answer2(input: &str) -> usize { let mut mem: HashMap = HashMap::new(); let mut mask: String = String::new(); - input.lines() - .map(&str::trim) - .for_each(|line: &str| { - if line.starts_with("mask") { - mask = extract_mask(line); - } else { - let (address, value) = extract_address_value(line); - let addresses = generate_addresses(create_mask(address, mask.as_str()).as_str()); - addresses.iter() - .for_each(|addr| { - mem.insert(bit_to_usize(addr), value); - }) - } - }); - - mem.values() - .sum() + input.lines().map(&str::trim).for_each(|line: &str| { + if line.starts_with("mask") { + mask = extract_mask(line); + } else { + let (address, value) = extract_address_value(line); + let addresses = generate_addresses(create_mask(address, mask.as_str()).as_str()); + addresses.iter().for_each(|addr| { + mem.insert(bit_to_usize(addr), value); + }) + } + }); + + mem.values().sum() } fn bit_to_usize(input: &str) -> usize { - input.chars() - .fold(0, |acc, bit_char| acc << 1 | if bit_char == '0' { 0 } else { 1 }) + input.chars().fold(0, |acc, bit_char| { + acc << 1 | if bit_char == '0' { 0 } else { 1 } + }) } #[cfg(test)] @@ -131,15 +129,20 @@ mod tests { #[test] fn test_extract_mask() { - assert_eq!(extract_mask("mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"), "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"); + assert_eq!( + extract_mask("mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"), + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X" + ); } #[test] fn test_extract_address_value() { - assert_eq!(extract_address_value("mem[23073] = 4721114"), (23073, 4721114)); + assert_eq!( + extract_address_value("mem[23073] = 4721114"), + (23073, 4721114) + ); } - #[test] fn test_apply_mask() { assert_eq!(apply_mask(11, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X"), 73); @@ -149,16 +152,27 @@ mod tests { #[test] fn test_find_answer1() { - assert_eq!(find_answer1(r#"mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X + assert_eq!( + find_answer1( + r#"mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X mem[8] = 11 mem[7] = 101 - mem[8] = 0"#), 165); + mem[8] = 0"# + ), + 165 + ); } #[test] fn test_create_mask() { - assert_eq!(create_mask(42, "000000000000000000000000000000X1001X"), "000000000000000000000000000000X1101X"); - assert_eq!(create_mask(26, "00000000000000000000000000000000X0XX"), "00000000000000000000000000000001X0XX"); + assert_eq!( + create_mask(42, "000000000000000000000000000000X1001X"), + "000000000000000000000000000000X1101X" + ); + assert_eq!( + create_mask(26, "00000000000000000000000000000000X0XX"), + "00000000000000000000000000000001X0XX" + ); } #[test] @@ -177,10 +191,15 @@ mod tests { #[test] fn test_find_answer2() { - assert_eq!(find_answer2(r#"mask = 000000000000000000000000000000X1001X + assert_eq!( + find_answer2( + r#"mask = 000000000000000000000000000000X1001X mem[42] = 100 mask = 00000000000000000000000000000000X0XX - mem[26] = 1"#), 208); + mem[26] = 1"# + ), + 208 + ); } #[test] diff --git a/adv2020/src/day15.rs b/adv2020/src/day15.rs index a6861ee..758316d 100644 --- a/adv2020/src/day15.rs +++ b/adv2020/src/day15.rs @@ -14,14 +14,17 @@ struct Game { impl Game { fn new(input: &str) -> Game { let mut numbers: HashMap = HashMap::new(); - let round = input.split(|c| c == ',') + let round = input + .split(|c| c == ',') .map(&str::parse::) .filter_map(Result::ok) .enumerate() .map(|(pos, num)| { numbers.insert(num, pos + 1); pos + 1 - }).max().unwrap_or_default(); + }) + .max() + .unwrap_or_default(); Game { numbers_rounds: numbers, @@ -51,7 +54,8 @@ impl Game { next_number = Some(0); } - self.numbers_rounds.insert(last_number.unwrap(), self.round - 1); + self.numbers_rounds + .insert(last_number.unwrap(), self.round - 1); } if next_number.is_some() { @@ -110,13 +114,13 @@ mod tests { #[ignore] fn test_find_number_30000000() { assert_eq!(find_number_30000000("0,3,6"), 175594); -/* - assert_eq!(find_number_30000000("1,3,2"), 2578); - assert_eq!(find_number_30000000("2,1,3"), 3544142); - assert_eq!(find_number_30000000("1,2,3"), 261214); - assert_eq!(find_number_30000000("2,3,1"), 6895259); - assert_eq!(find_number_30000000("3,2,1"), 18); - assert_eq!(find_number_30000000("3,1,2"), 362); - */ + /* + assert_eq!(find_number_30000000("1,3,2"), 2578); + assert_eq!(find_number_30000000("2,1,3"), 3544142); + assert_eq!(find_number_30000000("1,2,3"), 261214); + assert_eq!(find_number_30000000("2,3,1"), 6895259); + assert_eq!(find_number_30000000("3,2,1"), 18); + assert_eq!(find_number_30000000("3,1,2"), 362); + */ } } diff --git a/adv2020/src/day16.rs b/adv2020/src/day16.rs index 5c42dfb..412b819 100644 --- a/adv2020/src/day16.rs +++ b/adv2020/src/day16.rs @@ -8,7 +8,8 @@ struct Validation<'a> { impl Validation<'_> { fn is_valid(&self, number: usize) -> bool { - self.rules.iter() + self.rules + .iter() .any(|rule| (rule.0..=rule.1).contains(&number)) } } @@ -19,10 +20,13 @@ pub fn find_invalid_tickets(input: &str) -> usize { lines.find(|&line| line == "nearby tickets:"); - lines.map(parse_numbers) - .map(|numbers: Vec| validate_all_rules(&numbers, &validations) - .iter() - .sum::()) + lines + .map(parse_numbers) + .map(|numbers: Vec| { + validate_all_rules(&numbers, &validations) + .iter() + .sum::() + }) .sum::() } @@ -40,22 +44,26 @@ pub fn find_departure_tickets(input: &str) -> usize { lines.find(|&line| line == "nearby tickets:"); - let other_tickets = lines.map(parse_numbers) - .filter(|numbers| numbers.iter() - .all(|number| is_number_correct(*number, &validations)) - ) + let other_tickets = lines + .map(parse_numbers) + .filter(|numbers| { + numbers + .iter() + .all(|number| is_number_correct(*number, &validations)) + }) .collect::>>(); let correct_combination = find_validation_combination(&other_tickets, &validations); - correct_combination.iter() + correct_combination + .iter() .enumerate() .filter(|&(_, rule)| rule.name.starts_with("departure")) .map(|(pos, _)| your_ticket[pos]) .product() } -fn extract_rules<'a>(lines: &mut dyn Iterator) -> Vec> { +fn extract_rules<'a>(lines: &mut dyn Iterator) -> Vec> { let mut validations: Vec = Vec::new(); while let Some(line) = lines.next() { @@ -73,28 +81,29 @@ fn extract_rules<'a>(lines: &mut dyn Iterator) -> Vec Option { let mut splitter = input.split(':'); let name = splitter.next()?; - let range = splitter.next()?.split("or") + let range = splitter + .next()? + .split("or") .map(&str::trim) - .map(|part: &str| + .map(|part: &str| { part.split('-') .map(&str::parse::) .filter_map(Result::ok) .collect::>() - ) - .filter_map(|parts| if parts.len() == 2 { - Some((parts[0], parts[1])) - } else { - None + }) + .filter_map(|parts| { + if parts.len() == 2 { + Some((parts[0], parts[1])) + } else { + None + } }) .collect::>(); if range.is_empty() { None } else { - Some(Validation { - name, - rules: range, - }) + Some(Validation { name, rules: range }) } } @@ -106,21 +115,25 @@ fn validate_all_rules(vec: &Vec, validations: &Vec) -> Vec) -> bool { - validations.iter() - .any(|Validation { rules, .. }| - rules.iter() - .any(|&(from, to)| (from..=to).contains(&number)) - ) + validations.iter().any(|Validation { rules, .. }| { + rules + .iter() + .any(|&(from, to)| (from..=to).contains(&number)) + }) } fn parse_numbers(input: &str) -> Vec { - input.split(',') + input + .split(',') .map(&str::parse::) .filter_map(Result::ok) .collect::>() } -fn find_validation_combination<'a>(tickets: &Vec>, validations: &'a Vec>) -> Vec<&'a Validation<'a>> { +fn find_validation_combination<'a>( + tickets: &Vec>, + validations: &'a Vec>, +) -> Vec<&'a Validation<'a>> { let validations_count = validations.len(); let mut valid_rules = HashMap::::new(); @@ -134,8 +147,7 @@ fn find_validation_combination<'a>(tickets: &Vec>, validations: &'a V continue 'pos; } - if tickets.iter() - .all(|ticket| rule.is_valid(ticket[pos])) { + if tickets.iter().all(|ticket| rule.is_valid(ticket[pos])) { if candidate.is_none() { candidate = Some((rule, pos)); } else { @@ -151,7 +163,8 @@ fn find_validation_combination<'a>(tickets: &Vec>, validations: &'a V } } - valid_rules.into_iter() + valid_rules + .into_iter() .sorted_by(|a, b| a.0.cmp(&b.0)) .map(|(_, rule)| rule) .collect() @@ -223,7 +236,8 @@ nearby tickets: fn test_extract_rules() { let mut lines = r#"class: 1-3 or 5-7 row: 6-11 or 33-44 -seat: 13-40 or 45-50"#.lines(); +seat: 13-40 or 45-50"# + .lines(); let result = extract_rules(&mut lines); assert_eq!(result.len(), 3); @@ -244,13 +258,10 @@ seat: 13-40 or 45-50"#.lines(); fn test_find_validation_combination() { let mut lines = r#"class: 0-1 or 4-19 row: 0-5 or 8-19 -seat: 0-13 or 16-19"#.lines(); +seat: 0-13 or 16-19"# + .lines(); let rules = extract_rules(&mut lines); - let tickets = vec![ - vec![3, 9, 18], - vec![15, 1, 5], - vec![5, 14, 9] - ]; + let tickets = vec![vec![3, 9, 18], vec![15, 1, 5], vec![5, 14, 9]]; let ordered_rules = find_validation_combination(&tickets, &rules); diff --git a/adv2020/src/day17.rs b/adv2020/src/day17.rs index fb19e73..67d11f3 100644 --- a/adv2020/src/day17.rs +++ b/adv2020/src/day17.rs @@ -1,6 +1,6 @@ -use std::collections::HashSet; -use std::cmp::{min, max}; use itertools::iproduct; +use std::cmp::{max, min}; +use std::collections::HashSet; pub fn count_standard_cube(input: &str) -> usize { let mut cube = Cube::load_from_string(input); @@ -72,25 +72,24 @@ impl Cube { self.dim_w.1 = max(self.dim_w.1, w); } } - false => { self.cells.remove(coord); } + false => { + self.cells.remove(coord); + } }; } fn load_from_string(input: &str) -> Cube { let mut cube = Cube::new(); - input.lines() + input + .lines() .map(&str::trim) .enumerate() .for_each(|(row, line)| { - line.chars() - .enumerate() - .for_each(|(col, c)| { - match c { - '#' => cube.set(&Coord(col as i32, row as i32, 0, 0), true), - _ => (), - } - }) + line.chars().enumerate().for_each(|(col, c)| match c { + '#' => cube.set(&Coord(col as i32, row as i32, 0, 0), true), + _ => (), + }) }); cube @@ -99,17 +98,19 @@ impl Cube { fn evolve(&mut self, is_hyper: bool) { let mut new_cube = Cube::new(); - iproduct!(self.dim_x.0 - 1..=self.dim_x.1 + 1, - self.dim_y.0 - 1..=self.dim_y.1 + 1, - self.dim_z.0 - 1..=self.dim_z.1 + 1, - self.dim_w.0 - 1..=self.dim_w.1 + 1) - .filter(|&(_, _, _, w)| is_hyper || w == 0) - .for_each(|(x, y, z, w)| { - let coord = Coord(x, y, z, w); - let should_activate = self.evolve_cell(&coord, is_hyper); + iproduct!( + self.dim_x.0 - 1..=self.dim_x.1 + 1, + self.dim_y.0 - 1..=self.dim_y.1 + 1, + self.dim_z.0 - 1..=self.dim_z.1 + 1, + self.dim_w.0 - 1..=self.dim_w.1 + 1 + ) + .filter(|&(_, _, _, w)| is_hyper || w == 0) + .for_each(|(x, y, z, w)| { + let coord = Coord(x, y, z, w); + let should_activate = self.evolve_cell(&coord, is_hyper); - new_cube.set(&coord, should_activate); - }); + new_cube.set(&coord, should_activate); + }); self.cells = new_cube.cells; self.dim_x = new_cube.dim_x; @@ -124,13 +125,15 @@ impl Cube { let neighbours_count = iproduct!(-1..=1, -1..=1, -1..=1, -1..=1) .filter(|&(_, _, _, w)| is_hyper || w == 0) .filter(|&(dx, dy, dz, dw)| !(dx == 0 && dy == 0 && dz == 0 && dw == 0)) // exclude center - .filter(|&(dx, dy, dz, dw)| self.is_active(&Coord(cell_x + dx, cell_y + dy, cell_z + dz, cell_w + dw))) + .filter(|&(dx, dy, dz, dw)| { + self.is_active(&Coord(cell_x + dx, cell_y + dy, cell_z + dz, cell_w + dw)) + }) .count(); let current_cell = self.is_active(coord); match current_cell { - true => (neighbours_count == 2 || neighbours_count == 3), + true => neighbours_count == 2 || neighbours_count == 3, false => neighbours_count == 3, } } diff --git a/adv2020/src/day2.rs b/adv2020/src/day2.rs index 32fc7da..0858be4 100644 --- a/adv2020/src/day2.rs +++ b/adv2020/src/day2.rs @@ -1,19 +1,13 @@ pub fn count_simple_passwords(input: &str) -> usize { - parse_input(input) - .filter(is_password_simple) - .count() + parse_input(input).filter(is_password_simple).count() } pub fn count_complex_passwords(input: &str) -> usize { - parse_input(input) - .filter(is_password_complex) - .count() + parse_input(input).filter(is_password_complex).count() } fn is_password_simple(rule: &Rule) -> bool { - let actual_count = rule.password.chars() - .filter(|c| *c == rule.letter) - .count(); + let actual_count = rule.password.chars().filter(|c| *c == rule.letter).count(); actual_count >= rule.from && actual_count <= rule.to } @@ -42,28 +36,28 @@ struct Rule { password: String, } -fn parse_input<'a>(input: &'a str) -> impl Iterator + 'a { - input.lines() - .filter_map(|line| { - let v: Vec<&str> = line.split(|c: char| c.is_whitespace() || c.is_ascii_punctuation() - ).filter(|&s| !s.is_empty()) - .collect(); - - if v.len() != 4 { - return None; - } - - let from = v[0].parse::().ok(); - let to = v[1].parse::().ok(); - let letter = v[2].parse::().ok(); - - Some(Rule { - from: from?, - to: to?, - letter: letter?, - password: String::from(v[3]), - }) +fn parse_input<'a>(input: &'a str) -> impl Iterator + 'a { + input.lines().filter_map(|line| { + let v: Vec<&str> = line + .split(|c: char| c.is_whitespace() || c.is_ascii_punctuation()) + .filter(|&s| !s.is_empty()) + .collect(); + + if v.len() != 4 { + return None; + } + + let from = v[0].parse::().ok(); + let to = v[1].parse::().ok(); + let letter = v[2].parse::().ok(); + + Some(Rule { + from: from?, + to: to?, + letter: letter?, + password: String::from(v[3]), }) + }) } #[cfg(test)] @@ -76,8 +70,11 @@ mod tests { #[test] fn test_parse_input() { - let result: Vec = parse_input(r#"17-18 f: fffffffffffffffffff - 1 abc"#).collect(); + let result: Vec = parse_input( + r#"17-18 f: fffffffffffffffffff + 1 abc"#, + ) + .collect(); assert_eq!(result.len(), 1); assert_eq!(result[0].from, 17); assert_eq!(result[0].to, 18); diff --git a/adv2020/src/day3.rs b/adv2020/src/day3.rs index 088ec51..36d7cb1 100644 --- a/adv2020/src/day3.rs +++ b/adv2020/src/day3.rs @@ -16,7 +16,8 @@ pub fn count_multiple_slopes(input: &str) -> usize { let input = parse_input(input); - multiple.iter() + multiple + .iter() .map(|slope| count_trees(&input, slope)) .fold(1, |count, acc| count * acc) } @@ -24,17 +25,20 @@ pub fn count_multiple_slopes(input: &str) -> usize { fn count_trees(field: &Vec>, slope: &Slope) -> usize { let mut col = 0usize; - field.iter() + field + .iter() .enumerate() .filter(|&row| { if row.0 % slope.down == 0 { - let is_tree = row.1.get(col % row.1.len()) - .unwrap_or(&Cell::Empty) == &Cell::Tree; + let is_tree = row.1.get(col % row.1.len()).unwrap_or(&Cell::Empty) == &Cell::Tree; col += slope.right; is_tree - } else { false } - }).count() + } else { + false + } + }) + .count() } #[derive(PartialEq)] @@ -49,11 +53,9 @@ struct Slope { } fn parse_input(input: &str) -> Vec> { - input.lines() - .map(|l| l.trim() - .chars() - .map(parse_cell) - .collect()) + input + .lines() + .map(|l| l.trim().chars().map(parse_cell).collect()) .collect() } diff --git a/adv2020/src/day4.rs b/adv2020/src/day4.rs index 804dfff..8f7dfb8 100644 --- a/adv2020/src/day4.rs +++ b/adv2020/src/day4.rs @@ -2,42 +2,47 @@ use itertools::Itertools; pub fn count_simple_results(input: &str) -> usize { let passports = parse_input(input); - passports.iter() - .filter(|pass| has_all_data(pass)) - .count() + passports.iter().filter(|pass| has_all_data(pass)).count() } pub fn count_advanced_results(input: &str) -> usize { let passports = parse_input(input); - passports.iter() + passports + .iter() .filter(|pass| has_all_data(pass) && is_valid_advanced(pass)) .count() } fn parse_input(input: &str) -> Vec { - input.lines() + input + .lines() .group_by(|elt| elt.is_empty()) .into_iter() .filter(|(key, _)| !key) - .map(|(_, group)| - group.collect_vec() + .map(|(_, group)| { + group + .collect_vec() .join(" ") .split_whitespace() .filter(|split| !split.is_empty()) .join(" ") - ).collect() + }) + .collect() } fn has_all_data(pass: &str) -> bool { pass.split_whitespace() - .filter(|pair| pair.starts_with("byr:") - || pair.starts_with("iyr:") - || pair.starts_with("eyr:") - || pair.starts_with("hgt:") - || pair.starts_with("hcl:") - || pair.starts_with("ecl:") - || pair.starts_with("pid:")) - .count() >= 7 + .filter(|pair| { + pair.starts_with("byr:") + || pair.starts_with("iyr:") + || pair.starts_with("eyr:") + || pair.starts_with("hgt:") + || pair.starts_with("hcl:") + || pair.starts_with("ecl:") + || pair.starts_with("pid:") + }) + .count() + >= 7 } fn is_valid_advanced(pass: &str) -> bool { @@ -69,19 +74,22 @@ fn is_valid_advanced(pass: &str) -> bool { _ => false, } - }).count() >= 7 + }) + .count() + >= 7 } fn is_hex_color(color: &str) -> bool { - color.chars() + color + .chars() .enumerate() - .filter(|c: &(usize, char)| { - match c.0 { - 0 => c.1 == '#', - 1..=6 => "0123456789abcdefABCDEF".contains(c.1), - _ => false, - } - }).count() == 7 + .filter(|c: &(usize, char)| match c.0 { + 0 => c.1 == '#', + 1..=6 => "0123456789abcdefABCDEF".contains(c.1), + _ => false, + }) + .count() + == 7 } fn is_eye_color(color: &str) -> bool { @@ -99,18 +107,21 @@ fn is_pid(input: &str) -> bool { fn is_height(input: &str) -> bool { input.len() > 2 - && (input.ends_with("cm") && (150..=193).contains(&input[..input.len() - 2].parse::().unwrap_or(0)) - || (input.ends_with("in") && (59..=76).contains(&input[..input.len() - 2].parse::().unwrap_or(0)))) + && (input.ends_with("cm") + && (150..=193).contains(&input[..input.len() - 2].parse::().unwrap_or(0)) + || (input.ends_with("in") + && (59..=76).contains(&input[..input.len() - 2].parse::().unwrap_or(0)))) } #[cfg(test)] mod tests { use super::*; - #[test] - fn test_answers() { - - assert_eq!(count_simple_results(r#"ecl:gry pid:860033327 eyr:2020 hcl:#fffffd + #[test] + fn test_answers() { + assert_eq!( + count_simple_results( + r#"ecl:gry pid:860033327 eyr:2020 hcl:#fffffd byr:1937 iyr:2017 cid:147 hgt:183cm iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 @@ -122,9 +133,14 @@ mod tests { hgt:179cm hcl:#cfa07d eyr:2025 pid:166559648 - iyr:2011 ecl:brn hgt:59in"#), 2); - - assert_eq!(count_advanced_results(r#"eyr:1972 cid:100 + iyr:2011 ecl:brn hgt:59in"# + ), + 2 + ); + + assert_eq!( + count_advanced_results( + r#"eyr:1972 cid:100 hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926 iyr:2019 @@ -136,9 +152,14 @@ mod tests { hgt:59cm ecl:zzz eyr:2038 hcl:74454a iyr:2023:iyr:2023 - pid:3556412378 byr:2007"#), 0); - - assert_eq!(count_advanced_results(r#"pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 + pid:3556412378 byr:2007"# + ), + 0 + ); + + assert_eq!( + count_advanced_results( + r#"pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 hcl:#623a2f eyr:2029 ecl:blu cid:129 byr:1989 @@ -149,8 +170,11 @@ mod tests { pid:545766238 ecl:hzl eyr:2022 - iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719"#), 4); - } + iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719"# + ), + 4 + ); + } #[test] fn test_parse_input() { @@ -170,18 +194,34 @@ mod tests { #[test] fn test_has_all_data() { - assert!(has_all_data("ecl:gry pid:860033327 eyr:2020 hcl:#fffffd byr:1937 iyr:2017 cid:147 hgt:183cm")); - assert!(!has_all_data("iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 hcl:#cfa07d byr:1929")); - assert!(has_all_data("hcl:#ae17e1 iyr:2013 eyr:2024 ecl:brn pid:760753108 byr:1931 hgt:179cm")); - assert!(!has_all_data("hcl:#cfa07d eyr:2025 pid:166559648 iyr:2011 ecl:brn hgt:59in")); + assert!(has_all_data( + "ecl:gry pid:860033327 eyr:2020 hcl:#fffffd byr:1937 iyr:2017 cid:147 hgt:183cm" + )); + assert!(!has_all_data( + "iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 hcl:#cfa07d byr:1929" + )); + assert!(has_all_data( + "hcl:#ae17e1 iyr:2013 eyr:2024 ecl:brn pid:760753108 byr:1931 hgt:179cm" + )); + assert!(!has_all_data( + "hcl:#cfa07d eyr:2025 pid:166559648 iyr:2011 ecl:brn hgt:59in" + )); } #[test] fn test_is_valid_advanced() { - assert!(is_valid_advanced("pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 hcl:#623a2f")); - assert!(!is_valid_advanced("eyr:1972 cid:100 hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926")); - assert!(is_valid_advanced("iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719")); - assert!(!is_valid_advanced("hgt:59cm ecl:zzz eyr:2038 hcl:74454a iyr:2023 pid:3556412378 byr:2007")); + assert!(is_valid_advanced( + "pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 hcl:#623a2f" + )); + assert!(!is_valid_advanced( + "eyr:1972 cid:100 hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926" + )); + assert!(is_valid_advanced( + "iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719" + )); + assert!(!is_valid_advanced( + "hgt:59cm ecl:zzz eyr:2038 hcl:74454a iyr:2023 pid:3556412378 byr:2007" + )); } #[test] diff --git a/adv2020/src/day5.rs b/adv2020/src/day5.rs index a03f8b0..a366d7f 100644 --- a/adv2020/src/day5.rs +++ b/adv2020/src/day5.rs @@ -8,26 +8,26 @@ pub fn find_maximum_seat_id(input: &str) -> usize { } pub fn find_your_seat(input: &str) -> usize { - if let Err(result) = parse_seats(input) - .map(|seat| seat.id()) - .sorted() - .try_fold(0, |acc, item| { - if item - acc == 1 || acc == 0 { - Ok(item) - } else { - Err(acc + 1) // next ID after the last successful - } - }) { - result - } else { - 0 - } + if let Err(result) = + parse_seats(input) + .map(|seat| seat.id()) + .sorted() + .try_fold(0, |acc, item| { + if item - acc == 1 || acc == 0 { + Ok(item) + } else { + Err(acc + 1) // next ID after the last successful + } + }) + { + result + } else { + 0 + } } -fn parse_seats<'a>(input: &'a str) -> impl Iterator + 'a { - input.lines() - .map(&str::trim) - .map(parse_seat) +fn parse_seats<'a>(input: &'a str) -> impl Iterator + 'a { + input.lines().map(&str::trim).map(parse_seat) } struct Seat(usize, usize); @@ -36,29 +36,27 @@ fn parse_seat(input: &str) -> Seat { let mut row = (0, 127usize); let mut column = (0, 7usize); - input.chars() + input + .chars() .map(|c| c.to_ascii_uppercase()) .enumerate() - .for_each(|(position, c)| { - match position { - 0..=6 => { - let lower = (row.0, (row.1 + row.0 + 1) / 2 - 1); - let upper = ((row.1 + row.0 + 1) / 2, row.1); - - row = if c == 'F' { lower } else { upper }; - } + .for_each(|(position, c)| match position { + 0..=6 => { + let lower = (row.0, (row.1 + row.0 + 1) / 2 - 1); + let upper = ((row.1 + row.0 + 1) / 2, row.1); - 7..=9 => { - let lower = (column.0, (column.1 + column.0 + 1) / 2 - 1); - let upper = ((column.1 + column.0 + 1) / 2, column.1); + row = if c == 'F' { lower } else { upper }; + } - column = if c == 'L' { lower } else { upper }; - } + 7..=9 => { + let lower = (column.0, (column.1 + column.0 + 1) / 2 - 1); + let upper = ((column.1 + column.0 + 1) / 2, column.1); - _ => {} + column = if c == 'L' { lower } else { upper }; } - }); + _ => {} + }); Seat(row.0, column.0) } diff --git a/adv2020/src/day6.rs b/adv2020/src/day6.rs index 089b9b8..4a133b3 100644 --- a/adv2020/src/day6.rs +++ b/adv2020/src/day6.rs @@ -10,10 +10,9 @@ pub fn find_answer1(input: &str) -> usize { result += set.len(); set.clear(); } else { - line.chars() - .for_each(|c: char| { - set.insert(c); - }) + line.chars().for_each(|c: char| { + set.insert(c); + }) } } @@ -28,30 +27,25 @@ pub fn find_answer2(input: &str) -> usize { for line in input.lines() { if line.is_empty() { - result += map_stats.iter() - .filter(|&(_, v)| *v == lines) - .count(); + result += map_stats.iter().filter(|&(_, v)| *v == lines).count(); lines = 0; map_stats.clear(); } else { - line.chars() - .for_each(|c: char| { - if map_stats.contains_key(&c) { - let value = map_stats.get(&c).unwrap(); - let value = *value + 1; - map_stats.insert(c, value); - } else { - map_stats.insert(c, 1); - } - }); + line.chars().for_each(|c: char| { + if map_stats.contains_key(&c) { + let value = map_stats.get(&c).unwrap(); + let value = *value + 1; + map_stats.insert(c, value); + } else { + map_stats.insert(c, 1); + } + }); lines += 1; } } - result + map_stats.iter() - .filter(|&(_, v)| *v == lines) - .count() + result + map_stats.iter().filter(|&(_, v)| *v == lines).count() } /* struct AggregateIterator<'a, T: Iterator + 'a> { @@ -91,10 +85,11 @@ impl Iterator for AggregateIterator { mod tests { use super::*; - #[test] fn test_empty_answers() { - assert_eq!(find_answer1(r#"abc + assert_eq!( + find_answer1( + r#"abc a b @@ -108,7 +103,10 @@ a a a -b"#), 11); +b"# + ), + 11 + ); assert_eq!(find_answer2(""), 0); } } diff --git a/adv2020/src/day7.rs b/adv2020/src/day7.rs index e265492..212621f 100644 --- a/adv2020/src/day7.rs +++ b/adv2020/src/day7.rs @@ -4,23 +4,27 @@ use std::collections::HashMap; pub fn find_answer1(input: &str) -> usize { let mut rules: HashMap> = HashMap::new(); - input.lines() - .for_each(|line| { - let line_split: Vec<&str> = line.split("contain").collect(); - let what = line_split[0].split_whitespace().take(2).join(" "); - let mut map: HashMap = HashMap::new(); - let bags_split: Vec<&str> = line_split[1].split(", ").collect(); - if !bags_split.contains(&"no other") { - for bag in bags_split { - let bag = bag.split_whitespace().take(3).join(" "); - let num = bag.split_whitespace().next().unwrap().parse::().unwrap_or_default(); - let color = bag.split_whitespace().skip(1).take(2).join(" "); - map.insert(color, num); - } + input.lines().for_each(|line| { + let line_split: Vec<&str> = line.split("contain").collect(); + let what = line_split[0].split_whitespace().take(2).join(" "); + let mut map: HashMap = HashMap::new(); + let bags_split: Vec<&str> = line_split[1].split(", ").collect(); + if !bags_split.contains(&"no other") { + for bag in bags_split { + let bag = bag.split_whitespace().take(3).join(" "); + let num = bag + .split_whitespace() + .next() + .unwrap() + .parse::() + .unwrap_or_default(); + let color = bag.split_whitespace().skip(1).take(2).join(" "); + map.insert(color, num); } + } - rules.insert(what, map); - }); + rules.insert(what, map); + }); let mut result = 0; @@ -80,23 +84,27 @@ fn count_bags(rules: &HashMap>, what: &String) -> pub fn find_answer2(input: &str) -> usize { let mut rules: HashMap> = HashMap::new(); - input.lines() - .for_each(|line| { - let line_split: Vec<&str> = line.split("contain").collect(); - let what = line_split[0].split_whitespace().take(2).join(" "); - let mut map: HashMap = HashMap::new(); - let bags_split: Vec<&str> = line_split[1].split(", ").collect(); - if !bags_split.contains(&"no other") { - for bag in bags_split { - let bag = bag.split_whitespace().take(3).join(" "); - let num = bag.split_whitespace().next().unwrap().parse::().unwrap_or_default(); - let color = bag.split_whitespace().skip(1).take(2).join(" "); - map.insert(color, num); - } + input.lines().for_each(|line| { + let line_split: Vec<&str> = line.split("contain").collect(); + let what = line_split[0].split_whitespace().take(2).join(" "); + let mut map: HashMap = HashMap::new(); + let bags_split: Vec<&str> = line_split[1].split(", ").collect(); + if !bags_split.contains(&"no other") { + for bag in bags_split { + let bag = bag.split_whitespace().take(3).join(" "); + let num = bag + .split_whitespace() + .next() + .unwrap() + .parse::() + .unwrap_or_default(); + let color = bag.split_whitespace().skip(1).take(2).join(" "); + map.insert(color, num); } + } - rules.insert(what, map); - }); + rules.insert(what, map); + }); count_bags(&rules, &String::from("shiny gold")) } @@ -112,7 +120,6 @@ fn parse_input<'a>(input: &'a str) -> impl Iterator + 'a { mod tests { use super::*; - #[test] fn test_empty_answers() { assert_eq!(find_answer1(""), 0); diff --git a/adv2020/src/day8.rs b/adv2020/src/day8.rs index c74db1d..529b467 100644 --- a/adv2020/src/day8.rs +++ b/adv2020/src/day8.rs @@ -5,7 +5,9 @@ pub fn execute_first_program(input: &str) -> i32 { if let Execution::Infinite(result) = execute_program(&program) { result - } else { 0 } + } else { + 0 + } } pub fn execute_second_program(input: &str) -> i32 { @@ -65,9 +67,7 @@ fn parse_line(input: &str) -> Option { } fn parse_program(input: &str) -> Vec { - input.lines() - .filter_map(parse_line) - .collect() + input.lines().filter_map(parse_line).collect() } fn execute_program(program: &Vec) -> Execution { @@ -120,7 +120,6 @@ enum Execution { mod tests { use super::*; - const INPUT_PROGRAM: &'static str = r#"nop +0 acc +1 jmp +4 diff --git a/adv2020/src/day9.rs b/adv2020/src/day9.rs index 29cbc02..56356c0 100644 --- a/adv2020/src/day9.rs +++ b/adv2020/src/day9.rs @@ -3,8 +3,7 @@ use itertools::Itertools; pub fn find_weak_number_25(input: &str) -> usize { let input: Vec = parse_input(input); - find_weak_number(&input, 25) - .unwrap_or((0, 0)).0 + find_weak_number(&input, 25).unwrap_or((0, 0)).0 } pub fn find_sum_of_any_numbers(input: &str) -> usize { @@ -12,8 +11,9 @@ pub fn find_sum_of_any_numbers(input: &str) -> usize { if let Some((weak_number, weak_number_pos)) = find_weak_number(&input, 25) { (3..weak_number_pos) - .find_map(|window_size| - find_possible_sum(&input[0..weak_number_pos], window_size, weak_number)) + .find_map(|window_size| { + find_possible_sum(&input[0..weak_number_pos], window_size, weak_number) + }) .unwrap_or_default() } else { 0 @@ -21,7 +21,8 @@ pub fn find_sum_of_any_numbers(input: &str) -> usize { } fn parse_input(input: &str) -> Vec { - input.lines() + input + .lines() .map(&str::trim) .map(&str::parse::) .filter_map(Result::ok) @@ -32,12 +33,12 @@ fn find_weak_number(input: &Vec, preamble: usize) -> Option<(usize, usize for num in preamble..input.len() { let last_numbers = &input[num.saturating_sub(preamble)..num]; - if last_numbers.into_iter() + if last_numbers + .into_iter() .combinations(2) - .find(|pair| pair.iter() - .map(|n| *n) - .sum::() == input[num]) - .is_none() { + .find(|pair| pair.iter().map(|n| *n).sum::() == input[num]) + .is_none() + { return Some((input[num], num)); } } @@ -46,7 +47,8 @@ fn find_weak_number(input: &Vec, preamble: usize) -> Option<(usize, usize } fn find_possible_sum(numbers: &[usize], window_size: usize, weak_number: usize) -> Option { - numbers.windows(window_size) + numbers + .windows(window_size) .filter_map(|window| { let sum = window.iter().sum::(); let min = window.iter().min(); @@ -65,7 +67,6 @@ fn find_possible_sum(numbers: &[usize], window_size: usize, weak_number: usize) mod tests { use super::*; - #[test] fn test_empty_answers() { assert_eq!(find_weak_number_25(""), 0); @@ -82,18 +83,38 @@ mod tests { #[test] fn test_find_weak_number() { - assert_eq!(find_weak_number(&vec![35, 20, 15, 25, 47, 40, 62, 55, 65, 95, - 102, 117, 150, 182, 127, 219, 299, 277, 309, 57], 5), Some((127, 14))); + assert_eq!( + find_weak_number( + &vec![ + 35, 20, 15, 25, 47, 40, 62, 55, 65, 95, 102, 117, 150, 182, 127, 219, 299, 277, + 309, 57 + ], + 5 + ), + Some((127, 14)) + ); assert_eq!(find_weak_number(&vec![35, 20, 15, 25, 47, 40, 62], 5), None); } #[test] fn test_find_possible_sum() { - assert_eq!(find_possible_sum(&vec![35, 20, 15, 25, 47, 40, 62, 55, 65, 95, - 102, 117, 150, 182], 4, 127), Some(62)); - - assert_eq!(find_possible_sum(&vec![35, 20, 15, 25, 47, 40, 62, 55, 65, 95, - 102, 117, 150, 182], 3, 127), None); + assert_eq!( + find_possible_sum( + &vec![35, 20, 15, 25, 47, 40, 62, 55, 65, 95, 102, 117, 150, 182], + 4, + 127 + ), + Some(62) + ); + + assert_eq!( + find_possible_sum( + &vec![35, 20, 15, 25, 47, 40, 62, 55, 65, 95, 102, 117, 150, 182], + 3, + 127 + ), + None + ); } } diff --git a/adv2020/src/lib.rs b/adv2020/src/lib.rs index e3667a1..690e7fb 100644 --- a/adv2020/src/lib.rs +++ b/adv2020/src/lib.rs @@ -1,13 +1,5 @@ /* */ mod day1; -mod day2; -mod day3; -mod day4; -mod day5; -mod day6; -mod day7; -mod day8; -mod day9; mod day10; mod day11; mod day12; @@ -16,6 +8,14 @@ mod day14; mod day15; mod day16; mod day17; +mod day2; +mod day3; +mod day4; +mod day5; +mod day6; +mod day7; +mod day8; +mod day9; /* */ pub fn print_answers(day: u8, input: String) { @@ -23,26 +23,112 @@ pub fn print_answers(day: u8, input: String) { let input = input.as_str().trim(); let prefix = format!("Day {} / 2020:", day); match day { - 1 => println!("{} {} and {}", prefix, day1::find_expenses(input), day1::find_more_expenses(input)), - 2 => println!("{} {} and {}", prefix, day2::count_simple_passwords(input), day2::count_complex_passwords(input)), - 3 => println!("{} {} and {}", prefix, day3::count_single_slope(input), day3::count_multiple_slopes(input)), - 4 => println!("{} {} and {}", prefix, day4::count_simple_results(input), day4::count_advanced_results(input)), - 5 => println!("{} {} and {}", prefix, day5::find_maximum_seat_id(input), day5::find_your_seat(input)), - 6 => println!("{} {} and {}", prefix, day6::find_answer1(input), day6::find_answer2(input)), - 7 => println!("{} {} and {}", prefix, day7::find_answer1(input), day7::find_answer2(input)), - 8 => println!("{} {} and {}", prefix, day8::execute_first_program(input), day8::execute_second_program(input)), - 9 => println!("{} {} and {}", prefix, day9::find_weak_number_25(input), day9::find_sum_of_any_numbers(input)), - 10 => println!("{} {} and {}", prefix, day10::find_one_by_three(input), day10::find_all_combinations(input)), - 11 => println!("{} {} and {}", prefix, day11::find_places_direct(input), day11::find_seats_visible_only(input)), - 12 => println!("{} {} and {}", prefix, day12::find_answer1(input), day12::find_answer2(input)), - 13 => println!("{} {} and {}", prefix, day13::find_earliest_bus(input), day13::find_earliest_timestamp(input)), - 14 => println!("{} {} and {}", prefix, day14::find_answer1(input), day14::find_answer2(input)), - 15 => println!("{} {} and {}", prefix, day15::find_number_2020(input), day15::find_number_30000000(input)), - 16 => println!("{} {} and {}", prefix, day16::find_invalid_tickets(input), day16::find_departure_tickets(input)), - 17 => println!("{} {} and {}", prefix, day17::count_standard_cube(input), day17::count_hyper_cube(input)), - // 9 => println!("{} {} and {}", prefix, day9::find_answer1(input), day9::find_answer2(input)), - - _ => { eprintln!("2020: I don't know the answer for day {} :(", day) } + 1 => println!( + "{} {} and {}", + prefix, + day1::find_expenses(input), + day1::find_more_expenses(input) + ), + 2 => println!( + "{} {} and {}", + prefix, + day2::count_simple_passwords(input), + day2::count_complex_passwords(input) + ), + 3 => println!( + "{} {} and {}", + prefix, + day3::count_single_slope(input), + day3::count_multiple_slopes(input) + ), + 4 => println!( + "{} {} and {}", + prefix, + day4::count_simple_results(input), + day4::count_advanced_results(input) + ), + 5 => println!( + "{} {} and {}", + prefix, + day5::find_maximum_seat_id(input), + day5::find_your_seat(input) + ), + 6 => println!( + "{} {} and {}", + prefix, + day6::find_answer1(input), + day6::find_answer2(input) + ), + 7 => println!( + "{} {} and {}", + prefix, + day7::find_answer1(input), + day7::find_answer2(input) + ), + 8 => println!( + "{} {} and {}", + prefix, + day8::execute_first_program(input), + day8::execute_second_program(input) + ), + 9 => println!( + "{} {} and {}", + prefix, + day9::find_weak_number_25(input), + day9::find_sum_of_any_numbers(input) + ), + 10 => println!( + "{} {} and {}", + prefix, + day10::find_one_by_three(input), + day10::find_all_combinations(input) + ), + 11 => println!( + "{} {} and {}", + prefix, + day11::find_places_direct(input), + day11::find_seats_visible_only(input) + ), + 12 => println!( + "{} {} and {}", + prefix, + day12::find_answer1(input), + day12::find_answer2(input) + ), + 13 => println!( + "{} {} and {}", + prefix, + day13::find_earliest_bus(input), + day13::find_earliest_timestamp(input) + ), + 14 => println!( + "{} {} and {}", + prefix, + day14::find_answer1(input), + day14::find_answer2(input) + ), + 15 => println!( + "{} {} and {}", + prefix, + day15::find_number_2020(input), + day15::find_number_30000000(input) + ), + 16 => println!( + "{} {} and {}", + prefix, + day16::find_invalid_tickets(input), + day16::find_departure_tickets(input) + ), + 17 => println!( + "{} {} and {}", + prefix, + day17::count_standard_cube(input), + day17::count_hyper_cube(input) + ), + // 9 => println!("{} {} and {}", prefix, day9::find_answer1(input), day9::find_answer2(input)), + _ => { + eprintln!("2020: I don't know the answer for day {} :(", day) + } } } diff --git a/adventofcode/Cargo.toml b/adventofcode/Cargo.toml index 599fc14..f89eaa2 100644 --- a/adventofcode/Cargo.toml +++ b/adventofcode/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adventofcode" -version = "0.2.17" +version = "0.2.18" authors = ["Vest "] edition = "2018" @@ -8,6 +8,6 @@ edition = "2018" [dependencies] reqwest = { version = "~0", features = ["blocking"] } -clap = "~3" +clap = "~4" adv2015 = { path = "../adv2015" } adv2020 = { path = "../adv2020" } diff --git a/adventofcode/src/advent.rs b/adventofcode/src/advent.rs index b430aef..8ddbfbe 100644 --- a/adventofcode/src/advent.rs +++ b/adventofcode/src/advent.rs @@ -1,6 +1,6 @@ -use reqwest::header::{HeaderMap, HeaderValue, InvalidHeaderValue}; -use std::fmt::{Display}; use core::fmt; +use reqwest::header::{HeaderMap, HeaderValue, InvalidHeaderValue}; +use std::fmt::Display; pub enum HttpError { WrongHeader(InvalidHeaderValue), @@ -38,7 +38,8 @@ pub fn get_input(day: u8, year: u16, session: &str) -> Result .default_headers(headers) .build()?; - let body = client.get(format!("https://adventofcode.com/{}/day/{}/input", year, day).as_str()) + let body = client + .get(format!("https://adventofcode.com/{}/day/{}/input", year, day).as_str()) .send()? .text()?; @@ -55,7 +56,10 @@ mod tests { assert!(input.is_ok(), "The input response is not successful"); let response = input.unwrap_or(String::from("fail")); - assert!(response.contains("Please log in"), "The response is unexpected: {}", response); + assert!( + response.contains("Please log in"), + "The response is unexpected: {}", + response + ); } } - diff --git a/adventofcode/src/main.rs b/adventofcode/src/main.rs index 89b1add..0c64bd8 100644 --- a/adventofcode/src/main.rs +++ b/adventofcode/src/main.rs @@ -1,53 +1,62 @@ mod advent; -use std::env; use clap::{Arg, Command}; +use std::env; fn main() { let matches = Command::new("Advent 2015, 2020!") .author("Vest ") .about("Solves advent calendar from https://adventofcode.com") - .arg(Arg::new("day") - .short('d') - .long("day") - .takes_value(true) - .required(false) - .help("A day of the advent")) - .arg(Arg::new("year") - .short('y') - .long("year") - .takes_value(true) - .required(false) - .help("A year of the calendar")) + .arg( + Arg::new("day") + .short('d') + .long("day") + .required(false) + .help("A day of the advent"), + ) + .arg( + Arg::new("year") + .short('y') + .long("year") + .required(false) + .default_value("2020") + .help("A year of the calendar"), + ) .get_matches(); - let day_str = matches.value_of("day"); - let year_str = matches.value_of("year").unwrap_or("2020"); - let year_num = year_str.parse::().unwrap_or(2020); + let day_num = matches.get_one::("day"); + let year_num = matches.get_one::("year").unwrap(); let key = "ADVENT_SESSION"; match env::var(key) { Ok(session_value) => { let session = session_value.as_str(); - for day_num in 1..26 { - if day_str.is_some() { - let day_parsed = day_str.unwrap().parse::(); - if day_parsed.is_ok() && day_parsed.unwrap() != day_num { + for day in 1..26 { + if let Some(day_num) = day_num { + if *day_num != day { continue; } } - let input = advent::get_input(day_num, year_num, session); + let input = advent::get_input(day, *year_num, session); if input.is_err() { - eprintln!("Couldn't get input value for day {} / {}. Error: {}", day_num, year_num, input.unwrap_err()); + eprintln!( + "Couldn't get input value for day {} / {}. Error: {}", + day, + year_num, + input.unwrap_err() + ); return; } - print_answers(day_num, year_num, input.ok().unwrap()); + print_answers(day, *year_num, input.ok().unwrap()); } } - Err(e) => println!("Couldn't get {} key from environment variable. Description: {}", key, e), + Err(e) => println!( + "Couldn't get {} key from environment variable. Description: {}", + key, e + ), } println!("Done");