mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-27 13:50:32 +01:00
Compare commits
16 Commits
dba146b299
...
2022/4-ran
| Author | SHA1 | Date | |
|---|---|---|---|
| f904d050cc | |||
| 6802a7bf33 | |||
| 9d23e80256 | |||
| e1b3b9d179 | |||
| 30d1a16075 | |||
| 256d351f8e | |||
| 48594a75e6 | |||
| 85a51b13c1 | |||
| 2ae2d6baa8 | |||
| 4a55e53182 | |||
| af0897300d | |||
| cabae7b1fd | |||
| 0635141ac6 | |||
| d9d5947c3b | |||
| cc8b4ce353 | |||
| 0b91da04b3 |
@@ -1,7 +1,7 @@
|
|||||||
on:
|
on:
|
||||||
- push
|
- push
|
||||||
|
|
||||||
name: Advent of Code 2021
|
name: Advent of Code 2022
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
continue-on-error: ${{ matrix.experimental }}
|
continue-on-error: ${{ matrix.experimental }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install toolchain
|
- name: Install toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
@@ -30,17 +30,23 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|
||||||
|
- name: Set up caching
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: >
|
||||||
|
2022 -> target
|
||||||
|
|
||||||
- name: Build binaries
|
- name: Build binaries
|
||||||
working-directory: 2021
|
working-directory: 2022
|
||||||
run: >
|
run: >
|
||||||
cargo build --all-targets
|
cargo build --all-targets
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: 2021
|
working-directory: 2022
|
||||||
run: >
|
run: >
|
||||||
cargo test
|
cargo test
|
||||||
|
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
working-directory: 2021
|
working-directory: 2022
|
||||||
run: >
|
run: >
|
||||||
cargo clippy -- --deny warnings
|
cargo clippy -- --deny warnings
|
||||||
@@ -4,4 +4,4 @@ version = "0.1.0"
|
|||||||
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "0.1"
|
regex = "1"
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ fn main() {
|
|||||||
let door_label = line.unwrap();
|
let door_label = line.unwrap();
|
||||||
let caps = room_pattern.captures(&door_label).unwrap();
|
let caps = room_pattern.captures(&door_label).unwrap();
|
||||||
|
|
||||||
let name = caps.at(1).unwrap();
|
let name = caps.get(1).unwrap().as_str();
|
||||||
let checksum = caps.at(4).unwrap();
|
let checksum = caps.get(4).unwrap().as_str();
|
||||||
if is_valid(name, checksum) {
|
if is_valid(name, checksum) {
|
||||||
let sector_id = caps.at(3).unwrap().parse().unwrap();
|
let sector_id = caps.get(3).unwrap().as_str().parse().unwrap();
|
||||||
cur_sum += sector_id;
|
cur_sum += sector_id;
|
||||||
|
|
||||||
let decoded: String = name.chars()
|
let decoded: String = name.chars()
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "^0.1"
|
regex = "1"
|
||||||
lazy_static = "^0.2"
|
lazy_static = "1"
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ version = "0.1.0"
|
|||||||
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
authors = ["Bert Peters <bert.ljpeters@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex="^0.1"
|
regex="1"
|
||||||
|
|||||||
@@ -20,3 +20,15 @@ OPTIONS:
|
|||||||
-i, --input <INPUT> Read input from the given file instead of stdin
|
-i, --input <INPUT> Read input from the given file instead of stdin
|
||||||
-t, --time Print time taken
|
-t, --time Print time taken
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## That goal was achieved
|
||||||
|
|
||||||
|
Runtime benchmarked with [Criterion], reading input directly from memory to avoid disk IO
|
||||||
|
inconsistencies.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
[Criterion]: https://github.com/bheisler/criterion.rs
|
||||||
|
|||||||
97
2021/create_timing_plots.py
Executable file
97
2021/create_timing_plots.py
Executable file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
def read_timings() -> Dict[int, Dict]:
|
||||||
|
timings = {}
|
||||||
|
|
||||||
|
for day in Path('target/criterion/part1').iterdir():
|
||||||
|
with open(day / 'new' / 'estimates.json', mode='rb') as f:
|
||||||
|
timings[int(day.parts[-1])] = {
|
||||||
|
1: json.load(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
for day in Path('target/criterion/part2').iterdir():
|
||||||
|
with open(day / 'new' / 'estimates.json', mode='rb') as f:
|
||||||
|
timings[int(day.parts[-1])][2] = json.load(f)
|
||||||
|
|
||||||
|
return timings
|
||||||
|
|
||||||
|
|
||||||
|
def plot_cumulative_time(timings: Dict[int, Dict]):
|
||||||
|
plt.clf()
|
||||||
|
|
||||||
|
times = [0]
|
||||||
|
|
||||||
|
for day in range(min(timings.keys()), max(timings.keys()) + 1):
|
||||||
|
times.append(timings[day][1]['mean']['point_estimate'])
|
||||||
|
if day < 25:
|
||||||
|
times.append(timings[day][2]['mean']['point_estimate'])
|
||||||
|
else:
|
||||||
|
times.append(0)
|
||||||
|
|
||||||
|
cumulative = np.cumsum(times)
|
||||||
|
# Convert from nanoseconds to seconds
|
||||||
|
cumulative /= 1e9
|
||||||
|
|
||||||
|
x = np.arange(0.0, 25.5, 0.5)
|
||||||
|
|
||||||
|
plt.plot(x, cumulative, label="Cumulative time", drawstyle='steps-post')
|
||||||
|
plt.plot([0, 25], [0, 0.5], label="Target time")
|
||||||
|
plt.ylabel('Cumulative time (s)')
|
||||||
|
plt.xlabel('Days completed')
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
plt.xlim(0, 25)
|
||||||
|
plt.ylim(0, 0.5)
|
||||||
|
|
||||||
|
plt.savefig('cumulative-time.svg')
|
||||||
|
|
||||||
|
|
||||||
|
def plot_individual_times(timings: Dict[int, Dict]):
|
||||||
|
plt.clf()
|
||||||
|
|
||||||
|
def plot(parts, **kwargs):
|
||||||
|
x = np.arange(1, len(parts) + 1)
|
||||||
|
|
||||||
|
values = np.array(list(part['mean']['point_estimate'] for part in parts))
|
||||||
|
upper = np.array(list(part['mean']['confidence_interval']['upper_bound'] for part in parts))
|
||||||
|
lower = np.array(list(part['mean']['confidence_interval']['lower_bound'] for part in parts))
|
||||||
|
|
||||||
|
# Convert from ns to s
|
||||||
|
yerr = np.array([upper - values, lower - values]) / 1e9
|
||||||
|
values = values / 1e9
|
||||||
|
|
||||||
|
plt.bar(x, values, yerr=yerr, align='edge', log=True, **kwargs)
|
||||||
|
pass
|
||||||
|
|
||||||
|
plot(list(timings[day][1] for day in range(1, 26)), label="Part 1", width=-0.4)
|
||||||
|
plot(list(timings[day][2] for day in range(1, 25)), label="Part 2", width=0.4)
|
||||||
|
|
||||||
|
plt.ylabel('Runtime (s)')
|
||||||
|
plt.xlabel('Day')
|
||||||
|
|
||||||
|
plt.xlim(0, 26)
|
||||||
|
plt.xticks(np.arange(1, 26))
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
plt.savefig('individual-time.svg')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
timings = read_timings()
|
||||||
|
plot_cumulative_time(timings)
|
||||||
|
plot_individual_times(timings)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
1
2021/cumulative-time.svg
Normal file
1
2021/cumulative-time.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 16 KiB |
1
2021/individual-time.svg
Normal file
1
2021/individual-time.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 32 KiB |
@@ -48,7 +48,7 @@ fn parse_fold(input: &[u8]) -> IResult<&[u8], Fold> {
|
|||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_fold(dots: &mut Vec<Coords>, fold: Fold) {
|
fn apply_fold(dots: &mut [Coords], fold: Fold) {
|
||||||
match fold {
|
match fold {
|
||||||
Fold::X(coord) => dots.iter_mut().for_each(|(x, _)| {
|
Fold::X(coord) => dots.iter_mut().for_each(|(x, _)| {
|
||||||
if *x >= coord {
|
if *x >= coord {
|
||||||
|
|||||||
27
2022/Cargo.toml
Normal file
27
2022/Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "aoc_2022"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.66"
|
||||||
|
clap = { version = "4.0.19", features = ["derive"] }
|
||||||
|
itertools = "0.10.5"
|
||||||
|
nom = "7.1.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = "0.4.0"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
# Keep debug information in release for better flamegraphs
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
# And same for benchmarking
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "days"
|
||||||
|
harness = false
|
||||||
20
2022/README.md
Normal file
20
2022/README.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Advent of Code 2022
|
||||||
|
|
||||||
|
Another year and another Advent of Code in Rust. Because last year went so well, this time we'll be
|
||||||
|
aiming for a total time of under 250ms.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ target/release/aoc_2022 --help
|
||||||
|
Advent of Code 2022 runner
|
||||||
|
|
||||||
|
Usage: aoc_2022 [OPTIONS] <DAY>
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
<DAY> Which day to run
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-t, --time Print time taken
|
||||||
|
-2, --part2 Run part 2 instead of part 1
|
||||||
|
-i, --input <INPUT> Read input from the given file instead of stdin
|
||||||
|
-h, --help Print help information
|
||||||
|
```
|
||||||
46
2022/benches/days.rs
Normal file
46
2022/benches/days.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use aoc_2022::get_implementation;
|
||||||
|
use criterion::criterion_group;
|
||||||
|
use criterion::criterion_main;
|
||||||
|
use criterion::BenchmarkId;
|
||||||
|
use criterion::Criterion;
|
||||||
|
|
||||||
|
/// Number of days we have an implementation to benchmark
|
||||||
|
const DAYS_IMPLEMENTED: u8 = 4;
|
||||||
|
|
||||||
|
fn read_input(day: u8) -> Vec<u8> {
|
||||||
|
let input_path = format!("inputs/{:02}.txt", day);
|
||||||
|
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
File::open(input_path)
|
||||||
|
.expect("Failed to open input file")
|
||||||
|
.read_to_end(&mut buffer)
|
||||||
|
.expect("Failed to read input file");
|
||||||
|
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn benchmark_days(c: &mut Criterion) {
|
||||||
|
for day in 1..=DAYS_IMPLEMENTED {
|
||||||
|
let input = read_input(day);
|
||||||
|
|
||||||
|
let part1 = get_implementation(day, false).unwrap();
|
||||||
|
|
||||||
|
c.bench_with_input(BenchmarkId::new("part1", day), &input, |b, i| {
|
||||||
|
b.iter(|| part1(i));
|
||||||
|
});
|
||||||
|
|
||||||
|
if day < 25 {
|
||||||
|
let part2 = get_implementation(day, true).unwrap();
|
||||||
|
|
||||||
|
c.bench_with_input(BenchmarkId::new("part2", day), &input, |b, i| {
|
||||||
|
b.iter(|| part2(i));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, benchmark_days);
|
||||||
|
criterion_main!(benches);
|
||||||
0
2022/inputs/.gitkeep
Normal file
0
2022/inputs/.gitkeep
Normal file
2259
2022/inputs/01.txt
Normal file
2259
2022/inputs/01.txt
Normal file
File diff suppressed because it is too large
Load Diff
2500
2022/inputs/02.txt
Normal file
2500
2022/inputs/02.txt
Normal file
File diff suppressed because it is too large
Load Diff
300
2022/inputs/03.txt
Normal file
300
2022/inputs/03.txt
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
NJvhJcQWTJWTNTFFMTqqGqfTmB
|
||||||
|
VwVzPldRZVLVRmfsvfjvqfmm
|
||||||
|
ZDPDHZHVcvDhbvnv
|
||||||
|
FHHwHBzzVCWWmmCzCPrVmgBwbLTtRFFbbbttRGRLjTcLpbbT
|
||||||
|
vhZZvdsNSdSMdNvjncppCLcLnGnj
|
||||||
|
CDZZsNZMZqdNSdlNZCqrzPHDzgrgzwVVWwmwwm
|
||||||
|
ndlndntsFJntFvccLjjLrjBShcBBfc
|
||||||
|
GpCGHzVwmmzqQWSSSfWHBhQL
|
||||||
|
mpCMGGCZVzVwGGVwmJsZnFtZnTSTJtdsvl
|
||||||
|
nCnPDGmDNmVCsVQDmGSWqvzchWSjjcWGqS
|
||||||
|
gTnBRLpfTRnrTdZgdLfRdrThvqcvWWhFFWvcFSSgjqqzjv
|
||||||
|
pfZfTMwrbLTTfsbmQtlVtHHnbs
|
||||||
|
wNdSdsbTvTZMTvTv
|
||||||
|
rrdRWdWQhFVdHWBGWQmmmnnMvCfmnhvmCmtZ
|
||||||
|
rJrVDRWpGddpbSlNSlspPP
|
||||||
|
chTNrthMMwWMTjfsmRzZszJpwm
|
||||||
|
BLnFFCngbcBnbbldDlpRjGpmsCzGsGsRGmmG
|
||||||
|
dqvnvlgbqtcPPMhH
|
||||||
|
QcLNqZbCzJDQBJJRpwzRpdnRldgnpf
|
||||||
|
GmmmvVGsHrWffrlwdCWd
|
||||||
|
CMsFVVFjCmFStGQbbLZNBbJBcTjc
|
||||||
|
LQVggbQvcLbQLHgvVLhWGGsChssrMWfzGccc
|
||||||
|
qDnRTTRqJttPfWMChJhGslWlzh
|
||||||
|
qRTRwPBTBtRZdnjnqqqnQVbjbNLFbbfLgVmgHLQm
|
||||||
|
cZbzwCwZPlJcMLrNSNfHWNBBNZ
|
||||||
|
vsQsDCqtsDhmtjVrBNWNjBHrhr
|
||||||
|
TtDTGnvTlgbbRCGg
|
||||||
|
BgBlplHlsgNNsJlVpBtPwJhMPRRQSSttRtSP
|
||||||
|
bvhTnmdFTzddStwStQRddt
|
||||||
|
ZnZDLvnvqZzbbhFzzmTbnFsVjVlNgsCCNVsVLpNWVgsB
|
||||||
|
TdptqrrcVGhhzFtw
|
||||||
|
DRnSfwJlDmmDDVGv
|
||||||
|
RCSQNSCQZndwbcMqQrBB
|
||||||
|
wvRlrlwVwwqzgbZRdCJBWfmdzCWfBdhf
|
||||||
|
cFcsQpNtLLsGTtNGpMdPmDdPBmmBvJPWvDtC
|
||||||
|
TpjssTFFvLLLcFFQpwbwwHngjHRrZRqZVH
|
||||||
|
mqqddrPPcPmqPDlrQnjTrbvMvbHzzsjjpTvz
|
||||||
|
gtBWgGgVhLGWHzMDztzstDHj
|
||||||
|
hfWRhBBNBGgLNQDPwdNPcPdw
|
||||||
|
LhQzdhhbTzpMhddhhhTzhnZcBFllHZFtrrHZHMHFjlHr
|
||||||
|
mwwssqDvjptrvplr
|
||||||
|
NCSgVDPDwmDgVJVpLfTznQJdhfLhnhQQ
|
||||||
|
GzjzDhjhhZzcrRgQCBjBPBBjQCgT
|
||||||
|
vHHHmntsbSgLwbsSmNHbwNbvpqPCBVppCpFTpTPTBtqWBCqV
|
||||||
|
NJbwNSwdndvmvwhGhgzcfMcDJfgJ
|
||||||
|
GncgDvvcMGnttjDvrgRRFSZZLZFWdJFJwGQwZBWZ
|
||||||
|
bPqpChPfsshfZZBdZdLTFZ
|
||||||
|
lNqqsClmbsNlPbHqPsmblmsrHdvdMngcVrjggvrvggRDcn
|
||||||
|
bDvtgVVVpMQvjQWmQL
|
||||||
|
rwTflmlfZJBBdQWQWjQqdM
|
||||||
|
HsJJmZZwscHrwTrcRbzpcbPgtCSbgz
|
||||||
|
CsCsRvshMjpbqCqf
|
||||||
|
ncblgDBgtDmmmTlBgwlgbHHqMFHLqPDMHPHHpqWfFM
|
||||||
|
TcBctSmTZTtSTzsZvsvJZRsGVb
|
||||||
|
znznvngttwltzlLwhtThHbqHPvNbNHSSHmmNWHjP
|
||||||
|
FBcLrRMFQpPqpPSpqHHW
|
||||||
|
fRQMJZJfrcMcMVrQJJftnwCzVCltgTnstTVnVL
|
||||||
|
MfLlRfCMrLzRlQgwNqQFcsGd
|
||||||
|
jtTjjBTvbdqcGjqFcj
|
||||||
|
vvShDSBDppzhCmzq
|
||||||
|
plWMptTvfrnncvcRfwqzqLGhzhzThNzNNJqD
|
||||||
|
jSdSHFPQQbdPCQCssjSbBmhJGNZZNGNqqJNBlJqqLh
|
||||||
|
VCCCVCQgjdddjCgljCjbbwgRRttgrpftfWrgvpwpnf
|
||||||
|
MWlbBcPjjvvjPWWMPqgRQZfJZDGGbRZJffQQwh
|
||||||
|
HrHrnncHpzrJQJfVDQVR
|
||||||
|
zzsSTtSTLzsspSdtTmHHmpmtFgqcgPlgFqWBqqqBMdWWvFlg
|
||||||
|
nSqBbJbqlnBBClVZcMgZVgcP
|
||||||
|
FQwrwHrRwWWFBRPNgNgcCGZZZC
|
||||||
|
rWFWFTwpwwWzHrnDbfJDLDbBBbbz
|
||||||
|
BMmNtLMMtFCNFNMvvLmcndpgcdgppPrgrGPPrgJD
|
||||||
|
WVWWhbTtVnGpjrrPhr
|
||||||
|
HWssSTHWfRHRsQQFLvfvFFCLCNMNlt
|
||||||
|
sTmDsQffVrrLCjTFltTFWL
|
||||||
|
BnwwQBJbJndMMRzMwCLlWlLWWCWLLtRlWF
|
||||||
|
cqqBMcMqwnznMGzcvDmQhrvssHmPDVssrP
|
||||||
|
pQGQGJDDrDVJbbfVzvvgPcCZwhZhncscZWWc
|
||||||
|
SqMMlBBljMmRlchhPTqThCZnPs
|
||||||
|
FMjMBmjRNFHQJJpHVhVDhG
|
||||||
|
tHNNdBdNtBBBMgsMpsZm
|
||||||
|
wVPzVvbwqzhrVqvjqzzsZpDsZDsZmsCPCgZgCM
|
||||||
|
bVbvLThvvbrWqHmmnJLdHdJQLn
|
||||||
|
PzTspPZpdLLDZTplPLpPDpvbfhnqNvqzfvNMzQQfNwnQ
|
||||||
|
GWRHmjmFWMMSnhbhHw
|
||||||
|
JWWcmtBrBtWBFWGJpsgTgldhLVLpJl
|
||||||
|
DwLMDzLMhvMcwvgdVqWWlCVgvlqF
|
||||||
|
TTSBBRpbStHZVgjWFldjRVlV
|
||||||
|
SnbTBdJBmnpQzMPDMcMznr
|
||||||
|
nNlMNBPPNtJQnbZhZsgSbh
|
||||||
|
czzCjcwTdvSbgQNcgNQq
|
||||||
|
VTdNdGDTzDTdlFFPtBrtLtDr
|
||||||
|
FMbbfMlzvFsmgVZmmg
|
||||||
|
SrNTHGmdSQDqLhtQhhgggs
|
||||||
|
dRDTSDPPcHRdHGDHlwJBbmwljmMcfjbW
|
||||||
|
sQgWLtqLtWhdqlpNZRpG
|
||||||
|
blTHTjlvTCJnJvRZdGGhHHGZhFGV
|
||||||
|
CCDlJclnCmbrmBMgcwcLWtcBsB
|
||||||
|
vqPWWvqwwCFvFZfZPRFRrcGQrQwsDrNcrwnbDNcQ
|
||||||
|
LVgJLSBBVtzTLzBMmTMJmLnnDNQcrsGbsQbNbrbDjs
|
||||||
|
zggVSmmhVdfqFhvHWG
|
||||||
|
WwdndGGmmmLwwwmRwWSncLRnZqZqhqZthBtqtBqZBgtdtvMH
|
||||||
|
FfHHzlQQDsFzzrNsVTfttZvTvttTqqtbqb
|
||||||
|
lQjFDNQFPjCsVCCDjGCwwSGGnccwcHppGp
|
||||||
|
mrjggcFsFMjdjZRpSZpn
|
||||||
|
NCqfLCFNbQPzPPlPzNfSRTRZdSdWWwndpqRSSd
|
||||||
|
vDvzzbPQFNCFtllLLNMBhMcDHGBGMggMmcBc
|
||||||
|
jhjlBvvnjbtDNPjtSjBDBbDNgHggrQrhghRQrqRrZcRwwqVg
|
||||||
|
pLdTMsWdLLmpMdqZZdPdVqZgHPwH
|
||||||
|
WLTCGmMLfPSlbGjlnnJD
|
||||||
|
gtbwhgHbHgqqbgQthgQLtZZCRjMcjjnRnrRNJmMRJrNhRc
|
||||||
|
bGWVTTvDvfpVFFBpvvVTdRDMJcrccCrJnMRnNnNCcc
|
||||||
|
FVWTBsdvdTzTBFWssVQtLgSQtHqqPzPbqHbw
|
||||||
|
dlzrPTSSjSrllzWhsvVmVtTRTWtf
|
||||||
|
bJMpLGcqGhNbJQttVQmmvRWWsp
|
||||||
|
qLbMwqqbGHFGzrlZrjhPHCrj
|
||||||
|
rNrrffVlqqrfLlPpltcBBTTGRzzZRPRsBTcJ
|
||||||
|
msbsmWSsMmQwjdMbWMhMhQmcRZRzGjTBGTBcBJBjCHJGcC
|
||||||
|
FwWbvdhbmrsFrfrgsN
|
||||||
|
rHjrQHdhdQrvSddcHWLssBSVVpBSWWWWWf
|
||||||
|
JNfTGtqDwVWBMBMpwM
|
||||||
|
qlltZgfJFvcRgcRjvc
|
||||||
|
CqfcwfDqwwmRnnqmRdNRBTRTRrdGdNpTvF
|
||||||
|
WVbzsZszBbrsvpdMpdQM
|
||||||
|
tJhbVZHWLLHDgnSwnSSgHB
|
||||||
|
TZCqqlTsqpZVVsZQJSBSLpLmppnJzmFz
|
||||||
|
brSgNtGjjRjRRjDddDtrRJcJJbJmmwcmBmnPcJFwFB
|
||||||
|
jgdRtMjNNjfqlMvShvSZSZ
|
||||||
|
dJTdqCwMNCgqTQllGBdlGBmmmZ
|
||||||
|
fcVfVcnbVfrwDLWVfncZBQPlBHRGljLZQjHGQl
|
||||||
|
brwnnfSFDvfzCTqFzgMJTh
|
||||||
|
njnsPBjjsrrnGLnbTTjGvcldQPCMllNzMvRQPCdd
|
||||||
|
ggZgfZtmZVpqZqZWDgFmgqfCcQRcRcWhQcccQddMcvRQdQ
|
||||||
|
tfqgggVgHpDwDtfwbGLJRjbLjsrLTj
|
||||||
|
JmrfrmTlDWTfgQCdHCdpqBvQdD
|
||||||
|
jsZtVzNsSNVQQHnBlVQR
|
||||||
|
PljljFjPljSsLPtFLTTgTcFrrfMJmrrmrr
|
||||||
|
hmGcmmndhmGnfmtGnDzFLwrFJQsQFzNFrNJG
|
||||||
|
ZSqPlSWcWlbgqWVTVWRVZPrjQqjzjFNJzLsNJsLJNqNL
|
||||||
|
RHcWTZbSMMMPgZcWgSWPPbVMDnBffmtdpDBddfnnvmCdfC
|
||||||
|
vSJvsbFfJfvqCsTHJswssJnLTZjjhzrrzLrzLMrzhdjM
|
||||||
|
pBNQDPcpmWDcBNgMMnZPVjdddnndhH
|
||||||
|
QWlDgmpmgDBlGRgDDgffSqwSwGCwHfvqwSFJ
|
||||||
|
jvlgvMJclPdGdtdcjMVmMHbFHFVHWHbZHZ
|
||||||
|
CwhLzLhzQpnqfpfqDVHCHbsbDFZDmHmj
|
||||||
|
LnBzfQjSzQrPvJvdSSrr
|
||||||
|
wpcvcsqclDCnVCVvWfnZ
|
||||||
|
BLRMRtbnbbBLNCjNCjVVZhbC
|
||||||
|
rFgMPSRnrRpmqpJwqFDs
|
||||||
|
LZQNQbMrZppLNLQplvlGLNvVmmmfjbwVCfjbwJwCmBCwfj
|
||||||
|
ShTPRFtTHZPCsnwswsFwCF
|
||||||
|
WtHRPdThSqZTRtDqtdRWTdpGDLLzrNczvzMGLlQLGDDM
|
||||||
|
hdcffBvldjhCMljqPwWwWNwWdwqHZr
|
||||||
|
LtQmbQRVsZQZMZPQSN
|
||||||
|
tmMRsJMpDhjJzJhv
|
||||||
|
wNQCMFCDQDBmrHmmRWrrHN
|
||||||
|
SShLnfqpcqpSZSfrzJvRVrvfrrJH
|
||||||
|
cRpqdGclpScltTQQtsFQMQsTCT
|
||||||
|
NCjggZmgfBgnBmgWbcwcTFctcWWfvb
|
||||||
|
HsDGthRGrtppSQpbFFJTVcJdFbTRvd
|
||||||
|
rPDGhDDrSzZLtzBLZMCB
|
||||||
|
RsBBMBsCBlFFCgRsBJzlMjMPNSdPhSrSrzLbmSDrDNmDSd
|
||||||
|
pZHZZJpGHHHpTTHvTncZqVLdqLbhLrDLdhrSLLbLDDdD
|
||||||
|
tGtwnJccvCtCffMBgt
|
||||||
|
wbddvVjfwPhbjjbDbbvbjvTNCNmfHZfpCZRJNzCmJmnJNC
|
||||||
|
BslcLtclZWsZJWNrRRNRpRmR
|
||||||
|
BSLBlScGtFMcssMBBFGLlQZTDZQjPddVwwbTdvvdhTZb
|
||||||
|
NSZHzmLZBnzHmLLzLSntDttDDtddhDtttDWW
|
||||||
|
QgfjsrrvNNJwtMddcvcvtq
|
||||||
|
jrfgfQpQrTTVLSNBClFV
|
||||||
|
GQWcWWPPQRcrJQNDdRcDmmLCFSnqNSmqhCNvFnql
|
||||||
|
zHfwjzpMjwZmCLqvvnlljC
|
||||||
|
ZgtVZBtHHZtgQGgPrbPRJdPv
|
||||||
|
TWdWpJTJTdgLWfWLlLFLrfrgBGsNqhGslBGHqSNqqBNshnws
|
||||||
|
ZpQmjzbZZCjZCCCPZtttRCCwsBnHNssBHbShsshHqsGBqN
|
||||||
|
RDRRPpPCzmZCtRpVVJFrfTfWFLLJggJrDv
|
||||||
|
pDDFlglsvFMgntlTMMqNffmTdfddRM
|
||||||
|
jhGJLVCHQpHGQCCzLjWdTTdZZdNdcRWNccWfNN
|
||||||
|
jQjSGjrjCQLhzVSLSCSHGDpngbrnDFtFBwBglBnBvg
|
||||||
|
wsLzstsgszcpcGLHGpcgcghlDBvQvjQvbFbQCbJBtCCJJv
|
||||||
|
mnSqRSSqSRThWRnmWWRSJDFTFCFCblbBCFQFCjFj
|
||||||
|
rZRRWqSSdZZfMVnZLspPsMgHpzMhHGPg
|
||||||
|
mwHrCLSWWwrsHCHDDsVrsmhfFZFnSSBlFlgZbbgBglbggj
|
||||||
|
GJdpcRtGJvNRdcPtdpJJdbQZfjfQBlnQBjnBtbfFnB
|
||||||
|
qcPpqqzFzJqvPVCCmWrVwhrWrz
|
||||||
|
jjMbvbhDvnRjNRGMmjbMZftSSwwwthJSffStctcwqd
|
||||||
|
lTQrVlpCVvCcfdcSJqLVcw
|
||||||
|
srHFWCHrFlrHlrsBsprljjRmDZZnmbDngNBgbNZv
|
||||||
|
MgTlQJlTQJZWpgLrRssrVqqqpRts
|
||||||
|
bBNbbzSSjMBPjzhMjsPtRVVRVPRqLttGGs
|
||||||
|
SjHBbfjNCDfjZgTlZdMJnDJW
|
||||||
|
lpThgTwtplhghgwhThqnnrdZctSZSjSZcRSRfbdrrc
|
||||||
|
RBVBGvmBmfdrcvrbbr
|
||||||
|
PmVGNGmmGRLLQwwLqTnglQ
|
||||||
|
nHwnBwBTnFHQwRsMhwghmzcm
|
||||||
|
GtprdCpdtqWdbqbrfdnPPszsWmRzRnShPszS
|
||||||
|
dGptbCfCrlnVDBJNLDLLVDLQ
|
||||||
|
CZtCjhTndCzqbCNq
|
||||||
|
dwpGvpsmwGslDszrNNrzqDMzWMgJ
|
||||||
|
vmcGccvpBVPTVTjTdTTTdZ
|
||||||
|
jWZhvZLjZfCZDwrDrSSzJGhVdJccscGsgV
|
||||||
|
blMBlRqqqgSJLBLcsJ
|
||||||
|
blmHLmFMMMnRqLmMMFqHmfPDfjQDnCDDQrZvfCjvDr
|
||||||
|
rnvnHrDLFZmMFLvrHQBMGQggBztzglplRl
|
||||||
|
sbWWhdNzsshsfhcsjJJPPbWdtQGVGllRTRjRRgBgQlpRlppB
|
||||||
|
PPCCwNWhPhNfWCzbqmFnDFFnCDLSrvZS
|
||||||
|
GChNjwWlWJWTJZBggvdgnQgdhdnd
|
||||||
|
HPsHfHHrpHDpFFrcSfsfpCMmQdntLBMgtmtBgDdLLC
|
||||||
|
SqpPscpPzpSWzjlCjjCGjl
|
||||||
|
nvgLvcLgvgvngbLprpJNTDCCRNVJrNPlDDTV
|
||||||
|
WZsMtsffGQtMzWFqFmWmWsVNJNlDwwCDVRTwJlCCDVLz
|
||||||
|
BQfGZGmmsMWFstWFmfMsfBccdncbpbSbvbbvHnLbpc
|
||||||
|
tsmDsvswNZmcZTccfh
|
||||||
|
zCTpGCbWBRWFWHGRFZJbMbJfnrhnhfMnnZ
|
||||||
|
TzFGFBRLdpHHNNQddDQDvwQN
|
||||||
|
fhBBpJgdHddjZQfmVmNzNNLmFN
|
||||||
|
qvMRrvlbwqlbTTMBMvLssFNmVzzwFDmLLzVD
|
||||||
|
TRSRWqRRMcBHhGHcdGgPGp
|
||||||
|
lSjHmtmnpHStblnpSlHSrtmMzLWzqzqCZDDTzTTWqMFqCqVV
|
||||||
|
sLRLLfPPRQfCTqqVVqFT
|
||||||
|
dNJgRPNQNsJJhBRvdJvQvNNsjSrrSmrcctpbpHtBrBjLjmSH
|
||||||
|
nwFwpppjfwSlpLTsqsTgNshhjM
|
||||||
|
ccBRGvtsmgGNPqNNGP
|
||||||
|
BCcJHvssdcWBCVmVHSSrZrwVzblpwbzZnf
|
||||||
|
rcfQRrBPPczjcRBctZDNlnVNHbgZGjVDjN
|
||||||
|
TvMsFJGSFMhJnNZlwVVnDNTZ
|
||||||
|
qhSqqmqLCLhFdJLqSvLhmQRQRWcRPczPtzrCrWGRBp
|
||||||
|
JVhdPhsFPFqLDBHVdHLPvhHDCMwcgJJwbwRgnnCMbwGwcmGC
|
||||||
|
fzjzpTZTQQQLwCbgGgbMmQcR
|
||||||
|
jzNpTzfSZtfNSWZlVVtdFFFDHHqLHVqv
|
||||||
|
TwSNnSnSGVTpNppGlPTlTcVqQrRhVBqdqBRqZqQZqQ
|
||||||
|
DcDCMfDbCMHJdrRBqbdjRBRZ
|
||||||
|
gvftMCJHcHfCDmDLgfMmMmmWlwWnWsTTwlGTlWTwppNlGL
|
||||||
|
pbGMbllDQPhhWWQDpPgVGlMCvRRrQLcCCcfBBQzLBcvQBv
|
||||||
|
wqnJjSmjrstdqwwFBLcRsBRRszzLFC
|
||||||
|
qwdddTJTdHtjndqJqHZHmwVWGpDbGTlbWWpWWrPGhhhM
|
||||||
|
WGllqLjjLCpSffmBmvfpHs
|
||||||
|
dnrQwZzRTdZwnCThdzzFTVmcBHBJBmsHfBPHcfvcSVHs
|
||||||
|
QgQrzCdrTRCZzrZLbjGLqNMWGgNNLt
|
||||||
|
sgPnhPPTTPTTwlJfwNHlqcfs
|
||||||
|
LMCpFbLLbRpMGbMcCFLVlNlNqrHqVfbHHwNDwr
|
||||||
|
GjBcCCtWMtMRZTSvgWQTngvg
|
||||||
|
BCMtJJMpRDlMMvBJBBnfjtcjPhPmZgnhgdcf
|
||||||
|
NrsrsqFNvrVLVGVrsHsqFgfmcPGdcmhfjdPgfjcnZd
|
||||||
|
zFTzsNqHqFssLVLQqNTFbsBDwCCwvWlDwRMRCTRBDMDS
|
||||||
|
zQtLgvggSRtgvVRtLvvnzdnjnGwGdmmrlpnlGz
|
||||||
|
JssBFpqsDqPNnlWWjrrjqrnj
|
||||||
|
DHDFBNDfPbJBsFHNMPvpvStQvMRVTtgVTVtv
|
||||||
|
FvzttFvBTJJzLbvwhCnnVnWwjCnBNC
|
||||||
|
mQdZgZPDPdPPSsMSQPdZgCwVGmnwnWpGnGhqNWjWCG
|
||||||
|
ggdDgfQSdcjtFHjlLJfF
|
||||||
|
ghcgScNNSsCvGSzmpVFlZbrzcFcV
|
||||||
|
MWWRLRqqqdQwTtLjjmqMlFpFlzVnbFVDwplFzlDr
|
||||||
|
LHMHqdHWjdQMdMtLHHLtWjJRsGCGSNghmSvPBJBNhsGfvfGP
|
||||||
|
CbVqqqDbcbMHnnDqcCbrRFCfBvvwGjzrBwQGzrwwBjGwBQ
|
||||||
|
sTPmpNWdWPTJssSSLPfNljjBvflGtjwwBzMG
|
||||||
|
mmWgmgSZLTLMZWpnhqZbhFFCnhqnnn
|
||||||
|
QQmjmZqnmQrfTZlbbcVbBcfbHfzf
|
||||||
|
vpdSNShNppFdSRtdGBqvJBDlDzqbPPHVBH
|
||||||
|
tRNSNRFhNpSRhFRMFtGhRGswLZZsZqWnmrmZwqwsTZmmmQ
|
||||||
|
gGWCllFCGWtGGWdlGlWNZdwpnnSbwpMvpphZpndn
|
||||||
|
RsshDDLcQVMSJQwJwnvw
|
||||||
|
HVPzrPcDNhPFGhPC
|
||||||
|
jtHQGHjGGtdTLjnqTQlmvRPRPBBwRBnFPPWP
|
||||||
|
hZbzNzVrczZzcbNssVspZZVvBwbmPmJPWmvbBRvPlmvRJF
|
||||||
|
fzNVDsZMhzpVhpVhlZcMNfcDDdQTLTjGDTCqGCjtSQHdHL
|
||||||
|
GrbFggGrTrzSrgfwJjdTmwmNJZJd
|
||||||
|
VMPQplPDptchwdsjmlml
|
||||||
|
MqMWtBDPPWDWHQtvqQtWPjbzCGLgSBgGbzgrzFgnnz
|
||||||
|
fcJccCcwcDfcpbRnCfWJnQJqtqtqPQdsGdgPsgTQqg
|
||||||
|
LSjVMhzSFFrljdNbltNGtgdqQq
|
||||||
|
MMhSHFFMLzBWDcHHcfcHwb
|
||||||
|
rwmWtJWMwSNRJMtwNmMrrSsmtTjjlgqnTqZZZPlHnTngTTgn
|
||||||
|
BGqGqqFBFggjjdGHlj
|
||||||
|
QDhhLbDQCDFMNcmhRhqJNW
|
||||||
|
BnRnRvMnLGLSCHvvSnlRfWbbTNQJsJsbNbJTBfQT
|
||||||
|
tzMmmMwjhcpFjDmMcptrcjzFQggfQPTsWsfgNbbgfhJbPhQT
|
||||||
|
FdzcrtDwDMtcwtFGRZdRLvdnHRSZZv
|
||||||
|
HVpsSpvjpNjsBmbGFBnMNnDM
|
||||||
|
WRRWhZtfrVtLJrBZMnDmDbnZBTGF
|
||||||
|
thhPLzWzhzwPtLRLWrQlpPvvClcVcCppSvpl
|
||||||
|
lZPbhnZLRPnnPZZPdlGMBWcBMgMQHBBcvvvzBL
|
||||||
|
jpFjmwwwCDDbsjvjjgcvQgcNBQ
|
||||||
|
rbFmppbwhqhGRGZr
|
||||||
|
ggrLwFgWCBwbMWBbFwLMgNBZdmZHclJPllnJlNRPmSNZRR
|
||||||
|
ppszzDfhDfhsqpnvDVTfGpSPlPmclHcdRcZmmmdPPGSP
|
||||||
|
pvtDDVDVpqDfzDfngBLCwQrgCtCwFwrg
|
||||||
|
pbGjFFGGDjpbsGsmNhNFNRBBBtRhhhHv
|
||||||
|
JnczJVCvwWJvhPgghgNtNtNJ
|
||||||
|
nwVSSzdzzqSpvQSZQG
|
||||||
|
mssLLttQrsMrMzLCRmMmrrSQpvWpDNlBTBDlvNTccDQl
|
||||||
|
HdHJwJqVPwHnqJwbjJbGjnSgSTWPpNgWWpgBBgcvDWWN
|
||||||
|
ZHVwVZGwwdndqJVJqfHbGwnwrRLtLMftMvMMRrhmLMthhLmz
|
||||||
|
RgHGLbTqlZlPRZPHfvvfZttJnvfvjnzr
|
||||||
|
sVcChDVDccwNhhvjTvVzWJjnzFff
|
||||||
|
mpNcCMTCGmLqBLGH
|
||||||
|
wVJwHJHVMtMpBmDDWPQVPWDGDD
|
||||||
|
zCrlZzCblBvnCDWNGLmvGDLPNG
|
||||||
|
dqZglgbzrzbbgZqzTFSBHHFJSSSfjjSMfwhj
|
||||||
|
NMWJSjLMCnHHNMNNHWCHMbVVGBPZTrPVPBVDrBSDGTTr
|
||||||
|
zvttlFpgdtldwwvftPDPTWQdBZrsrWrGBZ
|
||||||
|
hFlFmhRFvfCbmWJWHcnj
|
||||||
1000
2022/inputs/04.txt
Normal file
1000
2022/inputs/04.txt
Normal file
File diff suppressed because it is too large
Load Diff
106
2022/src/common.rs
Normal file
106
2022/src/common.rs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
//! Common helper utilities to all days
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use nom::error::ErrorKind;
|
||||||
|
use nom::error::ParseError;
|
||||||
|
use nom::Finish;
|
||||||
|
use nom::IResult;
|
||||||
|
use nom::InputLength;
|
||||||
|
use nom::Parser;
|
||||||
|
|
||||||
|
/// Parse input from some nom parser and return as an anyhow result
|
||||||
|
///
|
||||||
|
/// This method exists as a convenience because nom's errors cannot otherwise be easily converted to
|
||||||
|
/// an anyhow error, and I don't want to keep track of custom error implementations here.
|
||||||
|
pub fn parse_input<'a, O>(
|
||||||
|
input: &'a [u8],
|
||||||
|
mut parser: impl Parser<&'a [u8], O, nom::error::Error<&'a [u8]>>,
|
||||||
|
) -> Result<O> {
|
||||||
|
let (unparsed, output) = parser.parse(input).finish().map_err(|e| {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"Parser error {:?} to parse at {}",
|
||||||
|
e.code,
|
||||||
|
String::from_utf8_lossy(e.input)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if !unparsed.is_empty() {
|
||||||
|
Err(anyhow::anyhow!(
|
||||||
|
"Not all input consumed: {}",
|
||||||
|
String::from_utf8_lossy(unparsed)
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies a parser iteratively and reduces the results using the given function. Fails if the
|
||||||
|
/// embedded parser doesn't return at least one result.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// - `f`: the function to apply
|
||||||
|
/// - `g`: the function that combines the result o `f` with previous results
|
||||||
|
///
|
||||||
|
/// This implementation is based on [`nom::multi::fold_many1`] with minor differences. If
|
||||||
|
/// successful, this should probably be upstreamed.
|
||||||
|
pub fn reduce_many1<I, O, E, F>(
|
||||||
|
mut f: F,
|
||||||
|
mut g: impl FnMut(O, O) -> O,
|
||||||
|
) -> impl FnMut(I) -> IResult<I, O, E>
|
||||||
|
where
|
||||||
|
I: Clone + InputLength,
|
||||||
|
E: ParseError<I>,
|
||||||
|
F: Parser<I, O, E>,
|
||||||
|
{
|
||||||
|
// Cannot delegate to fold_many0 because that would make the function FnOnce rather than FnMut,
|
||||||
|
// since it would transfer ownership of the embedded parser to fold_many0.
|
||||||
|
move |i: I| {
|
||||||
|
let _i = i.clone();
|
||||||
|
match f.parse(_i) {
|
||||||
|
Err(nom::Err::Error(_)) => {
|
||||||
|
Err(nom::Err::Error(E::from_error_kind(i, ErrorKind::Many1)))
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
Ok((i1, mut acc)) => {
|
||||||
|
let mut input = i1;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let _input = input.clone();
|
||||||
|
let len = input.input_len();
|
||||||
|
match f.parse(_input) {
|
||||||
|
Err(nom::Err::Error(_)) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
Ok((i, o)) => {
|
||||||
|
// infinite loop check: the parser must always consume
|
||||||
|
if i.input_len() == len {
|
||||||
|
return Err(nom::Err::Failure(E::from_error_kind(
|
||||||
|
i,
|
||||||
|
ErrorKind::Many1,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
acc = g(acc, o);
|
||||||
|
input = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((input, acc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the minimum and maximum of two unordered variables
|
||||||
|
pub fn minmax<T>(a: T, b: T) -> (T, T)
|
||||||
|
where
|
||||||
|
T: PartialOrd,
|
||||||
|
{
|
||||||
|
if a < b {
|
||||||
|
(a, b)
|
||||||
|
} else {
|
||||||
|
(b, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
50
2022/src/day01.rs
Normal file
50
2022/src/day01.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use nom::character::complete::newline;
|
||||||
|
use nom::multi::separated_list0;
|
||||||
|
use nom::sequence::terminated;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
use crate::common::parse_input;
|
||||||
|
use crate::common::reduce_many1;
|
||||||
|
|
||||||
|
fn parse_elf(input: &[u8]) -> IResult<&[u8], i32> {
|
||||||
|
reduce_many1(terminated(nom::character::complete::i32, newline), Add::add)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(input: &[u8]) -> Result<String> {
|
||||||
|
let elves = parse_input(input, parse_elf_list)?;
|
||||||
|
Ok(elves.into_iter().fold(0, Ord::max).to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_elf_list(input: &[u8]) -> IResult<&[u8], Vec<i32>> {
|
||||||
|
separated_list0(newline, parse_elf)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &[u8]) -> Result<String> {
|
||||||
|
let mut elves = parse_input(input, parse_elf_list)?;
|
||||||
|
|
||||||
|
let (first, third, _) = elves.select_nth_unstable_by(2, |a, b| Ord::cmp(b, a));
|
||||||
|
|
||||||
|
let result = first[1] + first[0] + *third;
|
||||||
|
|
||||||
|
Ok(result.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SAMPLE: &[u8] = include_bytes!("samples/01.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
assert_eq!(part1(SAMPLE).unwrap(), "24000");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
assert_eq!(part2(SAMPLE).unwrap(), "45000");
|
||||||
|
}
|
||||||
|
}
|
||||||
125
2022/src/day02.rs
Normal file
125
2022/src/day02.rs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use nom::character::complete::newline;
|
||||||
|
use nom::combinator::map_res;
|
||||||
|
use nom::multi::many0;
|
||||||
|
use nom::sequence::separated_pair;
|
||||||
|
use nom::sequence::terminated;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
use crate::common::parse_input;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
|
enum Rps {
|
||||||
|
Rock,
|
||||||
|
Paper,
|
||||||
|
Scissors,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rps {
|
||||||
|
/// Score we get by playing this move
|
||||||
|
fn score(self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Rps::Rock => 1,
|
||||||
|
Rps::Paper => 2,
|
||||||
|
Rps::Scissors => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Score we get from the result from playing given other
|
||||||
|
fn score_against(self, other: Self) -> u32 {
|
||||||
|
match (self, other) {
|
||||||
|
(a, b) if a == b => 3,
|
||||||
|
(Rps::Rock, Rps::Paper) | (Rps::Paper, Rps::Scissors) | (Rps::Scissors, Rps::Rock) => 0,
|
||||||
|
_ => 6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Score if the result is according to the instruction
|
||||||
|
fn score_result(self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Rps::Rock => 0, // Rock is lose
|
||||||
|
Rps::Paper => 3, // Paper is draw
|
||||||
|
Rps::Scissors => 6, // Scissors is win
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move we need to achieve the result indicated by self
|
||||||
|
fn needed(self, other: Self) -> Self {
|
||||||
|
match (self, other) {
|
||||||
|
(Rps::Paper, other) => other,
|
||||||
|
(Rps::Rock, Rps::Rock) => Rps::Scissors,
|
||||||
|
(Rps::Rock, Rps::Paper) => Rps::Rock,
|
||||||
|
(Rps::Rock, Rps::Scissors) => Rps::Paper,
|
||||||
|
(Rps::Scissors, Rps::Rock) => Rps::Paper,
|
||||||
|
(Rps::Scissors, Rps::Paper) => Rps::Scissors,
|
||||||
|
(Rps::Scissors, Rps::Scissors) => Rps::Rock,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for Rps {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
b'A' | b'X' => Ok(Rps::Rock),
|
||||||
|
b'B' | b'Y' => Ok(Rps::Paper),
|
||||||
|
b'C' | b'Z' => Ok(Rps::Scissors),
|
||||||
|
_ => Err(anyhow::anyhow!("Invalid RPS: {value}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_plan(input: &[u8]) -> IResult<&[u8], Vec<(Rps, Rps)>> {
|
||||||
|
fn parse_rps(input: &[u8]) -> IResult<&[u8], Rps> {
|
||||||
|
// Note: alpha1 also sort of works but is significantly slower
|
||||||
|
map_res(nom::bytes::complete::take(1usize), |v: &[u8]| {
|
||||||
|
Rps::try_from(v[0])
|
||||||
|
})(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(input: &[u8]) -> IResult<&[u8], (Rps, Rps)> {
|
||||||
|
separated_pair(parse_rps, nom::character::complete::char(' '), parse_rps)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
many0(terminated(parse_line, newline))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(input: &[u8]) -> Result<String> {
|
||||||
|
let plan = parse_input(input, parse_plan)?;
|
||||||
|
|
||||||
|
let result: u32 = plan
|
||||||
|
.into_iter()
|
||||||
|
.map(|(them, us)| us.score() + us.score_against(them))
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
Ok(result.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &[u8]) -> Result<String> {
|
||||||
|
let plan = parse_input(input, parse_plan)?;
|
||||||
|
|
||||||
|
let result: u32 = plan
|
||||||
|
.into_iter()
|
||||||
|
.map(|(them, us)| us.score_result() + us.needed(them).score())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
Ok(result.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SAMPLE: &[u8] = include_bytes!("samples/02.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
assert_eq!(part1(SAMPLE).unwrap(), "15")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
assert_eq!(part2(SAMPLE).unwrap(), "12")
|
||||||
|
}
|
||||||
|
}
|
||||||
79
2022/src/day03.rs
Normal file
79
2022/src/day03.rs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
fn priority(item: u8) -> u32 {
|
||||||
|
match item {
|
||||||
|
b'a'..=b'z' => item - b'a' + 1,
|
||||||
|
b'A'..=b'Z' => item - b'A' + 27,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seen(backpack: &[u8]) -> u64 {
|
||||||
|
let mut seen = 0;
|
||||||
|
|
||||||
|
for &b in backpack {
|
||||||
|
seen |= 1 << priority(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
seen
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(input: &[u8]) -> Result<String> {
|
||||||
|
let mut total = 0;
|
||||||
|
|
||||||
|
for line in input.split(|&b| b == b'\n') {
|
||||||
|
let (first, last) = line.split_at(line.len() / 2);
|
||||||
|
|
||||||
|
let seen = seen(first);
|
||||||
|
|
||||||
|
for &b in last {
|
||||||
|
let prio = priority(b);
|
||||||
|
|
||||||
|
if (seen & (1 << prio)) != 0 {
|
||||||
|
total += prio;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(total.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &[u8]) -> Result<String> {
|
||||||
|
let mut total = 0;
|
||||||
|
|
||||||
|
for chunk in &input.split(|&b| b == b'\n').chunks(3) {
|
||||||
|
let mut mask = u64::MAX;
|
||||||
|
|
||||||
|
for backpack in chunk {
|
||||||
|
let seen = seen(backpack);
|
||||||
|
mask &= seen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mask != 0 {
|
||||||
|
debug_assert_eq!(1, mask.count_ones());
|
||||||
|
total += mask.trailing_zeros();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(total.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SAMPLE: &[u8] = include_bytes!("samples/03.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
assert_eq!(part1(SAMPLE).unwrap(), "157")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
assert_eq!(part2(SAMPLE).unwrap(), "70")
|
||||||
|
}
|
||||||
|
}
|
||||||
75
2022/src/day04.rs
Normal file
75
2022/src/day04.rs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::newline;
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::multi::many0;
|
||||||
|
use nom::sequence::separated_pair;
|
||||||
|
use nom::sequence::terminated;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
use crate::common::parse_input;
|
||||||
|
|
||||||
|
type Assignment = RangeInclusive<u32>;
|
||||||
|
|
||||||
|
fn parse_assignments(
|
||||||
|
input: &[u8],
|
||||||
|
) -> IResult<&[u8], Vec<(RangeInclusive<u32>, RangeInclusive<u32>)>> {
|
||||||
|
use nom::character::complete::u32;
|
||||||
|
|
||||||
|
fn parse_single(input: &[u8]) -> IResult<&[u8], Assignment> {
|
||||||
|
map(separated_pair(u32, tag("-"), u32), |(start, end)| {
|
||||||
|
start..=end
|
||||||
|
})(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
let parse_line = separated_pair(parse_single, tag(","), parse_single);
|
||||||
|
|
||||||
|
many0(terminated(parse_line, newline))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_contained(a: &Assignment, b: &Assignment) -> bool {
|
||||||
|
if a.size_hint().0 > b.size_hint().0 {
|
||||||
|
a.contains(b.start()) && a.contains(b.end())
|
||||||
|
} else {
|
||||||
|
b.contains(a.start()) && b.contains(a.end())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_overlapping(a: &Assignment, b: &Assignment) -> bool {
|
||||||
|
b.end() >= a.start() && b.start() <= a.end() || a.end() >= b.start() && a.start() <= b.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parts_common(input: &[u8], filter: impl Fn(&Assignment, &Assignment) -> bool) -> Result<String> {
|
||||||
|
let assigments = parse_input(input, parse_assignments)?;
|
||||||
|
|
||||||
|
let overlapping = assigments.into_iter().filter(|(a, b)| filter(a, b)).count();
|
||||||
|
|
||||||
|
Ok(overlapping.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(input: &[u8]) -> Result<String> {
|
||||||
|
parts_common(input, is_contained)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &[u8]) -> Result<String> {
|
||||||
|
parts_common(input, is_overlapping)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SAMPLE: &[u8] = include_bytes!("samples/04.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
assert_eq!(part1(SAMPLE).unwrap(), "2")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
assert_eq!(part2(SAMPLE).unwrap(), "4")
|
||||||
|
}
|
||||||
|
}
|
||||||
9
2022/src/day05.rs
Normal file
9
2022/src/day05.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day06.rs
Normal file
9
2022/src/day06.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day07.rs
Normal file
9
2022/src/day07.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day08.rs
Normal file
9
2022/src/day08.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day09.rs
Normal file
9
2022/src/day09.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day10.rs
Normal file
9
2022/src/day10.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day11.rs
Normal file
9
2022/src/day11.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day12.rs
Normal file
9
2022/src/day12.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day13.rs
Normal file
9
2022/src/day13.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day14.rs
Normal file
9
2022/src/day14.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day15.rs
Normal file
9
2022/src/day15.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day16.rs
Normal file
9
2022/src/day16.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day17.rs
Normal file
9
2022/src/day17.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day18.rs
Normal file
9
2022/src/day18.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day19.rs
Normal file
9
2022/src/day19.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day20.rs
Normal file
9
2022/src/day20.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day21.rs
Normal file
9
2022/src/day21.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day22.rs
Normal file
9
2022/src/day22.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day23.rs
Normal file
9
2022/src/day23.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
9
2022/src/day24.rs
Normal file
9
2022/src/day24.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
5
2022/src/day25.rs
Normal file
5
2022/src/day25.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub fn part1(_input: &[u8]) -> Result<String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
91
2022/src/lib.rs
Normal file
91
2022/src/lib.rs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
mod day01;
|
||||||
|
mod day02;
|
||||||
|
mod day03;
|
||||||
|
mod day04;
|
||||||
|
mod day05;
|
||||||
|
mod day06;
|
||||||
|
mod day07;
|
||||||
|
mod day08;
|
||||||
|
mod day09;
|
||||||
|
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;
|
||||||
|
|
||||||
|
type Solution = fn(&[u8]) -> Result<String>;
|
||||||
|
|
||||||
|
pub fn get_implementation(day: u8, part2: bool) -> Result<Solution> {
|
||||||
|
if !part2 {
|
||||||
|
match day {
|
||||||
|
1 => Ok(day01::part1),
|
||||||
|
2 => Ok(day02::part1),
|
||||||
|
3 => Ok(day03::part1),
|
||||||
|
4 => Ok(day04::part1),
|
||||||
|
5 => Ok(day05::part1),
|
||||||
|
6 => Ok(day06::part1),
|
||||||
|
7 => Ok(day07::part1),
|
||||||
|
8 => Ok(day08::part1),
|
||||||
|
9 => Ok(day09::part1),
|
||||||
|
10 => Ok(day10::part1),
|
||||||
|
11 => Ok(day11::part1),
|
||||||
|
12 => Ok(day12::part1),
|
||||||
|
13 => Ok(day13::part1),
|
||||||
|
14 => Ok(day14::part1),
|
||||||
|
15 => Ok(day15::part1),
|
||||||
|
16 => Ok(day16::part1),
|
||||||
|
17 => Ok(day17::part1),
|
||||||
|
18 => Ok(day18::part1),
|
||||||
|
19 => Ok(day19::part1),
|
||||||
|
20 => Ok(day20::part1),
|
||||||
|
21 => Ok(day21::part1),
|
||||||
|
22 => Ok(day22::part1),
|
||||||
|
23 => Ok(day23::part1),
|
||||||
|
24 => Ok(day24::part1),
|
||||||
|
25 => Ok(day25::part1),
|
||||||
|
_ => anyhow::bail!("Invalid day for part 1: {day}"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match day {
|
||||||
|
1 => Ok(day01::part2),
|
||||||
|
2 => Ok(day02::part2),
|
||||||
|
3 => Ok(day03::part2),
|
||||||
|
4 => Ok(day04::part2),
|
||||||
|
5 => Ok(day05::part2),
|
||||||
|
6 => Ok(day06::part2),
|
||||||
|
7 => Ok(day07::part2),
|
||||||
|
8 => Ok(day08::part2),
|
||||||
|
9 => Ok(day09::part2),
|
||||||
|
10 => Ok(day10::part2),
|
||||||
|
11 => Ok(day11::part2),
|
||||||
|
12 => Ok(day12::part2),
|
||||||
|
13 => Ok(day13::part2),
|
||||||
|
14 => Ok(day14::part2),
|
||||||
|
15 => Ok(day15::part2),
|
||||||
|
16 => Ok(day16::part2),
|
||||||
|
17 => Ok(day17::part2),
|
||||||
|
18 => Ok(day18::part2),
|
||||||
|
19 => Ok(day19::part2),
|
||||||
|
20 => Ok(day20::part2),
|
||||||
|
21 => Ok(day21::part2),
|
||||||
|
22 => Ok(day22::part2),
|
||||||
|
23 => Ok(day23::part2),
|
||||||
|
24 => Ok(day24::part2),
|
||||||
|
_ => anyhow::bail!("Invalid day for part 2: {day}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
2022/src/main.rs
Normal file
61
2022/src/main.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::num::NonZeroU8;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
use aoc_2022::get_implementation;
|
||||||
|
|
||||||
|
/// Advent of Code 2022 runner
|
||||||
|
#[derive(Parser)]
|
||||||
|
struct Opts {
|
||||||
|
/// Which day to run
|
||||||
|
day: NonZeroU8,
|
||||||
|
|
||||||
|
/// Print time taken
|
||||||
|
#[clap(short, long)]
|
||||||
|
time: bool,
|
||||||
|
|
||||||
|
/// Run part 2 instead of part 1
|
||||||
|
#[clap(short = '2', long)]
|
||||||
|
part2: bool,
|
||||||
|
|
||||||
|
/// Read input from the given file instead of stdin
|
||||||
|
#[clap(short, long)]
|
||||||
|
input: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Opts {
|
||||||
|
fn input_data(&self) -> Result<Vec<u8>> {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
|
||||||
|
if let Some(input) = &self.input {
|
||||||
|
File::open(input)?.read_to_end(&mut buffer)?;
|
||||||
|
} else {
|
||||||
|
std::io::stdin().read_to_end(&mut buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let opts: Opts = Opts::parse();
|
||||||
|
|
||||||
|
let input = opts.input_data()?;
|
||||||
|
|
||||||
|
let implementation = get_implementation(opts.day.get(), opts.part2)?;
|
||||||
|
|
||||||
|
let begin = Instant::now();
|
||||||
|
let result = implementation(&input)?;
|
||||||
|
|
||||||
|
if opts.time {
|
||||||
|
eprintln!("Execution time: {:?}", Instant::now().duration_since(begin));
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}", result);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
0
2022/src/samples/.gitkeep
Normal file
0
2022/src/samples/.gitkeep
Normal file
14
2022/src/samples/01.txt
Normal file
14
2022/src/samples/01.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
1000
|
||||||
|
2000
|
||||||
|
3000
|
||||||
|
|
||||||
|
4000
|
||||||
|
|
||||||
|
5000
|
||||||
|
6000
|
||||||
|
|
||||||
|
7000
|
||||||
|
8000
|
||||||
|
9000
|
||||||
|
|
||||||
|
10000
|
||||||
3
2022/src/samples/02.txt
Normal file
3
2022/src/samples/02.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
A Y
|
||||||
|
B X
|
||||||
|
C Z
|
||||||
6
2022/src/samples/03.txt
Normal file
6
2022/src/samples/03.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
vJrwpWtwJgWrhcsFMMfFFhFp
|
||||||
|
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||||
|
PmmdzqPrVvPwwTWBwg
|
||||||
|
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||||
|
ttgJtRGJQctTZtZT
|
||||||
|
CrZsJsPPZsGzwwsLwLmpwMDw
|
||||||
6
2022/src/samples/04.txt
Normal file
6
2022/src/samples/04.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
2-4,6-8
|
||||||
|
2-3,4-5
|
||||||
|
5-7,7-9
|
||||||
|
2-8,3-7
|
||||||
|
6-6,4-6
|
||||||
|
2-6,4-8
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Advent of Code
|
# Advent of Code
|
||||||
|
|
||||||
[](https://github.com/bertptrs/adventofcode/actions/workflows/2021.yml)
|
[](https://github.com/bertptrs/adventofcode/actions/workflows/2022.yml)
|
||||||
|
|
||||||
This repository contains my solutions for Advent of Code. See:
|
This repository contains my solutions for Advent of Code. See:
|
||||||
|
|
||||||
@@ -11,3 +11,4 @@ This repository contains my solutions for Advent of Code. See:
|
|||||||
- [2019 edition](./2019)
|
- [2019 edition](./2019)
|
||||||
- [2020 edition](./2020)
|
- [2020 edition](./2020)
|
||||||
- [2021 edition](./2021)
|
- [2021 edition](./2021)
|
||||||
|
- [2022 edition](./2022)
|
||||||
|
|||||||
Reference in New Issue
Block a user