mirror of
https://github.com/LeMoonStar/AoC24.git
synced 2025-07-07 21:49:59 +02:00
🎉 Initialized repository based on 2023 code
This commit is contained in:
commit
cc42c33b5d
65 changed files with 3897 additions and 0 deletions
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!();
|
Loading…
Add table
Add a link
Reference in a new issue