module Music.Theory.Z.Morris_1974 where
import Control.Monad
import qualified Control.Monad.Logic as L
fromList :: MonadPlus m => [a] -> m a
fromList :: forall (m :: * -> *) a. MonadPlus m => [a] -> m a
fromList = forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (m :: * -> *) a. Monad m => a -> m a
return
int_n :: Integral a => a -> a -> a -> a
int_n :: forall a. Integral a => a -> a -> a -> a
int_n a
n a
i a
j = forall a. Num a => a -> a
abs ((a
j forall a. Num a => a -> a -> a
- a
i) forall a. Integral a => a -> a -> a
`mod` a
n)
all_interval_m :: (MonadPlus m, L.MonadLogic m) => Int -> m [Int]
all_interval_m :: forall (m :: * -> *). (MonadPlus m, MonadLogic m) => Int -> m [Int]
all_interval_m Int
n =
let recur :: Int -> [Int] -> [Int] -> m [Int]
recur Int
k [Int]
p [Int]
q =
if Int
k forall a. Eq a => a -> a -> Bool
== Int
n
then forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. [a] -> [a]
reverse [Int]
p)
else do Int
i <- forall (m :: * -> *) a. MonadPlus m => [a] -> m a
fromList [Int
1 .. Int
n forall a. Num a => a -> a -> a
- Int
1]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Int
i forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Int]
p)
let j :: Int
j = forall a. [a] -> a
head [Int]
p
m :: Int
m = forall a. Integral a => a -> a -> a -> a
int_n Int
n Int
i Int
j
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Int
m forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Int]
q)
Int -> [Int] -> [Int] -> m [Int]
recur (Int
k forall a. Num a => a -> a -> a
+ Int
1) (Int
i forall a. a -> [a] -> [a]
: [Int]
p) (Int
m forall a. a -> [a] -> [a]
: [Int]
q)
in forall {m :: * -> *}.
MonadPlus m =>
Int -> [Int] -> [Int] -> m [Int]
recur Int
1 [Int
0] []
all_interval :: Int -> [[Int]]
all_interval :: Int -> [[Int]]
all_interval = forall a. Logic a -> [a]
L.observeAll forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *). (MonadPlus m, MonadLogic m) => Int -> m [Int]
all_interval_m