module Math.SetCover.Cuboid where

import qualified Data.Map as Map
import qualified Data.Set as Set

import qualified Data.Traversable as Trav
import qualified Data.Foldable as Fold
import Control.Applicative (Applicative, liftA2, liftA3, pure, (<*>))
import Data.List (sort)


data Coords a = Coords a a a
   deriving (Coords a -> Coords a -> Bool
(Coords a -> Coords a -> Bool)
-> (Coords a -> Coords a -> Bool) -> Eq (Coords a)
forall a. Eq a => Coords a -> Coords a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Coords a -> Coords a -> Bool
== :: Coords a -> Coords a -> Bool
$c/= :: forall a. Eq a => Coords a -> Coords a -> Bool
/= :: Coords a -> Coords a -> Bool
Eq, Eq (Coords a)
Eq (Coords a)
-> (Coords a -> Coords a -> Ordering)
-> (Coords a -> Coords a -> Bool)
-> (Coords a -> Coords a -> Bool)
-> (Coords a -> Coords a -> Bool)
-> (Coords a -> Coords a -> Bool)
-> (Coords a -> Coords a -> Coords a)
-> (Coords a -> Coords a -> Coords a)
-> Ord (Coords a)
Coords a -> Coords a -> Bool
Coords a -> Coords a -> Ordering
Coords a -> Coords a -> Coords a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Coords a)
forall a. Ord a => Coords a -> Coords a -> Bool
forall a. Ord a => Coords a -> Coords a -> Ordering
forall a. Ord a => Coords a -> Coords a -> Coords a
$ccompare :: forall a. Ord a => Coords a -> Coords a -> Ordering
compare :: Coords a -> Coords a -> Ordering
$c< :: forall a. Ord a => Coords a -> Coords a -> Bool
< :: Coords a -> Coords a -> Bool
$c<= :: forall a. Ord a => Coords a -> Coords a -> Bool
<= :: Coords a -> Coords a -> Bool
$c> :: forall a. Ord a => Coords a -> Coords a -> Bool
> :: Coords a -> Coords a -> Bool
$c>= :: forall a. Ord a => Coords a -> Coords a -> Bool
>= :: Coords a -> Coords a -> Bool
$cmax :: forall a. Ord a => Coords a -> Coords a -> Coords a
max :: Coords a -> Coords a -> Coords a
$cmin :: forall a. Ord a => Coords a -> Coords a -> Coords a
min :: Coords a -> Coords a -> Coords a
Ord, Int -> Coords a -> ShowS
[Coords a] -> ShowS
Coords a -> String
(Int -> Coords a -> ShowS)
-> (Coords a -> String) -> ([Coords a] -> ShowS) -> Show (Coords a)
forall a. Show a => Int -> Coords a -> ShowS
forall a. Show a => [Coords a] -> ShowS
forall a. Show a => Coords a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Coords a -> ShowS
showsPrec :: Int -> Coords a -> ShowS
$cshow :: forall a. Show a => Coords a -> String
show :: Coords a -> String
$cshowList :: forall a. Show a => [Coords a] -> ShowS
showList :: [Coords a] -> ShowS
Show)

instance Functor Coords where
   fmap :: forall a b. (a -> b) -> Coords a -> Coords b
fmap a -> b
f (Coords a
x a
y a
z) = b -> b -> b -> Coords b
forall a. a -> a -> a -> Coords a
Coords (a -> b
f a
x) (a -> b
f a
y) (a -> b
f a
z)

instance Applicative Coords where
   pure :: forall a. a -> Coords a
pure a
x = a -> a -> a -> Coords a
forall a. a -> a -> a -> Coords a
Coords a
x a
x a
x
   Coords a -> b
fx a -> b
fy a -> b
fz <*> :: forall a b. Coords (a -> b) -> Coords a -> Coords b
<*> Coords a
x a
y a
z = b -> b -> b -> Coords b
forall a. a -> a -> a -> Coords a
Coords (a -> b
fx a
x) (a -> b
fy a
y) (a -> b
fz a
z)

instance Fold.Foldable Coords where
   foldMap :: forall m a. Monoid m => (a -> m) -> Coords a -> m
foldMap = (a -> m) -> Coords a -> m
forall (t :: * -> *) m a.
(Traversable t, Monoid m) =>
(a -> m) -> t a -> m
Trav.foldMapDefault

instance Trav.Traversable Coords where
   traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Coords a -> f (Coords b)
traverse a -> f b
f (Coords a
x a
y a
z) = (b -> b -> b -> Coords b) -> f b -> f b -> f b -> f (Coords b)
forall (f :: * -> *) a b c d.
Applicative f =>
(a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 b -> b -> b -> Coords b
forall a. a -> a -> a -> Coords a
Coords (a -> f b
f a
x) (a -> f b
f a
y) (a -> f b
f a
z)


coordsFromString :: [[String]] -> [Coords Int]
coordsFromString :: [[String]] -> [Coords Int]
coordsFromString [[String]]
ss = do
   (Int
planeN,[String]
plane) <- [Int] -> [[String]] -> [(Int, [String])]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [[String]]
ss
   (Int
rowN,String
row) <- [Int] -> [String] -> [(Int, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [String]
plane
   (Int
colN,Char
c) <- [Int] -> String -> [(Int, Char)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] String
row
   case Char
c of
      Char
' '  -> []
      Char
'.'  -> [Int -> Int -> Int -> Coords Int
forall a. a -> a -> a -> Coords a
Coords Int
planeN Int
rowN Int
colN]
      Char
_ -> String -> [Coords Int]
forall a. HasCallStack => String -> a
error String
"forbidden character"

coordsFrom2LayerString :: [String] -> [Coords Int]
coordsFrom2LayerString :: [String] -> [Coords Int]
coordsFrom2LayerString [String]
ss = do
   (Int
rowN,String
row) <- [Int] -> [String] -> [(Int, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [String]
ss
   (Int
colN,Char
c) <- [Int] -> String -> [(Int, Char)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] String
row
   (Int -> Coords Int) -> [Int] -> [Coords Int]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Int -> Int -> Coords Int
forall a. a -> a -> a -> Coords a
Coords Int
rowN Int
colN) ([Int] -> [Coords Int]) -> [Int] -> [Coords Int]
forall a b. (a -> b) -> a -> b
$
      case Char
c of
         Char
' '  -> []
         Char
'.'  -> [Int
0]
         Char
'\'' -> [Int
1]
         Char
':'  -> [Int
0, Int
1]
         Char
_ -> String -> [Int]
forall a. HasCallStack => String -> a
error String
"forbidden character"

numberOf2LayerAtoms :: [[String]] -> Int
numberOf2LayerAtoms :: [[String]] -> Int
numberOf2LayerAtoms =
   Map Char Int -> Int
forall a. Num a => Map Char a -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Fold.sum (Map Char Int -> Int)
-> ([[String]] -> Map Char Int) -> [[String]] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (Int -> Int -> Int) -> Map Char Int -> Map Char Int -> Map Char Int
forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWith Int -> Int -> Int
forall a. Num a => a -> a -> a
(*) ([(Char, Int)] -> Map Char Int
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Char
'.', Int
1), (Char
'\'', Int
1), (Char
':', Int
2)]) (Map Char Int -> Map Char Int)
-> ([[String]] -> Map Char Int) -> [[String]] -> Map Char Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (Int -> Int -> Int) -> [(Char, Int)] -> Map Char Int
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ([(Char, Int)] -> Map Char Int)
-> ([[String]] -> [(Char, Int)]) -> [[String]] -> Map Char Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> (Char, Int)) -> String -> [(Char, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ((Char -> Int -> (Char, Int)) -> Int -> Char -> (Char, Int)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (,) Int
1) (String -> [(Char, Int)])
-> ([[String]] -> String) -> [[String]] -> [(Char, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String)
-> ([[String]] -> [String]) -> [[String]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat


forNestedCoords ::
   (Enum a, Num a) =>
   ([z] -> b) ->
   ([y] -> z) ->
   ([x] -> y) ->
   (Coords a -> x) ->
   Coords a -> b
forNestedCoords :: forall a z b y x.
(Enum a, Num a) =>
([z] -> b)
-> ([y] -> z) -> ([x] -> y) -> (Coords a -> x) -> Coords a -> b
forNestedCoords [z] -> b
fz [y] -> z
fy [x] -> y
fx Coords a -> x
f Coords a
sz =
   case (a -> [a]) -> Coords a -> Coords [a]
forall a b. (a -> b) -> Coords a -> Coords b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a
k -> [a
0 .. a
ka -> a -> a
forall a. Num a => a -> a -> a
-a
1]) Coords a
sz of
      Coords [a]
rx [a]
ry [a]
rz ->
         [z] -> b
fz ([z] -> b) -> [z] -> b
forall a b. (a -> b) -> a -> b
$ ((a -> z) -> [a] -> [z]) -> [a] -> (a -> z) -> [z]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> z) -> [a] -> [z]
forall a b. (a -> b) -> [a] -> [b]
map [a]
rz ((a -> z) -> [z]) -> (a -> z) -> [z]
forall a b. (a -> b) -> a -> b
$ \a
z ->
         [y] -> z
fy ([y] -> z) -> [y] -> z
forall a b. (a -> b) -> a -> b
$ ((a -> y) -> [a] -> [y]) -> [a] -> (a -> y) -> [y]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> y) -> [a] -> [y]
forall a b. (a -> b) -> [a] -> [b]
map [a]
ry ((a -> y) -> [y]) -> (a -> y) -> [y]
forall a b. (a -> b) -> a -> b
$ \a
y ->
         [x] -> y
fx ([x] -> y) -> [x] -> y
forall a b. (a -> b) -> a -> b
$ ((a -> x) -> [a] -> [x]) -> [a] -> (a -> x) -> [x]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> x) -> [a] -> [x]
forall a b. (a -> b) -> [a] -> [b]
map [a]
rx ((a -> x) -> [x]) -> (a -> x) -> [x]
forall a b. (a -> b) -> a -> b
$ \a
x ->
         Coords a -> x
f (a -> a -> a -> Coords a
forall a. a -> a -> a -> Coords a
Coords a
x a
y a
z)


newtype PackedCoords = PackedCoords Int
   deriving (PackedCoords -> PackedCoords -> Bool
(PackedCoords -> PackedCoords -> Bool)
-> (PackedCoords -> PackedCoords -> Bool) -> Eq PackedCoords
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PackedCoords -> PackedCoords -> Bool
== :: PackedCoords -> PackedCoords -> Bool
$c/= :: PackedCoords -> PackedCoords -> Bool
/= :: PackedCoords -> PackedCoords -> Bool
Eq, Eq PackedCoords
Eq PackedCoords
-> (PackedCoords -> PackedCoords -> Ordering)
-> (PackedCoords -> PackedCoords -> Bool)
-> (PackedCoords -> PackedCoords -> Bool)
-> (PackedCoords -> PackedCoords -> Bool)
-> (PackedCoords -> PackedCoords -> Bool)
-> (PackedCoords -> PackedCoords -> PackedCoords)
-> (PackedCoords -> PackedCoords -> PackedCoords)
-> Ord PackedCoords
PackedCoords -> PackedCoords -> Bool
PackedCoords -> PackedCoords -> Ordering
PackedCoords -> PackedCoords -> PackedCoords
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PackedCoords -> PackedCoords -> Ordering
compare :: PackedCoords -> PackedCoords -> Ordering
$c< :: PackedCoords -> PackedCoords -> Bool
< :: PackedCoords -> PackedCoords -> Bool
$c<= :: PackedCoords -> PackedCoords -> Bool
<= :: PackedCoords -> PackedCoords -> Bool
$c> :: PackedCoords -> PackedCoords -> Bool
> :: PackedCoords -> PackedCoords -> Bool
$c>= :: PackedCoords -> PackedCoords -> Bool
>= :: PackedCoords -> PackedCoords -> Bool
$cmax :: PackedCoords -> PackedCoords -> PackedCoords
max :: PackedCoords -> PackedCoords -> PackedCoords
$cmin :: PackedCoords -> PackedCoords -> PackedCoords
min :: PackedCoords -> PackedCoords -> PackedCoords
Ord, Int -> PackedCoords -> ShowS
[PackedCoords] -> ShowS
PackedCoords -> String
(Int -> PackedCoords -> ShowS)
-> (PackedCoords -> String)
-> ([PackedCoords] -> ShowS)
-> Show PackedCoords
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackedCoords -> ShowS
showsPrec :: Int -> PackedCoords -> ShowS
$cshow :: PackedCoords -> String
show :: PackedCoords -> String
$cshowList :: [PackedCoords] -> ShowS
showList :: [PackedCoords] -> ShowS
Show)


rotX, rotY, rotZ :: Num a => Coords a -> Coords a
rotX :: forall a. Num a => Coords a -> Coords a
rotX (Coords a
x a
y a
z) = a -> a -> a -> Coords a
forall a. a -> a -> a -> Coords a
Coords a
x (-a
z) a
y -- [1 0  0; 0 0 -1; 0 1 0]
rotY :: forall a. Num a => Coords a -> Coords a
rotY (Coords a
x a
y a
z) = a -> a -> a -> Coords a
forall a. a -> a -> a -> Coords a
Coords (-a
z) a
y a
x -- [0 0 -1; 0 1 0; 1 0 0]
rotZ :: forall a. Num a => Coords a -> Coords a
rotZ (Coords a
x a
y a
z) = a -> a -> a -> Coords a
forall a. a -> a -> a -> Coords a
Coords (-a
y) a
x a
z -- [0 -1 0; 1 0 0; 0 0 1]

primRotations :: Num a => Coords (Coords a -> Coords a)
primRotations :: forall a. Num a => Coords (Coords a -> Coords a)
primRotations = (Coords a -> Coords a)
-> (Coords a -> Coords a)
-> (Coords a -> Coords a)
-> Coords (Coords a -> Coords a)
forall a. a -> a -> a -> Coords a
Coords Coords a -> Coords a
forall a. Num a => Coords a -> Coords a
rotX Coords a -> Coords a
forall a. Num a => Coords a -> Coords a
rotY Coords a -> Coords a
forall a. Num a => Coords a -> Coords a
rotZ

rotations :: Num a => [Coords a -> Coords a]
rotations :: forall a. Num a => [Coords a -> Coords a]
rotations = Coords (Coords a -> Coords a) -> [Coords a -> Coords a]
forall a.
Num a =>
Coords (Coords a -> Coords a) -> [Coords a -> Coords a]
rotationsGen Coords (Coords a -> Coords a)
forall a. Num a => Coords (Coords a -> Coords a)
primRotations

rotationsGen :: Num a => Coords (Coords a -> Coords a) -> [Coords a -> Coords a]
rotationsGen :: forall a.
Num a =>
Coords (Coords a -> Coords a) -> [Coords a -> Coords a]
rotationsGen (Coords Coords a -> Coords a
rx Coords a -> Coords a
ry Coords a -> Coords a
rz) =
   ((Coords a -> Coords a)
 -> (Coords a -> Coords a) -> Coords a -> Coords a)
-> [Coords a -> Coords a]
-> [Coords a -> Coords a]
-> [Coords a -> Coords a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)
      [Coords a -> Coords a
forall a. a -> a
id, Coords a -> Coords a
rx, Coords a -> Coords a
rx(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
rx, Coords a -> Coords a
rx(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
rx(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
rx]
      [Coords a -> Coords a
forall a. a -> a
id, Coords a -> Coords a
rz, Coords a -> Coords a
rz(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
rz, Coords a -> Coords a
rz(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
rz(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
rz, Coords a -> Coords a
ry, Coords a -> Coords a
ry(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
ry(Coords a -> Coords a)
-> (Coords a -> Coords a) -> Coords a -> Coords a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Coords a -> Coords a
ry]


type Size = Coords Int

unpackCoords :: Size -> PackedCoords -> Coords Int
unpackCoords :: Coords Int -> PackedCoords -> Coords Int
unpackCoords Coords Int
sz (PackedCoords Int
n) =
   (Int, Coords Int) -> Coords Int
forall a b. (a, b) -> b
snd ((Int, Coords Int) -> Coords Int)
-> (Int, Coords Int) -> Coords Int
forall a b. (a -> b) -> a -> b
$ (Int -> Int -> (Int, Int))
-> Int -> Coords Int -> (Int, Coords Int)
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
Trav.mapAccumL Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
divMod Int
n Coords Int
sz

packCoords :: Size -> Coords Int -> PackedCoords
packCoords :: Coords Int -> Coords Int -> PackedCoords
packCoords Coords Int
sz =
   Int -> PackedCoords
PackedCoords (Int -> PackedCoords)
-> (Coords Int -> Int) -> Coords Int -> PackedCoords
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int) -> Int -> Int) -> Int -> Coords (Int, Int) -> Int
forall a b. (a -> b -> b) -> b -> Coords a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Fold.foldr (\(Int
k,Int
x) Int
s -> Int
kInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
x) Int
0 (Coords (Int, Int) -> Int)
-> (Coords Int -> Coords (Int, Int)) -> Coords Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> (Int, Int))
-> Coords Int -> Coords Int -> Coords (Int, Int)
forall a b c. (a -> b -> c) -> Coords a -> Coords b -> Coords c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) Coords Int
sz

normalForm :: (Ord a, Num a) => [Coords a] -> [Coords a]
normalForm :: forall a. (Ord a, Num a) => [Coords a] -> [Coords a]
normalForm [Coords a]
ts = [Coords a] -> [Coords a]
forall a. Ord a => [a] -> [a]
sort ([Coords a] -> [Coords a]) -> [Coords a] -> [Coords a]
forall a b. (a -> b) -> a -> b
$ (Coords a -> Coords a) -> [Coords a] -> [Coords a]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> a -> a) -> Coords a -> Coords a -> Coords a
forall a b c. (a -> b -> c) -> Coords a -> Coords b -> Coords c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Num a => a -> a -> a
subtract Coords a
xyzm) [Coords a]
ts
   where xyzm :: Coords a
xyzm = (Coords a -> Coords a -> Coords a) -> [Coords a] -> Coords a
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 ((a -> a -> a) -> Coords a -> Coords a -> Coords a
forall a b c. (a -> b -> c) -> Coords a -> Coords b -> Coords c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Ord a => a -> a -> a
min) [Coords a]
ts

{- |
Object must be in 'normalForm'.
-}
size :: [Coords Int] -> Coords Int
size :: [Coords Int] -> Coords Int
size = (Int -> Int) -> Coords Int -> Coords Int
forall a b. (a -> b) -> Coords a -> Coords b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Int
forall a. Enum a => a -> a
succ (Coords Int -> Coords Int)
-> ([Coords Int] -> Coords Int) -> [Coords Int] -> Coords Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Coords Int -> Coords Int -> Coords Int)
-> [Coords Int] -> Coords Int
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 ((Int -> Int -> Int) -> Coords Int -> Coords Int -> Coords Int
forall a b c. (a -> b -> c) -> Coords a -> Coords b -> Coords c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Int -> Int -> Int
forall a. Ord a => a -> a -> a
max)

move :: Coords Int -> [Coords Int] -> [Coords Int]
move :: Coords Int -> [Coords Int] -> [Coords Int]
move Coords Int
displacement = (Coords Int -> Coords Int) -> [Coords Int] -> [Coords Int]
forall a b. (a -> b) -> [a] -> [b]
map ((Int -> Int -> Int) -> Coords Int -> Coords Int -> Coords Int
forall a b c. (a -> b -> c) -> Coords a -> Coords b -> Coords c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) Coords Int
displacement)

allPositions :: Size -> [Coords Int] -> [[Coords Int]]
allPositions :: Coords Int -> [Coords Int] -> [[Coords Int]]
allPositions Coords Int
sz [Coords Int]
ts =
   (Coords Int -> [Coords Int]) -> [Coords Int] -> [[Coords Int]]
forall a b. (a -> b) -> [a] -> [b]
map ((Coords Int -> [Coords Int] -> [Coords Int])
-> [Coords Int] -> Coords Int -> [Coords Int]
forall a b c. (a -> b -> c) -> b -> a -> c
flip Coords Int -> [Coords Int] -> [Coords Int]
move [Coords Int]
ts) ([Coords Int] -> [[Coords Int]]) -> [Coords Int] -> [[Coords Int]]
forall a b. (a -> b) -> a -> b
$
   (Int -> [Int]) -> Coords Int -> [Coords Int]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Coords a -> f (Coords b)
Trav.traverse (Int -> Int -> [Int]
forall a. Enum a => a -> a -> [a]
enumFromTo Int
0) (Coords Int -> [Coords Int]) -> Coords Int -> [Coords Int]
forall a b. (a -> b) -> a -> b
$
   (Int -> Int -> Int) -> Coords Int -> Coords Int -> Coords Int
forall a b c. (a -> b -> c) -> Coords a -> Coords b -> Coords c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (-) Coords Int
sz ([Coords Int] -> Coords Int
size [Coords Int]
ts)

allOrientations :: (Num a, Ord a) => [Coords a] -> [[Coords a]]
allOrientations :: forall a. (Num a, Ord a) => [Coords a] -> [[Coords a]]
allOrientations = Coords (Coords a -> Coords a) -> [Coords a] -> [[Coords a]]
forall a.
(Num a, Ord a) =>
Coords (Coords a -> Coords a) -> [Coords a] -> [[Coords a]]
allOrientationsGen Coords (Coords a -> Coords a)
forall a. Num a => Coords (Coords a -> Coords a)
primRotations

allOrientationsGen ::
   (Num a, Ord a) => Coords (Coords a -> Coords a) -> [Coords a] -> [[Coords a]]
allOrientationsGen :: forall a.
(Num a, Ord a) =>
Coords (Coords a -> Coords a) -> [Coords a] -> [[Coords a]]
allOrientationsGen Coords (Coords a -> Coords a)
pr [Coords a]
ts =
   Set [Coords a] -> [[Coords a]]
forall a. Set a -> [a]
Set.toList (Set [Coords a] -> [[Coords a]]) -> Set [Coords a] -> [[Coords a]]
forall a b. (a -> b) -> a -> b
$ [[Coords a]] -> Set [Coords a]
forall a. Ord a => [a] -> Set a
Set.fromList ([[Coords a]] -> Set [Coords a]) -> [[Coords a]] -> Set [Coords a]
forall a b. (a -> b) -> a -> b
$
   ((Coords a -> Coords a) -> [Coords a])
-> [Coords a -> Coords a] -> [[Coords a]]
forall a b. (a -> b) -> [a] -> [b]
map ([Coords a] -> [Coords a]
forall a. (Ord a, Num a) => [Coords a] -> [Coords a]
normalForm ([Coords a] -> [Coords a])
-> ((Coords a -> Coords a) -> [Coords a])
-> (Coords a -> Coords a)
-> [Coords a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Coords a -> Coords a) -> [Coords a] -> [Coords a])
-> [Coords a] -> (Coords a -> Coords a) -> [Coords a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Coords a -> Coords a) -> [Coords a] -> [Coords a]
forall a b. (a -> b) -> [a] -> [b]
map [Coords a]
ts) ([Coords a -> Coords a] -> [[Coords a]])
-> [Coords a -> Coords a] -> [[Coords a]]
forall a b. (a -> b) -> a -> b
$ Coords (Coords a -> Coords a) -> [Coords a -> Coords a]
forall a.
Num a =>
Coords (Coords a -> Coords a) -> [Coords a -> Coords a]
rotationsGen Coords (Coords a -> Coords a)
pr