use cubing::{alg::Move, kpuzzle::InvalidAlgError};
use num_integer::lcm;
use crate::_internal::{
puzzle_traits::puzzle_traits::SemiGroupActionPuzzle, search::move_count::MoveCount,
};
#[derive(Clone, Debug)]
pub struct CompoundPuzzle<TPuzzle0: SemiGroupActionPuzzle, TPuzzle1: SemiGroupActionPuzzle> {
pub tpuzzle0: TPuzzle0,
pub tpuzzle1: TPuzzle1,
}
impl<TPuzzle0: SemiGroupActionPuzzle, TPuzzle1: SemiGroupActionPuzzle> SemiGroupActionPuzzle
for CompoundPuzzle<TPuzzle0, TPuzzle1>
{
type Pattern = (TPuzzle0::Pattern, TPuzzle1::Pattern);
type Transformation = (TPuzzle0::Transformation, TPuzzle1::Transformation);
fn move_order(&self, r#move: &Move) -> Result<MoveCount, cubing::kpuzzle::InvalidAlgError> {
Ok(MoveCount(lcm(
self.tpuzzle0.move_order(r#move)?.0,
self.tpuzzle1.move_order(r#move)?.0,
)))
}
fn puzzle_transformation_from_move(
&self,
r#move: &Move,
) -> Result<Self::Transformation, cubing::kpuzzle::InvalidAlgError> {
Ok((
self.tpuzzle0.puzzle_transformation_from_move(r#move)?,
self.tpuzzle1.puzzle_transformation_from_move(r#move)?,
))
}
fn do_moves_commute(&self, move1: &Move, move2: &Move) -> Result<bool, InvalidAlgError> {
Ok(self.tpuzzle0.do_moves_commute(move1, move2)?
&& self.tpuzzle1.do_moves_commute(move1, move2)?)
}
fn pattern_apply_transformation(
&self,
pattern: &Self::Pattern,
transformation_to_apply: &Self::Transformation,
) -> Option<Self::Pattern> {
let pattern0 = self
.tpuzzle0
.pattern_apply_transformation(&pattern.0, &transformation_to_apply.0)?;
let pattern1 = self
.tpuzzle1
.pattern_apply_transformation(&pattern.1, &transformation_to_apply.1)?;
Some((pattern0, pattern1))
}
fn pattern_apply_transformation_into(
&self,
pattern: &Self::Pattern,
transformation_to_apply: &Self::Transformation,
into_pattern: &mut Self::Pattern,
) -> bool {
self.tpuzzle0.pattern_apply_transformation_into(
&pattern.0,
&transformation_to_apply.0,
&mut into_pattern.0,
) && self.tpuzzle1.pattern_apply_transformation_into(
&pattern.1,
&transformation_to_apply.1,
&mut into_pattern.1,
)
}
}