cube-hs-0.4.0.0: src/Data/Cube/Def.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Data.Cube.Def where
import Data.Cube.Raw (rawBase6)
import Data.Vector.Sized (Vector)
import qualified Data.Vector.Sized as V
import Data.Array (Array, listArray, (!))
import Data.Maybe (fromMaybe)
import Data.List (sort)
data Color = U | R | F | D | L | B
deriving (Eq, Show, Enum, Bounded)
data Face
= U1 | U2 | U3 | U4 | U5 | U6 | U7 | U8 | U9
| R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9
| F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9
| D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9
| L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8 | L9
| B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9
deriving (Eq, Show, Enum, Bounded)
data Turn
= Ux1 | Ux2 | Ux3
| Rx1 | Rx2 | Rx3
| Fx1 | Fx2 | Fx3
| Dx1 | Dx2 | Dx3
| Lx1 | Lx2 | Lx3
| Bx1 | Bx2 | Bx3
deriving (Eq, Show, Enum, Bounded)
newtype Cube = Cube (Vector 54 Color)
deriving (Eq)
newtype Move = Move (Vector 54 Int)
deriving (Eq)
instance Semigroup Move where
Move m1 <> Move m2 = Move (V.backpermute m1 m2)
instance Monoid Move where
mempty = Move (fromMaybe (error "mempty") (V.fromList [0..53]))
class ActsOn c m where
(&>) :: c -> m -> c
instance ActsOn Cube Move where
(Cube c) &> (Move p) = Cube (V.backpermute c p)
class Actionable a where
toMove :: a -> Move
toAction :: a -> (Cube -> Cube)
toAction a = (&> toMove a)
instance Actionable a => Actionable [a] where
toMove = mconcat . map toMove
instance Actionable Move where
toMove = id
instance Show Cube where
show (Cube v) = "Cube " ++ show (V.toList v)
instance Show Move where
show (Move v) = "Move " ++ show (map (toEnum :: Int -> Face) (V.toList v))
instance ActsOn Cube Turn where
c &> t = c &> toMove t
instance Actionable Turn where
toMove t = moveTable_ ! fromEnum t
moveTable_ :: Array Int Move
moveTable_ = listArray(0,17) (concatMap powers base6) where
powers v = [v, v <> v, v <> v <> v]
base6 = map unsafeMoveFromRaw rawBase6
moveFaces :: Move -> [Face]
moveFaces (Move v) = map toEnum (V.toList v)
showAction :: Actionable a => a -> String
showAction a = "Action " ++ show (moveFaces (toMove a))
moveFromRaw :: [Int] -> Maybe Move
moveFromRaw xs
| isValidPerm xs = Move <$> V.fromList (map toEnum xs)
| otherwise = Nothing
where
isValidPerm ys = sort ys == [0..53]
unsafeMoveFromRaw :: [Int] -> Move
unsafeMoveFromRaw xs = case moveFromRaw xs of
Just m -> m
Nothing -> error "unsafeMoveFromRaw: input is not a valid 0..53 permutation"