-- Jonathan Frech, 2022-02-18, 2022-03-18, 2022-03-19
-- See `https://blog.jfrech.com/256/`.
type Action = [Int] -> ([Int],[Int])
flat :: Int -> Action
flat k xs = (take k xs, drop k xs)
grab :: (Int,Int) -> Action
grab (j,k) xs = (take k (drop j xs), take j xs ++ drop (j+k) xs)
eval :: [Action] -> [Int] -> [Int]
eval (a:as) xs = fst (a xs) ++ eval as (snd $ a xs)
tcheFlat :: Int -> [Int]
tcheFlat 1 = [1..]
tcheFlat n = eval (cycle actions) $ tcheFlat (n-1) where
actions = concat [[flat (n-m), grab (n-m-1,m)] | m <- [1..n-1]]
chunksOf :: Int -> [a] -> [[a]]
chunksOf n xs = take n xs : chunksOf n (drop n xs)
infixl 9 ##
(##) :: [a] -> Int -> a
xs ## k = xs !! (k-1)
tche n i j | j <= n = (chunksOf n $ tcheFlat n) ## i ## j
| otherwise = -n
discreteLimit :: (Int -> Int) -> Int
discreteLimit f = converge $ map f [1..] where
converge (x:x':xs) | x == x' = x
| otherwise = converge (x':xs)
tcheInf i j = discreteLimit $ \n -> tche n i j