All Source For ghc |
Ackermann's Function |
-- $Id: ackermann.ghc,v 1.5 2001/06/16 01:33:06 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- shortened by Bryn Keller
import System(getArgs)
main = do
~[number] <- getArgs
let n = read number in
putStrLn ("Ack(3," ++ (show n) ++ "): " ++ (show (ack 3 n)))
ack :: Int -> Int -> Int
ack 0 n = n+1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) (ack m (n-1));
|
Array Access |
-- $Id: ary3.ghc,v 1.2 2001/06/01 17:56:49 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- TBD: try rewrite with STUArray or IOUArray
module Main where
import IArray
import System
make_x :: Int -> UArray Int Int
make_x len = array (1,len) [(i, i) | i <- [1..len]]
make_y0 :: Int -> UArray Int Int
make_y0 len = array (1,len) [(i, 0) | i <- [1..len]]
add_array :: Int -> UArray Int Int -> UArray Int Int -> UArray Int Int
add_array 0 a b = b
add_array len a b = array (1,len) [(i, ((a ! i) + (b ! i))) | i <- [1..len]]
add_arrays_n :: Int -> Int -> UArray Int Int -> UArray Int Int -> UArray Int Int
add_arrays_n 0 len a b = b
add_arrays_n n len a b =
add_arrays_n (n-1) len a (add_array len a b)
ary3 :: Int -> IO ()
ary3 len = do putStr (show (y ! 1)) ; putStr " " ; putStrLn (show (y ! len))
where y = add_arrays_n 1000 len (make_x len) (make_y0 len)
main = do
~[n] <- getArgs
ary3 (read n::Int)
|
Count Lines/Words/Chars |
-- $Id: wc.ghc,v 1.2 2001/05/24 14:05:53 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Brian Gregor
module Main where
-- compile with: ghc -O -o wc -package lang wc.hs
import IO
import IOExts
import PackedString
main = do
-- set buffer to 4k
hSetBuffering stdin (BlockBuffering (Just 4096))
-- these are mutable variables
nL <- newIORef 0
nW <- newIORef 0
nC <- newIORef 0
(nl,nw,nc) <- countAll nL nW nC
putStrLn ((show nl)++" "++(show nw)++" "++(show nc))
countAll :: IORef Int -> IORef Int -> IORef Int -> IO (Int,Int,Int)
countAll nL nW nC = do
end <- hIsEOF stdin
nl <- readIORef nL
nw <- readIORef nW
nc <- readIORef nC
if (not end)
then (do
inStr <- hGetLine stdin
-- using a packed string is a small speed win
let str = packString inStr
-- using IORefs makes it easy to force strict
-- evaluation - how to easily do this without
-- IORefs?
writeIORef nL $! (nl + 1)
writeIORef nW $! (nw + (length (wordsPS str)))
writeIORef nC $! (nc + 1 + (lengthPS str))
countAll nL nW nC)
else return (nl,nw,nc)
|
Echo Client/Server |
-- $Id: echo.ghc,v 1.2 2001/05/01 20:19:52 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- Haskell echo/client server
-- written by Brian Gregor
-- compile with:
-- ghc -O -o echo -package net -package concurrent -package lang echo.hs
module Main where
import SocketPrim
import Concurrent
import System (getArgs,exitFailure)
import Exception(finally)
import MVar
server_sock = do
s <- socket AF_INET Stream 6
setSocketOption s ReuseAddr 1
bindSocket s (SockAddrInet (mkPortNumber portnum) iNADDR_ANY)
listen s 2
return s
echo_server s = do
(s', clientAddr) <- accept s
proc <- read_data s' 0
putStrLn ("server processed "++(show proc)++" bytes")
sClose s'
where
read_data sock totalbytes = do
(str,i) <- readSocket sock 19
if (i >= 19)
then (do
writ <- writeSocket sock str
read_data sock $! (totalbytes+(length $! str)))
else (return totalbytes)
local = "127.0.0.1"
message = "Hello there sailor\n"
portnum = 7001
client_sock = do
s <- socket AF_INET Stream 6
ia <- inet_addr local
connect s (SockAddrInet (mkPortNumber portnum) ia)
return s
echo_client n = do
s <- client_sock
drop <- server_echo s n
sClose s
where
server_echo sock n
| n > 0 =(do
writeSocket sock message
(str,i) <- readSocket sock 19
if (str /= message) then (do exitFailure)
else server_echo sock (n-1))
| otherwise = (return [])
main = do
~[n] <- getArgs
-- server & client semaphores
--get the server socket
ssock <- server_sock
-- fork off the server
s <- myForkIO (echo_server ssock)
-- fork off the client
c <- myForkIO (echo_client (read n::Int))
-- let 'em run until they've signaled they're done
join s ; join c
-- these are used to make the main thread wait until
-- the child threads have exited
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
forkIO (io `finally` putMVar mvar ())
return mvar
join :: MVar () -> IO ()
join mvar = readMVar mvar
|
Exception Mechanisms |
-- $Id: except.ghc,v 1.2 2001/05/20 00:21:36 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Simon Marlow
import System
import Exception
import IOExts
blowup n | even n = throw (ErrorCall "H")
| otherwise = throw (ErrorCall "L")
lo_function lo n =
Exception.catchAllIO (blowup n)
(\ex -> case ex of
ErrorCall "L" -> do nlo <- readIORef lo
writeIORef lo (nlo + 1)
_ -> throw ex
)
hi_function hi lo n =
Exception.catchAllIO (lo_function lo n)
(\ex -> case ex of
ErrorCall "H" -> do nhi <- readIORef hi
writeIORef hi (nhi + 1)
_ -> throw ex
)
some_function hi lo n = hi_function hi lo n
main = do
[arg] <- getArgs
let n = read arg :: Int
hi <- newIORef (0 :: Int)
lo <- newIORef (0 :: Int)
mapM (some_function hi lo) [n,n-1..1]
nhi <- readIORef hi
nlo <- readIORef lo
putStrLn ("Exceptions: HI=" ++ show nhi ++ " / LO=" ++ show nlo)
|
Fibonacci Numbers |
-- $Id: fibo.ghc,v 1.4 2001/06/14 23:55:06 doug Exp $
-- http://www.bagley.org/~doug/shootout/
import System(getArgs, getProgName, exitWith, ExitCode(..))
main = do
arg <- getArgs
case arg of
[number] -> putStrLn (show (fib (read number)))
_ -> do
progname <- getProgName
putStrLn ("Usage: " ++ progname ++ " number")
exitWith (ExitFailure 1)
fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
|
Hash (Associative Array) Access |
-- $Id: hash.ghc,v 1.3 2001/06/18 18:17:03 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Bryn Keller
-- build with ghc -O2 -package data hash.ghc
import System (getArgs)
import FiniteMap
import Numeric (showInt)
countKeys tbl 0 = 0
countKeys tbl n = case (lookupWithDefaultFM tbl False (show n)) of
True -> 1 + countKeys tbl (n - 1)
_ -> countKeys tbl (n - 1)
buildTable tbl max num | num <= max = buildTable (addToFM tbl (showHex num "") True) max (num + 1)
| otherwise = tbl
showHex n r = let (n',d) = quotRem n 16
r' = toEnum (fromEnum '0' + fromIntegral d) : r
in if n' == 0 then r' else showHex n' r'
main = do args <- getArgs
case args of
[number] -> let num = read number
tbl = buildTable emptyFM num 1
in do putStrLn $ show (countKeys tbl num)
_ -> fail "You must enter a number."
|
Heapsort |
-- $Id: heapsort.ghc,v 1.2 2001/05/08 02:46:59 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange
module Main(main) where
import System(getArgs, exitWith, ExitCode(..))
import Numeric(showFFloat)
main = do
arg <- getArgs
case arg of
[num] -> putStrLn (showFFloat (Just 10) answer "")
where
answer = last . heapsort .
take (read num) . random $ 1.0
_ -> exitWith (ExitFailure 1)
-- construct an infinite list of random numbers
random :: Double -> [Double]
random max = map norm . rand $ 42
where norm x = (fromIntegral x) * (max / (fromIntegral im))
rand x = x' : (rand x')
where x' = (x * ia + ic) `mod` im
im = 139968
ia = 3877
ic = 29573
-- fold up a list like a tree
treefold f z [] = z
treefold f z [x] = x
treefold f z (a:b:l) = treefold f z (f a b : pairfold l)
where pairfold (x:y:rest) = f x y : pairfold rest
pairfold l = l
-- heapfold using linked lists
data Heap a = Nil | Node a [Heap a]
heapsort :: Ord a => [a] -> [a]
heapsort = flatten_heap . merge_heaps . map heapify
where heapify x = Node x []
merge_heaps :: Ord a => [Heap a] -> Heap a
merge_heaps = treefold merge_heap Nil
flatten_heap Nil = []
flatten_heap (Node x heaps) = x:flatten_heap (merge_heaps heaps)
merge_heap Nil Nil = Nil
merge_heap heap@(Node _ _) Nil = heap
merge_heap node_a@(Node a heaps_a) node_b@(Node b heaps_b)
| a < b = Node a (node_b : heaps_a)
| otherwise = Node b (node_a : heaps_b)
|
Hello World |
-- $Id: hello.ghc,v 1.1 2001/06/17 22:00:34 doug Exp $
-- http://www.bagley.org/~doug/shootout/
main = do putStrLn "hello world"
|
List Operations |
-- $Id: lists.ghc,v 1.1 2001/06/12 04:47:12 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Michal Gajda
module Main(main) where
import Prelude
copy [] = []
copy (x:xs) = x:copy xs
-- to be honest, in pure functional language the RIGHT
-- thing is copy list = list, because it's not mutable anyway
-- (and the price is paid when doing reverse or (++) anyway)
-- `seq`s below force evaluation of isok1 and isok2
test :: Int -> Int
test size = isok1 `seq` length l3
where single x = [x]
l1 = [1..size]
l2 = copy l1 -- Should be just: "l1"
l3 = foldl (++) [] (map single l2)
l2' = foldr (++) [] (map single l3)
l1' = reverse l1
isok1 = head l1' == size
isok2 = l1' == l2'
main = do s <- getLine
putStrLn . show . test . read $ s
|
Matrix Multiplication |
-- $Id: matrix.ghc,v 1.3 2001/06/01 17:56:49 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange
-- TBD: try rewrite with STUArray or IOUArray?
module Main(main) where
import System(getArgs, exitWith, ExitCode(..))
import Numeric(readDec)
import List(transpose)
main = do
arg <- getArgs
case arg of
[number] -> putStrLn (disp m 0 0 ++ " " ++
disp m 2 3 ++ " " ++
disp m 3 2 ++ " " ++
disp m 4 4)
where
disp m row col = show (m!!row!!col)
m = powmat (fst (head (readDec number)))
_ -> exitWith (ExitFailure 1)
size = 30
-- ghc is able to optimize out enough invariants so that the
-- traditional form this test runs in O(1)
--
-- this would have ghc trounce all other entrants, so to get
-- closer to the general meaning of the test, we cascade
-- matrix multiplications. this means the results are, by necessity,
-- different, but involve just as many mmults. i.e for n=1 the results
-- are identical.
powmat n = power n (mmult . transpose $ mkmat size) (mkmat size)
where
power n f | n > 0 = f . (power (n-1) f)
| otherwise = id
mkmat x = [[(y-1)*x+1..y*x]| y <- [1..x]]
mmult a b = [[dot row col 0 | col <- a]| row <- b]
where
dot :: [Int] -> [Int] -> Int -> Int
dot (x:xs) (y:ys) z = dot xs ys (z + x*y)
dot _ _ z = z
-- slightly slower transposing mmult in one line:
-- mmult a b = [[sum$zipWith (*) row col 0 | col <- transpose a]| row <-b]
|
Nested Loops |
-- $Id: nestedloop.ghc,v 1.1 2001/02/22 23:22:11 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Brian Gregor
module Main where
import System(getArgs, exitWith, ExitCode(..))
import Numeric(readDec)
main = do
arg <- getArgs
case arg of
[number] -> let n = fst (head (readDec number)) in
putStrLn (show (loopA n n 0))
_ -> exitWith (ExitFailure 1)
loopA :: Int -> Int -> Int -> Int
loopA n m x
| n > 0 = loopA (n-1) m (loopB m m x)
| otherwise = x
loopB :: Int -> Int -> Int -> Int
loopB n m x
| n > 0 = loopB (n-1) m (loopC m m x)
| otherwise = x
loopC :: Int -> Int -> Int -> Int
loopC n m x
| n > 0 = loopC (n-1) m (loopD m m x)
| otherwise = x
loopD :: Int -> Int -> Int -> Int
loopD n m x
| n > 0 = loopD (n-1) m (loopE m m x)
| otherwise = x
loopE :: Int -> Int -> Int -> Int
loopE n m x
| n > 0 = loopE (n-1) m (loopF m x)
| otherwise = x
loopF :: Int -> Int -> Int
loopF n x
| n > 0 = loopF (n-1) (x+1)
| otherwise = x
|
Producer/Consumer Threads |
-- $Id: prodcons.ghc,v 1.1 2001/02/28 01:08:27 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Josef Svenningsson
module Main where
import CVar
import MVar
import Concurrent
import Exception
import IOExts
import System
producer :: Int -> IORef Int -> CVar Int -> IO ()
producer n p ch = sequence_ (map send [1..n])
where send i = do writeCVar ch i
prod <- readIORef p
writeIORef p (prod+1)
consumer :: Int -> IORef Int -> CVar Int -> IO ()
consumer n c ch = cons 1
where cons i | n <= i = return ()
cons i
= do i <- readCVar ch
con <- readIORef c
writeIORef c (con+1)
cons i
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
forkIO (io `finally` putMVar mvar ())
return mvar
join :: MVar () -> IO ()
join mvar = readMVar mvar
main = do (a:_) <- getArgs
let n = read a
produced <- newIORef 0
consumed <- newIORef 0
channel <- newCVar
p <- myForkIO (producer n produced channel)
c <- myForkIO (consumer n consumed channel)
join p; join c
prod <- readIORef produced
cons <- readIORef consumed
putStrLn (show prod ++ " " ++ show cons)
|
Random Number Generator |
-- $Id: random.ghc,v 1.5 2001/05/18 07:10:55 doug Exp $
-- http://www.bagley.org/~doug/shootout/
module Main(main) where
import System(getArgs)
import Numeric(showFFloat)
main = do
~[n] <- getArgs
putStrLn (showFFloat (Just 9) (randloop (read n::Int) 42 0.0 100.0) "")
return 1
randloop :: Int -> Int -> Double -> Double -> Double
randloop 0 seed r max = r
randloop n seed r max = randloop (n-1) newseed newrand max
where normalize x max = (fromIntegral x) * (max / imd)
newseed = (seed * ia + ic) `mod` im
newrand = normalize newseed max
im = 139968
imd = fromIntegral im
ia = 3877
ic = 29573
|
Reverse a File |
-- $Id: reversefile.ghc,v 1.5 2001/02/26 17:18:27 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange
main = interact $ unlines . reverse . lines
|
Sieve of Erathostenes |
-- $Id: sieve.ghc,v 1.4 2001/07/26 13:16:43 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Roland Dowdeswell
module Main where
import System(getArgs)
main = getArgs >>= putStrLn . ("Count: "++) . show . mytest . read . headOr1
where headOr1 x = if length x /= 1 then "1" else head x
-- here we try to force it to recompute at each step. Note
-- that we are not naming `sieve [2..8192]' and we are forcing
-- a comparison with -1. Of course there is still no guarantee
-- that any particular Haskell implementation will actually
-- recompute the value.
mytest :: Int -> Int
mytest 1 = length (sieve [2..8192])
mytest n | length (sieve [2..8192]) == -1 = error "doh"
| otherwise = mytest (n-1)
-- we use Int rather than let Haskell default to Integer,
-- because we are trying to remain competetive with other
-- languages that do not do arbitrary precision math by
-- default...
sieve :: [Int] -> [Int]
sieve [] = []
sieve (h:t) = h : sieve [x| x<-t, x`mod`h /= 0]
|
Spell Checker |
-- $Id: spellcheck.ghc,v 1.1 2001/03/02 15:46:08 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange
-- compile with: ghc -O -package data
module Main(main) where
import FiniteMap(addToFM_C,emptyFM,elemFM)
addFM fm [] = fm
addFM fm (x:xs) = addFM (addToFM_C (\_ _ -> ()) fm x ()) xs
main = do
d <- readFile "Usr.Dict.Words"
interact $ unlines . filter (\x -> not $ elemFM x (addFM emptyFM (lines d))) . lines
|
Statistical Moments |
-- $Id: moments.ghc,v 1.1 2001/02/14 22:12:21 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Brian Gregor
module Main where
import IO
import System
import Numeric
-- read the file
main = do input <- getContents
putAns (lines input)
-- print out the answers
putAns :: [String] -> IO ()
putAns st_nums = do
putStrLn ("n: " ++ (showInt (truncate n) ""))
putStrLn ("median: " ++ (showFFloat (Just 6) (median nums n) ""))
putStrLn ("mean: " ++ (showFFloat (Just 6) mean ""))
putStrLn ("average_deviation: " ++ (showFFloat (Just 6) avg_dev ""))
putStrLn ("standard_deviation: " ++ (showFFloat (Just 6) std_dev ""))
putStrLn ("variance: " ++ (showFFloat (Just 6) var ""))
putStrLn ("skew: " ++ (showFFloat (Just 6) skew ""))
putStrLn ("kurtosis: " ++ (showFFloat (Just 6) kurt ""))
where
n = fromIntegral (length nums)
nums = strToDoub st_nums
mean = (sum nums) / n
deviation = [x-mean | x <- nums]
avg_dev = (sum [abs x | x <- deviation])/ n
var = (sum [x**2 | x <- deviation]) / (n-1)
std_dev = sqrt var
skew = (sum [x**3 | x <- deviation]) / (n*var*std_dev)
kurt = (sum [x**4 | x <- deviation]) / (n*var*var)-3.0
-- convert the strings to doubles
strToDoub :: [String] -> [Double]
strToDoub nums = map conv nums
where conv x = fst (head (readFloat x))
-- calculate the median
median :: [Double] -> Double -> Double
median nums n = mid (mSort nums)
where
mid x
| odd (length x) = x!! midpt
| otherwise = ((x!!(midpt-1)) + (x!!midpt)) / 2.0
midpt :: Int
midpt = floor (n/2)
-- Sorting: the various languages use various algorithms
-- here's an optimized mergesort from
-- "Algorithms - a Functional Approach" by
-- Fethi Rabhe & Guy Lapalme
split :: (Ord a) => [a] -> [[a]]
split [] = []
split (x:xs) = [x]:split xs
merge :: (Ord a) => [a] -> [a] -> [a]
merge [] b = b
merge a [] = a
merge a@(x:xs) b@(y:ys)
| (x<=y) = x : (merge xs b)
| otherwise = y : (merge a ys)
mergepairs :: (Ord a) => [[a]] -> [[a]]
mergepairs [] = []
mergepairs x@[l] = x
mergepairs (l1:l2:rest) = (merge l1 l2) : (mergepairs $! rest)
-- The actual sort
mSort :: (Ord a) => [a] -> [a]
mSort l = ms (split l)
where ms [r] = r
ms l = ms (mergepairs l)
|
String Concatenation |
-- $Id: strcat.ghc,v 1.3 2001/06/16 01:24:09 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Josef Svenningsson
-- shortened by Bryn Keller
import System(getArgs, getProgName)
lengthNHellos n = length (concat (replicate n "hello\n"))
main = do
arg <- getArgs
case arg of
[number] -> putStrLn $ show $ lengthNHellos (read number)
_ -> do name <- getProgName; fail ("Usage: " ++ name ++ "number")
|
Sum a Column of Integers |
-- $Id: sumcol.ghc,v 1.4 2001/02/24 23:49:59 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange
module Main where
import Numeric(readDec)
main = interact (flip (++) "\n" . show . sum . nums . lines)
where
nums = map (fst . head . readDec)
|
Word Frequency Count |
-- $Id: wordfreq.ghc,v 1.2 2001/02/27 04:04:35 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Julian Assange
-- compile with:
-- ghc -O -package data wordfreq.hs -o wordfreq
module Main where
import List(sortBy)
import Char(toLower,isLower)
import FiniteMap(fmToList,emptyFM,addToFM_C)
main = interact $ unlines . pretty . sort . fmToList . makemap . cwords . lower
where
pretty l = [pad 7 (show n) ++ "\t" ++ w | (w,n) <- l]
where
pad n s = replicate (n - length s) ' ' ++ s
sort = sortBy (\(w0,n0) (w1,n1) -> case compare n1 n0 of
EQ -> compare w1 w0
x -> x)
makemap = addFM emptyFM
where addFM fm [] = fm
addFM fm (x:xs) = addFM (addToFM_C (+) fm x 1) xs
cwords s = case dropWhile (not . isLower) s of
"" -> []
s' -> w : (cwords s'')
where (w, s'') = span isLower s'
lower = map toLower
|