Eh... it"s not drawing the input lines... fuck this.

Fortune for day14's current commit: Small curse − 小凶
master
Avril 2 years ago
parent 6a2aefc1d9
commit 774c71d5d4
Signed by: flanchan
GPG Key ID: 284488987C31F630

9
day14/Cargo.lock generated

@ -26,6 +26,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "arrayvec"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
name = "atty"
version = "0.2.14"
@ -177,6 +183,9 @@ checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "linebuffer"
version = "0.1.1"
dependencies = [
"arrayvec",
]
[[package]]
name = "log"

@ -1,3 +1,180 @@
//! Grid of lines and sands
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
})
}
}

@ -7,6 +7,7 @@ use std::{
io,
iter,
path::Path,
fmt,
};
use color_eyre::{
@ -29,14 +30,27 @@ const _:() = {
mod grid;
/// Base coordinate
pub type Coord = u64;
/// A point is a vector
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)]
#[repr(simd)]
struct Point {
pub x: u64,
pub y: u64,
pub struct Point {
pub x: Coord,
pub y: Coord,
}
impl fmt::Display for Point
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{},{}", self.x, self.y)
}
}
impl str::FromStr for Point
{
type Err = <u64 as str::FromStr>::Err;
@ -52,14 +66,86 @@ impl str::FromStr for Point
/// A `Line` is potentially two X any Ys
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)]
struct Line {
pub struct Line {
start: Point,
end: Point,
}
impl fmt::Display for Line
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{} -> {}", self.start, self.end)
}
}
impl From<Point> for (Coord, Coord)
{
#[inline]
fn from(from: Point) -> Self
{
(from.x, from.y)
}
}
impl From<(Coord, Coord)> for Point
{
#[inline(always)]
fn from((x,y): (Coord, Coord)) -> Self
{
Self {x,y}
}
}
impl Line {
fn normalised(self) -> Self
{
let x = std::cmp::min(self.start.x, self.end.x);
let y = std::cmp::min(self.start.y, self.end.y);
let start = Point {x,y};
let x = std::cmp::max(self.start.x, self.end.x);
let y = std::cmp::max(self.start.y, self.end.y);
let end = Point {x,y};
Self {
start, end
}
}
#[inline]
fn normalise(&mut self)
{
*self = self.clone().normalised();
}
#[inline]
pub fn over_horizontal(&self) -> impl IntoIterator<Item = Point> + 'static
{
let x = self.start.x;
let y = self.start.y;
(self.start.x..=self.end.x).map(move |x| (x, y).into())
}
#[inline]
pub fn over_vertical(&self) -> impl IntoIterator<Item = Point> + 'static
{
let x = self.start.x;
(self.start.y..=self.end.y).map(move |y| (x, y).into())
}
#[inline]
pub fn unroll(&self) -> impl IntoIterator<Item = Point> + 'static
{
self.over_horizontal().into_iter()
.chain(self.over_vertical().into_iter())
}
}
/// A single parsed line into `Line`s.
#[derive(Debug, Clone, Default)]
struct Lines {
pub struct Lines {
lines: Vec<Line>,
}
@ -75,6 +161,28 @@ impl IntoIterator for Lines
}
}
impl FromIterator<Lines> for Lines
{
#[inline]
fn from_iter<I: IntoIterator<Item=Lines>>(lines: I) -> Self
{
Self {
lines: Self::flattening(lines).into_iter().collect(),
}
}
}
impl FromIterator<Line> for Lines
{
#[inline]
fn from_iter<I: IntoIterator<Item=Line>>(lines: I) -> Self
{
Self {
lines: lines.into_iter().collect()
}
}
}
impl Lines {
#[inline]
@ -84,16 +192,16 @@ impl Lines {
self
}
#[inline(always)]
pub fn flattening<'a>(lines: impl IntoIterator<Item = Self> + 'a) -> impl IntoIterator<Item = Line> + 'a
pub fn flattening<'a, T: 'a>(lines: impl IntoIterator<Item = T> + 'a) -> impl IntoIterator<Item = Line> + 'a
where T: IntoIterator<Item = Line>
{
lines.into_iter().map(|x| x.lines.into_iter()).flatten()
lines.into_iter().map(|x| x.into_iter()).flatten()
}
#[inline]
pub fn flatten(lines: impl IntoIterator<Item = Self>) -> Self
{
Self {
lines: Self::flattening(lines).into_iter().collect(),
}
lines.into_iter().collect()
}
}
@ -190,16 +298,38 @@ fn init() -> eyre::Result<()>
Ok(())
}
fn draw_grid<W: io::Write>(mut to: W, bound: Line, grid: &grid::Grid) -> io::Result<()>
{
for cells in grid.iterate_sparse(bound).chunk((bound.end.x - bound.start.x) as usize)
{
for cell in cells {
write!(&mut to, "{}", cell)?;
}
write!(&mut to, "\n")?;
}
Ok(())
}
/// Simulate the grid falling from `origin` in `grid`.
fn simulate(grid: &mut grid::Grid, origin: &Point) -> eyre::Result<()>
{
Ok(())
}
fn main() -> eyre::Result<()> {
init().wrap_err("Failed to install handlers and hooks")?;
// Input
let input = load_input_from(INPUT_FILENAME)
.wrap_err("Failed to open input file")?;
// Parsed input
let input = {
// Input file
let input = load_input_from(INPUT_FILENAME)
.wrap_err("Failed to open input file")?;
// Parse input
let input = Input::parse(input)
.wrap_err("Failed to parse input")?;
// Parse input
Input::parse(input)
.wrap_err("Failed to parse input")?
};
if cfg!(feature="status") {
debug!("Read {} zipped lines from input", input.zipped_len());
@ -207,12 +337,23 @@ fn main() -> eyre::Result<()> {
trace!("Input is:\n```{input:#?}```");
}
todo!("Deconstruction, draw, and simulation from `ORIGIN_POINT`");
//TODO: Deconstruct each `Line` into the horizontal and vertical movements
//Draw lines into grid before starting simulation of sand from `origin`.
let (mut grid, origin) = grid::sparse_grid(input.all);
//TODO: Draw lines into grid before starting simulation of sand from `ORIGIN_POINT`.
debug!("Read {} unzipped lines", grid.len());
//TODO: Simulate falling, adding and counting each stopped particle until the sand drops below the bottom of the lowest vertical line.
simulate(&mut grid, &origin)
.wrap_err("Failed to simulate grid")?;
// Draw grid
if cfg!(feature="status")
{
let bound = grid.find_bound();
debug!("Current map (bound: {}):", bound);
draw_grid(io::stderr().lock(), bound, &grid).wrap_err("Failed to draw grid to stderr")?;
}
Ok(())
}

Loading…
Cancel
Save