{- | Two phase algorithm to solve a Rubik's cube -} {-# LANGUAGE RecordWildCards, ViewPatterns #-} module Rubik.Solver.TwoPhase where import Rubik.Cube import Rubik.Misc import Rubik.Solver import Rubik.Tables.Moves import Rubik.Tables.Distances import Data.Function ( on ) import Data.Monoid {-# INLINE phase1Proj #-} phase1Proj = rawProjection |*| rawProjection |.| rawProjection phase1Convert = convertP phase1Proj phase1Dist = maxDistance [ (\((,,) co _ uds) -> (co, uds)) >$< distanceWith2 d_CornerOrien_UDSlice , (\((,,) _ eo uds) -> (eo, uds)) >$< distanceWith2 d_EdgeOrien_UDSlice ] phase1 :: Cube -> Move phase1 = solveWith move18Names moves phase1Proj phase1Dist where moves = (,,) move18CornerOrien move18EdgeOrien move18UDSlice -- | > phase1Solved (phase1 c) phase1Solved :: Cube -> Bool phase1Solved = ((==) `on` phase1Convert) iden -- phase2Proj = rawProjection |*| rawProjection |.| rawProjection phase2Convert = convertP phase2Proj phase2Dist = maxDistance [ (\((,,) cp _ udsp) -> (cp, udsp)) >$< distanceWith2 d_CornerPermu_UDSlicePermu2 , (\((,,) _ udep udsp) -> (udep, udsp)) >$< distanceWith2 d_UDEdgePermu2_UDSlicePermu2 ] phase2 :: Cube -> Move phase2 = solveWith move10Names moves phase2Proj phase2Dist where moves = (,,) move10CornerPermu move10UDEdgePermu2 move10UDSlicePermu2 -- | > phase1Solved c ==> phase2Solved (phase2 c) phase2Solved :: Cube -> Bool phase2Solved = (== iden) -- | Solve a scrambled Rubik's cube. -- -- Make sure the cube is actually solvable with 'Cubie.solvable', -- before calling this function. solve :: Cube -> Move solve c = let s1 = phase1 c c1 = c <> moveToCube s1 s2 = phase2 c1 in reduceMove $ s1 ++ s2