{-# LANGUAGE UnicodeSyntax #-}
module Data.Rhythm.Binary.RuskeySavageWang
( necklaces,
necklaces',
nodesToNecklaces,
)
where
import Data.Bits (Bits (complementBit, rotateL, shiftL))
import Data.FastDigits (digits)
import Data.List (sortOn)
import Data.List.NonEmpty qualified as NE
import Data.Ord (Down (..))
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)
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
nodesToNecklaces :: Int -> [Integer] -> [[Int]]
nodesToNecklaces :: Int -> [Integer] -> [[Int]]
nodesToNecklaces !Int
n =
([Int] -> Down [Int]) -> [[Int]] -> [[Int]]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn [Int] -> Down [Int]
forall a. a -> Down a
Down
([[Int]] -> [[Int]])
-> ([Integer] -> [[Int]]) -> [Integer] -> [[Int]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> [Int]) -> [Integer] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> [Int] -> [Int]
padUpTo Int
n ([Int] -> [Int]) -> (Integer -> [Int]) -> Integer -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer -> [Int]
digits Int
2)
padUpTo :: Int -> [Int] -> [Int]
padUpTo :: Int -> [Int] -> [Int]
padUpTo !Int
n [] = Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
n Int
0
padUpTo !Int
n (Int
x : [Int]
xs) = Int
x Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: Int -> [Int] -> [Int]
padUpTo (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Int]
xs