{- Copyright 2012 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 qualified Data.Map as M; import System.Environment(getArgs); import Data.List(tails) ; type Imap = M.Map Integer Integer; gothrough :: Integer -> Imap ; gothrough d = M.fromListWith (+) $ do { k <- [0..32767] ; return $ (div (multiplier*k) d , 1) } ; {- large multiplier makes it more uniform; look at the output of gothrough (try ./a.out gothrough 128) to see. multiplier 2^48 is the maximum that does not overflow the expr command .-} multiplier :: Integer ; multiplier = 2^48; ceilDiv :: Integer -> Integer -> Integer ; ceilDiv x y = let { (d,m)=divMod x y } in if m>0 then d+1 else d ; get_divisor :: Integer -> Integer; get_divisor sec = ceilDiv (32768*multiplier) ( {- the 1+ makes the random value inclusive, that is, up to and including (say) 10 seconds, not just up to 9 seconds -} 1+ sec) ; prefix :: [Integer] -> [Integer] -> [[Integer]] ; prefix chunksize numchunks = do { last <- numchunks ; return $ last : chunksize } ; sixty :: [Integer] ; sixty = [1,2,5,10,15,20,30,40,45]; dateseries :: [Integer] ; dateseries = [7,24,60,60] ; regular_times :: [[Integer]] ; regular_times = reverse$concat$zipWith prefix (tails dateseries) (map reverse [[1,2,3,4],[1,2,3,4,5,6],[1,2,3,4,6,8,9,12,16,18],sixty,sixty]); day :: [Integer] ; day = tail dateseries ; times3 = regular_times ++ map (\x -> x:day) [30,60,61,90,91,180,182,240,243,270,274,360,365] ; showdiv :: [Integer] -> IO () ; showdiv i = do { putStrLn $ (show i) ++ " " ++ (show $ get_divisor $ product i) } ; main :: IO (); main = do { args <- getArgs ; case args of { ["gothrough",x] -> gothroughtest $ read x ; ["get_divisor",x] -> print $ get_divisor $ read x ; _ -> showdivtest } } ; showdivtest :: IO () ; showdivtest = mapM_ showdiv times3 ; dateseriestest :: IO(); dateseriestest = mapM_ print times3 ; gothroughtest :: Integer -> IO () ; gothroughtest x = print $ gothrough $ get_divisor x ; }