module Jikka.Common.Combinatorics where

fact :: Integral a => a -> a
fact :: a -> a
fact a
n | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"Jikka.Common.Combinatorics.fact: invalid argument"
fact a
n = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [a
1 .. a
n]

choose :: Integral a => a -> a -> a
choose :: a -> a -> a
choose a
n a
r | Bool -> Bool
not (a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
r Bool -> Bool -> Bool
&& a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
n) = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"Jikka.Common.Combinatorics.choose: invalid argument"
choose a
n a
r = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [a
n a -> a -> a
forall a. Num a => a -> a -> a
- a
r a -> a -> a
forall a. Num a => a -> a -> a
+ a
1 .. a
n] a -> a -> a
forall a. Integral a => a -> a -> a
`div` [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [a
1 .. a
r]

permute :: Integral a => a -> a -> a
permute :: a -> a -> a
permute a
n a
r | Bool -> Bool
not (a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
r Bool -> Bool -> Bool
&& a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
n) = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"Jikka.Common.Combinatorics.permute: invalid argument"
permute a
n a
r = [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [a
n a -> a -> a
forall a. Num a => a -> a -> a
- a
r a -> a -> a
forall a. Num a => a -> a -> a
+ a
1 .. a
n]

multichoose :: Integral a => a -> a -> a
multichoose :: a -> a -> a
multichoose a
n a
r | Bool -> Bool
not (a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
r Bool -> Bool -> Bool
&& a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
n) = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"Jikka.Common.Combinatorics.multichoose: invalid argument"
multichoose a
0 a
0 = a
1
multichoose a
n a
r = a -> a -> a
forall a. Integral a => a -> a -> a
choose (a
n a -> a -> a
forall a. Num a => a -> a -> a
+ a
r a -> a -> a
forall a. Num a => a -> a -> a
- a
1) a
r