import Data.List (intercalate) -- Widened borrow of a particular repeated amount -- i.e., for borrow2 qr 2, the borrow is 22 = 100 -- `qr` is an integer division function returning the quotient and remainder. -- i.e., either `divMod` or `quotRem` borrow2' qr b | b == 1 = error "Cannot borrow 1: implies positional symbol zero disallowed" | otherwise = borrow' [] where borrow' zs (x:y:z:xs) | abs x >= b = zipUp ys zs -- carry here | otherwise = borrow' (x:zs) (y:z:xs) -- try borrowing at a higher place value where ys = r : y-x+r : z+q : xs (q, r) = x `qr` b zipUp = foldl (flip (:)) borrow2 = borrow2' quotRem --degenerate `borrow2 1` that remedies inadequacies in below for 1, i.e., the borrow is 11 = 100 --this system is VERY bad because we invoke the place value '0' to expand into --borrow1' zs (x:y:z:xs) | abs x > 1 = zipUp ys zs -- | otherwise = borrow1' (x:zs) (y:z:xs) -- where ys = (signum x):(y-x+signum x):z+(x-1):xs -- Truncate the adic expansion to n digits, for a system where borrows are two digits wide and both b truncadic' n b = (!! n) . iterate (borrow2 b) truncadic n = (take n .) . truncadic' n -- same but, produce a list of expansions, taking modulo m in between borrows truncadicMod b m n = map (take n) . take n . iterate (map (`rem` m) . borrow2 2) -- Find moduli starting from `s` where truncations agree -- Caveat: the last of truncadicMod is not guaranteed to exhaust terms outside alphabet -- i.e., for b = 2, the alphabet {-1, 0, 1} findAccurate n b s xs = map fst $ filter ((==good) . snd) bads where good = truncadic n b xs bads = map (\m -> (,) m $ last $ truncadicMod b m n xs) [s..] -- Given an amount of digits `n`, a 2-wide borrow `b`, and a canonical representation of `b` -- construct integer multiples of `b` evens n b = ([0]:) . map (take n) . iterate addb -- add b to an adic expansion where addb = truncadic' n b . (b:) . tail -- first 200 digits of cendree-adic expansions of even numbers adics = evens 200 2 $ 0:0:cycle [1,-1] adic2 = adics !! 1 -- Expansion of 4, generated from incrementing the expansion of 2 twice adic4 = adics !! 2 -- Expansion of 4, generated from pointwise multiplication of the expansion of 2 adic4' = truncadic 200 2 $ (++repeat 0) $ map (*2) adic2 -- Note: `truncadic 200 n $ 4:repeat 0` is the aggressive application of the carry to 4 -- but this could be done better since there are only 3 terms in the head, and no higher -- series terms get in the way; the remainders would be emitted while the thunk continued truncadicQR' qr n b = (!! n) . iterate (borrow2' qr b) truncadicQR qr n b = take n . truncadicQR' qr n b -- Given an amount of digits `n`, a 2-wide borrow `b`, and a canonical representation of `b` -- construct integer multiples of `b` evensQR qr n b = ([0]:) . map (take n) . iterate addb -- add b to an adic expansion where addb = truncadicQR' qr n b . (b:) . tail data QRMethod = QuotRem | DivMod deriving Show qrMethod QuotRem = quotRem qrMethod DivMod = divMod cendreeEvens' :: QRMethod -> Int -> Int -> [[Int]] cendreeEvens' qr m n = take m $ evensQR qr' n 2 $ truncadicQR qr' (n + 2) 2 $ 2:repeat 0 where qr' = qrMethod qr cendreeEvens :: QRMethod -> Int -> Int -> IO () cendreeEvens qr m n = writeFile fn $ display $ cendreeEvens' qr m n where display = unlines . map (intercalate "," . map show) fn = "cendree_" ++ show qr ++ "_count_" ++ show m ++ "_" ++ show n ++ "_digits.csv"