module BishBosh.State.InstancesByPosition(
leastCyclicPlies,
InstancesByPosition(),
countConsecutiveRepeatablePlies,
countPositionRepetitions,
getNDistinctPositions,
findMaximumInstances,
mkInstancesByPosition,
mkSingleton,
insertPosition,
deletePosition,
anyInstancesByPosition
) where
import qualified BishBosh.Property.Empty as Property.Empty
import qualified BishBosh.Property.Reflectable as Property.Reflectable
import qualified BishBosh.Type.Count as Type.Count
import qualified Control.DeepSeq
import qualified Control.Exception
import qualified Data.Foldable
import qualified Data.Map.Strict as Map
leastCyclicPlies :: Type.Count.NPlies
leastCyclicPlies :: NPlies
leastCyclicPlies = NPlies
4
type NPositionsByPosition position = Map.Map position Type.Count.NPositions
insertPosition' :: Ord position => position -> NPositionsByPosition position -> NPositionsByPosition position
insertPosition' :: position
-> NPositionsByPosition position -> NPositionsByPosition position
insertPosition' = (position
-> NPlies
-> NPositionsByPosition position
-> NPositionsByPosition position)
-> NPlies
-> position
-> NPositionsByPosition position
-> NPositionsByPosition position
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((NPlies -> NPlies -> NPlies)
-> position
-> NPlies
-> NPositionsByPosition position
-> NPositionsByPosition position
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith ((NPlies -> NPlies -> NPlies)
-> position
-> NPlies
-> NPositionsByPosition position
-> NPositionsByPosition position)
-> (NPlies -> NPlies -> NPlies)
-> position
-> NPlies
-> NPositionsByPosition position
-> NPositionsByPosition position
forall a b. (a -> b) -> a -> b
$ (NPlies -> NPlies) -> NPlies -> NPlies -> NPlies
forall a b. a -> b -> a
const NPlies -> NPlies
forall a. Enum a => a -> a
succ) NPlies
1
newtype InstancesByPosition position = MkInstancesByPosition {
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition :: NPositionsByPosition position
} deriving InstancesByPosition position
-> InstancesByPosition position -> Bool
(InstancesByPosition position
-> InstancesByPosition position -> Bool)
-> (InstancesByPosition position
-> InstancesByPosition position -> Bool)
-> Eq (InstancesByPosition position)
forall position.
Eq position =>
InstancesByPosition position
-> InstancesByPosition position -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InstancesByPosition position
-> InstancesByPosition position -> Bool
$c/= :: forall position.
Eq position =>
InstancesByPosition position
-> InstancesByPosition position -> Bool
== :: InstancesByPosition position
-> InstancesByPosition position -> Bool
$c== :: forall position.
Eq position =>
InstancesByPosition position
-> InstancesByPosition position -> Bool
Eq
instance Control.DeepSeq.NFData position => Control.DeepSeq.NFData (InstancesByPosition position) where
rnf :: InstancesByPosition position -> ()
rnf MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = NPositionsByPosition position -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf NPositionsByPosition position
m
instance (
Ord position,
Property.Reflectable.ReflectableOnX position
) => Property.Reflectable.ReflectableOnX (InstancesByPosition position) where
reflectOnX :: InstancesByPosition position -> InstancesByPosition position
reflectOnX MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = NPositionsByPosition position -> InstancesByPosition position
forall position.
NPositionsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NPositionsByPosition position -> InstancesByPosition position)
-> NPositionsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ (position -> position)
-> NPositionsByPosition position -> NPositionsByPosition position
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys position -> position
forall a. ReflectableOnX a => a -> a
Property.Reflectable.reflectOnX NPositionsByPosition position
m
mkInstancesByPosition
:: (Foldable foldable, Ord position)
=> (a -> position)
-> foldable a
-> InstancesByPosition position
mkInstancesByPosition :: (a -> position) -> foldable a -> InstancesByPosition position
mkInstancesByPosition a -> position
f = NPositionsByPosition position -> InstancesByPosition position
forall position.
NPositionsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NPositionsByPosition position -> InstancesByPosition position)
-> (foldable a -> NPositionsByPosition position)
-> foldable a
-> InstancesByPosition position
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
-> NPositionsByPosition position -> NPositionsByPosition position)
-> NPositionsByPosition position
-> foldable a
-> NPositionsByPosition position
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Data.Foldable.foldr (position
-> NPositionsByPosition position -> NPositionsByPosition position
forall position.
Ord position =>
position
-> NPositionsByPosition position -> NPositionsByPosition position
insertPosition' (position
-> NPositionsByPosition position -> NPositionsByPosition position)
-> (a -> position)
-> a
-> NPositionsByPosition position
-> NPositionsByPosition position
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> position
f) NPositionsByPosition position
forall a. Empty a => a
Property.Empty.empty
mkSingleton :: position -> InstancesByPosition position
mkSingleton :: position -> InstancesByPosition position
mkSingleton = NPositionsByPosition position -> InstancesByPosition position
forall position.
NPositionsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NPositionsByPosition position -> InstancesByPosition position)
-> (position -> NPositionsByPosition position)
-> position
-> InstancesByPosition position
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (position -> NPlies -> NPositionsByPosition position
forall k a. k -> a -> Map k a
`Map.singleton` NPlies
1)
countConsecutiveRepeatablePlies :: InstancesByPosition position -> Type.Count.NPlies
countConsecutiveRepeatablePlies :: InstancesByPosition position -> NPlies
countConsecutiveRepeatablePlies MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = NPlies -> NPlies
forall a b. (Integral a, Num b) => a -> b
fromIntegral (NPlies -> NPlies) -> NPlies -> NPlies
forall a b. (a -> b) -> a -> b
$ (NPlies -> NPlies -> NPlies)
-> NPlies -> NPositionsByPosition position -> NPlies
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Data.Foldable.foldl' NPlies -> NPlies -> NPlies
forall a. Num a => a -> a -> a
(+) (
NPlies -> NPlies
forall a. Num a => a -> a
negate NPlies
1
) NPositionsByPosition position
m
countPositionRepetitions :: InstancesByPosition position -> Type.Count.NPositions
countPositionRepetitions :: InstancesByPosition position -> NPlies
countPositionRepetitions MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = (NPlies -> NPlies -> NPlies)
-> NPlies -> NPositionsByPosition position -> NPlies
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Data.Foldable.foldl' (
NPlies -> NPlies -> NPlies
forall a. Num a => a -> a -> a
(+) (NPlies -> NPlies -> NPlies)
-> (NPlies -> NPlies) -> NPlies -> NPlies -> NPlies
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NPlies -> NPlies
forall a. Enum a => a -> a
pred
) NPlies
0 NPositionsByPosition position
m
getNDistinctPositions :: InstancesByPosition position -> Type.Count.NPositions
getNDistinctPositions :: InstancesByPosition position -> NPlies
getNDistinctPositions MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = NPlies -> NPlies
forall a b. (Integral a, Num b) => a -> b
fromIntegral (NPlies -> NPlies) -> NPlies -> NPlies
forall a b. (a -> b) -> a -> b
$ NPositionsByPosition position -> NPlies
forall (t :: * -> *) a. Foldable t => t a -> NPlies
Data.Foldable.length NPositionsByPosition position
m
anyInstancesByPosition
:: (Type.Count.NPositions -> Bool)
-> InstancesByPosition position
-> Bool
anyInstancesByPosition :: (NPlies -> Bool) -> InstancesByPosition position -> Bool
anyInstancesByPosition NPlies -> Bool
predicate MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = (NPlies -> Bool) -> NPositionsByPosition position -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
Data.Foldable.any NPlies -> Bool
predicate NPositionsByPosition position
m
findMaximumInstances :: InstancesByPosition position -> Type.Count.NPositions
findMaximumInstances :: InstancesByPosition position -> NPlies
findMaximumInstances MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m }
| NPositionsByPosition position -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
Data.Foldable.null NPositionsByPosition position
m = NPlies
0
| Bool
otherwise = NPositionsByPosition position -> NPlies
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
Data.Foldable.maximum NPositionsByPosition position
m
type Transformation position = InstancesByPosition position -> InstancesByPosition position
insertPosition
:: Ord position
=> Bool
-> position
-> Transformation position
insertPosition :: Bool -> position -> Transformation position
insertPosition Bool
isRepeatable position
position MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m }
| Bool
isRepeatable = NPositionsByPosition position -> InstancesByPosition position
forall position.
NPositionsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NPositionsByPosition position -> InstancesByPosition position)
-> NPositionsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ position
-> NPositionsByPosition position -> NPositionsByPosition position
forall position.
Ord position =>
position
-> NPositionsByPosition position -> NPositionsByPosition position
insertPosition' position
position NPositionsByPosition position
m
| Bool
otherwise = position -> InstancesByPosition position
forall position. position -> InstancesByPosition position
mkSingleton position
position
deletePosition :: Ord position => position -> Transformation position
deletePosition :: position -> Transformation position
deletePosition position
position MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> NPositionsByPosition position
getNPositionsByPosition = NPositionsByPosition position
m } = NPositionsByPosition position -> InstancesByPosition position
forall position.
NPositionsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NPositionsByPosition position -> InstancesByPosition position)
-> (NPositionsByPosition position -> NPositionsByPosition position)
-> NPositionsByPosition position
-> InstancesByPosition position
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NPlies -> Maybe NPlies)
-> position
-> NPositionsByPosition position
-> NPositionsByPosition position
forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Map.update (
\NPlies
n -> if NPlies
n NPlies -> NPlies -> Bool
forall a. Eq a => a -> a -> Bool
== NPlies
1
then Maybe NPlies
forall a. Maybe a
Nothing
else NPlies -> Maybe NPlies
forall a. a -> Maybe a
Just (NPlies -> Maybe NPlies) -> NPlies -> Maybe NPlies
forall a b. (a -> b) -> a -> b
$ NPlies -> NPlies
forall a. Enum a => a -> a
pred NPlies
n
) position
position (NPositionsByPosition position -> InstancesByPosition position)
-> NPositionsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ Bool
-> NPositionsByPosition position -> NPositionsByPosition position
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (position -> NPositionsByPosition position -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member position
position NPositionsByPosition position
m) NPositionsByPosition position
m