module BishBosh.State.InstancesByPosition(
leastCyclicPlies,
InstancesByPosition(),
countConsecutiveRepeatablePlies,
countPositionRepetitions,
getNDistinctPositions,
findMaximumInstances,
mkInstancesByPosition,
mkSingleton,
insertPosition,
deletePosition,
anyInstancesByPosition
) where
import qualified BishBosh.Data.Exception as Data.Exception
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
leastCyclicPlies :: Type.Count.NPlies
leastCyclicPlies :: NPlies
leastCyclicPlies = NPlies
4
newtype InstancesByPosition position = MkInstancesByPosition {
InstancesByPosition position -> Map position NPlies
getNPositionsByPosition :: Data.Map.Strict.Map position Type.Count.NPositions
} 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 -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m } = Map position NPlies -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf Map position NPlies
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 -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m } = Map position NPlies -> InstancesByPosition position
forall position.
Map position NPlies -> InstancesByPosition position
MkInstancesByPosition (Map position NPlies -> InstancesByPosition position)
-> Map position NPlies -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ (position -> position)
-> Map position NPlies -> Map position NPlies
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Data.Map.Strict.mapKeys position -> position
forall a. ReflectableOnX a => a -> a
Property.Reflectable.reflectOnX Map position NPlies
m
mkInstancesByPosition :: Data.Map.Strict.Map position Type.Count.NPositions -> InstancesByPosition position
mkInstancesByPosition :: Map position NPlies -> InstancesByPosition position
mkInstancesByPosition Map position NPlies
nPositionsByPosition
| (NPlies -> Bool) -> Map position NPlies -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
Data.Foldable.any (NPlies -> NPlies -> Bool
forall a. Ord a => a -> a -> Bool
< NPlies
1) Map position NPlies
nPositionsByPosition = Exception -> InstancesByPosition position
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> InstancesByPosition position)
-> Exception -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ String -> Exception
Data.Exception.mkOutOfBounds String
"BishBosh.State.InstancesByPosition.mkInstancesByPosition:\teach specified position must have been visited at least once."
| Bool
otherwise = Map position NPlies -> InstancesByPosition position
forall position.
Map position NPlies -> InstancesByPosition position
MkInstancesByPosition Map position NPlies
nPositionsByPosition
mkSingleton :: position -> InstancesByPosition position
mkSingleton :: position -> InstancesByPosition position
mkSingleton position
position = Map position NPlies -> InstancesByPosition position
forall position.
Map position NPlies -> InstancesByPosition position
MkInstancesByPosition (Map position NPlies -> InstancesByPosition position)
-> Map position NPlies -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ position -> NPlies -> Map position NPlies
forall k a. k -> a -> Map k a
Data.Map.Strict.singleton position
position NPlies
1
countConsecutiveRepeatablePlies :: InstancesByPosition position -> Type.Count.NPlies
countConsecutiveRepeatablePlies :: InstancesByPosition position -> NPlies
countConsecutiveRepeatablePlies MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> Map position NPlies
getNPositionsByPosition = Map position NPlies
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 -> Map position NPlies -> NPlies
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Data.Map.Strict.foldl' NPlies -> NPlies -> NPlies
forall a. Num a => a -> a -> a
(+) (
NPlies -> NPlies
forall a. Num a => a -> a
negate NPlies
1
) Map position NPlies
m
countPositionRepetitions :: InstancesByPosition position -> Type.Count.NPositions
countPositionRepetitions :: InstancesByPosition position -> NPlies
countPositionRepetitions MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m } = (NPlies -> NPlies -> NPlies)
-> NPlies -> Map position NPlies -> NPlies
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Data.Map.Strict.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 Map position NPlies
m
getNDistinctPositions :: InstancesByPosition position -> Type.Count.NPositions
getNDistinctPositions :: InstancesByPosition position -> NPlies
getNDistinctPositions MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m } = NPlies -> NPlies
forall a b. (Integral a, Num b) => a -> b
fromIntegral (NPlies -> NPlies) -> NPlies -> NPlies
forall a b. (a -> b) -> a -> b
$ Map position NPlies -> NPlies
forall k a. Map k a -> NPlies
Data.Map.Strict.size Map position NPlies
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 -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m } = (NPlies -> Bool) -> Map position NPlies -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
Data.Foldable.any NPlies -> Bool
predicate Map position NPlies
m
findMaximumInstances :: InstancesByPosition position -> Type.Count.NPositions
findMaximumInstances :: InstancesByPosition position -> NPlies
findMaximumInstances MkInstancesByPosition { getNPositionsByPosition :: forall position.
InstancesByPosition position -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m }
| Map position NPlies -> Bool
forall k a. Map k a -> Bool
Data.Map.Strict.null Map position NPlies
m = NPlies
0
| Bool
otherwise = Map position NPlies -> NPlies
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
Data.Foldable.maximum Map position NPlies
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 -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m }
| Bool
isRepeatable = Map position NPlies -> InstancesByPosition position
forall position.
Map position NPlies -> InstancesByPosition position
MkInstancesByPosition (Map position NPlies -> InstancesByPosition position)
-> Map position NPlies -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ (NPlies -> NPlies -> NPlies)
-> position -> NPlies -> Map position NPlies -> Map position NPlies
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Data.Map.Strict.insertWith ((NPlies -> NPlies) -> NPlies -> NPlies -> NPlies
forall a b. a -> b -> a
const NPlies -> NPlies
forall a. Enum a => a -> a
succ) position
position NPlies
1 Map position NPlies
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 -> Map position NPlies
getNPositionsByPosition = Map position NPlies
m } = Map position NPlies -> InstancesByPosition position
forall position.
Map position NPlies -> InstancesByPosition position
MkInstancesByPosition (Map position NPlies -> InstancesByPosition position)
-> (Map position NPlies -> Map position NPlies)
-> Map position NPlies
-> InstancesByPosition position
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NPlies -> Maybe NPlies)
-> position -> Map position NPlies -> Map position NPlies
forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Data.Map.Strict.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 (Map position NPlies -> InstancesByPosition position)
-> Map position NPlies -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ Bool -> Map position NPlies -> Map position NPlies
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (position -> Map position NPlies -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Data.Map.Strict.member position
position Map position NPlies
m) Map position NPlies
m