import Data.Bool (bool) import Data.List (intercalate, transpose) import qualified Data.Map.Strict as M import Data.Maybe (maybe) --------------------------- MAIN ------------------------- main :: IO () main = (putStrLn . unlines) $ mayanFramed <$> [ 4005, 8017, 326205, 886205, 1081439556, 1000000, 1000000000 ] ---------------------- MAYAN NUMBERS --------------------- mayanGlyph :: Int -> [[String]] mayanGlyph = filter (any (not . null)) . transpose . leftPadded . flip (showIntAtBaseS 20 mayanDigit) [] mayanDigit :: Int -> [String] mayanDigit n | 0 /= n = replicate (rem n 5) mayaOne : concat ( replicate (quot n 5) [mayaFive] ) | otherwise = [[mayaZero]] mayanFramed :: Int -> String mayanFramed = ("Mayan " <>) . ( (<>) <$> show <*> ( (":\n\n" <>) . wikiTable ( M.fromList [ ( "style", concat [ "text-align:center;", "background-color:#F0EDDE;", "color:#605B4B;", "border:2px solid silver;" ] ), ("colwidth", "3em;") ] ) . mayanGlyph ) ) mayaZero, mayaOne :: Char mayaZero = '\920' mayaOne = '\9679' mayaFive :: String mayaFive = "\9473\9473" ---------------------- NUMERIC BASES --------------------- -- Based on the Prelude showIntAtBase but uses an -- (Int -> [String]) (rather than Int -> Char) function -- as its second argument. -- -- Shows a /non-negative/ 'Integral' number using the base -- specified by the first argument, and the **String** -- representation specified by the second. showIntAtBaseS :: Integral a => a -> (Int -> [String]) -> a -> [[String]] -> [[String]] showIntAtBaseS base toStr n0 r0 = let go (n, d) r = seq s $ case n of 0 -> r_ _ -> go (quotRem n base) r_ where s = toStr (fromIntegral d) r_ = s : r in go (quotRem n0 base) r0 ------------------------- DISPLAY ------------------------ wikiTable :: M.Map String String -> [[String]] -> String wikiTable opts rows | null rows = [] | otherwise = "{| " <> foldr ( \k a -> maybe a ( ((a <> k <> "=\"") <>) . ( <> "\" " ) ) (M.lookup k opts) ) [] ["class", "style"] <> ( '\n' : intercalate "|-\n" ( zipWith renderedRow rows [0 ..] ) ) <> "|}\n\n" where renderedRow row i = unlines ( fmap ( ( bool [] ( maybe "|" (("|style=\"width:" <>) . (<> "\"")) (M.lookup "colwidth" opts) ) (0 == i) <> ) . ('|' :) ) row ) leftPadded :: [[String]] -> [[String]] leftPadded xs = let w = maximum (length <$> xs) in ((<>) =<< flip replicate [] . (-) w . length) <$> xs