Compare commits
No commits in common. "a330505361416dc23a793633670c496c8a01eb27" and "6fb08930bce2d25ed979a7110659983c78da523b" have entirely different histories.
a330505361
...
6fb08930bc
9 changed files with 0 additions and 3465 deletions
|
@ -1,2 +0,0 @@
|
||||||
4364
|
|
||||||
2508
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,11 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "rust_2022_18"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
aoc = { path = "../../../common/rust" }
|
|
||||||
petgraph = "0.6.2"
|
|
||||||
strum = "0.24.1"
|
|
|
@ -1,155 +0,0 @@
|
||||||
#![warn(clippy::pedantic)]
|
|
||||||
#![feature(generators)]
|
|
||||||
#![feature(iter_from_generator)]
|
|
||||||
#![feature(let_chains)]
|
|
||||||
|
|
||||||
use petgraph::{algo::tarjan_scc, prelude::GraphMap, Undirected};
|
|
||||||
use std::{io::stdin, iter};
|
|
||||||
use strum::IntoEnumIterator;
|
|
||||||
|
|
||||||
use aoc::vecn::{Direction3, VecN};
|
|
||||||
|
|
||||||
type Position = VecN<3, u64>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
struct Face {
|
|
||||||
position: Position,
|
|
||||||
side: Direction3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Face {
|
|
||||||
fn facing(self) -> Option<Position> {
|
|
||||||
let pos = self.position.try_map(i64::try_from).ok()? + self.side.into();
|
|
||||||
|
|
||||||
pos.try_map(u64::try_from).ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inverse(self) -> Option<Face> {
|
|
||||||
Some(Face {
|
|
||||||
position: self.facing()?,
|
|
||||||
side: -self.side,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn neighbours(self) -> impl Iterator<Item = (Angle, Face)> {
|
|
||||||
iter::from_generator(move || {
|
|
||||||
let orthogonal_sides =
|
|
||||||
Direction3::iter().filter(move |&side| side != self.side && side != -self.side);
|
|
||||||
|
|
||||||
for side in orthogonal_sides.clone() {
|
|
||||||
yield (
|
|
||||||
Angle::Convex,
|
|
||||||
Face {
|
|
||||||
position: self.position,
|
|
||||||
side,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(facing) = self.facing() {
|
|
||||||
for side in orthogonal_sides.clone() {
|
|
||||||
if let Some(inverse) = (Face {
|
|
||||||
position: facing,
|
|
||||||
side,
|
|
||||||
})
|
|
||||||
.inverse()
|
|
||||||
{
|
|
||||||
yield (Angle::Concave, inverse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for side in orthogonal_sides {
|
|
||||||
if let Some(facing) = (Face {
|
|
||||||
position: self.position,
|
|
||||||
side,
|
|
||||||
})
|
|
||||||
.facing()
|
|
||||||
{
|
|
||||||
yield (
|
|
||||||
Angle::Flat,
|
|
||||||
Face {
|
|
||||||
position: facing,
|
|
||||||
side: self.side,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
enum Angle {
|
|
||||||
Concave,
|
|
||||||
Convex,
|
|
||||||
Flat,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let cubes = stdin().lines().map(|l| l.unwrap().parse().unwrap());
|
|
||||||
let faces =
|
|
||||||
cubes.flat_map(|position| Direction3::iter().map(move |side| Face { position, side }));
|
|
||||||
|
|
||||||
let mut graph = GraphMap::<Face, Angle, Undirected>::new();
|
|
||||||
for face in faces {
|
|
||||||
if let Some(inverse) = face.inverse() {
|
|
||||||
if graph.remove_node(inverse) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.add_node(face);
|
|
||||||
|
|
||||||
for (angle, neighbour_face) in face.neighbours() {
|
|
||||||
if graph.contains_node(neighbour_face) {
|
|
||||||
graph.add_edge(face, neighbour_face, angle);
|
|
||||||
|
|
||||||
if let Angle::Concave = angle {
|
|
||||||
graph.remove_edge(
|
|
||||||
face,
|
|
||||||
Face {
|
|
||||||
position: face.position,
|
|
||||||
side: -neighbour_face.side,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
graph.remove_edge(
|
|
||||||
neighbour_face,
|
|
||||||
Face {
|
|
||||||
position: neighbour_face.position,
|
|
||||||
side: -face.side,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{:?}", graph.node_count());
|
|
||||||
|
|
||||||
let sum_outside = tarjan_scc(&graph)
|
|
||||||
.into_iter()
|
|
||||||
.filter(|surface| {
|
|
||||||
graph
|
|
||||||
.all_edges()
|
|
||||||
.filter_map(|(start, end, angle)| {
|
|
||||||
if surface.contains(&start) || surface.contains(&end) {
|
|
||||||
Some(angle)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|angle| match angle {
|
|
||||||
Angle::Concave => -1,
|
|
||||||
Angle::Convex => 1,
|
|
||||||
Angle::Flat => 0,
|
|
||||||
})
|
|
||||||
.sum::<i64>()
|
|
||||||
> 0
|
|
||||||
})
|
|
||||||
.map(|surface| surface.len())
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
println!("{:?}", sum_outside);
|
|
||||||
}
|
|
65
Cargo.lock
generated
65
Cargo.lock
generated
|
@ -16,8 +16,6 @@ name = "aoc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"strum",
|
|
||||||
"thiserror",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -215,12 +213,6 @@ version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
|
@ -619,21 +611,6 @@ dependencies = [
|
||||||
"aoc",
|
"aoc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust_2022_18"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"aoc",
|
|
||||||
"petgraph",
|
|
||||||
"strum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustversion"
|
|
||||||
version = "1.0.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -693,28 +670,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum"
|
|
||||||
version = "0.24.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
|
||||||
dependencies = [
|
|
||||||
"strum_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum_macros"
|
|
||||||
version = "0.24.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
|
||||||
dependencies = [
|
|
||||||
"heck",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rustversion",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.105"
|
version = "1.0.105"
|
||||||
|
@ -735,26 +690,6 @@ dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "1.0.38"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "1.0.38"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinytemplate"
|
name = "tinytemplate"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
|
|
@ -25,5 +25,4 @@ members = [
|
||||||
"2022/day13/rust",
|
"2022/day13/rust",
|
||||||
"2022/day14/rust",
|
"2022/day14/rust",
|
||||||
"2022/day15/rust",
|
"2022/day15/rust",
|
||||||
"2022/day18/rust",
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,5 +7,3 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = "0.2.15"
|
num-traits = "0.2.15"
|
||||||
strum = { version = "0.24.1", features = ["derive"] }
|
|
||||||
thiserror = "1.0.38"
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
mod section_range;
|
mod section_range;
|
||||||
pub mod vec2;
|
pub mod vec2;
|
||||||
pub mod vecn;
|
|
||||||
|
|
||||||
use std::{mem, path::Path};
|
use std::{mem, path::Path};
|
||||||
|
|
||||||
|
|
|
@ -1,365 +0,0 @@
|
||||||
use std::{
|
|
||||||
array,
|
|
||||||
iter::Sum,
|
|
||||||
ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use num_traits::{one, zero, One, Zero};
|
|
||||||
use strum::EnumIter;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
pub trait Abs {
|
|
||||||
type Output;
|
|
||||||
fn abs(self) -> Self::Output;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_abs_signed {
|
|
||||||
($($t:ty)*) => {
|
|
||||||
$(impl Abs for $t {
|
|
||||||
type Output = $t;
|
|
||||||
fn abs(self) -> Self {
|
|
||||||
self.abs()
|
|
||||||
}
|
|
||||||
})*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
impl_abs_signed!(i8 i16 i32 i64 i128 f32 f64);
|
|
||||||
|
|
||||||
macro_rules! impl_abs_noop {
|
|
||||||
($($t:ty)*) => {
|
|
||||||
$(impl Abs for $t {
|
|
||||||
type Output = $t;
|
|
||||||
fn abs(self) -> Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
})*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
impl_abs_noop!(u8 u16 u32 u64 u128);
|
|
||||||
|
|
||||||
/// A vector in `N`-space.
|
|
||||||
///
|
|
||||||
/// The coordinate system is canonically left-handed:
|
|
||||||
///
|
|
||||||
/// Axis | + | -
|
|
||||||
/// -----|---------|------
|
|
||||||
/// x | right | left
|
|
||||||
/// y | up | down
|
|
||||||
/// z | forward | back
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct VecN<const N: usize, T> {
|
|
||||||
coords: [T; N],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> VecN<2, T> {
|
|
||||||
#[must_use]
|
|
||||||
pub const fn new(x: T, y: T) -> Self {
|
|
||||||
Self { coords: [x, y] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> VecN<3, T> {
|
|
||||||
#[must_use]
|
|
||||||
pub const fn new(x: T, y: T, z: T) -> Self {
|
|
||||||
Self { coords: [x, y, z] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> VecN<N, T> {
|
|
||||||
#[must_use]
|
|
||||||
pub fn map<U>(self, f: impl FnMut(T) -> U) -> VecN<N, U> {
|
|
||||||
VecN {
|
|
||||||
coords: self.coords.map(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_map<U, E>(self, mut f: impl FnMut(T) -> Result<U, E>) -> Result<VecN<N, U>, E>
|
|
||||||
where
|
|
||||||
[U; N]: Default,
|
|
||||||
{
|
|
||||||
let mut coords: [U; N] = Default::default();
|
|
||||||
for (coord, x) in coords.iter_mut().zip(self.coords) {
|
|
||||||
*coord = f(x)?;
|
|
||||||
}
|
|
||||||
Ok(VecN { coords })
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn len(self) -> f64
|
|
||||||
where
|
|
||||||
T: Into<f64>,
|
|
||||||
{
|
|
||||||
self.coords
|
|
||||||
.into_iter()
|
|
||||||
.map(|l| l.into().powi(2))
|
|
||||||
.sum::<f64>()
|
|
||||||
.sqrt()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn manhattan_len<U>(self) -> U
|
|
||||||
where
|
|
||||||
T: Abs<Output = U>,
|
|
||||||
U: Sum,
|
|
||||||
{
|
|
||||||
self.coords.into_iter().map(Abs::abs).sum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> Add for VecN<N, T>
|
|
||||||
where
|
|
||||||
T: Add<Output = T>,
|
|
||||||
{
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
|
||||||
let mut coords = self.coords.into_iter().zip(rhs.coords).map(|(l, r)| l + r);
|
|
||||||
Self {
|
|
||||||
coords: array::from_fn(|_| coords.next().unwrap()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> AddAssign for VecN<N, T>
|
|
||||||
where
|
|
||||||
T: AddAssign,
|
|
||||||
{
|
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
|
||||||
for (l, r) in self.coords.iter_mut().zip(rhs.coords) {
|
|
||||||
*l += r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> Sub for VecN<N, T>
|
|
||||||
where
|
|
||||||
T: Sub<Output = T>,
|
|
||||||
{
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn sub(self, rhs: Self) -> Self::Output {
|
|
||||||
let mut coords = self.coords.into_iter().zip(rhs.coords).map(|(l, r)| l - r);
|
|
||||||
Self {
|
|
||||||
coords: array::from_fn(|_| coords.next().unwrap()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> SubAssign for VecN<N, T>
|
|
||||||
where
|
|
||||||
T: SubAssign,
|
|
||||||
{
|
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
|
||||||
for (l, r) in self.coords.iter_mut().zip(rhs.coords) {
|
|
||||||
*l -= r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T, U> Mul<U> for VecN<N, T>
|
|
||||||
where
|
|
||||||
T: Mul<U, Output = T>,
|
|
||||||
U: Copy,
|
|
||||||
{
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn mul(self, n: U) -> Self::Output {
|
|
||||||
Self {
|
|
||||||
coords: self.coords.map(|c| c * n),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
impl<const N: usize, T> Mul<VecN<N, T>> for T
|
|
||||||
where
|
|
||||||
T: Mul<Output = T>,
|
|
||||||
{
|
|
||||||
type Output = VecN<N, T>;
|
|
||||||
|
|
||||||
fn mul(self, vec: VecN<N, T>) -> Self::Output {
|
|
||||||
VecN {
|
|
||||||
coords: vec.coords.map(|c| c * self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
impl<const N: usize, T> From<[T; N]> for VecN<N, T> {
|
|
||||||
fn from(coords: [T; N]) -> Self {
|
|
||||||
Self { coords }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> From<VecN<N, T>> for [T; N] {
|
|
||||||
fn from(v: VecN<N, T>) -> Self {
|
|
||||||
v.coords
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<Direction2> for VecN<2, T>
|
|
||||||
where
|
|
||||||
T: Zero + One + Neg<Output = T>,
|
|
||||||
{
|
|
||||||
/// Creates a unit vector in the given direction.
|
|
||||||
fn from(dir: Direction2) -> Self {
|
|
||||||
let z = zero();
|
|
||||||
let o = one();
|
|
||||||
|
|
||||||
match dir {
|
|
||||||
Direction2::Right => Self::new(o, z),
|
|
||||||
Direction2::Left => Self::new(-o, z),
|
|
||||||
Direction2::Up => Self::new(z, o),
|
|
||||||
Direction2::Down => Self::new(z, -o),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<Direction3> for VecN<3, T>
|
|
||||||
where
|
|
||||||
T: Zero + One + Neg<Output = T> + Copy,
|
|
||||||
{
|
|
||||||
/// Creates a unit vector in the given direction.
|
|
||||||
fn from(dir: Direction3) -> Self {
|
|
||||||
let z = zero();
|
|
||||||
let o = one();
|
|
||||||
|
|
||||||
match dir {
|
|
||||||
Direction3::Right => Self::new(o, z, z),
|
|
||||||
Direction3::Left => Self::new(-o, z, z),
|
|
||||||
Direction3::Up => Self::new(z, o, z),
|
|
||||||
Direction3::Down => Self::new(z, -o, z),
|
|
||||||
Direction3::Forward => Self::new(z, z, o),
|
|
||||||
Direction3::Back => Self::new(z, z, -o),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
|
|
||||||
pub enum ParseVecError<E> {
|
|
||||||
#[error("failed to parse axis {axis}")]
|
|
||||||
AxisParseError {
|
|
||||||
axis: usize,
|
|
||||||
#[source]
|
|
||||||
source: E,
|
|
||||||
},
|
|
||||||
#[error("not enough dimensions specified, expected {expected}")]
|
|
||||||
NotEnoughDimensions { expected: usize },
|
|
||||||
#[error("too many dimensions specified, expected {expected}")]
|
|
||||||
TooManyDimensions { expected: usize },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const N: usize, T> FromStr for VecN<N, T>
|
|
||||||
where
|
|
||||||
[T; N]: Default,
|
|
||||||
T: FromStr,
|
|
||||||
{
|
|
||||||
type Err = ParseVecError<T::Err>;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mut parts = s.split(',');
|
|
||||||
|
|
||||||
let mut coords: [T; N] = Default::default();
|
|
||||||
for (i, axis) in coords.iter_mut().enumerate() {
|
|
||||||
*axis = parts
|
|
||||||
.next()
|
|
||||||
.ok_or(ParseVecError::NotEnoughDimensions { expected: N })?
|
|
||||||
.parse()
|
|
||||||
.map_err(|e| ParseVecError::AxisParseError { axis: i, source: e })?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if parts.next().is_some() {
|
|
||||||
return Err(ParseVecError::TooManyDimensions { expected: N });
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { coords })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter)]
|
|
||||||
pub enum Direction2 {
|
|
||||||
Right,
|
|
||||||
Left,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Neg for Direction2 {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn neg(self) -> Self::Output {
|
|
||||||
match self {
|
|
||||||
Direction2::Right => Direction2::Left,
|
|
||||||
Direction2::Left => Direction2::Right,
|
|
||||||
Direction2::Up => Direction2::Down,
|
|
||||||
Direction2::Down => Direction2::Up,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Direction2 {
|
|
||||||
type Err = ();
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s {
|
|
||||||
"R" => Ok(Direction2::Right),
|
|
||||||
"L" => Ok(Direction2::Left),
|
|
||||||
"U" => Ok(Direction2::Up),
|
|
||||||
"D" => Ok(Direction2::Down),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter)]
|
|
||||||
pub enum Direction3 {
|
|
||||||
Right = 0,
|
|
||||||
Left = 1,
|
|
||||||
Up = 2,
|
|
||||||
Down = 4,
|
|
||||||
Forward = 5,
|
|
||||||
Back = 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Direction2> for Direction3 {
|
|
||||||
fn from(dir: Direction2) -> Self {
|
|
||||||
match dir {
|
|
||||||
Direction2::Right => Direction3::Right,
|
|
||||||
Direction2::Left => Direction3::Left,
|
|
||||||
Direction2::Up => Direction3::Up,
|
|
||||||
Direction2::Down => Direction3::Down,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Neg for Direction3 {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn neg(self) -> Self::Output {
|
|
||||||
match self {
|
|
||||||
Direction3::Right => Direction3::Left,
|
|
||||||
Direction3::Left => Direction3::Right,
|
|
||||||
Direction3::Up => Direction3::Down,
|
|
||||||
Direction3::Down => Direction3::Up,
|
|
||||||
Direction3::Forward => Direction3::Back,
|
|
||||||
Direction3::Back => Direction3::Forward,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Direction3 {
|
|
||||||
type Err = ();
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s {
|
|
||||||
"R" => Ok(Direction3::Right),
|
|
||||||
"L" => Ok(Direction3::Left),
|
|
||||||
"U" => Ok(Direction3::Up),
|
|
||||||
"D" => Ok(Direction3::Down),
|
|
||||||
"F" => Ok(Direction3::Forward),
|
|
||||||
"B" => Ok(Direction3::Back),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue