{- Generate digit sequences having digit patterns that make it (somewhat) easy to count its length. Usage examples: 1. Generate a decimal digit sequence of length 123: ./a.out 10 123 2. Generate base-4 digit sequences of length 1 through length 70: ./a.out demo4 70 Copyright 2022 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 . -} {-# LANGUAGE ScopedTypeVariables, LambdaCase #-} module Main(main) where { import System.Environment(getArgs); import Data.Function((&)); import Control.Category((>>>)); import Prelude hiding((.),(>>)); import qualified Data.List as List; import Data.Tuple(swap); main :: IO(); main = getArgs >>= \case{ ["go",base,n] -> createstring (read base) (read n) & putStrLn; ["demo4",n] -> strings_demo 4 (read n); _ -> undefined; }; -- this works up to base 36 positive_digits :: String; positive_digits = "123456789" ++ ['a'..'z']; -- output is little-endian, i.e., the 1's place is at the head of the list. radix_convert :: Integer -> Integer -> [Integer]; radix_convert base = List.unfoldr $ \n -> if n==0 then Nothing else Just $ swap $ divMod n base; -- expand by 10 dogrow :: Integer -> Char -> String; dogrow base '1' = List.genericTake (base-1) positive_digits ++ "0"; dogrow base c = List.genericReplicate base c; -- process little-endian input one digit at a time growasdigits :: Integer -> [Integer] -> String; growasdigits _base [] = ""; growasdigits base (h:t) = (growasdigits base t & concatMap (dogrow base)) ++ List.genericTake h positive_digits; createstring :: Integer -> Integer -> String; createstring base = radix_convert base >>> growasdigits base; strings_demo :: Integer -> Integer -> IO(); strings_demo base num = flip mapM_ [1..num] $ \n -> putStrLn $(radix_convert base n & reverse & map show & concat) ++ " " ++ createstring base n; } --end