mirror of
https://github.com/LeMoonStar/AoC24.git
synced 2025-07-07 10:05:31 +02:00
🎉 Initialized repository based on 2023 code
This commit is contained in:
commit
cc42c33b5d
65 changed files with 3897 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
.aoc23_cache
|
21
Cargo.toml
Normal file
21
Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "aoc24"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "2.34", features = ["suggestions", "color", "wrap_help"] }
|
||||
colored = "2.0"
|
||||
aoc-macro = {path="aoc-macro"}
|
||||
reqwest = { version = "0.11", features=["cookies", "blocking"] }
|
||||
mut_static="5.0"
|
||||
lazy_static="1.4"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = 'abort'
|
||||
strip = true
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 LeMoonStar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
49
README.md
Normal file
49
README.md
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Advent of Code 2024
|
||||
|
||||
[](https://adventofcode.com/2024/about)
|
||||
[](https://en.wikipedia.org/wiki/Rust_(programming_language))
|
||||
[](https://mit-license.org/)
|
||||

|
||||

|
||||
|
||||
> ⚠️ This README is copied from my previous years solution. It is not fully adopted to 2024 yet.
|
||||
|
||||
Last Years README:
|
||||
> This is the third year in a row I (plan to) use rust to solve Advent of Code. But I must warn you: I haven't programmed a lot over the past year, so I am likely not in the best shape (School has been rough - I need a break) - expect the worst.
|
||||
> Just like last year, I am lazy and currently setting this project up in a hurry (In class, actually) just so I have the basic framework once the event starts. So this project is literally a cleaned-up copy of my [solutions for the previous year](https://github.com/LeMoonStar/AoC22), which in term are a cleaned up version of my [Advent of Code 2021 solutions](https://github.com/LeMoonStar/AoC21).
|
||||
> **The Following therefore still contains screenshots of the 2021 binary. The usage is the same, but the name is `aoc24` instead of `aoc21`**
|
||||
>
|
||||
> Later on, maybe even before AoC starts, I'll clean this up more, maybe create a crate out of the framework so I don't have to copy each year over and over again.
|
||||
|
||||
Well, not much changed. This is now the fourth year I'll use Rust - after not using Rust in a while and likely with a lot less time at hand. We'll see how it goes. I am finally out of school tough - that's a relief!
|
||||
|
||||
## Usage
|
||||
|
||||
There are multiple ways to run my solutions, the easiest and most comfortable one is the `auto` command:
|
||||
It automatically downloads your input. For this it requires you to provide your Advent of Code session id, which you can find in the websites cookies after logging in.
|
||||
Simply provide the session token by setting the `AOC_SESSION` environment variable or using the -s argument:
|
||||
`AOC_SESSION=XXXMYSESSION ./aoc24 [DAY] auto` or `./aoc24 [DAY] auto -s XXXMYSESSION`.
|
||||
In this example, the environment variable for the AoC session is set using `export AOC_SESSION=XXXMYSESSION`, so I can run the command without specifying the session token again:
|
||||

|
||||
|
||||
If you don't want to automatically download the input, you can also use the `run` command, which uses a locally stored file or the stdin input:
|
||||
`./aoc24 [DAY] run -f my_input.txt`:
|
||||

|
||||
|
||||
If you just want to run the day's example, simply use the `test` command, as this project already includes the examples:
|
||||
`./aoc24 [DAY] test`:
|
||||

|
||||
|
||||
## Compiling
|
||||
|
||||
This project uses `Cargo`, so compiling is pretty easy:
|
||||
`cargo build --release`
|
||||
The resulting binary can be found at `./targets/release/aoc22`. You can also directly run the project using `cargo run --release [arguments for aoc24]`
|
||||
the `--release` option is not required, but it results in better performance.
|
||||
|
||||
## Check out other AoC24 solutions
|
||||
|
||||
| Repository | Language |
|
||||
|----------------------------------------------------------------------------------|----------|
|
||||
| [Trojaner's AdventofCode2024](https://github.com/TrojanerHD/AdventofCode2024) | Rust |
|
||||
| [Niklas' Advent-of-Code-2024](https://github.com/derNiklaas/Advent-of-Code-2024) | Kotlin |
|
1
aoc-macro/.gitignore
vendored
Normal file
1
aoc-macro/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
46
aoc-macro/Cargo.lock
generated
Normal file
46
aoc-macro/Cargo.lock
generated
Normal file
|
@ -0,0 +1,46 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aoc-macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
13
aoc-macro/Cargo.toml
Normal file
13
aoc-macro/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "aoc-macro"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro=true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
quote = "^1.0"
|
||||
syn = "^1.0"
|
108
aoc-macro/src/lib.rs
Normal file
108
aoc-macro/src/lib.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
// Again, huge thanks to andi_makes
|
||||
// this is basically a copy of his macros, with very slight modifications.
|
||||
|
||||
#[proc_macro]
|
||||
pub fn mod_days(_input: TokenStream) -> TokenStream {
|
||||
let mut res = String::new();
|
||||
for i in 1..26 {
|
||||
res += &format!("mod d{:02};", i);
|
||||
}
|
||||
res.parse().unwrap()
|
||||
}
|
||||
|
||||
/*#[proc_macro]
|
||||
pub fn match_and_run_day(_input: TokenStream) -> TokenStream {
|
||||
let mut res = "match day {".to_string();
|
||||
for i in 1..26 {
|
||||
res += &format!("{} => Day::<{}>::run_timed(input),", i, i);
|
||||
}
|
||||
res += "_ => panic!(\"Days out of Bounds! No presents for you!\")};";
|
||||
res.parse().unwrap()
|
||||
}*/
|
||||
|
||||
#[proc_macro]
|
||||
pub fn match_and_run_day_both(_input: TokenStream) -> TokenStream {
|
||||
let r = 1_u8..26; // == [1,25]
|
||||
let res = quote! {
|
||||
match day {
|
||||
#(#r => {
|
||||
Day::<#r>::run_timed(input.trim_end())
|
||||
})*
|
||||
_ => panic!("Days out of Bounds! No presents for you!"),
|
||||
}
|
||||
};
|
||||
res.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn match_and_run_day_one(_input: TokenStream) -> TokenStream {
|
||||
let r = 1_u8..26; // == [1,25]
|
||||
let res = quote! {
|
||||
match day {
|
||||
#(#r => {
|
||||
Day::<#r>::run_one_timed(input.trim_end())
|
||||
})*
|
||||
_ => panic!("Days out of Bounds! No presents for you!"),
|
||||
}
|
||||
};
|
||||
res.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn match_and_run_day_two(_input: TokenStream) -> TokenStream {
|
||||
let r = 1_u8..26; // == [1,25]
|
||||
let res = quote! {
|
||||
match day {
|
||||
#(#r => {
|
||||
Day::<#r>::run_two_timed(input.trim_end())
|
||||
})*
|
||||
_ => panic!("Days out of Bounds! No presents for you!"),
|
||||
}
|
||||
};
|
||||
res.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn match_and_test_day_both(_input: TokenStream) -> TokenStream {
|
||||
let r = 1_u8..26; // == [1,25]
|
||||
let res = quote! {
|
||||
match day {
|
||||
#(#r => {
|
||||
Day::<#r>::test()
|
||||
})*
|
||||
_ => panic!("Days out of Bounds! No presents for you!"),
|
||||
}
|
||||
};
|
||||
res.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn match_and_test_day_one(_input: TokenStream) -> TokenStream {
|
||||
let r = 1_u8..26; // == [1,25]
|
||||
let res = quote! {
|
||||
match day {
|
||||
#(#r => {
|
||||
Day::<#r>::test_one()
|
||||
})*
|
||||
_ => panic!("Days out of Bounds! No presents for you!"),
|
||||
}
|
||||
};
|
||||
res.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn match_and_test_day_two(_input: TokenStream) -> TokenStream {
|
||||
let r = 1_u8..26; // == [1,25]
|
||||
let res = quote! {
|
||||
match day {
|
||||
#(#r => {
|
||||
Day::<#r>::test_two()
|
||||
})*
|
||||
_ => panic!("Days out of Bounds! No presents for you!"),
|
||||
}
|
||||
};
|
||||
res.into()
|
||||
}
|
BIN
images/auto.png
Normal file
BIN
images/auto.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
images/run.png
Normal file
BIN
images/run.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
images/test.png
Normal file
BIN
images/test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
32
src/days/d01.rs
Normal file
32
src/days/d01.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 1;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test01.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d02.rs
Normal file
32
src/days/d02.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 2;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test02.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d03.rs
Normal file
32
src/days/d03.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 3;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test03.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d04.rs
Normal file
32
src/days/d04.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 4;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test04.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d05.rs
Normal file
32
src/days/d05.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 5;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test05.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d06.rs
Normal file
32
src/days/d06.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 6;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test06.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d07.rs
Normal file
32
src/days/d07.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 7;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test07.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d08.rs
Normal file
32
src/days/d08.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 8;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test08.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d09.rs
Normal file
32
src/days/d09.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 9;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test09.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d10.rs
Normal file
32
src/days/d10.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 10;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test10.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d11.rs
Normal file
32
src/days/d11.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 11;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test11.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d12.rs
Normal file
32
src/days/d12.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 12;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test12.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d13.rs
Normal file
32
src/days/d13.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 13;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test13.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d14.rs
Normal file
32
src/days/d14.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 14;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test14.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d15.rs
Normal file
32
src/days/d15.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 15;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test15.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d16.rs
Normal file
32
src/days/d16.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 16;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test16.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d17.rs
Normal file
32
src/days/d17.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 17;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test17.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d18.rs
Normal file
32
src/days/d18.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 18;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test18.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d19.rs
Normal file
32
src/days/d19.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 19;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test19.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d20.rs
Normal file
32
src/days/d20.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 20;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test20.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d21.rs
Normal file
32
src/days/d21.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 21;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test21.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d22.rs
Normal file
32
src/days/d22.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 22;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test22.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d23.rs
Normal file
32
src/days/d23.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 23;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test23.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d24.rs
Normal file
32
src/days/d24.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 24;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test24.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
32
src/days/d25.rs
Normal file
32
src/days/d25.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use super::{Answer, Day, DayImpl};
|
||||
|
||||
const CURRENT_DAY: u8 = 25;
|
||||
|
||||
type Data = Vec<u64>;
|
||||
impl DayImpl<Data> for Day<CURRENT_DAY> {
|
||||
fn init_test() -> (Self, Data) {
|
||||
Self::init(include_str!("test_inputs/test25.txt"))
|
||||
}
|
||||
|
||||
fn expected_results() -> (Answer, Answer) {
|
||||
(Answer::Number(0), Answer::Number(0))
|
||||
}
|
||||
|
||||
fn init(input: &str) -> (Self, Data) {
|
||||
(
|
||||
Self {},
|
||||
input
|
||||
.lines()
|
||||
.map(|v| v.parse::<u64>().expect("error while parsing input."))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn one(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
|
||||
fn two(&self, data: &mut Data) -> Answer {
|
||||
Answer::Number(data.len() as u64)
|
||||
}
|
||||
}
|
250
src/days/mod.rs
Normal file
250
src/days/mod.rs
Normal file
|
@ -0,0 +1,250 @@
|
|||
use aoc_macro::mod_days;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub mod utils;
|
||||
|
||||
// Thanks to andi-makes with his AoC project https://github.com/andi-makes/aoc2021,
|
||||
// this system is heavily inspired by his system.
|
||||
|
||||
pub struct Day<const DAY: u8>;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Answer {
|
||||
Number(u64),
|
||||
String(String),
|
||||
Bitmap(Vec<Vec<bool>>),
|
||||
}
|
||||
|
||||
impl Answer {
|
||||
fn append_per_line(str: String, prefix: &str) -> String {
|
||||
str.lines()
|
||||
.map(|v| prefix.to_owned() + v + "\n")
|
||||
.collect::<String>()
|
||||
.strip_suffix('\n')
|
||||
.unwrap()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
fn bm_get(bm: &[Vec<bool>], x: usize, y: usize) -> bool {
|
||||
if let Some(line) = bm.get(y) {
|
||||
if let Some(v) = line.get(x) {
|
||||
return *v;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn minify_bitmap(bm: &Vec<Vec<bool>>) -> String {
|
||||
let height = bm.len();
|
||||
let width = bm[0].len();
|
||||
|
||||
let mut out = String::new();
|
||||
|
||||
for y in (0..height).step_by(2) {
|
||||
if y != 0 {
|
||||
out += "\n"
|
||||
}
|
||||
for x in (0..width).step_by(2) {
|
||||
let m = (
|
||||
Self::bm_get(bm, x, y),
|
||||
Self::bm_get(bm, x + 1, y),
|
||||
Self::bm_get(bm, x, y + 1),
|
||||
Self::bm_get(bm, x + 1, y + 1),
|
||||
);
|
||||
|
||||
out += match m {
|
||||
(false, false, false, false) => " ",
|
||||
(true, false, false, false) => "▘",
|
||||
(false, true, false, false) => "▝",
|
||||
(true, true, false, false) => "▀",
|
||||
(false, false, true, false) => "▖",
|
||||
(true, false, true, false) => "▌",
|
||||
(false, true, true, false) => "▞",
|
||||
(true, true, true, false) => "▛",
|
||||
(false, false, false, true) => "▗",
|
||||
(true, false, false, true) => "▚",
|
||||
(false, true, false, true) => "▐",
|
||||
(true, true, false, true) => "▜",
|
||||
(false, false, true, true) => "▄",
|
||||
(true, false, true, true) => "▙",
|
||||
(false, true, true, true) => "▟",
|
||||
(true, true, true, true) => "█",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self::append_per_line(out, "\t\t")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Answer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Number(n) => write!(f, "{}", n),
|
||||
Self::String(s) => write!(f, "{}", s),
|
||||
Self::Bitmap(bm) => {
|
||||
writeln!(f).unwrap();
|
||||
write!(f, "{}", Self::minify_bitmap(bm))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Answer {
|
||||
fn from(n: u64) -> Self {
|
||||
Self::Number(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Answer {
|
||||
fn from(s: String) -> Self {
|
||||
Self::String(s)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DayImpl<T>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
/// Parses the test input.
|
||||
fn init_test() -> (Self, T)
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn expected_results() -> (Answer, Answer);
|
||||
|
||||
/// Parse input
|
||||
fn init(input: &str) -> (Self, T)
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Compute part 1
|
||||
fn one(&self, data: &mut T) -> Answer;
|
||||
|
||||
/// Compute part 2
|
||||
fn two(&self, data: &mut T) -> Answer;
|
||||
|
||||
/// Parse input and measure the time it took
|
||||
fn init_timed(input: &str) -> ((Self, T), Duration)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let s = Instant::now();
|
||||
(Self::init(input), s.elapsed())
|
||||
}
|
||||
|
||||
/// Compute part 1 and measure the time it took
|
||||
fn one_timed(&self, data: &mut T) -> (Answer, Duration) {
|
||||
let s = Instant::now();
|
||||
(self.one(data), s.elapsed())
|
||||
}
|
||||
|
||||
/// Compute part 2 and measure the time it took
|
||||
fn two_timed(&self, data: &mut T) -> (Answer, Duration) {
|
||||
let s = Instant::now();
|
||||
(self.two(data), s.elapsed())
|
||||
}
|
||||
|
||||
/// Compute both parts
|
||||
fn run(input: &str) -> (Answer, Answer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let (day, mut data) = Self::init(input);
|
||||
(day.one(&mut data.clone()), day.two(&mut data))
|
||||
}
|
||||
|
||||
/// Init and compute part 1
|
||||
fn run_one(input: &str) -> Answer
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let (day, mut data) = Self::init(input);
|
||||
day.one(&mut data)
|
||||
}
|
||||
|
||||
/// Init and compute part 1
|
||||
fn run_two(input: &str) -> Answer
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let (day, mut data) = Self::init(input);
|
||||
day.two(&mut data)
|
||||
}
|
||||
|
||||
/// Init and compute part 1
|
||||
fn run_one_timed(input: &str) -> (Answer, Duration, Duration)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let ((day, mut data), init_t) = Self::init_timed(input);
|
||||
let (one, one_t) = day.one_timed(&mut data);
|
||||
(one, init_t, one_t)
|
||||
}
|
||||
|
||||
/// Init and compute part 1
|
||||
fn run_two_timed(input: &str) -> (Answer, Duration, Duration)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let ((day, mut data), init_t) = Self::init_timed(input);
|
||||
let (two, two_t) = day.two_timed(&mut data);
|
||||
(two, init_t, two_t)
|
||||
}
|
||||
|
||||
/// Compute both parts, and measure the time each step took
|
||||
fn run_timed(input: &str) -> (Answer, Answer, Duration, Duration, Duration)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let ((day, mut data), i_t) = Self::init_timed(input);
|
||||
let (one, one_t) = day.one_timed(&mut data.clone());
|
||||
let (two, two_t) = day.two_timed(&mut data);
|
||||
|
||||
(one, two, i_t, one_t, two_t)
|
||||
}
|
||||
|
||||
/// Test part one
|
||||
fn test_one() -> (bool, Answer, Answer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let (day, mut data) = Self::init_test();
|
||||
let one = day.one(&mut data);
|
||||
|
||||
let (one_e, _) = Self::expected_results();
|
||||
|
||||
(one_e == one, one, one_e)
|
||||
}
|
||||
|
||||
/// Test part two
|
||||
fn test_two() -> (bool, Answer, Answer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let (day, mut data) = Self::init_test();
|
||||
let two = day.two(&mut data);
|
||||
|
||||
let (_, two_e) = Self::expected_results();
|
||||
|
||||
(two_e == two, two, two_e)
|
||||
}
|
||||
|
||||
/// Run both tests
|
||||
fn test() -> ((bool, Answer, Answer), (bool, Answer, Answer))
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let (day, mut data) = Self::init_test();
|
||||
let one = day.one(&mut data.clone());
|
||||
let two = day.two(&mut data);
|
||||
|
||||
let (one_e, two_e) = Self::expected_results();
|
||||
|
||||
((one_e == one, one, one_e), (two_e == two, two, two_e))
|
||||
}
|
||||
}
|
||||
|
||||
mod_days!();
|
1000
src/days/test_inputs/test01.txt
Normal file
1000
src/days/test_inputs/test01.txt
Normal file
File diff suppressed because it is too large
Load diff
5
src/days/test_inputs/test02.txt
Normal file
5
src/days/test_inputs/test02.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
10
src/days/test_inputs/test03.txt
Normal file
10
src/days/test_inputs/test03.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
467..114..
|
||||
...*......
|
||||
..35..633.
|
||||
......#...
|
||||
617*......
|
||||
.....+.58.
|
||||
..592.....
|
||||
......755.
|
||||
...$.*....
|
||||
.664.598..
|
6
src/days/test_inputs/test04.txt
Normal file
6
src/days/test_inputs/test04.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
|
33
src/days/test_inputs/test05.txt
Normal file
33
src/days/test_inputs/test05.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4
|
2
src/days/test_inputs/test06.txt
Normal file
2
src/days/test_inputs/test06.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Time: 7 15 30
|
||||
Distance: 9 40 200
|
5
src/days/test_inputs/test07.txt
Normal file
5
src/days/test_inputs/test07.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483
|
752
src/days/test_inputs/test08.txt
Normal file
752
src/days/test_inputs/test08.txt
Normal file
|
@ -0,0 +1,752 @@
|
|||
LLRRLRRRLLRLRRLLLLRLRRLRRRLRLRRRLLRRLRRRLLRRLRRLRRLLRRRLRRLRRLRRRLRRLRLRLRRLRRLRRRLLRRLLLRRLRRRLRRRLRRRLRRLRRRLRLLRLRRRLRLRRLLRLRRRLRRRLRLRRRLRRRLRLRLRRLRRLRLRRLLRRRLRRRLRRRLLRRRLRLRLRLRLLRRRLRRRLRRLRRRLLRLRRLRRLRRRLRRRLRRLRLRLRRRLRRLRRLRRRLLRRLRLRLRRRLRLRLRRLRRLLRRLRRRLLRLLRLRLRRRR
|
||||
|
||||
FGF = (HTC, DTX)
|
||||
PTP = (MCL, BDN)
|
||||
LHL = (LJF, BDX)
|
||||
XMM = (KCX, JHL)
|
||||
GLD = (RNN, MXG)
|
||||
HSR = (JPX, CXF)
|
||||
CRF = (BMJ, FHT)
|
||||
QSS = (KPH, FVD)
|
||||
RHV = (LRD, XDS)
|
||||
KTT = (XPS, VCX)
|
||||
LQK = (TLF, VJX)
|
||||
MMK = (VJV, HQV)
|
||||
RKX = (RKG, XJB)
|
||||
HDM = (NFK, JNB)
|
||||
PFJ = (QDJ, NDH)
|
||||
JKB = (MDK, MRJ)
|
||||
BSP = (QBQ, JPM)
|
||||
FQH = (HJD, VHF)
|
||||
QQL = (VDB, KGM)
|
||||
TRB = (KTC, RGN)
|
||||
VXC = (NDK, MVK)
|
||||
BCS = (PSX, PLK)
|
||||
FHK = (MLK, RDP)
|
||||
TVB = (JXV, SSR)
|
||||
GXD = (KSF, BRK)
|
||||
MNJ = (MHG, CRF)
|
||||
RLC = (TGD, CHV)
|
||||
LBQ = (NQK, MHP)
|
||||
JLH = (FGB, KNM)
|
||||
PCN = (CQF, NDF)
|
||||
FVP = (NKS, RCB)
|
||||
GHL = (TTB, KLQ)
|
||||
MTB = (VDM, FKT)
|
||||
LLB = (VXL, TRT)
|
||||
RSS = (GDP, TKD)
|
||||
SFH = (FCM, GKF)
|
||||
KSF = (VQB, JXJ)
|
||||
LJH = (PNS, DGC)
|
||||
TJC = (KQM, BVL)
|
||||
PRL = (TCG, GCQ)
|
||||
NBG = (GNR, SRM)
|
||||
CST = (FXL, BDF)
|
||||
XXH = (KVH, KSM)
|
||||
FJP = (PKX, DSF)
|
||||
DTS = (FFF, DQM)
|
||||
CMG = (VBJ, DBF)
|
||||
NHD = (TCJ, DHF)
|
||||
KKF = (RVP, FVR)
|
||||
LDS = (VPJ, MPN)
|
||||
GHC = (DBK, SCS)
|
||||
KVK = (NFV, MXJ)
|
||||
NTN = (TDC, VNC)
|
||||
FCR = (DCR, FQH)
|
||||
PLK = (GHT, PBT)
|
||||
VJF = (VJN, PVB)
|
||||
TKR = (GHS, TTP)
|
||||
PQJ = (VGB, SGP)
|
||||
TGM = (JQM, PPK)
|
||||
LFQ = (QGB, QXB)
|
||||
RDP = (HSF, MQV)
|
||||
SGP = (HVK, XMV)
|
||||
FTB = (RFV, MLT)
|
||||
LCX = (RSB, RSB)
|
||||
VGD = (XJB, RKG)
|
||||
PFD = (RGK, JGB)
|
||||
DBK = (RMP, RSH)
|
||||
TTC = (NDH, QDJ)
|
||||
PVF = (QRG, QCV)
|
||||
BGV = (TDS, DRK)
|
||||
VHF = (XTB, TGM)
|
||||
DBF = (GGT, BRQ)
|
||||
TFG = (SVV, FCV)
|
||||
MDK = (THF, PLQ)
|
||||
NDF = (BSP, STC)
|
||||
SMZ = (KHB, TST)
|
||||
SLC = (BKM, BCS)
|
||||
NSV = (VVM, VQG)
|
||||
GCA = (XQT, RCD)
|
||||
FVD = (NXJ, MBJ)
|
||||
HCH = (MRF, RQJ)
|
||||
PLN = (BNK, CLF)
|
||||
TTP = (BCP, SLC)
|
||||
BRF = (SHR, CTK)
|
||||
KCX = (PDR, HHQ)
|
||||
GMG = (NFV, MXJ)
|
||||
SNN = (XDS, LRD)
|
||||
SBB = (JXL, BFK)
|
||||
NCV = (KVH, KSM)
|
||||
DQQ = (FFF, DQM)
|
||||
THT = (MFP, VSD)
|
||||
GVH = (KHF, TKB)
|
||||
HPC = (MKX, SVS)
|
||||
KSS = (QQQ, HSR)
|
||||
NCP = (FCV, SVV)
|
||||
FGB = (LGN, LKJ)
|
||||
TST = (DFV, GND)
|
||||
PJR = (VMQ, HPB)
|
||||
BHB = (VMQ, HPB)
|
||||
LMG = (SHS, XJC)
|
||||
GGT = (TQQ, XQK)
|
||||
PKR = (QQR, JGG)
|
||||
FLR = (LJP, VQT)
|
||||
NFK = (HKG, BPJ)
|
||||
MGG = (SST, MCT)
|
||||
BVD = (SNV, TTH)
|
||||
GHX = (GMK, JXG)
|
||||
PDR = (HCD, HNG)
|
||||
XJN = (NHR, CBN)
|
||||
XRG = (LBQ, MTV)
|
||||
VFM = (MMS, VXT)
|
||||
PPP = (LHR, HJH)
|
||||
FJG = (NLS, CCF)
|
||||
NDK = (RHD, BVD)
|
||||
VSB = (LKB, CCX)
|
||||
NJG = (PTK, MCD)
|
||||
MLS = (XCQ, FCR)
|
||||
QSM = (CBJ, GRG)
|
||||
PTC = (NJG, FLT)
|
||||
MRJ = (PLQ, THF)
|
||||
HJD = (XTB, TGM)
|
||||
XCQ = (DCR, FQH)
|
||||
HPN = (CQD, CTP)
|
||||
BDJ = (JND, JRB)
|
||||
PXL = (VXT, MMS)
|
||||
NFV = (SFX, BDQ)
|
||||
SNQ = (PQJ, TNG)
|
||||
LSL = (KFN, JFL)
|
||||
SMK = (FQS, FJJ)
|
||||
QDV = (BDX, LJF)
|
||||
GMK = (TSJ, SVF)
|
||||
GDP = (MML, MML)
|
||||
GRG = (PVF, CKG)
|
||||
CXF = (MNJ, TBZ)
|
||||
LKM = (HJH, LHR)
|
||||
GHS = (BCP, SLC)
|
||||
XBH = (BDS, NDQ)
|
||||
NLL = (NJT, QCJ)
|
||||
MXJ = (BDQ, SFX)
|
||||
FCF = (QQQ, QQQ)
|
||||
SXG = (LFQ, TTZ)
|
||||
PLP = (MJL, FPL)
|
||||
FSV = (SBB, JFC)
|
||||
NLH = (TDS, DRK)
|
||||
QDM = (GHX, GGM)
|
||||
JJB = (MSQ, MMK)
|
||||
TRS = (BXN, RLM)
|
||||
DMP = (RTP, CHG)
|
||||
XGG = (PCC, XKH)
|
||||
MCT = (NLK, DTM)
|
||||
DLC = (JTQ, BLF)
|
||||
VBJ = (GGT, BRQ)
|
||||
XQD = (NTN, XRC)
|
||||
FKM = (QKK, JBQ)
|
||||
PNN = (RGN, KTC)
|
||||
LCM = (DTG, GHC)
|
||||
LKJ = (LFV, RNG)
|
||||
HRR = (JND, JRB)
|
||||
BDN = (SNQ, NVC)
|
||||
RSH = (PJS, LHG)
|
||||
CTP = (DJM, NHF)
|
||||
XMV = (CFJ, MDV)
|
||||
HXM = (PTP, XVQ)
|
||||
CKG = (QCV, QRG)
|
||||
GKK = (CRG, MPJ)
|
||||
LNS = (VSB, GNQ)
|
||||
RVP = (JJB, LCN)
|
||||
DVH = (QLD, QGV)
|
||||
CPH = (PMN, QSC)
|
||||
BXQ = (CPH, DSQ)
|
||||
SDM = (DSB, CNV)
|
||||
RNN = (SHM, LSL)
|
||||
VQC = (GKH, DMP)
|
||||
KXV = (GKN, PTC)
|
||||
TNK = (NMK, PKR)
|
||||
TSL = (MTV, LBQ)
|
||||
VSD = (LGH, HNM)
|
||||
QRQ = (QXH, GRQ)
|
||||
NKS = (NSL, HPN)
|
||||
TQC = (JQK, TXF)
|
||||
THF = (TVM, KKF)
|
||||
VSL = (PLN, GDS)
|
||||
SSN = (FTB, NXF)
|
||||
NHF = (BFG, XTZ)
|
||||
HSP = (QRQ, DFC)
|
||||
JQM = (BNP, PMD)
|
||||
GDV = (RVK, MQF)
|
||||
MTK = (TGD, CHV)
|
||||
FFX = (DSN, XXJ)
|
||||
HKG = (THT, KNJ)
|
||||
RCN = (DCB, XFN)
|
||||
HCD = (TDF, BQM)
|
||||
TKJ = (JPV, GRR)
|
||||
RVK = (HXX, PRL)
|
||||
HDN = (TRT, VXL)
|
||||
KHQ = (DQQ, DTS)
|
||||
MPJ = (PLP, KBG)
|
||||
SFX = (KTT, NTG)
|
||||
NMJ = (BGV, NLH)
|
||||
LXK = (CRB, GXD)
|
||||
KBG = (FPL, MJL)
|
||||
GNQ = (LKB, CCX)
|
||||
MRV = (RVK, MQF)
|
||||
PKH = (NPN, MHQ)
|
||||
NLK = (LTJ, RXP)
|
||||
LBH = (VTP, SGG)
|
||||
NTG = (VCX, XPS)
|
||||
CCD = (GVF, SSJ)
|
||||
BBB = (SSR, JXV)
|
||||
NSL = (CQD, CQD)
|
||||
BNK = (SGS, JQD)
|
||||
TTB = (KVK, GMG)
|
||||
FDR = (RBS, TXD)
|
||||
PJG = (RTV, JQS)
|
||||
LGV = (LSB, NPF)
|
||||
XVQ = (MCL, BDN)
|
||||
BMJ = (KRT, XXN)
|
||||
XCM = (LXK, VKJ)
|
||||
CCF = (SDR, PTQ)
|
||||
GSS = (PJR, BHB)
|
||||
CJL = (QKK, JBQ)
|
||||
FBT = (VJF, SGL)
|
||||
DSB = (QKQ, RBK)
|
||||
SGS = (MLQ, PXT)
|
||||
PKX = (KPF, CNQ)
|
||||
JND = (SDG, SND)
|
||||
DJM = (BFG, BFG)
|
||||
LHK = (SBB, JFC)
|
||||
QLD = (SGX, KDP)
|
||||
NPF = (VDC, KHQ)
|
||||
BRQ = (XQK, TQQ)
|
||||
NGQ = (JNB, NFK)
|
||||
NFH = (MPN, VPJ)
|
||||
KHF = (LKG, GLD)
|
||||
XKC = (XTX, XTX)
|
||||
DJG = (XGL, BTF)
|
||||
LGN = (RNG, LFV)
|
||||
HQV = (CJL, FKM)
|
||||
JPV = (SVD, XJN)
|
||||
TSJ = (NMD, MGG)
|
||||
QRG = (HBD, CST)
|
||||
FXL = (PFX, HVV)
|
||||
TNG = (VGB, SGP)
|
||||
HXX = (GCQ, TCG)
|
||||
RTP = (CDD, QJR)
|
||||
RXN = (LFQ, LFQ)
|
||||
MVK = (BVD, RHD)
|
||||
PLR = (FVP, DHP)
|
||||
GRR = (XJN, SVD)
|
||||
DHJ = (VRN, DTR)
|
||||
HSF = (TSS, JSQ)
|
||||
TXN = (FGF, NMV)
|
||||
CBJ = (CKG, PVF)
|
||||
GHT = (RCN, NTR)
|
||||
SMH = (FJG, LQD)
|
||||
CVN = (PLR, DDF)
|
||||
SJK = (TTF, SLQ)
|
||||
LMN = (XHT, CFF)
|
||||
KLQ = (GMG, KVK)
|
||||
KXC = (CHP, NLL)
|
||||
KNM = (LKJ, LGN)
|
||||
QHK = (LNV, GKK)
|
||||
BTH = (KVR, FNQ)
|
||||
QFV = (PRK, LTV)
|
||||
DBH = (HND, HFC)
|
||||
CRG = (KBG, PLP)
|
||||
TCG = (DVF, BXQ)
|
||||
SJQ = (KPR, QKP)
|
||||
JMJ = (TTB, KLQ)
|
||||
RFV = (XBH, CGX)
|
||||
AAA = (QDM, GMV)
|
||||
JTQ = (HRR, BDJ)
|
||||
MHQ = (HPQ, KXC)
|
||||
SDG = (HGR, RJN)
|
||||
PNS = (FMC, JKB)
|
||||
KHB = (DFV, GND)
|
||||
NXJ = (MLS, HLT)
|
||||
HND = (LVF, BBJ)
|
||||
FCZ = (RCD, XQT)
|
||||
NFP = (FVD, KPH)
|
||||
NTH = (FVH, DJG)
|
||||
GMV = (GHX, GGM)
|
||||
FKT = (CLC, BTH)
|
||||
LTV = (BKP, HVT)
|
||||
VLF = (DLX, FMB)
|
||||
NNP = (NFH, LDS)
|
||||
GQV = (RTR, NMJ)
|
||||
MCD = (PFK, HPC)
|
||||
XML = (RNR, GJF)
|
||||
TXD = (LGT, QSM)
|
||||
DKG = (RTV, JQS)
|
||||
MQF = (PRL, HXX)
|
||||
XJB = (HKV, FLR)
|
||||
SHS = (VVH, CHN)
|
||||
PMD = (NSV, BMQ)
|
||||
TLJ = (DMP, GKH)
|
||||
CMA = (TST, KHB)
|
||||
CRB = (KSF, BRK)
|
||||
XQT = (TXN, LNN)
|
||||
QHF = (XKH, PCC)
|
||||
FQM = (PKR, NMK)
|
||||
DHP = (NKS, RCB)
|
||||
KSM = (DKP, SDM)
|
||||
LKB = (RQV, BRF)
|
||||
BVL = (TRB, PNN)
|
||||
GJF = (NTH, JRX)
|
||||
HTC = (HRL, HXM)
|
||||
JGB = (QVX, GMR)
|
||||
VJV = (CJL, FKM)
|
||||
RGK = (QVX, GMR)
|
||||
KPF = (JCK, XDV)
|
||||
LNV = (CRG, MPJ)
|
||||
QNP = (LXK, VKJ)
|
||||
MFT = (NJK, VVL)
|
||||
PBT = (RCN, NTR)
|
||||
CKV = (XHT, CFF)
|
||||
RCD = (TXN, LNN)
|
||||
MBJ = (HLT, MLS)
|
||||
QDC = (NMJ, RTR)
|
||||
SVV = (FJC, MJR)
|
||||
STN = (LQC, HFR)
|
||||
QXB = (RPJ, MHL)
|
||||
VJN = (TVB, BBB)
|
||||
GKH = (RTP, CHG)
|
||||
XGL = (PMX, FFX)
|
||||
KNH = (FGB, KNM)
|
||||
TVN = (QKP, KPR)
|
||||
JFC = (BFK, JXL)
|
||||
LHG = (TFG, NCP)
|
||||
HFT = (HND, HFC)
|
||||
DKP = (DSB, CNV)
|
||||
LGH = (DCG, QPN)
|
||||
LGC = (VVL, NJK)
|
||||
HSC = (NTJ, QQL)
|
||||
CFF = (JMJ, GHL)
|
||||
PFH = (SGL, VJF)
|
||||
LGT = (GRG, CBJ)
|
||||
JSQ = (SFH, RVQ)
|
||||
VDM = (CLC, BTH)
|
||||
NTR = (DCB, XFN)
|
||||
KVH = (DKP, SDM)
|
||||
BVQ = (LSH, SDX)
|
||||
NRC = (QCH, TRS)
|
||||
DCB = (KBT, TSR)
|
||||
DGC = (FMC, JKB)
|
||||
VMQ = (LJR, LJR)
|
||||
MXG = (LSL, SHM)
|
||||
CPM = (TRS, QCH)
|
||||
DLX = (LQN, TJC)
|
||||
GDS = (BNK, CLF)
|
||||
JRK = (PGJ, NHD)
|
||||
JXV = (DRH, CVN)
|
||||
SVD = (CBN, NHR)
|
||||
LCN = (MSQ, MMK)
|
||||
MJL = (RQL, RGF)
|
||||
JLT = (QRQ, DFC)
|
||||
BGP = (DPV, VXC)
|
||||
PSQ = (PJR, BHB)
|
||||
NTJ = (KGM, VDB)
|
||||
SGX = (VFM, PXL)
|
||||
QBQ = (MCM, VNV)
|
||||
CHV = (QJN, CMG)
|
||||
DRK = (BKT, LBH)
|
||||
SVS = (NPV, HCH)
|
||||
BCP = (BKM, BCS)
|
||||
BXN = (PSQ, GSS)
|
||||
GQJ = (SMH, XHX)
|
||||
NPV = (RQJ, MRF)
|
||||
NMV = (HTC, DTX)
|
||||
LKR = (SPG, SJK)
|
||||
HLT = (XCQ, FCR)
|
||||
SKX = (HSC, CFR)
|
||||
SDR = (BLQ, FKV)
|
||||
FCN = (FKT, VDM)
|
||||
VPB = (CJR, FHK)
|
||||
MHL = (PFJ, TTC)
|
||||
XQK = (BBK, PBQ)
|
||||
MDV = (SCJ, BKF)
|
||||
VDC = (DQQ, DTS)
|
||||
RTV = (LDP, PCN)
|
||||
GRQ = (FDR, DHG)
|
||||
NDH = (JGX, SSN)
|
||||
NCG = (GNR, SRM)
|
||||
LQN = (BVL, KQM)
|
||||
NHR = (FQM, TNK)
|
||||
LJR = (GDP, GDP)
|
||||
JXL = (VKV, MJQ)
|
||||
QCH = (BXN, RLM)
|
||||
QGB = (MHL, RPJ)
|
||||
DDN = (GLT, DHJ)
|
||||
SHR = (BGP, FCX)
|
||||
DPV = (MVK, NDK)
|
||||
XHT = (GHL, JMJ)
|
||||
QKK = (LCX, LCX)
|
||||
TRT = (QFV, NHT)
|
||||
PBQ = (DPX, LNS)
|
||||
JHL = (HHQ, PDR)
|
||||
DCG = (JLX, VSL)
|
||||
SST = (NLK, DTM)
|
||||
QPN = (JLX, VSL)
|
||||
GXS = (FJP, DCM)
|
||||
VJX = (DKB, FCZ)
|
||||
XXJ = (HDN, LLB)
|
||||
JPM = (VNV, MCM)
|
||||
QGV = (SGX, KDP)
|
||||
QNA = (QGB, QXB)
|
||||
CQD = (DJM, DJM)
|
||||
TTF = (TVN, SJQ)
|
||||
CHP = (QCJ, NJT)
|
||||
BBJ = (LVT, TKJ)
|
||||
VKJ = (CRB, GXD)
|
||||
LJF = (FFL, KXV)
|
||||
TKD = (MML, ZZZ)
|
||||
QKP = (CKV, LMN)
|
||||
CQF = (STC, BSP)
|
||||
PHM = (FHK, CJR)
|
||||
BTF = (PMX, FFX)
|
||||
JRX = (FVH, DJG)
|
||||
PMN = (NBG, NCG)
|
||||
LKG = (RNN, MXG)
|
||||
NXB = (JLH, KNH)
|
||||
MLQ = (FBT, PFH)
|
||||
JML = (XKC, GLX)
|
||||
NHT = (PRK, LTV)
|
||||
BLQ = (SKX, HGL)
|
||||
BDX = (FFL, KXV)
|
||||
DVN = (SCR, JML)
|
||||
FPL = (RQL, RGF)
|
||||
MMS = (SVR, KSV)
|
||||
FLT = (PTK, MCD)
|
||||
PTQ = (BLQ, FKV)
|
||||
DHG = (RBS, TXD)
|
||||
QSC = (NCG, NBG)
|
||||
LFV = (NXP, GMF)
|
||||
XDS = (KQP, STN)
|
||||
PVB = (BBB, TVB)
|
||||
JGX = (NXF, FTB)
|
||||
CNB = (PRR, JRK)
|
||||
TQQ = (PBQ, BBK)
|
||||
GMF = (MKH, CRH)
|
||||
SDP = (KCQ, PKV)
|
||||
MHP = (HMR, LCM)
|
||||
RRS = (QGV, QLD)
|
||||
PKV = (XKG, HTH)
|
||||
JLX = (GDS, PLN)
|
||||
RJN = (VGD, RKX)
|
||||
NMK = (QQR, JGG)
|
||||
PFK = (SVS, MKX)
|
||||
NXF = (MLT, RFV)
|
||||
VVM = (HDM, NGQ)
|
||||
VSJ = (QDG, VKM)
|
||||
RBS = (QSM, LGT)
|
||||
KFN = (RRS, DVH)
|
||||
XXN = (XMM, SKM)
|
||||
TXF = (LKM, PPP)
|
||||
DFV = (VLF, GPC)
|
||||
RMP = (PJS, LHG)
|
||||
LVP = (QDG, VKM)
|
||||
DFC = (QXH, GRQ)
|
||||
GPC = (DLX, FMB)
|
||||
LJP = (CCD, FSM)
|
||||
MPN = (PFD, RSN)
|
||||
SGG = (RHV, SNN)
|
||||
BDF = (HVV, PFX)
|
||||
QQR = (GVH, QSB)
|
||||
RPJ = (TTC, PFJ)
|
||||
NDQ = (NXV, XQD)
|
||||
RGF = (BVQ, GMB)
|
||||
TXM = (DCM, FJP)
|
||||
VRN = (XFV, MFG)
|
||||
FCX = (VXC, DPV)
|
||||
RQJ = (HFT, DBH)
|
||||
MLT = (CGX, XBH)
|
||||
TSR = (QSS, NFP)
|
||||
BCD = (VQC, TLJ)
|
||||
JQK = (PPP, LKM)
|
||||
DSF = (CNQ, KPF)
|
||||
CVS = (LDS, NFH)
|
||||
VTP = (SNN, RHV)
|
||||
FTA = (MHG, CRF)
|
||||
RNR = (NTH, JRX)
|
||||
DRH = (PLR, DDF)
|
||||
KSV = (SMK, NHC)
|
||||
VKM = (HFV, LMG)
|
||||
DTR = (XFV, MFG)
|
||||
MML = (QDM, GMV)
|
||||
HPQ = (CHP, NLL)
|
||||
GKF = (QHK, TDM)
|
||||
TDF = (DHX, LPT)
|
||||
PXT = (FBT, PFH)
|
||||
BRK = (VQB, JXJ)
|
||||
VXT = (KSV, SVR)
|
||||
HNM = (QPN, DCG)
|
||||
HHQ = (HNG, HCD)
|
||||
MPG = (JJS, SMZ)
|
||||
CGS = (QDC, GQV)
|
||||
GMR = (GQJ, RMH)
|
||||
BKF = (CNB, NKP)
|
||||
VDB = (VPB, PHM)
|
||||
DSQ = (PMN, QSC)
|
||||
DTX = (HRL, HXM)
|
||||
QXH = (FDR, DHG)
|
||||
LPT = (QDV, LHL)
|
||||
DKB = (XQT, RCD)
|
||||
QJN = (VBJ, DBF)
|
||||
FVR = (JJB, LCN)
|
||||
MFG = (CPM, NRC)
|
||||
FMC = (MDK, MRJ)
|
||||
JLL = (RXN, SXG)
|
||||
NQK = (LCM, HMR)
|
||||
KBT = (QSS, NFP)
|
||||
DHX = (QDV, LHL)
|
||||
SKM = (JHL, KCX)
|
||||
FSM = (SSJ, GVF)
|
||||
NVC = (TNG, PQJ)
|
||||
SRM = (HSP, JLT)
|
||||
FCM = (TDM, QHK)
|
||||
NPN = (HPQ, KXC)
|
||||
JGG = (QSB, GVH)
|
||||
DCM = (DSF, PKX)
|
||||
BLF = (BDJ, HRR)
|
||||
JXJ = (JCC, LGV)
|
||||
PSX = (PBT, GHT)
|
||||
CRH = (NXX, BCD)
|
||||
SCS = (RSH, RMP)
|
||||
LTJ = (FSV, LHK)
|
||||
PSV = (PKV, KCQ)
|
||||
TVM = (FVR, RVP)
|
||||
LSH = (DDN, HNX)
|
||||
XTX = (RXN, RXN)
|
||||
RKG = (FLR, HKV)
|
||||
JNB = (BPJ, HKG)
|
||||
GKN = (NJG, FLT)
|
||||
RLM = (PSQ, GSS)
|
||||
CNQ = (XDV, JCK)
|
||||
HFR = (TQC, KLB)
|
||||
RQV = (SHR, CTK)
|
||||
DSN = (HDN, LLB)
|
||||
FFF = (KSR, KSR)
|
||||
FJJ = (FCF, KSS)
|
||||
KPH = (NXJ, MBJ)
|
||||
KCQ = (XKG, HTH)
|
||||
PPK = (BNP, PMD)
|
||||
TKB = (LKG, GLD)
|
||||
JQD = (MLQ, PXT)
|
||||
BPJ = (THT, KNJ)
|
||||
RBK = (FCN, MTB)
|
||||
PDK = (GHS, TTP)
|
||||
SDX = (DDN, HNX)
|
||||
BQM = (DHX, LPT)
|
||||
KNJ = (MFP, VSD)
|
||||
CLC = (FNQ, KVR)
|
||||
XPS = (NXB, SXK)
|
||||
CLF = (JQD, SGS)
|
||||
DQM = (KSR, LQK)
|
||||
XKG = (MRV, GDV)
|
||||
RHD = (TTH, SNV)
|
||||
RTR = (BGV, NLH)
|
||||
QSB = (TKB, KHF)
|
||||
BKP = (PJG, DKG)
|
||||
RMH = (XHX, SMH)
|
||||
PGR = (PNS, DGC)
|
||||
GND = (VLF, GPC)
|
||||
PCC = (QNP, XCM)
|
||||
KDP = (PXL, VFM)
|
||||
SPG = (TTF, SLQ)
|
||||
SXK = (KNH, JLH)
|
||||
PFX = (MFT, LGC)
|
||||
BKM = (PLK, PSX)
|
||||
TGD = (CMG, QJN)
|
||||
NXV = (NTN, XRC)
|
||||
MFP = (HNM, LGH)
|
||||
MQQ = (RSB, MPG)
|
||||
TBZ = (CRF, MHG)
|
||||
XDV = (TKR, PDK)
|
||||
DVF = (CPH, DSQ)
|
||||
SNV = (GXS, TXM)
|
||||
DCR = (HJD, VHF)
|
||||
QDG = (LMG, HFV)
|
||||
MHG = (FHT, BMJ)
|
||||
NKP = (PRR, JRK)
|
||||
XRC = (VNC, TDC)
|
||||
JFL = (RRS, DVH)
|
||||
KRT = (SKM, XMM)
|
||||
CDD = (DVN, PDM)
|
||||
NXP = (MKH, CRH)
|
||||
LVT = (GRR, JPV)
|
||||
NJT = (RLC, MTK)
|
||||
HVV = (MFT, LGC)
|
||||
RNG = (GMF, NXP)
|
||||
SVR = (SMK, NHC)
|
||||
QDJ = (SSN, JGX)
|
||||
RQL = (BVQ, GMB)
|
||||
HMR = (GHC, DTG)
|
||||
CGX = (BDS, NDQ)
|
||||
MJQ = (LVP, VSJ)
|
||||
XJC = (CHN, VVH)
|
||||
FFL = (GKN, PTC)
|
||||
XJS = (SJK, SPG)
|
||||
JQS = (PCN, LDP)
|
||||
SHM = (JFL, KFN)
|
||||
HPB = (LJR, RSS)
|
||||
JXG = (SVF, TSJ)
|
||||
STC = (QBQ, JPM)
|
||||
FHT = (XXN, KRT)
|
||||
LRD = (KQP, STN)
|
||||
VCX = (SXK, NXB)
|
||||
KSR = (TLF, TLF)
|
||||
KQM = (PNN, TRB)
|
||||
KTC = (TSL, XRG)
|
||||
VKV = (VSJ, LVP)
|
||||
XTB = (PPK, JQM)
|
||||
BFK = (MJQ, VKV)
|
||||
GLT = (VRN, DTR)
|
||||
VPJ = (PFD, RSN)
|
||||
BKT = (SGG, VTP)
|
||||
BMQ = (VVM, VQG)
|
||||
KVR = (QHF, XGG)
|
||||
LNH = (QDC, GQV)
|
||||
SLQ = (SJQ, TVN)
|
||||
CJR = (RDP, MLK)
|
||||
JCK = (TKR, PDK)
|
||||
GVF = (XXH, NCV)
|
||||
LQC = (TQC, KLB)
|
||||
TSS = (SFH, RVQ)
|
||||
HRL = (XVQ, PTP)
|
||||
TDM = (GKK, LNV)
|
||||
BNP = (BMQ, NSV)
|
||||
BFG = (RNQ, PKH)
|
||||
CFJ = (BKF, SCJ)
|
||||
QQQ = (JPX, JPX)
|
||||
MQV = (JSQ, TSS)
|
||||
XHX = (LQD, FJG)
|
||||
PMX = (XXJ, DSN)
|
||||
KGM = (VPB, PHM)
|
||||
GNR = (JLT, HSP)
|
||||
NLS = (PTQ, SDR)
|
||||
MSQ = (VJV, HQV)
|
||||
FMB = (TJC, LQN)
|
||||
XFV = (NRC, CPM)
|
||||
RSN = (JGB, RGK)
|
||||
PRK = (HVT, BKP)
|
||||
HFV = (XJC, SHS)
|
||||
SVF = (NMD, MGG)
|
||||
QVX = (GQJ, RMH)
|
||||
TCF = (BLF, JTQ)
|
||||
MLK = (HSF, MQV)
|
||||
RVQ = (FCM, GKF)
|
||||
GLX = (XTX, JLL)
|
||||
PDM = (SCR, JML)
|
||||
HGR = (RKX, VGD)
|
||||
JRB = (SND, SDG)
|
||||
FKV = (SKX, HGL)
|
||||
TDC = (LNH, CGS)
|
||||
FVH = (XGL, BTF)
|
||||
NHC = (FQS, FJJ)
|
||||
BBK = (LNS, DPX)
|
||||
VVH = (NNP, CVS)
|
||||
NJK = (DLC, TCF)
|
||||
SGL = (VJN, PVB)
|
||||
MTV = (NQK, MHP)
|
||||
PJS = (TFG, NCP)
|
||||
DTG = (SCS, DBK)
|
||||
TCJ = (SDP, PSV)
|
||||
VGB = (HVK, XMV)
|
||||
MCL = (SNQ, NVC)
|
||||
NXX = (TLJ, VQC)
|
||||
HVK = (MDV, CFJ)
|
||||
NMD = (MCT, SST)
|
||||
TTZ = (QXB, QGB)
|
||||
VNC = (LNH, CGS)
|
||||
GMB = (LSH, SDX)
|
||||
CHN = (NNP, CVS)
|
||||
FCV = (MJR, FJC)
|
||||
HNG = (TDF, BQM)
|
||||
SCR = (XKC, GLX)
|
||||
DDF = (DHP, FVP)
|
||||
CTK = (BGP, FCX)
|
||||
CHG = (QJR, CDD)
|
||||
VXL = (QFV, NHT)
|
||||
SSJ = (XXH, NCV)
|
||||
RNQ = (NPN, MHQ)
|
||||
FJC = (XJF, XML)
|
||||
XTZ = (PKH, RNQ)
|
||||
CBN = (TNK, FQM)
|
||||
RSB = (JJS, JJS)
|
||||
TTH = (GXS, TXM)
|
||||
HJH = (LKR, XJS)
|
||||
VQB = (JCC, LGV)
|
||||
HKV = (LJP, VQT)
|
||||
RGN = (XRG, TSL)
|
||||
MKX = (NPV, HCH)
|
||||
JJS = (TST, KHB)
|
||||
JPX = (MNJ, MNJ)
|
||||
HTH = (MRV, GDV)
|
||||
VQT = (CCD, FSM)
|
||||
PGJ = (DHF, TCJ)
|
||||
DHF = (SDP, PSV)
|
||||
XJF = (GJF, RNR)
|
||||
LQD = (CCF, NLS)
|
||||
MRF = (DBH, HFT)
|
||||
FNQ = (XGG, QHF)
|
||||
GGM = (JXG, GMK)
|
||||
BDS = (NXV, XQD)
|
||||
MCM = (PGR, LJH)
|
||||
LDP = (NDF, CQF)
|
||||
QCJ = (RLC, MTK)
|
||||
CCX = (RQV, BRF)
|
||||
HBD = (BDF, FXL)
|
||||
CBA = (RNQ, PKH)
|
||||
MJR = (XJF, XML)
|
||||
JCC = (LSB, NPF)
|
||||
VQG = (NGQ, HDM)
|
||||
RCB = (NSL, HPN)
|
||||
QCV = (HBD, CST)
|
||||
TDS = (LBH, BKT)
|
||||
CNV = (QKQ, RBK)
|
||||
KLB = (JQK, TXF)
|
||||
XKH = (QNP, XCM)
|
||||
SCJ = (CNB, NKP)
|
||||
HGL = (CFR, HSC)
|
||||
BDQ = (NTG, KTT)
|
||||
PRR = (PGJ, NHD)
|
||||
KPR = (CKV, LMN)
|
||||
HFC = (LVF, BBJ)
|
||||
TLF = (DKB, DKB)
|
||||
SND = (HGR, RJN)
|
||||
VNV = (PGR, LJH)
|
||||
PLQ = (KKF, TVM)
|
||||
LVF = (LVT, TKJ)
|
||||
QJR = (PDM, DVN)
|
||||
HVT = (DKG, PJG)
|
||||
CFR = (QQL, NTJ)
|
||||
DTM = (LTJ, RXP)
|
||||
HNX = (GLT, DHJ)
|
||||
QKQ = (FCN, MTB)
|
||||
PTK = (HPC, PFK)
|
||||
FQS = (FCF, KSS)
|
||||
JBQ = (LCX, MQQ)
|
||||
RXP = (LHK, FSV)
|
||||
SSR = (DRH, CVN)
|
||||
LSB = (VDC, KHQ)
|
||||
DPX = (GNQ, VSB)
|
||||
ZZZ = (GMV, QDM)
|
||||
XFN = (TSR, KBT)
|
||||
LNN = (NMV, FGF)
|
||||
KQP = (LQC, HFR)
|
||||
LHR = (XJS, LKR)
|
||||
GCQ = (DVF, BXQ)
|
||||
VVL = (TCF, DLC)
|
||||
MKH = (NXX, BCD)
|
3
src/days/test_inputs/test09.txt
Normal file
3
src/days/test_inputs/test09.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
0 3 6 9 12 15
|
||||
1 3 6 10 15 21
|
||||
10 13 16 21 30 45
|
10
src/days/test_inputs/test10.txt
Normal file
10
src/days/test_inputs/test10.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
FF7FSF7F7F7F7F7F---7
|
||||
L|LJ||||||||||||F--J
|
||||
FL-7LJLJ||||||LJL-77
|
||||
F--JF--7||LJLJ7F7FJ-
|
||||
L---JF-JLJ.||-FJLJJ7
|
||||
|F|F-JF---7F7-L7L|7|
|
||||
|FFJF7L7F-JF7|JL---7
|
||||
7-L-JL7||F7|L7F-7F7|
|
||||
L.L7LFJ|||||FJL7||LJ
|
||||
L7JLJL-JLJLJL--JLJ.L
|
10
src/days/test_inputs/test11.txt
Normal file
10
src/days/test_inputs/test11.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
...#......
|
||||
.......#..
|
||||
#.........
|
||||
..........
|
||||
......#...
|
||||
.#........
|
||||
.........#
|
||||
..........
|
||||
.......#..
|
||||
#...#.....
|
6
src/days/test_inputs/test12.txt
Normal file
6
src/days/test_inputs/test12.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
???.### 1,1,3
|
||||
.??..??...?##. 1,1,3
|
||||
?#?#?#?#?#?#?#? 1,3,1,6
|
||||
????.#...#... 4,1,1
|
||||
????.######..#####. 1,6,5
|
||||
?###???????? 3,2,1
|
15
src/days/test_inputs/test13.txt
Normal file
15
src/days/test_inputs/test13.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
#.##..##.
|
||||
..#.##.#.
|
||||
##......#
|
||||
##......#
|
||||
..#.##.#.
|
||||
..##..##.
|
||||
#.#.##.#.
|
||||
|
||||
#...##..#
|
||||
#....#..#
|
||||
..##..###
|
||||
#####.##.
|
||||
#####.##.
|
||||
..##..###
|
||||
#....#..#
|
10
src/days/test_inputs/test14.txt
Normal file
10
src/days/test_inputs/test14.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
O....#....
|
||||
O.OO#....#
|
||||
.....##...
|
||||
OO.#O....O
|
||||
.O.....O#.
|
||||
O.#..O.#.#
|
||||
..O..#O..O
|
||||
.......O..
|
||||
#....###..
|
||||
#OO..#....
|
1
src/days/test_inputs/test15.txt
Normal file
1
src/days/test_inputs/test15.txt
Normal file
|
@ -0,0 +1 @@
|
|||
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
|
10
src/days/test_inputs/test16.txt
Normal file
10
src/days/test_inputs/test16.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
.|...\....
|
||||
|.-.\.....
|
||||
.....|-...
|
||||
........|.
|
||||
..........
|
||||
.........\
|
||||
..../.\\..
|
||||
.-.-/..|..
|
||||
.|....-|.\
|
||||
..//.|....
|
13
src/days/test_inputs/test17.txt
Normal file
13
src/days/test_inputs/test17.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
2413432311323
|
||||
3215453535623
|
||||
3255245654254
|
||||
3446585845452
|
||||
4546657867536
|
||||
1438598798454
|
||||
4457876987766
|
||||
3637877979653
|
||||
4654967986887
|
||||
4564679986453
|
||||
1224686865563
|
||||
2546548887735
|
||||
4322674655533
|
14
src/days/test_inputs/test18.txt
Normal file
14
src/days/test_inputs/test18.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
R 6 (#70c710)
|
||||
D 5 (#0dc571)
|
||||
L 2 (#5713f0)
|
||||
D 2 (#d2c081)
|
||||
R 2 (#59c680)
|
||||
D 2 (#411b91)
|
||||
L 5 (#8ceee2)
|
||||
U 2 (#caa173)
|
||||
L 1 (#1b58a2)
|
||||
U 2 (#caa171)
|
||||
R 2 (#7807d2)
|
||||
U 3 (#a77fa3)
|
||||
L 2 (#015232)
|
||||
U 2 (#7a21e3)
|
0
src/days/test_inputs/test19.txt
Normal file
0
src/days/test_inputs/test19.txt
Normal file
0
src/days/test_inputs/test20.txt
Normal file
0
src/days/test_inputs/test20.txt
Normal file
0
src/days/test_inputs/test21.txt
Normal file
0
src/days/test_inputs/test21.txt
Normal file
0
src/days/test_inputs/test22.txt
Normal file
0
src/days/test_inputs/test22.txt
Normal file
0
src/days/test_inputs/test23.txt
Normal file
0
src/days/test_inputs/test23.txt
Normal file
0
src/days/test_inputs/test24.txt
Normal file
0
src/days/test_inputs/test24.txt
Normal file
0
src/days/test_inputs/test25.txt
Normal file
0
src/days/test_inputs/test25.txt
Normal file
161
src/days/utils.rs
Normal file
161
src/days/utils.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
/// A general purpose struct able to store 2-Dimensional maps of Tiles.
|
||||
///
|
||||
/// Can be parsed from a multi-line &str, if the T type implements [`From<char>`](std::convert::From).
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct Map<T> {
|
||||
tiles: Vec<Vec<T>>,
|
||||
dim: (usize, usize),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> Map<T> {
|
||||
/// Returns the dimensions of the map as a tuple `(x: usize, y: usize)`
|
||||
pub fn dimensions(&self) -> (usize, usize) {
|
||||
self.dim
|
||||
}
|
||||
|
||||
/// Gets the tile of a specified position.
|
||||
///
|
||||
/// May return None, if the position is outside the dimensions.
|
||||
pub fn get(&self, x: usize, y: usize) -> Option<&T> {
|
||||
self.tiles.get(y)?.get(x)
|
||||
}
|
||||
|
||||
/// Sets the tile of a specified position.
|
||||
pub fn set(&mut self, x: usize, y: usize, value: T) {
|
||||
self.tiles[y][x] = value;
|
||||
}
|
||||
|
||||
/// Get the internally stored tile data.
|
||||
pub fn get_raw_tiles(&self) -> &Vec<Vec<T>> {
|
||||
&self.tiles
|
||||
}
|
||||
|
||||
/// Get the internally stored tile data as mutable reference.
|
||||
pub fn get_raw_tiles_mut(&mut self) -> &mut Vec<Vec<T>> {
|
||||
&mut self.tiles
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vec<Vec<T>>> for Map<T> {
|
||||
/// Creates a Map from a `Vec<Vec<T>>`.
|
||||
/// The dimensions are derived from the length of the y-Axis and first x line.
|
||||
fn from(value: Vec<Vec<T>>) -> Self {
|
||||
Self {
|
||||
dim: (value[0].len(), value.len()),
|
||||
tiles: value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<&str> for Map<T>
|
||||
where
|
||||
T: From<char>,
|
||||
{
|
||||
fn from(value: &str) -> Self {
|
||||
let tiles: Vec<Vec<T>> = value
|
||||
.lines()
|
||||
.map(|v| v.chars().map(|v| v.into()).collect())
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
dim: (tiles[0].len(), tiles.len()),
|
||||
tiles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Direction {
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn opposite(&self) -> Direction {
|
||||
match self {
|
||||
Self::North => Self::South,
|
||||
Self::South => Self::North,
|
||||
Self::West => Self::East,
|
||||
Self::East => Self::West,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_pos(
|
||||
&self,
|
||||
pos: (usize, usize),
|
||||
upper_limit: (usize, usize),
|
||||
) -> Option<(usize, usize)> {
|
||||
match self {
|
||||
Self::North => {
|
||||
if pos.1 != 0 {
|
||||
Some((pos.0, pos.1 - 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::South => {
|
||||
if pos.1 < upper_limit.1 {
|
||||
Some((pos.0, pos.1 + 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::West => {
|
||||
if pos.0 != 0 {
|
||||
Some((pos.0 - 1, pos.1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::East => {
|
||||
if pos.0 < upper_limit.0 {
|
||||
Some((pos.0 + 1, pos.1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_pos_signed(
|
||||
&self,
|
||||
pos: (isize, isize),
|
||||
lower_limit: (isize, isize),
|
||||
upper_limit: (isize, isize),
|
||||
) -> Option<(isize, isize)> {
|
||||
match self {
|
||||
Self::North => {
|
||||
if pos.1 > lower_limit.1 {
|
||||
Some((pos.0, pos.1 - 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::South => {
|
||||
if pos.1 < upper_limit.1 {
|
||||
Some((pos.0, pos.1 + 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::West => {
|
||||
if pos.0 > lower_limit.0 {
|
||||
Some((pos.0 - 1, pos.1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::East => {
|
||||
if pos.0 < upper_limit.0 {
|
||||
Some((pos.0 + 1, pos.1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
261
src/lib.rs
Normal file
261
src/lib.rs
Normal file
|
@ -0,0 +1,261 @@
|
|||
use crate::days::Answer;
|
||||
use crate::days::Day;
|
||||
use crate::days::DayImpl;
|
||||
use aoc_macro::*;
|
||||
use colored::*;
|
||||
use lazy_static::lazy_static;
|
||||
use mut_static::MutStatic;
|
||||
use std::time::Duration;
|
||||
|
||||
mod days;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Verbosity {
|
||||
None,
|
||||
Verbose,
|
||||
Development,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Part {
|
||||
One,
|
||||
Two,
|
||||
Both,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Settings {
|
||||
verbosity: Verbosity,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
fn set_verbosity(&mut self, new: Verbosity) {
|
||||
self.verbosity = new;
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref VERBOSITY: MutStatic<Settings> = MutStatic::from(Settings {
|
||||
verbosity: Verbosity::None
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_verbosity(new_verbosity: Verbosity) {
|
||||
let mut handle = VERBOSITY.write().unwrap();
|
||||
handle.set_verbosity(new_verbosity);
|
||||
}
|
||||
|
||||
pub fn get_verbosity() -> Verbosity {
|
||||
VERBOSITY.read().unwrap().verbosity.clone()
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! vprintln {
|
||||
($($arg:tt)*) => {
|
||||
#[cfg(debug_assertions)]
|
||||
if $crate::get_verbosity() == $crate::Verbosity::Verbose || $crate::get_verbosity() == $crate::Verbosity::Development {
|
||||
println!(
|
||||
$($arg)*
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! vprint {
|
||||
($($arg:tt)*) => {
|
||||
#[cfg(debug_assertions)]
|
||||
if $crate::get_verbosity() == $crate::Verbosity::Verbose || $crate::get_verbosity() == $crate::Verbosity::Development {
|
||||
print!(
|
||||
$($arg)*
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! dprintln {
|
||||
($($arg:tt)*) => {
|
||||
#[cfg(debug_assertions)]
|
||||
if $crate::get_verbosity() == $crate::Verbosity::Development {
|
||||
println!(
|
||||
$($arg)*
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! dprint {
|
||||
($($arg:tt)*) => {
|
||||
#[cfg(debug_assertions)]
|
||||
if $crate::get_verbosity() == $crate::Verbosity::Development {
|
||||
print!(
|
||||
$($arg)*
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn dynamic_range_time_format(d: &Duration) -> String {
|
||||
let nanos = d.as_nanos();
|
||||
|
||||
if nanos < 1000 {
|
||||
// less than one microsecond
|
||||
format!("{} ns", nanos)
|
||||
} else if nanos < 100000 {
|
||||
// less than 10 microseconds
|
||||
format!("{:.3} µs", nanos as f64 / 1000.0)
|
||||
} else if nanos < 1000000 {
|
||||
// less than one millisecond
|
||||
format!("{} µs", nanos / 1000)
|
||||
} else if nanos < 10000000 {
|
||||
// less than 10 milliseconds
|
||||
format!("{:.3} ms", nanos as f64 / 1000000.0)
|
||||
} else if nanos < 1000000000 {
|
||||
// less than a second
|
||||
format!("{} ms", nanos / 1000000)
|
||||
} else if nanos < 10000000000 {
|
||||
// less than 10 seconds
|
||||
format!("{:.3} s", nanos as f64 / 1000000000.0)
|
||||
} else {
|
||||
// more than 10 seconds
|
||||
format!("{} s", nanos / 1000000000)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_day(day: u8, part: Part, input: &str) {
|
||||
println!("{} Day {}", "Starting".green().bold(), day);
|
||||
println!("{}", "-----------------------".green().bold());
|
||||
let (one, two, init_t, one_t, two_t) = match part {
|
||||
Part::Both => match_and_run_day_both!(),
|
||||
Part::One => {
|
||||
let (one, init_t, one_t) = match_and_run_day_one!();
|
||||
(one, Answer::Number(0), init_t, one_t, Duration::ZERO)
|
||||
}
|
||||
Part::Two => {
|
||||
let (two, init_t, two_t) = match_and_run_day_two!();
|
||||
(Answer::Number(0), two, init_t, Duration::ZERO, two_t)
|
||||
}
|
||||
};
|
||||
|
||||
println!("{}:", "Results".green().bold());
|
||||
println!(
|
||||
"\t{}: {}",
|
||||
"Parsing time".green(),
|
||||
dynamic_range_time_format(&init_t).bold().blue()
|
||||
);
|
||||
if part == Part::Both || part == Part::One {
|
||||
println!("\t{}:", "Part 1".green());
|
||||
println!("\t\tSolution: {}", format!("{}", one).bold().blue());
|
||||
println!(
|
||||
"\t\tTook: {}",
|
||||
if cfg!(debug_assertions) {
|
||||
(dynamic_range_time_format(&one_t) + " (DEBUG)")
|
||||
.bold()
|
||||
.red()
|
||||
} else {
|
||||
dynamic_range_time_format(&one_t).bold().blue()
|
||||
}
|
||||
);
|
||||
}
|
||||
if part == Part::Both || part == Part::Two {
|
||||
println!("\t{}:", "Part 2".green());
|
||||
println!("\t\tSolution: {}", format!("{}", two).bold().blue());
|
||||
println!(
|
||||
"\t\tTook: {}",
|
||||
if cfg!(debug_assertions) {
|
||||
(dynamic_range_time_format(&two_t) + " (DEBUG)")
|
||||
.bold()
|
||||
.red()
|
||||
} else {
|
||||
dynamic_range_time_format(&two_t).bold().blue()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_day(day: u8, part: Part) -> bool {
|
||||
println!("{} Day {}", "Testing".green().bold(), day);
|
||||
println!("{}", "-----------------------".green().bold());
|
||||
match part {
|
||||
Part::Both => {
|
||||
let ((one_p, one_r, one_e), (two_p, two_r, two_e)) = match_and_test_day_both!();
|
||||
|
||||
println!("{}:", "Results".green().bold());
|
||||
println!(
|
||||
"\t{}: {}",
|
||||
"Part 1".green(),
|
||||
match one_p {
|
||||
true => {
|
||||
"PASSED".green().bold()
|
||||
}
|
||||
false => {
|
||||
"FAILED".red().bold()
|
||||
}
|
||||
}
|
||||
);
|
||||
println!("\t\tResult: {}", format!("{}", one_r).bold().blue());
|
||||
println!("\t\tExpected: {}", format!("{}", one_e).bold().blue());
|
||||
|
||||
println!(
|
||||
"\t{}: {}",
|
||||
"Part 2".green(),
|
||||
match two_p {
|
||||
true => {
|
||||
"PASSED".green().bold()
|
||||
}
|
||||
false => {
|
||||
"FAILED".red().bold()
|
||||
}
|
||||
}
|
||||
);
|
||||
println!("\t\tResult: {}", format!("{}", two_r).bold().blue());
|
||||
println!("\t\tExpected: {}", format!("{}", two_e).bold().blue());
|
||||
|
||||
!(!two_p || !one_p)
|
||||
}
|
||||
Part::One => {
|
||||
let (one_p, one_r, one_e) = match_and_test_day_one!();
|
||||
|
||||
println!("{}:", "Results".green().bold());
|
||||
println!(
|
||||
"\t{}: {}",
|
||||
"Part 1".green(),
|
||||
match one_p {
|
||||
true => {
|
||||
"PASSED".green().bold()
|
||||
}
|
||||
false => {
|
||||
"FAILED".red().bold()
|
||||
}
|
||||
}
|
||||
);
|
||||
println!("\t\tResult: {}", format!("{}", one_r).bold().blue());
|
||||
println!("\t\tExpected: {}", format!("{}", one_e).bold().blue());
|
||||
|
||||
!one_p
|
||||
}
|
||||
Part::Two => {
|
||||
let (two_p, two_r, two_e) = match_and_test_day_two!();
|
||||
|
||||
println!("{}:", "Results".green().bold());
|
||||
println!(
|
||||
"\t{}: {}",
|
||||
"Part 2".green(),
|
||||
match two_p {
|
||||
true => {
|
||||
"PASSED".green().bold()
|
||||
}
|
||||
false => {
|
||||
"FAILED".red().bold()
|
||||
}
|
||||
}
|
||||
);
|
||||
println!("\t\tResult: {}", format!("{}", two_r).bold().blue());
|
||||
println!("\t\tExpected: {}", format!("{}", two_e).bold().blue());
|
||||
|
||||
!two_p
|
||||
}
|
||||
}
|
||||
}
|
259
src/main.rs
Normal file
259
src/main.rs
Normal file
|
@ -0,0 +1,259 @@
|
|||
use aoc23::{run_day, set_verbosity, test_day, Part, Verbosity};
|
||||
use clap::{App, AppSettings, Arg, SubCommand};
|
||||
use colored::*;
|
||||
use reqwest::blocking::Client;
|
||||
use reqwest::cookie::Jar;
|
||||
use reqwest::header::USER_AGENT;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
// NOTE: Since this CLI was coded using clap in december of 2021, there seem to
|
||||
// have been huge breaking changes, requiring me to rewrite the CLI completely
|
||||
// to be able to update Clap. As I am on a limited time schedule RN, I will
|
||||
// probably do this later on.
|
||||
// 2023-11-29: still haven't done this, maybe I'll do is this year.
|
||||
// TODO: Rewrite CLI and update Clap
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("Advent Of Code 2023")
|
||||
.author("LeMoonStar <webmaster@unitcore.de>")
|
||||
.about("My Advent Of Code 2023 solutions.")
|
||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||
.arg(
|
||||
Arg::with_name("day")
|
||||
.help("The number of the day to execute")
|
||||
.required(true)
|
||||
.takes_value(true)
|
||||
.validator(|v| match v.parse::<u8>() {
|
||||
Ok(day) => {
|
||||
if 0 < day && day <= 25 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("The day must be between 1 and 25.".to_string())
|
||||
}
|
||||
}
|
||||
Err(_) => Err("The day must be a number between 1 and 25.".to_string()),
|
||||
}),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("part")
|
||||
.help("Specifies the part of the day to compute.")
|
||||
.long("part")
|
||||
.short("p")
|
||||
.default_value("b")
|
||||
.possible_values(&["1", "2", "b"])
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("verbose")
|
||||
.help("Print verbose information")
|
||||
.long("verbose")
|
||||
.short("v")
|
||||
.conflicts_with("development"))
|
||||
.arg(
|
||||
Arg::with_name("development")
|
||||
.help("Print development information")
|
||||
.long("dev")
|
||||
.short("d")
|
||||
.conflicts_with("verbose"))
|
||||
.subcommand(
|
||||
SubCommand::with_name("test").about("Test the day with the example input data."),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("auto")
|
||||
.about("Automatically download input from AoC using the provided session and run the solution.")
|
||||
.arg(Arg::with_name("session")
|
||||
.help("The AoC browser session string. If not provided, uses the AOC_SESSION environment variable.")
|
||||
.short("s")
|
||||
.long("session")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("no_cache")
|
||||
.help("Don't cache the input, and delete any current cache for this day.")
|
||||
.short("N")
|
||||
.long("no-cache")))
|
||||
.subcommand(
|
||||
SubCommand::with_name("run")
|
||||
.about("Use either a file or stdin as input and run the solution.")
|
||||
.arg(Arg::with_name("file")
|
||||
.help("Specify a file to be used as input, otherwise use stdin.")
|
||||
.short("f")
|
||||
.long("file")
|
||||
.takes_value(true)
|
||||
)
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
println!(
|
||||
"{}",
|
||||
"This binary was built in debug mode. To improve performance, please add --release to the build command."
|
||||
.red()
|
||||
.bold()
|
||||
);
|
||||
}
|
||||
|
||||
let day = matches
|
||||
.value_of("day")
|
||||
.unwrap()
|
||||
.parse::<u8>()
|
||||
.expect("Failed to parse day argument.");
|
||||
|
||||
let part: Part = match matches.value_of("part") {
|
||||
Some("1") => Part::One,
|
||||
Some("2") => Part::Two,
|
||||
Some("b") => Part::Both,
|
||||
_ => panic!("unexpected part argument."),
|
||||
};
|
||||
|
||||
if matches.args.contains_key("verbose") {
|
||||
#[cfg(not(debug_assertions))]
|
||||
println!("{}", "verbosity and development prints are only available in unoptimized builds (compiled without --release).".red().bold());
|
||||
set_verbosity(Verbosity::Verbose);
|
||||
}
|
||||
|
||||
if matches.args.contains_key("development") {
|
||||
#[cfg(not(debug_assertions))]
|
||||
println!("{}", "verbosity and development prints are only available in unoptimized builds (compiled without --release).".red().bold());
|
||||
set_verbosity(Verbosity::Development);
|
||||
}
|
||||
|
||||
match matches.subcommand() {
|
||||
("run", c_matches) => {
|
||||
let input = match c_matches {
|
||||
Some(c_matches) => {
|
||||
if let Some(f) = c_matches.value_of("file") {
|
||||
fs::read_to_string(Path::new(f)).expect("Error while reading input file")
|
||||
} else {
|
||||
get_stdin_day_input(day)
|
||||
}
|
||||
}
|
||||
None => get_stdin_day_input(day),
|
||||
};
|
||||
run_day(day, part, &input);
|
||||
}
|
||||
("auto", c_matches) => {
|
||||
let session: Option<String> = match c_matches {
|
||||
Some(c_matches) => match c_matches.value_of("session") {
|
||||
Some(v) => Some(v.to_owned()),
|
||||
None => env::var("AOC_SESSION").ok(),
|
||||
},
|
||||
None => env::var("AOC_SESSION").ok(),
|
||||
};
|
||||
let cache = if let Some(c_matches) = c_matches {
|
||||
!c_matches.args.contains_key("no_cache")
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
let input = get_auto_input(day, session.as_ref(), cache);
|
||||
run_day(day, part, &input);
|
||||
}
|
||||
("test", _) => {
|
||||
if !test_day(day, part) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
_ => panic!("Unexpected Subcommand."),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_stdin_day_input(day: u8) -> String {
|
||||
let mut input = String::new();
|
||||
let stdin = std::io::stdin();
|
||||
|
||||
println!(
|
||||
"Please paste your input for day {}, and then press {}",
|
||||
day,
|
||||
match cfg!(windows) {
|
||||
true => "CTRL-Z",
|
||||
_ => "CTRL-D",
|
||||
}
|
||||
);
|
||||
|
||||
loop {
|
||||
match stdin.read_line(&mut input) {
|
||||
Ok(l) => {
|
||||
if l == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(err) => panic!("Error encountered while trying to read stdin: {}", err),
|
||||
}
|
||||
}
|
||||
|
||||
input
|
||||
}
|
||||
|
||||
fn download_input(day: u8, session: &String) -> Result<String, reqwest::Error> {
|
||||
println!("Downloading input for day {}", day);
|
||||
|
||||
let cookie_jar = Jar::default();
|
||||
cookie_jar.add_cookie_str(
|
||||
format!("session={}; Domain=adventofcode.com", session).as_ref(),
|
||||
&"https://adventofcode.com/".parse::<reqwest::Url>().unwrap(),
|
||||
);
|
||||
let client = Client::builder()
|
||||
.https_only(true)
|
||||
.cookie_provider(Arc::new(cookie_jar))
|
||||
.build()?;
|
||||
|
||||
let response = client
|
||||
.get(format!("https://adventofcode.com/2023/day/{}/input", day))
|
||||
.header(
|
||||
USER_AGENT,
|
||||
"https://github.com/LeMoonStar/AoC23 aoc23@unitcore.de",
|
||||
)
|
||||
.send()?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
panic!("Server error or invalid session.");
|
||||
}
|
||||
|
||||
response.text()
|
||||
}
|
||||
|
||||
fn get_auto_input(day: u8, session: Option<&String>, cache: bool) -> String {
|
||||
let cache_str = &format!("./.aoc23_cache/input{:02}.txt", day);
|
||||
let cache_path: &Path = Path::new(cache_str);
|
||||
match cache {
|
||||
true => match fs::read_to_string(cache_path) {
|
||||
Ok(input) => input,
|
||||
Err(_) => {
|
||||
if let Some(session) = session {
|
||||
match download_input(day, session) {
|
||||
Ok(input) => {
|
||||
let _ = fs::create_dir(Path::new("./.aoc23_cache"));
|
||||
match fs::write(cache_path, &input) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
println!("Warning! couldn't save input cache!{:?}", err)
|
||||
}
|
||||
}
|
||||
input
|
||||
}
|
||||
Err(err) => {
|
||||
panic!("Error while downloading input: {:?}", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Neither a session argument nor the AOC_SESSION environment variable were provided, and there is no cache of the day's input.");
|
||||
}
|
||||
}
|
||||
},
|
||||
false => {
|
||||
let _ = fs::remove_file(cache_path);
|
||||
if let Some(session) = session {
|
||||
match download_input(day, session) {
|
||||
Ok(input) => input,
|
||||
Err(err) => {
|
||||
panic!("Error while downloading input: {:?}", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Neither a session argument nor the AOC_SESSION environment variable were provided, and there is no cache of the day's input.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue