{-# LANGUAGE DataKinds #-}
{-# LANGUAGE UnicodeSyntax #-}
module Data.Rhythm.Binary.Necklaces
(
necklaces,
necklacesAllowed,
necklacesPopCount,
necklacesPopCountAllowed,
necklaces',
)
where
import Control.Bool ((<&&>))
import Data.Bits (Bits (complementBit, rotateL, shiftL), popCount)
import Data.IntSet qualified as IntSet
import Data.List.NonEmpty qualified as NE
import Data.Rhythm.Internal (countParts, nodesToNecklaces)
import Data.Tree (Tree (..), flatten, unfoldTree)
necklaces :: Int -> [[Int]]
necklaces :: Int -> [[Int]]
necklaces !Int
n =
Int -> [Integer] -> [[Int]]
nodesToNecklaces Int
n ([Integer] -> [[Int]]) -> [Integer] -> [[Int]]
forall a b. (a -> b) -> a -> b
$
Tree Integer -> [Integer]
forall a. Tree a -> [a]
flatten (Int -> Tree Integer
forall a. (Integral a, Bits a) => Int -> Tree a
necklaces' Int
n)
necklacesAllowed :: [Int] -> Int -> [[Int]]
necklacesAllowed :: [Int] -> Int -> [[Int]]
necklacesAllowed [Int]
allowed Int
n =
Int -> [Integer] -> [[Int]]
nodesToNecklaces Int
n ([Integer] -> [[Int]]) -> [Integer] -> [[Int]]
forall a b. (a -> b) -> a -> b
$
(Integer -> Bool) -> [Integer] -> [Integer]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0) (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool
forall (f :: * -> *). Applicative f => f Bool -> f Bool -> f Bool
<&&> Integer -> Bool
isAllowed) ([Integer] -> [Integer]) -> [Integer] -> [Integer]
forall a b. (a -> b) -> a -> b
$
Tree Integer -> [Integer]
forall a. Tree a -> [a]
flatten (Int -> Tree Integer
forall a. (Integral a, Bits a) => Int -> Tree a
necklaces' Int
n)
where
isAllowed :: Integer -> Bool
isAllowed = (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> IntSet -> Bool
`IntSet.member` [Int] -> IntSet
IntSet.fromList [Int]
allowed) ([Int] -> Bool) -> (Integer -> [Int]) -> Integer -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer -> [Int]
forall a. (Integral a, Bits a) => Int -> a -> [Int]
countParts Int
n
necklacesPopCount :: Int -> Int -> [[Int]]
necklacesPopCount :: Int -> Int -> [[Int]]
necklacesPopCount !Int
m !Int
n =
Int -> [Integer] -> [[Int]]
nodesToNecklaces Int
n ([Integer] -> [[Int]]) -> [Integer] -> [[Int]]
forall a b. (a -> b) -> a -> b
$
(Integer -> Bool) -> [Integer] -> [Integer]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
m) (Int -> Bool) -> (Integer -> Int) -> Integer -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a. Bits a => a -> Int
popCount) ([Integer] -> [Integer]) -> [Integer] -> [Integer]
forall a b. (a -> b) -> a -> b
$
Tree Integer -> [Integer]
forall a. Tree a -> [a]
flatten (Int -> Tree Integer
forall a. (Integral a, Bits a) => Int -> Tree a
necklaces' Int
n)
necklacesPopCountAllowed :: Int -> [Int] -> Int -> [[Int]]
necklacesPopCountAllowed :: Int -> [Int] -> Int -> [[Int]]
necklacesPopCountAllowed Int
m [Int]
allowed Int
n =
Int -> [Integer] -> [[Int]]
nodesToNecklaces Int
n ([Integer] -> [[Int]]) -> [Integer] -> [[Int]]
forall a b. (a -> b) -> a -> b
$
(Integer -> Bool) -> [Integer] -> [Integer]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0) (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool
forall (f :: * -> *). Applicative f => f Bool -> f Bool -> f Bool
<&&> ((Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
m) (Int -> Bool) -> (Integer -> Int) -> Integer -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a. Bits a => a -> Int
popCount) (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool
forall (f :: * -> *). Applicative f => f Bool -> f Bool -> f Bool
<&&> Integer -> Bool
isAllowed) ([Integer] -> [Integer]) -> [Integer] -> [Integer]
forall a b. (a -> b) -> a -> b
$
Tree Integer -> [Integer]
forall a. Tree a -> [a]
flatten (Int -> Tree Integer
forall a. (Integral a, Bits a) => Int -> Tree a
necklaces' Int
n)
where
isAllowed :: Integer -> Bool
isAllowed = (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> IntSet -> Bool
`IntSet.member` [Int] -> IntSet
IntSet.fromList [Int]
allowed) ([Int] -> Bool) -> (Integer -> [Int]) -> Integer -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer -> [Int]
forall a. (Integral a, Bits a) => Int -> a -> [Int]
countParts Int
n
necklaces' :: (Integral a, Bits a) => Int -> Tree a
necklaces' :: forall a. (Integral a, Bits a) => Int -> Tree a
necklaces' Int
0 = a -> [Tree a] -> Tree a
forall a. a -> [Tree a] -> Tree a
Node a
0 []
necklaces' !Int
n = a -> [Tree a] -> Tree a
forall a. a -> [Tree a] -> Tree a
Node a
0 [(a -> (a, [a])) -> a -> Tree a
forall b a. (b -> (a, [b])) -> b -> Tree a
unfoldTree a -> (a, [a])
search a
1]
where
σ :: a -> a
σ a
necklace = a -> Int -> a
forall a. Bits a => a -> Int -> a
rotateL a
necklace Int
1 a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
m
σʲ :: a -> [a]
σʲ = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ([a] -> [a]) -> (a -> [a]) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NE.tail (NonEmpty a -> [a]) -> (a -> NonEmpty a) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> a -> NonEmpty a
forall a. (a -> a) -> a -> NonEmpty a
NE.iterate a -> a
σ
τ :: a -> a
τ = (a -> Int -> a) -> Int -> a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> Int -> a
forall a. Bits a => a -> Int -> a
complementBit Int
0
search :: a -> (a, [a])
search !a
necklace
| a
necklace a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
m = (a
necklace, [])
| Bool
otherwise = (a
necklace, (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile a -> Bool
isNecklace ((a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map a -> a
τ (a -> [a]
σʲ a
necklace)))
isNecklace :: a -> Bool
isNecklace a
necklace =
a
necklace a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
m
Bool -> Bool -> Bool
|| (a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (a
necklace <=) (a -> [a]
σʲ a
necklace)
m :: a
m = a -> Int -> a
forall a. Bits a => a -> Int -> a
shiftL a
1 Int
n a -> a -> a
forall a. Num a => a -> a -> a
- a
1