use super::cube::{Face, PocketCube, Turn};
use Face::*;
use Turn::*;
struct Node {
cube: PocketCube,
depth: u8,
last_face: Option<Face>,
}
impl Node {
fn turn(&self, turn: Turn) -> Self {
Self {
cube: self.cube.turn(turn),
depth: self.depth + 1,
last_face: Some(turn.face()),
}
}
fn children(&self) -> impl IntoIterator<Item = Self> + '_ {
(self.depth < PocketCube::GODS_NUMBER)
.then(|| [Up, Right, Back])
.into_iter()
.flatten()
.filter(|face| self.last_face != Some(*face))
.flat_map(|face| [Clockwise(face), Halfway(face), CounterClockwise(face)])
.map(|turn| self.turn(turn))
}
}
impl From<PocketCube> for Node {
fn from(cube: PocketCube) -> Self {
Self {
cube,
depth: 0,
last_face: None,
}
}
}
pub struct DepthFirstSearch {
stack: Vec<Node>,
}
impl DepthFirstSearch {
pub fn new(cube: PocketCube) -> Self {
Self {
stack: vec![cube.into()],
}
}
#[allow(dead_code)]
pub fn try_split(&mut self) -> Option<Self> {
let len = self.stack.len();
if len >= 2 {
let stack = self.stack.split_off(len / 2);
Some(Self { stack })
} else {
None
}
}
}
impl Iterator for DepthFirstSearch {
type Item = PocketCube;
fn next(&mut self) -> Option<Self::Item> {
if let Some(node) = self.stack.pop() {
self.stack.extend(node.children());
Some(node.cube)
} else {
None
}
}
}