{-# LANGUAGE LambdaCase, ScopedTypeVariables #-} {- Copyright 2014 Ken Takusagawa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} module Main where { import Data.List(unfoldr,(\\),genericIndex,genericLength, intersperse); import Data.Tuple(swap); import System.Environment(getArgs); -- least significant digit at the head of the list radix_convert :: Integer -> Integer -> [Integer]; radix_convert base = unfoldr $ \n -> if n==0 then Nothing else Just $ swap $ divMod n base; -- radix_convert base = unfoldr $ single base; factorial :: Integer -> Integer; factorial n = product [1..n]; excluded :: [Int]; excluded = accents ++ tall -- ++ tall_15 ++ veryshort ++ aboveBaseline ; -- see http://kenta.blogspot.com/2014/02/azjtcizp-latin-1.html latin1 :: [String]; latin1 = latin1'; latin1' :: [String]; latin1' = map htmlentity $ [0..255] \\ (nonprinting ++ excluded); nonprinting :: [Int]; nonprinting = [0..31] ++ [128..159] ++ [32,127,160,173]; -- space del nbsp soft-hyphen -- these look weird not attached to a character accents :: [Int]; accents = [96,168,175,180,184]; -- tall characters (which happen all be capital) with an accent over them, making them even taller, which may interfere with line spacing. tall :: [Int]; tall = [192..221] \\ [198,199,208,215,216]; -- additional tall characters in ISO 8859-15 tall_15 :: [Int]; tall_15 = [166,180,190]; veryshort :: [Int]; veryshort = map fromEnum "_.," ; aboveBaseline :: [Int]; aboveBaseline = map fromEnum "\"'" ++ [170, 176, 178, 179, 185, 186]; -- fem ordinal, degree, 2, 3, 1, masc ordinal htmlentity :: Int -> String; htmlentity 38 = "&"; htmlentity 60 = "<"; htmlentity i = if i < 128 then [toEnum i] else "&#"++(show i)++";"; intersperser :: String; -- intersperser = "­"; intersperser = ""; makeHTML :: Integer -> String ; makeHTML n = "" ++ (show n) ++ "! in base " ++ (show $ length latin1)++ "

" ++ (concat $ intersperse intersperser $ case n of { 0 -> latin1 ; 1 -> map htmlentity excluded ; _ -> reverse $ map (genericIndex latin1) $ radix_convert (genericLength latin1) $ factorial n ; }) ++ "

"; main :: IO(); main = getArgs >>= putStrLn . makeHTML . read . head ; }