Fortune for day14's current commit: Small curse − 小凶master
parent
6a2aefc1d9
commit
774c71d5d4
@ -1,3 +1,180 @@
|
|||||||
//! Grid of lines and sands
|
//! Grid of lines and sands
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
borrow::Cow,
|
||||||
|
|
||||||
|
fmt,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Copy)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Cell
|
||||||
|
{
|
||||||
|
#[default]
|
||||||
|
Air = b'.',
|
||||||
|
Wall = b'#',
|
||||||
|
Settled = b'O',
|
||||||
|
Falling = b'~',
|
||||||
|
Source = b'+',
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Cell> for u8
|
||||||
|
{
|
||||||
|
#[inline(always)]
|
||||||
|
fn from(from: Cell) -> Self
|
||||||
|
{
|
||||||
|
from as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Cell
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
|
{
|
||||||
|
write!(f, "{}", u8::from(*self) as char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Grid
|
||||||
|
{
|
||||||
|
map: BTreeMap<Point, Cell>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Grid
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
pub const fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
map: BTreeMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn insert_single(&mut self, point: Point, cell: Cell) -> Option<Cell>
|
||||||
|
{
|
||||||
|
self.map.insert(point, cell)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn draw_line_with<F>(&mut self, line: Line, mut with: F)
|
||||||
|
where F: for<'a> FnMut(&'a Point) -> Cell
|
||||||
|
{
|
||||||
|
for point in line.unroll() {
|
||||||
|
let cell = with(&point);
|
||||||
|
self.map.insert(point, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn draw_line(&mut self, line: Line, cell: Cell)
|
||||||
|
{
|
||||||
|
self.draw_line_with(line, move |_| cell)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn draw_lines_with<I,F>(&mut self, line: I, mut with: F)
|
||||||
|
where F: for<'a> FnMut(&'a Point) -> Cell,
|
||||||
|
I: IntoIterator<Item = Line>
|
||||||
|
{
|
||||||
|
for point in line.into_iter().map(|x| x.normalised().unroll()).flatten() {
|
||||||
|
let cell = with(&point);
|
||||||
|
self.map.insert(point, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw these lines with this cell
|
||||||
|
#[inline]
|
||||||
|
pub fn draw_lines(&mut self, lines: impl IntoIterator<Item = Line>, cell: Cell)
|
||||||
|
{
|
||||||
|
self.draw_lines_with(lines, move |_| cell)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add the source to the grid
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn draw_source(&mut self, source: Point)
|
||||||
|
{
|
||||||
|
self.map.insert(source, Cell::Source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new sparse grid, returns the point.
|
||||||
|
///
|
||||||
|
/// A sparse grid does not draw air, only the specified `walls`.
|
||||||
|
#[inline]
|
||||||
|
pub fn sparse_grid(walls: Lines) -> (grid::Grid, Point)
|
||||||
|
{
|
||||||
|
let mut grid = grid::Grid::new();
|
||||||
|
// Add source
|
||||||
|
grid.draw_source(ORIGIN_POINT);
|
||||||
|
|
||||||
|
// Draw walls
|
||||||
|
grid.draw_lines(walls, Cell::Wall);
|
||||||
|
|
||||||
|
(grid, ORIGIN_POINT)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-drawing grid functions
|
||||||
|
impl Grid
|
||||||
|
{
|
||||||
|
/// Number of points in the grid
|
||||||
|
#[inline]
|
||||||
|
pub fn len(&self) -> usize
|
||||||
|
{
|
||||||
|
self.map.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the highest point in the collection
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn find_high_bound(&self) -> Point
|
||||||
|
{
|
||||||
|
let x = self.map.keys().max_by(|a, b| u64::cmp(&a.x, &b.x)).map(|x| x.x).unwrap_or(0);
|
||||||
|
let y = self.map.keys().max_by(|a, b| u64::cmp(&a.y, &b.y)).map(|y| y.y).unwrap_or(0);
|
||||||
|
Point{ x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the lowest point in the collection
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn find_low_bound(&self) -> Point
|
||||||
|
{
|
||||||
|
let x = self.map.keys().min_by(|a, b| u64::cmp(&a.x, &b.x)).map(|x| x.x).unwrap_or(0);
|
||||||
|
let y = self.map.keys().min_by(|a, b| u64::cmp(&a.y, &b.y)).map(|y| y.y).unwrap_or(0);
|
||||||
|
Point{ x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the low and high bound as a flattened line
|
||||||
|
#[inline]
|
||||||
|
pub fn find_bound(&self) -> Line
|
||||||
|
{
|
||||||
|
let start = self.find_low_bound();
|
||||||
|
let end = self.find_high_bound();
|
||||||
|
Line{ start, end }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over a sparse grid, bounded by `bound`, any not set cells will be drawn with air.
|
||||||
|
#[inline]
|
||||||
|
pub fn iterate_sparse<'g>(&'g self, bound: Line) -> impl Iterator<Item = &'g Cell> + 'g
|
||||||
|
{
|
||||||
|
const AIR: Cell = Cell::Air;
|
||||||
|
//let mut grid = start.map.iter().fuse().peekable();
|
||||||
|
bound.normalised().unroll().into_iter()
|
||||||
|
.map(move |point| {
|
||||||
|
if let Some(cell) = self.map.get(&point) {
|
||||||
|
// Contains the point, return that reference
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if let Some(&(next_wall, cell)) = grid.peek() {
|
||||||
|
if next_wall == &point {
|
||||||
|
// Take this point off the iterator if it matches
|
||||||
|
return grid.next().unwrap().1;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
&AIR
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in new issue