module Rubik.Solver.Optimal where
import Rubik.Cube
import Rubik.Solver
import Rubik.Tables.Moves
import Rubik.Tables.Distances
import Rubik.Tables.Internal
import qualified Data.Vector.Generic as G
optiProj
= fudsp |*| sfudsp |*| s sfudsp |*| co |*| sco |*| s sco |.| cp
where
fudsp = symProjFlipUDSlicePermu
sfudsp = s fudsp
co = rawProjection :: Projection' Move18 CornerOrien
sco = s co
cp = symProjCornerPermu
s x = symmetricProj symmetry_urf3 x
optiDist = maxDistance
[ maxOrEqualPlusOne
( (\((,,,,,,) fudsp _ _ co _ _ _) -> (fudsp, co)) >$< fudsp_co
, (\((,,,,,,) _ fudsp _ _ co _ _) -> (fudsp, co)) >$< fudsp_co
, (\((,,,,,,) _ _ fudsp _ _ co _) -> (fudsp, co)) >$< fudsp_co
)
, (\((,,,,,,) _ _ _ co _ _ cp) -> (cp, co)) >$< cp_co
]
maxOrEqualPlusOne (Distance f, Distance g, Distance h)
= Distance $ \x -> let a = f x ; b = g x ; c = h x
in if a == b && b == c && a /= 0 then a + 1
else a `max` b `max` c
solve :: Cube -> Move
solve = solveWith move18Names moves optiProj optiDist
where
moves = (,,,,,,) m_fudsp m_fudsp m_fudsp m_co m_co m_co move18SymCornerPermu
m_fudsp = move18SymFlipUDSlicePermu
m_co = move18CornerOrien
toIdx = uncurry $ indexWithSym invertedSym16CornerOrien (range ([] :: [CornerOrien]))
fudsp_co = toIdx >$< Distance (fromIntegral . (dSym_CornerOrien_FlipUDSlicePermu G.!))
cp_co = toIdx >$< Distance (dSym_CornerOrien_CornerPermu G.!)