{-# LANGUAGE RecordWildCards, ScopedTypeVariables, ViewPatterns #-} module Rubik.Tables.Moves where import Rubik.Cube import Rubik.Misc import Rubik.Solver import Rubik.Symmetry import Rubik.Tables.Internal import Data.Bifunctor import Data.Bits import Data.Maybe import Data.Monoid import qualified Data.Vector as V import qualified Data.Vector.Unboxed as U import qualified Data.Vector.Storable.Allocated as S type Moves m a = MoveTag m [RawMove a] move18CornerOrien = savedRawMoveTables "move18CornerOrien" move18 :: Moves Move18 CornerOrien move18CornerPermu = savedRawMoveTables "move18CornerPermu" move18 :: Moves Move18 CornerPermu move18EdgeOrien = savedRawMoveTables "move18EdgeOrien" move18 :: Moves Move18 EdgeOrien move18UDSlicePermu = savedRawMoveTables "move18UDSlicePermu" move18 :: Moves Move18 UDSlicePermu move18UDSlice = savedRawMoveTables "move18UDSlice" move18 :: Moves Move18 UDSlice move10CornerPermu = move18to10 move18CornerPermu :: Moves Move10 CornerPermu move10UDSlicePermu2 = savedRawMoveTables "move10UDSlicePermu2" move10 :: Moves Move10 UDSlicePermu2 move10UDEdgePermu2 = savedRawMoveTables "move10UDEdgePermu2" move10 :: Moves Move10 UDEdgePermu2 --move18SymFlipUDSlicePermu -- = (savedSymMoveTables -- "move10symFlipUDSlicePermu" -- move18 -- rawFlipUDSlicePermu -- actionFlipUDSlicePermu -- symReprFlipUDSlicePermu -- conjugateFlipUDSlicePermu) sym16CornerOrien = savedRawSymTables "sym16CornerOrien" conjugateCornerOrien sym16 :: Symmetries UDFix CornerOrien invertedSym16CornerOrien = MoveTag $ V.fromList [ unMoveTag sym16CornerOrien V.! j | i <- [0 .. 15], let SymCode j = invertSym (SymCode i) ] :: Symmetries UDFix CornerOrien sym16CornerPermu = savedRawSymTables "sym16CornerPermu" (conjugate . fromCube) sym16 :: Symmetries UDFix CornerPermu invertedSym16CornerPermu = MoveTag $ V.fromList [ unMoveTag sym16CornerPermu V.! j | i <- [0 .. 15], let SymCode j = invertSym (SymCode i) ] :: Symmetries UDFix CornerPermu {-# INLINE symProjCornerPermu #-} symProjCornerPermu = symProjection (rawToSymCornerPermu . encode) :: SymProjection Move18 UDFix CornerPermu move18SymCornerPermu :: MoveTag Move18 [SymMove UDFix CornerPermu] move18SymCornerPermu = saved' "move18SymCornerPermu" . MoveTag $ fmap (\moveCP -> SymMove . S.map (f moveCP) $ unSymClassTable classCornerPermu) (unMoveTag move18CornerPermu) where f (RawMove moveCP) = (\(SymClass c, SymCode i) -> flatIndex 16 c i) . rawToSymCornerPermu . RawCoord . (moveCP S.!) {-# INLINE symProjFlipUDSlicePermu #-} symProjFlipUDSlicePermu = symProjection (rawToSymFlipUDSlicePermu . encode) :: SymProjection Move18 UDFix FlipUDSlicePermu rawToSymCornerPermu (RawCoord x) = (SymClass c, SymCode i) where (r, i) = (unSymReprTable reprCornerPermu S.! x) `divMod` 16 c = fromJust . iFind r $ unSymClassTable classCornerPermu {-# INLINE symToRawCornerPermu #-} symToRawCornerPermu = symToRaw classCornerPermu (sym sym16CornerPermu) classCornerPermu :: SymClassTable UDFix CornerPermu classCornerPermu = saved' "classCornerPermu" $ symClassTable 16 reprCornerPermu reprCornerPermu :: SymReprTable UDFix CornerPermu reprCornerPermu = saved' "reprCornerPermu" $ symReprTable 16 $ \cp -> [ (encode . conj s . decode) cp | s <- sym16' ] where conj (fromCube -> s) (cp :: CornerPermu) = inverse s <> cp <> s move18SymFlipUDSlicePermu :: MoveTag Move18 [SymMove UDFix FlipUDSlicePermu] move18SymFlipUDSlicePermu = saved' "move18SymFlipUDSlicePermu" . MoveTag $ zipWith (\moveUDSP moveEO -> SymMove $ S.map (f moveUDSP moveEO) (unSymClassTable classFlipUDSlicePermu)) (unMoveTag move18UDSlicePermu) (unMoveTag move18EdgeOrien) where nEO = range ([] :: [EdgeOrien]) f (RawMove moveUDSP) (RawMove moveEO) x = let (i, j) = x `divMod` nEO z = flatIndex nEO (moveUDSP S.! i) (moveEO S.! j) (SymClass c, SymCode s) = rawToSymFlipUDSlicePermu (RawCoord z) in flatIndex 16 c s rawToSymFlipUDSlicePermu :: RawCoord FlipUDSlicePermu -> SymCoord UDFix FlipUDSlicePermu rawToSymFlipUDSlicePermu (RawCoord z) = (SymClass c, SymCode i) where (r, i) = (unSymReprTable reprFlipUDSlicePermu S.! z) `divMod` 16 c = fromJust . iFind r $ unSymClassTable classFlipUDSlicePermu rawToSymFlipUDSlicePermu' :: RawCoord UDSlicePermu -> RawCoord EdgeOrien -> SymCoord UDFix FlipUDSlicePermu rawToSymFlipUDSlicePermu' = rawToSymFlipUDSlicePermu .: flatCoord where (.:) = (.) (.) (.) {-# INLINE symToRawFlipUDSlicePermu #-} symToRawFlipUDSlicePermu = symToRaw classFlipUDSlicePermu $ \x (SymCode i) -> ( uncurry flatCoord . (V.! i) . uncurry conjugateFlipUDSlicePermu_ . splitCoord ) x classFlipUDSlicePermu :: SymClassTable UDFix FlipUDSlicePermu classFlipUDSlicePermu = saved' "classFlipUDSlicePermu" $ symClassTable 16 reprFlipUDSlicePermu reprFlipUDSlicePermu :: SymReprTable UDFix FlipUDSlicePermu reprFlipUDSlicePermu = saved' "reprFlipUDSlicePermu" . symReprTable 16 $ fmap (uncurry flatCoord) . uncurry conjugateFlipUDSlicePermu_ . splitCoord conjugateFlipUDSlicePermu' :: SymCode UDFix -> FlipUDSlicePermu -> FlipUDSlicePermu conjugateFlipUDSlicePermu' (SymCode c) (udsp, eo) = bimap decode decode (conjugateFlipUDSlicePermu_ i j V.! c) where i = encode udsp j = encode eo {-# INLINE conjugateFlipUDSlicePermu_ #-} conjugateFlipUDSlicePermu_ :: RawCoord UDSlicePermu -> RawCoord EdgeOrien -> V.Vector (RawCoord UDSlicePermu, RawCoord EdgeOrien) conjugateFlipUDSlicePermu_ (RawCoord i) (RawCoord j) = V.zipWith4 f conjUDSP udspComp eoComp cubeComp where conjUDSP = conjUDSlicePermu V.! i udspComp = udspComponentOfConjEdgeOrien V.! i eoComp = eoComponentOfConjEdgeOrien V.! j cubeComp = cubeComponentOfConjEdgeOrien f conjUDSP udspComp eoComp cubeComp = (conjUDSP, RawCoord (udspComp `xor` eoComp `xor` cubeComp)) conjugateUDSlicePermu' :: SymCode UDFix -> UDSlicePermu -> UDSlicePermu conjugateUDSlicePermu' (SymCode c) udsp = decode (conjUDSlicePermu V.! i V.! c) where RawCoord i = encode udsp -- x :: UDSlicePermu -> [ s^(-1) <> x <> s | s <- symUDFix ] conjUDSlicePermu :: V.Vector (V.Vector (RawCoord UDSlicePermu)) conjUDSlicePermu = V.generate (range ([] :: [UDSlicePermu])) $ \i -> V.fromList [ encode . conjugateUDSlicePermu c . decode $ RawCoord i | c <- sym16' ] -- | 11 bits describing edge orientations, as obtained by @encodeEdgeOrien'@ type EOComponent = Int type EOComponents = V.Vector Int udspComponentOfConjEdgeOrien :: V.Vector EOComponents udspComponentOfConjEdgeOrien = V.generate (range ([] :: [UDSlicePermu])) $ \i -> let udsp = fromUDSlicePermu . decode $ RawCoord i in V.fromList $ map (encodeEdgeOrien' . orien udsp) sym16' where orien udsp c = let (fromEdgeOrien -> eo_c, fromEdgePermu -> ep_c) = fromCube c altO = eo_c U.! 0 udsO = eo_c U.! 8 in U.map (\p -> bool altO udsO (p `U.elem` udsp)) ep_c eoComponentOfConjEdgeOrien :: V.Vector EOComponents eoComponentOfConjEdgeOrien = V.generate (range ([] :: [EdgeOrien])) $ \j -> let eo = fromEdgeOrien . decode $ RawCoord j in V.fromList $ map (encodeEdgeOrien' . orien eo) sym16' where orien eo = U.backpermute eo . fromEdgePermu . fromCube cubeComponentOfConjEdgeOrien :: EOComponents cubeComponentOfConjEdgeOrien = V.fromList $ map (encodeEdgeOrien' . fromEdgeOrien . fromCube) sym16'