day14: Started mod grid: A grid for drawing lines and writing in completed simulated sands

Added more extensions for tuples and iterators. (TODO: Extract these into a library like `linebuffer`)

Fortune for day14's current commit: Blessing − 吉
master
Avril 1 year ago
parent 2eb60791bf
commit bfccf7a426
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -0,0 +1,207 @@
//! Extensions
use std::iter::{
self,
FusedIterator,
};
/// An iterator adaptor for taking two items off an iterator
#[derive(Debug, Clone)]
pub struct TakeTwo<I: ?Sized>(I);
impl<I: ?Sized, T> Iterator for TakeTwo<I>
where I: Iterator<Item=T>
{
type Item = (T, Option<T>);
#[inline]
fn next(&mut self) -> Option<Self::Item>
{
let first = self.0.next()?;
Some((first, self.0.next()))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.0.size_hint();
(low / 2, high.map(|x| x/2))
}
}
impl<I: ?Sized + ExactSizeIterator> ExactSizeIterator for TakeTwo<I>{}
impl<I: ?Sized + FusedIterator> FusedIterator for TakeTwo<I> {}
pub trait TakeTwoExt: Sized {
/// Create an adaptor from `T` to `(T, Option<T>)`, taking the next available value if one exists in the iterator
fn take_two(self) -> TakeTwo<Self>;
}
pub trait TakeTwoBoxedExt {
/// Create an adaptor from `T` to `(T, Option<T>)`, taking the next available value if one exists in the iterator
fn take_two(self: Box<Self>) -> TakeTwo<Box<Self>>;
}
impl<I: Iterator> TakeTwoExt for I
{
#[inline(always)]
fn take_two(self) -> TakeTwo<Self> {
TakeTwo(self)
}
}
impl<I: ?Sized + Iterator> TakeTwoBoxedExt for I
{
#[inline(always)]
fn take_two(self: Box<Self>) -> TakeTwo<Box<Self>> {
TakeTwo(self)
}
}
pub trait Tuple2OptExt<T, U>: Sized
{
/// The unwrapped type for the option in the tuple
type OptionType;
/// Unwrap a tuple containing an option into an option containing the full tuple if the `Option` value in the tuple is `Some`
fn unwrap_two(self) -> Option<(T, U)>;
/// Unwrap the option value or get the value from `f`
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
where F: FnOnce() -> Self::OptionType;
}
impl<T, U> Tuple2OptExt<T, U> for (T, Option<U>)
{
type OptionType = U;
#[inline]
fn unwrap_two(self) -> Option<(T, U)> {
self.1.map(move |u| (self.0, u))
}
#[inline]
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
where F: FnOnce() -> Self::OptionType {
match self.1 {
Some(u) => (self.0, u),
None => (self.0, f()),
}
}
}
impl<T, U> Tuple2OptExt<T, U> for (Option<T>, U)
{
type OptionType = T;
#[inline]
fn unwrap_two(self) -> Option<(T, U)> {
self.0.map(move |u| (u, self.1))
}
#[inline]
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
where F: FnOnce() -> Self::OptionType {
match self.0 {
Some(u) => (u, self.1),
None => (f(), self.1),
}
}
}
impl<T, U> Tuple2OptExt<T, U> for (Option<T>, Option<U>)
{
type OptionType = (T, U);
#[inline]
fn unwrap_two(self) -> Option<(T, U)> {
self.0.and_then(move |u| self.1.map(move |v| (u, v)))
}
#[inline]
fn unwrap_two_or_else<F>(self, f: F) -> (T, U)
where F: FnOnce() -> Self::OptionType {
match self {
//XXX: This is not ideal...
(Some(u), Some(v)) => (u, v),
(Some(u), None) => (u, f().1),
(None, Some(v)) => (f().0, v),
_ => f()
}
}
}
pub trait Tuple2Ext<T,U>: Sized
{
/// Swap the elements in a 2-tuple
fn swap(self) -> (U, T);
/// Reduce the tuple elements into `V`
fn reduce<V>(self, into: V) -> V
where V: Extend<T> + Extend<U>;
/// Collect the tuple elements into `O`
fn collect<V, O>(self) -> O
where V: From<T> + From<U> + FromIterator<V>,
O: FromIterator<V>;
/// Consume into `V`
fn consume<V>(self) -> V
where V: FromIterator<T> + Extend<U>;
/// Consume both elements into a new single type.
fn into<V>(self) -> (V, V)
where V: From<T> + From<U>;
}
pub trait Tuple2STExt<T>: Sized
{
/// Consume into an array of two elements.
fn into_array(self) -> [T; 2];
/// Consume into an iterator of both elements
fn into_iter(self) -> <[T; 2] as IntoIterator>::IntoIter;
}
impl<T, U> Tuple2Ext<T, U> for (T, U)
{
#[inline]
fn swap(self) -> (U, T) {
(self.1, self.0)
}
#[inline]
fn reduce<V>(self, mut into: V) -> V
where V: Extend<T> + Extend<U> {
into.extend(iter::once(self.0));
into.extend(iter::once(self.1));
into
}
#[inline]
fn collect<V, O>(self) -> O
where V: From<T> + From<U>,
O: FromIterator<V> {
[self.0.into(), self.1.into()].into_iter().collect()
}
#[inline]
fn consume<V>(self) -> V
where V: FromIterator<T> + Extend<U> {
let mut o: V = iter::once(self.0).collect();
o.extend(iter::once(self.1));
o
}
#[inline]
fn into<V>(self) -> (V, V)
where V: From<T> + From<U> {
(self.0.into(), self.1.into())
}
}
impl<T> Tuple2STExt<T> for (T, T)
{
#[inline]
fn into_array(self) -> [T; 2] {
[self.0, self.1]
}
#[inline]
fn into_iter(self) -> <[T; 2] as IntoIterator>::IntoIter {
self.into_array().into_iter()
}
}

@ -0,0 +1,3 @@
//! Grid of lines and sands
use super::*;

@ -31,62 +31,17 @@ const _:() = {
static GLOBAL: Jemalloc = Jemalloc;
};
mod ext {
use super::iter::FusedIterator;
#[derive(Debug, Clone)]
pub struct TakeTwo<I: ?Sized>(I);
impl<I: ?Sized, T> Iterator for TakeTwo<I>
where I: Iterator<Item=T>
{
type Item = (T, Option<T>);
#[inline]
fn next(&mut self) -> Option<Self::Item>
{
let first = self.0.next()?;
Some((first, self.0.next()))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.0.size_hint();
(low / 2, high.map(|x| x/2))
}
}
impl<I: ?Sized + ExactSizeIterator> ExactSizeIterator for TakeTwo<I>{}
impl<I: ?Sized + FusedIterator> FusedIterator for TakeTwo<I> {}
pub trait TakeTwoExt: Sized {
fn take_two(self) -> TakeTwo<Self>;
}
pub trait TakeTwoBoxedExt {
fn take_two(self: Box<Self>) -> TakeTwo<Box<Self>>;
}
impl<I: Iterator> TakeTwoExt for I
{
#[inline(always)]
fn take_two(self) -> TakeTwo<Self> {
TakeTwo(self)
}
}
impl<I: ?Sized + Iterator> TakeTwoBoxedExt for I
{
#[inline(always)]
fn take_two(self: Box<Self>) -> TakeTwo<Box<Self>> {
TakeTwo(self)
}
}
}
mod ext;
use ext::{
TakeTwoExt as _,
TakeTwoBoxedExt as _,
Tuple2Ext as _,
Tuple2OptExt as _,
Tuple2STExt as _,
};
mod grid;
/// A point is a vector
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)]
#[repr(simd)]

Loading…
Cancel
Save