Solve day 4 in Rust
This commit is contained in:
parent
3114920494
commit
9fdd0cc28e
@ -4,9 +4,10 @@ use crate::puzzle::Puzzle;
|
|||||||
use puzzles::day1;
|
use puzzles::day1;
|
||||||
use puzzles::day2;
|
use puzzles::day2;
|
||||||
use puzzles::day3;
|
use puzzles::day3;
|
||||||
|
use puzzles::day4;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
const PUZZLES: [&dyn SomePuzzle; 3] = [&day1::PUZZLE, &day2::PUZZLE, &day3::PUZZLE];
|
const PUZZLES: [&dyn SomePuzzle; 4] = [&day1::PUZZLE, &day2::PUZZLE, &day3::PUZZLE, &day4::PUZZLE];
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
[false, true].iter().for_each(|is_real_data| {
|
[false, true].iter().for_each(|is_real_data| {
|
||||||
|
|||||||
129
rust/puzzles/day4.rs
Normal file
129
rust/puzzles/day4.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
use crate::puzzle::Puzzle;
|
||||||
|
use nom::{
|
||||||
|
Parser,
|
||||||
|
branch::alt,
|
||||||
|
character::complete::{char, newline},
|
||||||
|
combinator::{eof, value},
|
||||||
|
error::Error,
|
||||||
|
multi::{many1, separated_list1},
|
||||||
|
sequence::terminated,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PUZZLE: Puzzle<Vec<Vec<InTile>>, 2> = Puzzle {
|
||||||
|
number: 4,
|
||||||
|
parser: |input| {
|
||||||
|
terminated::<_, _, Error<&str>, _, _>(
|
||||||
|
terminated(
|
||||||
|
separated_list1(
|
||||||
|
newline,
|
||||||
|
many1(alt((
|
||||||
|
value(InTile::Empty, char('.')),
|
||||||
|
value(InTile::Roll, char('@')),
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
newline,
|
||||||
|
),
|
||||||
|
eof,
|
||||||
|
)
|
||||||
|
.parse(input)
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
},
|
||||||
|
parts: [
|
||||||
|
|input| {
|
||||||
|
let initial_rolls = count_rolls(&input);
|
||||||
|
let final_rolls = count_rolls(&remove_accessible_rolls(&find_accessible(&input)));
|
||||||
|
(initial_rolls - final_rolls).to_string()
|
||||||
|
},
|
||||||
|
|input| {
|
||||||
|
let mut grid = input.clone();
|
||||||
|
let initial_rolls = count_rolls(&grid);
|
||||||
|
loop {
|
||||||
|
let out_grid = find_accessible(&grid);
|
||||||
|
if none_accessible(&out_grid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
grid = remove_accessible_rolls(&out_grid);
|
||||||
|
}
|
||||||
|
let final_rolls = count_rolls(&grid);
|
||||||
|
(initial_rolls - final_rolls).to_string()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
|
pub enum InTile {
|
||||||
|
Empty,
|
||||||
|
Roll,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
|
enum OutTile {
|
||||||
|
Empty,
|
||||||
|
Roll,
|
||||||
|
Accessible,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_accessible(grid: &Vec<Vec<InTile>>) -> Vec<Vec<OutTile>> {
|
||||||
|
grid.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(y, row)| {
|
||||||
|
row.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(x, t)| match t {
|
||||||
|
InTile::Empty => OutTile::Empty,
|
||||||
|
InTile::Roll => {
|
||||||
|
let mut neighbor_rolls = 0;
|
||||||
|
for dx in -1..=1 {
|
||||||
|
for dy in -1..=1 {
|
||||||
|
if dx == 0 && dy == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if grid
|
||||||
|
.get(y.wrapping_add_signed(dy))
|
||||||
|
.and_then(|r| r.get(x.wrapping_add_signed(dx)))
|
||||||
|
== Some(&InTile::Roll)
|
||||||
|
{
|
||||||
|
neighbor_rolls += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if neighbor_rolls < 4 {
|
||||||
|
OutTile::Accessible
|
||||||
|
} else {
|
||||||
|
OutTile::Roll
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_accessible_rolls(grid: &Vec<Vec<OutTile>>) -> Vec<Vec<InTile>> {
|
||||||
|
grid.iter()
|
||||||
|
.map(|r| {
|
||||||
|
r.iter()
|
||||||
|
.map(|t| {
|
||||||
|
(|tile| match tile {
|
||||||
|
OutTile::Empty => InTile::Empty,
|
||||||
|
OutTile::Roll => InTile::Roll,
|
||||||
|
OutTile::Accessible => InTile::Empty,
|
||||||
|
})(t.clone())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn none_accessible(grid: &Vec<Vec<OutTile>>) -> bool {
|
||||||
|
!grid
|
||||||
|
.iter()
|
||||||
|
.any(|row| row.iter().any(|t| *t == OutTile::Accessible))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_rolls(grid: &Vec<Vec<InTile>>) -> usize {
|
||||||
|
grid.iter()
|
||||||
|
.map(|row| row.iter().filter(|t| **t == InTile::Roll).count())
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
pub(crate) mod day1;
|
pub(crate) mod day1;
|
||||||
pub(crate) mod day2;
|
pub(crate) mod day2;
|
||||||
pub(crate) mod day3;
|
pub(crate) mod day3;
|
||||||
|
pub(crate) mod day4;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user