{-# LANGUAGE CPP, BangPatterns #-}
module Math.Combinat.Partitions.Skew where
import Data.List
import Math.Combinat.Classes
import Math.Combinat.Partitions.Integer
import Math.Combinat.ASCII
newtype SkewPartition = SkewPartition [(Int,Int)] deriving (SkewPartition -> SkewPartition -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SkewPartition -> SkewPartition -> Bool
$c/= :: SkewPartition -> SkewPartition -> Bool
== :: SkewPartition -> SkewPartition -> Bool
$c== :: SkewPartition -> SkewPartition -> Bool
Eq,Eq SkewPartition
SkewPartition -> SkewPartition -> Bool
SkewPartition -> SkewPartition -> Ordering
SkewPartition -> SkewPartition -> SkewPartition
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
min :: SkewPartition -> SkewPartition -> SkewPartition
$cmin :: SkewPartition -> SkewPartition -> SkewPartition
max :: SkewPartition -> SkewPartition -> SkewPartition
$cmax :: SkewPartition -> SkewPartition -> SkewPartition
>= :: SkewPartition -> SkewPartition -> Bool
$c>= :: SkewPartition -> SkewPartition -> Bool
> :: SkewPartition -> SkewPartition -> Bool
$c> :: SkewPartition -> SkewPartition -> Bool
<= :: SkewPartition -> SkewPartition -> Bool
$c<= :: SkewPartition -> SkewPartition -> Bool
< :: SkewPartition -> SkewPartition -> Bool
$c< :: SkewPartition -> SkewPartition -> Bool
compare :: SkewPartition -> SkewPartition -> Ordering
$ccompare :: SkewPartition -> SkewPartition -> Ordering
Ord,Int -> SkewPartition -> ShowS
[SkewPartition] -> ShowS
SkewPartition -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SkewPartition] -> ShowS
$cshowList :: [SkewPartition] -> ShowS
show :: SkewPartition -> String
$cshow :: SkewPartition -> String
showsPrec :: Int -> SkewPartition -> ShowS
$cshowsPrec :: Int -> SkewPartition -> ShowS
Show)
mkSkewPartition :: (Partition,Partition) -> SkewPartition
mkSkewPartition :: (Partition, Partition) -> SkewPartition
mkSkewPartition ( lam :: Partition
lam@(Partition [Int]
bs) , mu :: Partition
mu@(Partition [Int]
as)) = if Partition
mu Partition -> Partition -> Bool
`isSubPartitionOf` Partition
lam
then [(Int, Int)] -> SkewPartition
SkewPartition forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
b Int
a -> (Int
a,Int
bforall a. Num a => a -> a -> a
-Int
a)) [Int]
bs ([Int]
as forall a. [a] -> [a] -> [a]
++ forall a. a -> [a]
repeat Int
0)
else forall a. HasCallStack => String -> a
error String
"mkSkewPartition: mu should be a subpartition of lambda!"
safeSkewPartition :: (Partition,Partition) -> Maybe SkewPartition
safeSkewPartition :: (Partition, Partition) -> Maybe SkewPartition
safeSkewPartition ( lam :: Partition
lam@(Partition [Int]
bs) , mu :: Partition
mu@(Partition [Int]
as)) = if Partition
mu Partition -> Partition -> Bool
`isSubPartitionOf` Partition
lam
then forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [(Int, Int)] -> SkewPartition
SkewPartition forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
b Int
a -> (Int
a,Int
bforall a. Num a => a -> a -> a
-Int
a)) [Int]
bs ([Int]
as forall a. [a] -> [a] -> [a]
++ forall a. a -> [a]
repeat Int
0)
else forall a. Maybe a
Nothing
skewPartitionWeight :: SkewPartition -> Int
skewPartitionWeight :: SkewPartition -> Int
skewPartitionWeight (SkewPartition [(Int, Int)]
abs) = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' forall a. Num a => a -> a -> a
(+) Int
0 (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd [(Int, Int)]
abs)
instance HasWeight SkewPartition where
weight :: SkewPartition -> Int
weight = SkewPartition -> Int
skewPartitionWeight
normalizeSkewPartition :: SkewPartition -> SkewPartition
normalizeSkewPartition :: SkewPartition -> SkewPartition
normalizeSkewPartition (SkewPartition [(Int, Int)]
abs) = [(Int, Int)] -> SkewPartition
SkewPartition [(Int, Int)]
abs' where
([Int]
as,[Int]
bs) = forall a b. [(a, b)] -> ([a], [b])
unzip [(Int, Int)]
abs
a0 :: Int
a0 = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Int]
as
k :: Int
k = forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall a. (a -> Bool) -> [a] -> [a]
takeWhile (forall a. Eq a => a -> a -> Bool
==Int
0) [Int]
bs)
abs' :: [(Int, Int)]
abs' = forall a b. [a] -> [b] -> [(a, b)]
zip [ Int
aforall a. Num a => a -> a -> a
-Int
a0 | Int
a <- forall a. Int -> [a] -> [a]
drop Int
k [Int]
as ] (forall a. Int -> [a] -> [a]
drop Int
k [Int]
bs)
fromSkewPartition :: SkewPartition -> (Partition,Partition)
fromSkewPartition :: SkewPartition -> (Partition, Partition)
fromSkewPartition (SkewPartition [(Int, Int)]
list) = ([Int] -> Partition
toPartition (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Num a => a -> a -> a
(+) [Int]
as [Int]
bs) , [Int] -> Partition
toPartition (forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Ord a => a -> a -> Bool
>Int
0) [Int]
as)) where
([Int]
as,[Int]
bs) = forall a b. [(a, b)] -> ([a], [b])
unzip [(Int, Int)]
list
outerPartition :: SkewPartition -> Partition
outerPartition :: SkewPartition -> Partition
outerPartition = forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. SkewPartition -> (Partition, Partition)
fromSkewPartition
innerPartition :: SkewPartition -> Partition
innerPartition :: SkewPartition -> Partition
innerPartition = forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. SkewPartition -> (Partition, Partition)
fromSkewPartition
dualSkewPartition :: SkewPartition -> SkewPartition
dualSkewPartition :: SkewPartition -> SkewPartition
dualSkewPartition = (Partition, Partition) -> SkewPartition
mkSkewPartition forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Partition, Partition) -> (Partition, Partition)
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. SkewPartition -> (Partition, Partition)
fromSkewPartition where
f :: (Partition, Partition) -> (Partition, Partition)
f (Partition
lam,Partition
mu) = (Partition -> Partition
dualPartition Partition
lam, Partition -> Partition
dualPartition Partition
mu)
instance HasDuality SkewPartition where
dual :: SkewPartition -> SkewPartition
dual = SkewPartition -> SkewPartition
dualSkewPartition
skewPartitionElements :: SkewPartition -> [(Int, Int)]
skewPartitionElements :: SkewPartition -> [(Int, Int)]
skewPartitionElements (SkewPartition [(Int, Int)]
abs) = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ (Int
i,Int
j) | Int
j <- [Int
aforall a. Num a => a -> a -> a
+Int
1 .. Int
aforall a. Num a => a -> a -> a
+Int
b] ]
| (Int
i,(Int
a,Int
b)) <- forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1..] [(Int, Int)]
abs
]
skewPartitionsWithOuterShape :: Partition -> Int -> [SkewPartition]
skewPartitionsWithOuterShape :: Partition -> Int -> [SkewPartition]
skewPartitionsWithOuterShape Partition
outer Int
skewWeight
| Int
innerWeight forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
innerWeight forall a. Ord a => a -> a -> Bool
> Int
outerWeight = []
| Bool
otherwise = [ (Partition, Partition) -> SkewPartition
mkSkewPartition (Partition
outer,Partition
inner) | Partition
inner <- Int -> Partition -> [Partition]
subPartitions Int
innerWeight Partition
outer ]
where
outerWeight :: Int
outerWeight = forall a. HasWeight a => a -> Int
weight Partition
outer
innerWeight :: Int
innerWeight = Int
outerWeight forall a. Num a => a -> a -> a
- Int
skewWeight
allSkewPartitionsWithOuterShape :: Partition -> [SkewPartition]
allSkewPartitionsWithOuterShape :: Partition -> [SkewPartition]
allSkewPartitionsWithOuterShape Partition
outer
= forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ Partition -> Int -> [SkewPartition]
skewPartitionsWithOuterShape Partition
outer Int
w | Int
w<-[Int
0..Int
outerWeight] ]
where
outerWeight :: Int
outerWeight = forall a. HasWeight a => a -> Int
weight Partition
outer
skewPartitionsWithInnerShape :: Partition -> Int -> [SkewPartition]
skewPartitionsWithInnerShape :: Partition -> Int -> [SkewPartition]
skewPartitionsWithInnerShape Partition
inner Int
skewWeight
| Int
innerWeight forall a. Ord a => a -> a -> Bool
> Int
outerWeight = []
| Bool
otherwise = [ (Partition, Partition) -> SkewPartition
mkSkewPartition (Partition
outer,Partition
inner) | Partition
outer <- Int -> Partition -> [Partition]
superPartitions Int
outerWeight Partition
inner ]
where
outerWeight :: Int
outerWeight = Int
innerWeight forall a. Num a => a -> a -> a
+ Int
skewWeight
innerWeight :: Int
innerWeight = forall a. HasWeight a => a -> Int
weight Partition
inner
asciiSkewFerrersDiagram :: SkewPartition -> ASCII
asciiSkewFerrersDiagram :: SkewPartition -> ASCII
asciiSkewFerrersDiagram = (Char, Char) -> PartitionConvention -> SkewPartition -> ASCII
asciiSkewFerrersDiagram' (Char
'@',Char
'.') PartitionConvention
EnglishNotation
asciiSkewFerrersDiagram'
:: (Char,Char)
-> PartitionConvention
-> SkewPartition
-> ASCII
asciiSkewFerrersDiagram' :: (Char, Char) -> PartitionConvention -> SkewPartition -> ASCII
asciiSkewFerrersDiagram' (Char
outer,Char
inner) PartitionConvention
orient (SkewPartition [(Int, Int)]
abs) = [String] -> ASCII
asciiFromLines [String]
stuff where
stuff :: [String]
stuff = case PartitionConvention
orient of
PartitionConvention
EnglishNotation -> [String]
ls
PartitionConvention
EnglishNotationCCW -> forall a. [a] -> [a]
reverse (forall a. [[a]] -> [[a]]
transpose [String]
ls)
PartitionConvention
FrenchNotation -> forall a. [a] -> [a]
reverse [String]
ls
ls :: [String]
ls = [ forall a. Int -> a -> [a]
replicate Int
a Char
inner forall a. [a] -> [a] -> [a]
++ forall a. Int -> a -> [a]
replicate Int
b Char
outer | (Int
a,Int
b) <- [(Int, Int)]
abs ]
instance DrawASCII SkewPartition where
ascii :: SkewPartition -> ASCII
ascii = SkewPartition -> ASCII
asciiSkewFerrersDiagram