Move the Grid type to the common library
This commit is contained in:
parent
92a66b3d5f
commit
05994ef2be
2 changed files with 117 additions and 88 deletions
123
src/bin/day4.rs
123
src/bin/day4.rs
|
|
@ -1,77 +1,27 @@
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use aoc_2025::{load, print_res};
|
use aoc_2025::{Grid, load, print_res};
|
||||||
use bstr::{BString, ByteSlice};
|
use bstr::{BString, ByteSlice};
|
||||||
use color_eyre::eyre::ContextCompat;
|
use color_eyre::eyre::ContextCompat;
|
||||||
|
|
||||||
type Parsed = Grid;
|
type Parsed = Grid<RollSlot>;
|
||||||
|
|
||||||
pub struct Grid {
|
#[derive(PartialEq, Eq)]
|
||||||
values: Vec<bool>,
|
pub enum RollSlot {
|
||||||
line_len: usize,
|
Roll,
|
||||||
col_len: usize,
|
Space,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Grid {
|
impl std::fmt::Display for RollSlot {
|
||||||
fn get(&self, line: isize, col: isize) -> Option<bool> {
|
|
||||||
if line < 0 || col < 0 || line as usize >= self.line_len || col as usize >= self.col_len {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self[(line as usize, col as usize)])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn neighbours(&self, line: usize, col: usize) -> usize {
|
|
||||||
let mut sum = 0;
|
|
||||||
for l in -1..=1 {
|
|
||||||
for c in -1..=1 {
|
|
||||||
if l == 0 && c == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self
|
|
||||||
.get(line as isize + l, col as isize + c)
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
sum += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Index<(usize, usize)> for Grid {
|
|
||||||
type Output = bool;
|
|
||||||
|
|
||||||
fn index(&self, (line, col): (usize, usize)) -> &Self::Output {
|
|
||||||
&self.values[line * self.line_len + col]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::IndexMut<(usize, usize)> for Grid {
|
|
||||||
fn index_mut(&mut self, (line, col): (usize, usize)) -> &mut Self::Output {
|
|
||||||
&mut self.values[line * self.line_len + col]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Grid {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
for line in self.values.chunks_exact(self.line_len) {
|
write!(
|
||||||
line.iter().try_for_each(|v| {
|
f,
|
||||||
write!(
|
"{}",
|
||||||
f,
|
match self {
|
||||||
"{}",
|
RollSlot::Roll => '@',
|
||||||
match v {
|
RollSlot::Space => '.',
|
||||||
true => '@',
|
}
|
||||||
false => '.',
|
)
|
||||||
}
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
writeln!(f)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,30 +31,27 @@ pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
|
||||||
let values: Vec<_> = input
|
let values: Vec<_> = input
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&&v| v != b'\n')
|
.filter(|&&v| v != b'\n')
|
||||||
.map(|&v| v == b'@')
|
.map(|&v| {
|
||||||
|
if v == b'@' {
|
||||||
|
RollSlot::Roll
|
||||||
|
} else {
|
||||||
|
RollSlot::Space
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
assert_eq!(
|
Ok(Grid::new(values, line_len))
|
||||||
values.len() % line_len,
|
|
||||||
0,
|
|
||||||
"Line length does not divide the grid size"
|
|
||||||
);
|
|
||||||
Ok(Grid {
|
|
||||||
line_len,
|
|
||||||
col_len: values.len() / line_len,
|
|
||||||
values,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn part1(input: Parsed) {
|
pub fn part1(input: Parsed) {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
for line in 0..input.line_len {
|
for (line, col) in input.coords() {
|
||||||
for col in 0..input.line_len {
|
if input[(line, col)] == RollSlot::Roll
|
||||||
if input[(line, col)] && input.neighbours(line, col) < 4 {
|
&& input.neighbour_count_like(line, col, &RollSlot::Roll) < 4
|
||||||
count += 1;
|
{
|
||||||
}
|
count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,13 +64,13 @@ pub fn part2(mut input: Parsed) {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for line in 0..input.line_len {
|
for (line, col) in input.coords() {
|
||||||
for col in 0..input.line_len {
|
if input[(line, col)] == RollSlot::Roll
|
||||||
if input[(line, col)] && input.neighbours(line, col) < 4 {
|
&& input.neighbour_count_like(line, col, &RollSlot::Roll) < 4
|
||||||
input[(line, col)] = false;
|
{
|
||||||
found = true;
|
input[(line, col)] = RollSlot::Space;
|
||||||
count += 1;
|
found = true;
|
||||||
}
|
count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
82
src/lib.rs
82
src/lib.rs
|
|
@ -6,6 +6,88 @@ use clap::Parser;
|
||||||
|
|
||||||
pub mod tinyvec;
|
pub mod tinyvec;
|
||||||
|
|
||||||
|
pub struct Grid<T> {
|
||||||
|
values: Vec<T>,
|
||||||
|
line_len: usize,
|
||||||
|
col_len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Grid<T> {
|
||||||
|
pub fn get(&self, line: isize, col: isize) -> Option<&T> {
|
||||||
|
if line < 0 || col < 0 || line as usize >= self.line_len || col as usize >= self.col_len {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&self[(line as usize, col as usize)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(values: Vec<T>, line_len: usize) -> Self {
|
||||||
|
assert_eq!(
|
||||||
|
values.len() % line_len,
|
||||||
|
0,
|
||||||
|
"Line length does not divide the grid size"
|
||||||
|
);
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
line_len,
|
||||||
|
col_len: values.len() / line_len,
|
||||||
|
values,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn coords(&self) -> impl Iterator<Item = (usize, usize)> + use<T> {
|
||||||
|
let line_len = self.line_len;
|
||||||
|
let col_len = self.col_len;
|
||||||
|
|
||||||
|
(0..line_len).flat_map(move |l| (0..col_len).map(move |c| (l, c)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PartialEq + Eq> Grid<T> {
|
||||||
|
pub fn neighbour_count_like(&self, line: usize, col: usize, like: &T) -> usize {
|
||||||
|
let mut sum = 0;
|
||||||
|
for l in -1..=1 {
|
||||||
|
for c in -1..=1 {
|
||||||
|
if l == 0 && c == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(v) = self.get(line as isize + l, col as isize + c)
|
||||||
|
&& v == like
|
||||||
|
{
|
||||||
|
sum += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Index<(usize, usize)> for Grid<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, (line, col): (usize, usize)) -> &Self::Output {
|
||||||
|
&self.values[line * self.line_len + col]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::IndexMut<(usize, usize)> for Grid<T> {
|
||||||
|
fn index_mut(&mut self, (line, col): (usize, usize)) -> &mut Self::Output {
|
||||||
|
&mut self.values[line * self.line_len + col]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::fmt::Display> std::fmt::Display for Grid<T> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
for line in self.values.chunks_exact(self.line_len) {
|
||||||
|
line.iter().try_for_each(|v| write!(f, "{v}"))?;
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn neighbours<L, C, T>(l: usize, c: usize, map: L) -> ArrayVec<(usize, usize), 4>
|
pub fn neighbours<L, C, T>(l: usize, c: usize, map: L) -> ArrayVec<(usize, usize), 4>
|
||||||
where
|
where
|
||||||
L: AsRef<[C]>,
|
L: AsRef<[C]>,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue