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
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 :: 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
phase2Solved :: Cube -> Bool
phase2Solved = (== iden)
solve :: Cube -> Move
solve c =
let s1 = phase1 c
c1 = c <> moveToCube s1
s2 = phase2 c1
in reduceMove $ s1 ++ s2