day 23 finished
This commit is contained in:
parent
80d724a6f6
commit
62cb729aee
6 changed files with 435 additions and 3 deletions
7
data/day23/example01.txt
Normal file
7
data/day23/example01.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
....#..
|
||||||
|
..###.#
|
||||||
|
#...#.#
|
||||||
|
.#...##
|
||||||
|
#.###..
|
||||||
|
##.#.##
|
||||||
|
.#..#..
|
||||||
6
data/day23/example02.txt
Normal file
6
data/day23/example02.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
.....
|
||||||
|
..##.
|
||||||
|
..#..
|
||||||
|
.....
|
||||||
|
..##.
|
||||||
|
.....
|
||||||
70
data/day23/input.txt
Normal file
70
data/day23/input.txt
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
###.###..#.....#..#.##..##.#...###.#####..#.##.#####.###..######.#.#.#
|
||||||
|
....##.#.#.#......#.###..##..###...#.#...####.##...#.#....#.##.##....#
|
||||||
|
#..#.#.#.##.........#####....#..##.......#.#.#.##....#.#....##..##..##
|
||||||
|
#.##.##....#.##.#.###.#...#..#.##.####.#.#.#.#.###.###.####....#.#.#.#
|
||||||
|
.#.#.#####.##...##.##..#..#.#..####.#..#.#.#######..#.##.#.###.#.....#
|
||||||
|
..#..#....###.#....###.##.#..#..#.#..#.#.#...##...#....##....#..##...#
|
||||||
|
###..........#..#.###....##.##...#####.###.#.##...#.##.....#.##.#.####
|
||||||
|
#.###.####...#..#.##.....#.####.##..##...#..##.....#...###..##.######.
|
||||||
|
.....#.####..##.#...#..##.###..#.##.####..#...#.###..##..#.#.###...#.#
|
||||||
|
.#.#.#..##.##..#.#.##.#.##.#.##..##.##.#..##.#.##..#####.#.###.#.##..#
|
||||||
|
###.#.###.##.##....#.#.#...##...#.#..#.#..#.#..##.#....#####...#...###
|
||||||
|
.#.#.#.#.#..#....###.#.##.#.#.####..#.#.#...#.#.#.###....#....#...##..
|
||||||
|
#.#....#........#....######...#....#..#.###...#.....###..###...##..#..
|
||||||
|
.###.##....#.#.#.###..###....#.#.#..###.##..#..#..#####.#.###.#..##..#
|
||||||
|
..###.##..####.....#...##.#....#...###..#.###.#...##....####........#.
|
||||||
|
#####.##..#..##..###....#.##....#.#...##.########...#.#.#..##..##..###
|
||||||
|
.##..#...##.....###.#...#..###.######.#.#...#...##..#.....#..#.##..#.#
|
||||||
|
.#####..#.######.#..#..#.#.#.##....##..#.......#....#.##.#.#..##...#.#
|
||||||
|
.#.##..#..###..#.######........##.##.##..#....#.###.######.##.#.#..##.
|
||||||
|
##.##.#..####.#....###.#..##..#...#.#####.#..#...#....##...#.###..#.##
|
||||||
|
#....##..#...#.#.###.#.#...##.#.#..###...####..##.#..##.#.#####.....##
|
||||||
|
.##.#..#.##.##.#.##.....#######..#...#.##.####...#.....#.##..#...##...
|
||||||
|
#.#.#.#####...#####..#.##....#.#.####.#..#.##..#.#.#...#..##.#...##...
|
||||||
|
#.#.#.#..#.#.#..#..###.#.....#.#.#..#.#####.#.#..#...#.###.###...#.#..
|
||||||
|
.####..####.#.#..#...##.##.#....#.#.....#.##.###..#...###.###.#....##.
|
||||||
|
....##.#.##.###.#..##.#..#.......##...#.###...#.......#..####.#.#.####
|
||||||
|
....#.#......####..#.#..#..#..#.##..#..#..###..#.#.##.#.##..###..#..#.
|
||||||
|
.##.#.....##.#..#..#..####..#.#.#...###.##.##.##...#..##..##.##...##..
|
||||||
|
#..####..#...#.#....##...##..#.....##.#######..#.####...##..######.#..
|
||||||
|
..#.##.##....##.#######..##...#..#..###.....##.#.#..#.#...##..###.####
|
||||||
|
#####......##..#.#..#......#..####.####...#####..######...##.###..##..
|
||||||
|
###..##.#.##....##..######.#.#.#......#..##.#.##.#.##...#.##...###..##
|
||||||
|
.....#.#.#.##..#.#####.##.#.#.....#.#..#.###.##..#.###.##..##.###....#
|
||||||
|
.###.####..####.###....####.#.##..##..#.....##.###.##.######.#..#.#...
|
||||||
|
.#.#######.#.#.###....#####..#.#.#..#.#.#.#.#..##..#..#...##..##..#.#.
|
||||||
|
.##..####..#.#...###.#...#....####...###.#..#.#.....#.#.##.#..##.#.#..
|
||||||
|
.#.#.#.#####..##.####..#..##......#..#.###.#..#....#...#....#...#.####
|
||||||
|
..##.##.###.#..#..#.#..#.###......##.#..#..#.#.####.#.#.#.####.##.....
|
||||||
|
##.#..#..##.#######..#..#....##..#...########.##.#.#...##...##.##.....
|
||||||
|
.#...#####.#..##.##.###.####.....###.#......########.#..##.##.#....###
|
||||||
|
...####.###....##..#..#....#..##.####..##..#..###.......#.#.###.##...#
|
||||||
|
.#.#......#####...##....#.#..#######.######.#.#.##.#..###..#....##..#.
|
||||||
|
..###.#.#####..##.#.####....#.###..#..#.##.#####.##..##.##..##..#.##.#
|
||||||
|
.####.#.######.###.###..#......#...#...#..#..##.###.##.#.####.#.#.##.#
|
||||||
|
#####.###.##.#########..###..#.#.##.#..#..##...#.###.#.#......###..##.
|
||||||
|
###...###.##.#.###.#.##.####.#######..##.#....#####.###.#..#.#...###..
|
||||||
|
.######...#...#..###......#.#.##........#..##.#.#.##.#....###.....##.#
|
||||||
|
#.#.....##.##.##..##..##.#.##.###.##.###.##.#.##.###....##..#.#.##....
|
||||||
|
#.####.##...##....#.#.....#.#.###..#..####.....#.##..##...##.###.#..##
|
||||||
|
#####.##.#...#....#..###.##..##...#....#....##.#.#....#####....####.##
|
||||||
|
####...##...#.###.##.##.#####...#.....##..#####...########..####......
|
||||||
|
#.#..##.##.#.######.###.#.##.......#......####..##.#.#.#..##.###.#..#.
|
||||||
|
#..#..########..##..#.######..#.#...#..#.#####.###.####......##..###.#
|
||||||
|
#..#.#...#..#....#..##.##.#..###.####.###########.#..#.###.#.##.###..#
|
||||||
|
##.#..#..#.....#.##.#..######..#..#...#.#...###.#.#.#.#.#.########...#
|
||||||
|
..###.#.##......###..#...##......#####.#.#....####.....##.#..#.#..#.#.
|
||||||
|
..######....#..##.#.#..#.##.#..##.##.#....##....###.#.##.##..##....###
|
||||||
|
.#####....##....###.#.#######.....##.###.#..#.#.#..###...#.##..#..#.#.
|
||||||
|
#..#####...#..##..#..#..#....#.##....#..##.......##..#....#.#..#.#.###
|
||||||
|
#.#..#####...#...#...##.#....#..##.#.##....#####.....#.##.....#..#.###
|
||||||
|
##.#.#....#...#.####....###....#...#.##...##.#....#.#.#.##......##.###
|
||||||
|
...##.#.#..#.###..#.#...##.#...##.#...##...#..###.#.###...###..#..##.#
|
||||||
|
.#####...#.#..###.#.##.##.#.##..##.#.#.....##....#.#..#.#.#..#####.###
|
||||||
|
#.####.####..###......##.....#.#.....##.#..##.##.#....###.....####..##
|
||||||
|
#..#####...#....#...###..##...###..####..####..#...#####.#####..#.###.
|
||||||
|
####.###.###....####....##..#..####...#....###.##.#.##...##.......####
|
||||||
|
.#.###....####..#..#.###.##.##.####..##.#..###..#..#.#.#..#..#.##..##.
|
||||||
|
....##......####.####.######...###.....###.#.#..##.#.##.......#...#...
|
||||||
|
##.###.##...#.....#.##.#.......####.##.###..###.#.#..#.##..#.####....#
|
||||||
|
....#..##.#...##.##.#.#.#..#.#..#..#.####....#####..#.....#####.#.....
|
||||||
|
|
@ -2,7 +2,7 @@ use super::direction::Direction;
|
||||||
use super::math::gcd;
|
use super::math::gcd;
|
||||||
use num_traits::{CheckedAdd, CheckedSub, Float, Num, NumCast, Signed, Zero};
|
use num_traits::{CheckedAdd, CheckedSub, Float, Num, NumCast, Signed, Zero};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub struct Pos2<T>([T; 2]);
|
pub struct Pos2<T>([T; 2]);
|
||||||
|
|
@ -157,7 +157,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, P: Into<Pos2<T>>> Add<P> for Pos2<T>
|
impl<T, P: Into<Pos2<T>>> Add<P> for Pos2<T>
|
||||||
where
|
where
|
||||||
T: Num + Copy,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
|
|
@ -168,6 +168,17 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, P: Into<Pos2<T>>> AddAssign<P> for Pos2<T>
|
||||||
|
where
|
||||||
|
T: AddAssign<T> + Copy,
|
||||||
|
{
|
||||||
|
fn add_assign(&mut self, rhs: P) {
|
||||||
|
let rhs = rhs.into();
|
||||||
|
self.0[0] += rhs.0[0];
|
||||||
|
self.0[1] += rhs.0[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, P: Into<Pos2<T>>> Sub<P> for Pos2<T>
|
impl<T, P: Into<Pos2<T>>> Sub<P> for Pos2<T>
|
||||||
where
|
where
|
||||||
T: Num + Copy,
|
T: Num + Copy,
|
||||||
|
|
|
||||||
336
src/days/day23/mod.rs
Normal file
336
src/days/day23/mod.rs
Normal file
|
|
@ -0,0 +1,336 @@
|
||||||
|
use super::template::{DayTrait, ResultType};
|
||||||
|
use crate::common::{area::Area, direction::Direction, pos2::Pos2};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
const DAY_NUMBER: usize = 23;
|
||||||
|
|
||||||
|
pub struct Day;
|
||||||
|
|
||||||
|
impl DayTrait for Day {
|
||||||
|
fn get_day_number(&self) -> usize {
|
||||||
|
DAY_NUMBER
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||||
|
let field: Field = lines.parse()?;
|
||||||
|
let elves = field.rounds(10);
|
||||||
|
|
||||||
|
Ok(ResultType::Integer(count_empty_tiles(&elves)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||||
|
let field: Field = lines.parse()?;
|
||||||
|
let round = field.forever() as i64;
|
||||||
|
Ok(ResultType::Integer(round))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_empty_tiles(elves: &[Pos2<i32>]) -> i64 {
|
||||||
|
let Some(area) = Area::from_iterator(elves.iter()) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
area.area() as i64 - elves.len() as i64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
enum FieldError {
|
||||||
|
#[error("Unknown Char: {0}")]
|
||||||
|
UnknownChar(char),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_direction(current: Direction) -> Direction {
|
||||||
|
match current {
|
||||||
|
Direction::North => Direction::South,
|
||||||
|
Direction::South => Direction::West,
|
||||||
|
Direction::West => Direction::East,
|
||||||
|
Direction::East => Direction::North,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DirectionDispenser(Direction);
|
||||||
|
|
||||||
|
impl DirectionDispenser {
|
||||||
|
fn new() -> DirectionDispenser {
|
||||||
|
Self(Direction::North)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn progress(&mut self) {
|
||||||
|
self.0 = next_direction(self.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter(&self) -> DispenserIterator {
|
||||||
|
DispenserIterator::new(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DispenserIterator {
|
||||||
|
start: Direction,
|
||||||
|
current: Option<Direction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DispenserIterator {
|
||||||
|
pub fn new(start: Direction) -> Self {
|
||||||
|
DispenserIterator {
|
||||||
|
start,
|
||||||
|
current: Some(start),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for DispenserIterator {
|
||||||
|
type Item = Direction;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let result = self.current;
|
||||||
|
if let Some(current) = self.current {
|
||||||
|
let next = next_direction(current);
|
||||||
|
if next == self.start {
|
||||||
|
self.current = None;
|
||||||
|
} else {
|
||||||
|
self.current = Some(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PosIterator {
|
||||||
|
pos: Pos2<i32>,
|
||||||
|
inc: Pos2<i32>,
|
||||||
|
count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PosIterator {
|
||||||
|
fn new(pos: Pos2<i32>, direction: Direction) -> Self {
|
||||||
|
let inc = direction.turn_right().into();
|
||||||
|
let pos = pos + direction - inc * 2;
|
||||||
|
Self { pos, inc, count: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PosIterator {
|
||||||
|
type Item = Pos2<i32>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.count > 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pos += self.inc;
|
||||||
|
self.count += 1;
|
||||||
|
Some(self.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MoveCheck {
|
||||||
|
NoNeighbors,
|
||||||
|
NoFreeSpace,
|
||||||
|
MoveTo(Pos2<i32>, Direction),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Field {
|
||||||
|
direction: DirectionDispenser,
|
||||||
|
elves: HashMap<Pos2<i32>, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Field {
|
||||||
|
type Err = FieldError;
|
||||||
|
|
||||||
|
fn from_str(lines: &str) -> Result<Self, Self::Err> {
|
||||||
|
let elves: HashMap<Pos2<i32>, bool> = lines
|
||||||
|
.split('\n')
|
||||||
|
.enumerate()
|
||||||
|
.map(|(y, row)| {
|
||||||
|
row.chars().enumerate().filter_map(move |(x, c)| match c {
|
||||||
|
'.' => None,
|
||||||
|
'#' => Some(Ok((Pos2::new(x as i32, y as i32), true))),
|
||||||
|
_ => Some(Err(FieldError::UnknownChar(c))),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.try_collect()?;
|
||||||
|
|
||||||
|
Ok(Field {
|
||||||
|
direction: DirectionDispenser::new(),
|
||||||
|
elves,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Field {
|
||||||
|
fn has_neighbors(&self, pos: Pos2<i32>) -> bool {
|
||||||
|
for x in -1..=1 {
|
||||||
|
for y in -1..=1 {
|
||||||
|
if x != 0 || y != 0 {
|
||||||
|
let check_pos = pos + (x, y);
|
||||||
|
if self.elves.contains_key(&check_pos) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(&self, pos: Pos2<i32>, directions: DispenserIterator) -> MoveCheck {
|
||||||
|
if !self.has_neighbors(pos) {
|
||||||
|
return MoveCheck::NoNeighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
for direction in directions {
|
||||||
|
if self.is_empty(pos, direction) {
|
||||||
|
return MoveCheck::MoveTo(pos + direction, direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MoveCheck::NoFreeSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
fn one_round(&mut self) -> bool {
|
||||||
|
let mut proposals: HashMap<Pos2<i32>, (Pos2<i32>, Direction)> = HashMap::new();
|
||||||
|
let mut deactivate = HashMap::new();
|
||||||
|
for elf in self
|
||||||
|
.elves
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(elf, active)| active.then_some(*elf))
|
||||||
|
{
|
||||||
|
match self.check(elf, self.direction.iter()) {
|
||||||
|
MoveCheck::MoveTo(proposal, direction) => {
|
||||||
|
if proposals.contains_key(&proposal) {
|
||||||
|
proposals.remove(&proposal);
|
||||||
|
} else {
|
||||||
|
proposals.insert(proposal, (elf, direction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MoveCheck::NoNeighbors => {
|
||||||
|
deactivate.insert(elf, false);
|
||||||
|
}
|
||||||
|
MoveCheck::NoFreeSpace => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if proposals.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.elves.extend(deactivate.into_iter());
|
||||||
|
|
||||||
|
for (to, (from, direction)) in proposals {
|
||||||
|
self.elves.remove(&from);
|
||||||
|
self.elves.insert(to, true);
|
||||||
|
for pos in PosIterator::new(to, direction) {
|
||||||
|
if let Some(active) = self.elves.get_mut(&pos) {
|
||||||
|
*active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.direction.progress();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self, pos: Pos2<i32>, direction: Direction) -> bool {
|
||||||
|
PosIterator::new(pos, direction).all(|pos| !self.elves.contains_key(&pos))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forever(mut self) -> usize {
|
||||||
|
for round in 0.. {
|
||||||
|
if !self.one_round() {
|
||||||
|
return round + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rounds(mut self, arg: usize) -> Vec<Pos2<i32>> {
|
||||||
|
for _ in 0..arg {
|
||||||
|
self.one_round();
|
||||||
|
}
|
||||||
|
self.elves.into_keys().collect_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::{common::file::read_string, hashmap, hashset};
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part1() -> Result<()> {
|
||||||
|
let day = Day {};
|
||||||
|
let lines = read_string(day.get_day_number(), "example01.txt")?;
|
||||||
|
let expected = ResultType::Integer(110);
|
||||||
|
let result = day.part1(&lines)?;
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part2() -> Result<()> {
|
||||||
|
let day = Day {};
|
||||||
|
let lines = read_string(day.get_day_number(), "example01.txt")?;
|
||||||
|
let expected = ResultType::Integer(20);
|
||||||
|
let result = day.part2(&lines)?;
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse() -> Result<()> {
|
||||||
|
let day = Day {};
|
||||||
|
let lines = read_string(day.get_day_number(), "example02.txt")?;
|
||||||
|
let expected = hashmap!(
|
||||||
|
Pos2::new(2, 1) => true,
|
||||||
|
Pos2::new(3, 1) => true,
|
||||||
|
Pos2::new(2, 2) => true,
|
||||||
|
Pos2::new(2, 4) => true,
|
||||||
|
Pos2::new(3, 4) => true
|
||||||
|
);
|
||||||
|
let field: Field = lines.parse()?;
|
||||||
|
assert_eq!(field.elves, expected);
|
||||||
|
assert_eq!(field.direction.0, Direction::North);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn round1() -> Result<()> {
|
||||||
|
let day = Day {};
|
||||||
|
let lines = read_string(day.get_day_number(), "example02.txt")?;
|
||||||
|
let expected = hashmap!(
|
||||||
|
Pos2::new(2, 0) => true,
|
||||||
|
Pos2::new(3, 0) => true,
|
||||||
|
Pos2::new(2, 2) => true,
|
||||||
|
Pos2::new(3, 3) => true,
|
||||||
|
Pos2::new(2, 4) => true
|
||||||
|
);
|
||||||
|
let mut field: Field = lines.parse()?;
|
||||||
|
field.one_round();
|
||||||
|
assert_eq!(field.elves, expected);
|
||||||
|
assert_eq!(field.direction.0, Direction::South);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn round2() -> Result<()> {
|
||||||
|
let day = Day {};
|
||||||
|
let lines = read_string(day.get_day_number(), "example02.txt")?;
|
||||||
|
let expected = hashset!(
|
||||||
|
Pos2::new(2, 1),
|
||||||
|
Pos2::new(3, 1),
|
||||||
|
Pos2::new(1, 2),
|
||||||
|
Pos2::new(4, 3),
|
||||||
|
Pos2::new(2, 5)
|
||||||
|
);
|
||||||
|
let field: Field = lines.parse()?;
|
||||||
|
let elves = HashSet::from_iter(field.rounds(2).into_iter());
|
||||||
|
assert_eq!(elves, expected);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ mod day19;
|
||||||
mod day20;
|
mod day20;
|
||||||
mod day21;
|
mod day21;
|
||||||
mod day22;
|
mod day22;
|
||||||
|
mod day23;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
pub use template::DayTrait;
|
pub use template::DayTrait;
|
||||||
|
|
@ -29,7 +30,7 @@ pub mod day_provider {
|
||||||
use super::*;
|
use super::*;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
const MAX_DAY: usize = 22;
|
const MAX_DAY: usize = 23;
|
||||||
|
|
||||||
pub fn get_day(day_num: usize) -> Result<Box<dyn DayTrait>, ProviderError> {
|
pub fn get_day(day_num: usize) -> Result<Box<dyn DayTrait>, ProviderError> {
|
||||||
match day_num {
|
match day_num {
|
||||||
|
|
@ -55,6 +56,7 @@ pub mod day_provider {
|
||||||
20 => Ok(Box::new(day20::Day)),
|
20 => Ok(Box::new(day20::Day)),
|
||||||
21 => Ok(Box::new(day21::Day)),
|
21 => Ok(Box::new(day21::Day)),
|
||||||
22 => Ok(Box::new(day22::Day)),
|
22 => Ok(Box::new(day22::Day)),
|
||||||
|
23 => Ok(Box::new(day23::Day)),
|
||||||
_ => Err(ProviderError::InvalidNumber(day_num)),
|
_ => Err(ProviderError::InvalidNumber(day_num)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue