Skip to content

Instantly share code, notes, and snippets.

@qtamaki
Created November 26, 2012 07:03
Show Gist options
  • Save qtamaki/4146955 to your computer and use it in GitHub Desktop.
Save qtamaki/4146955 to your computer and use it in GitHub Desktop.
Random Expression Generator
import System.Random
------------------------------------------------------------------------------
-- RANDOM Stream
------------------------------------------------------------------------------
randomX x = randomR (0,x -1)
type RandomF = StdGen -> (Int, StdGen)
ranStImpl :: StdGen -> RandomF -> [Int]
ranStImpl sg = \rf ->
let (a, sg') = rf sg
in a : ranStImpl sg' rf
randomStream :: Int -> IO [Int]
randomStream x = getStdRandom (\g -> let (g',g'') = split g
r = randomX x
in (ranStImpl g' r, g''))
-- TEST
-- randomStream >>= \l -> print $ foldl (+) 0 $ take 100 l
------------------------------------------------------------------------------
-- Expr Generator
------------------------------------------------------------------------------
-- Operator Stream
int2Ope :: Int -> Char
int2Ope x = case x of
0 -> '+'
1 -> '-'
2 -> '*'
3 -> '/'
opeStream = randomStream 4 >>= return . (map int2Ope)
-- Kakko Stream
data Kakko = Kak | Kok | None deriving Show
type Depth = Int
data KakkoNode = KakkoNode Kakko Kakko Depth deriving Show
kakkoStream = randomStream 2 >>= return . (map (\x -> if x == 0 then Kak else None))
kokkaStream = randomStream 2 >>= return . (map (\x -> if x == 0 then Kok else None))
calcDepth :: Kakko -> Kakko -> Depth -> KakkoNode
calcDepth Kak _ d = KakkoNode Kak None (d + 1)
calcDepth _ Kok d | d > 0 = KakkoNode None Kok (d - 1)
| otherwise = KakkoNode None None d
calcDepth ka ko d = KakkoNode ka ko d
knStream :: [Kakko] -> [Kakko] -> Depth -> [KakkoNode]
knStream [] _ _ = []
knStream (ka:kas) (ko:kos) d = case calcDepth ka ko d of
(KakkoNode ka' ko' d') -> KakkoNode ka' ko' d' : knStream kas kos d'
-- Nodes
data ExprNode = ENumber Int| EOpe Char| EKakko Kakko deriving Show
endKokkas :: Int -> [ExprNode]
endKokkas depth = take depth $ repeat $ EKakko Kok
joinEx :: [Int] -> [Char] -> [KakkoNode] -> [ExprNode]
joinEx (i:[]) (o:opes) (k:kakkos) = case k of
(KakkoNode st en depth) -> EKakko st : ENumber i : EKakko en : endKokkas depth
joinEx (i:ints) (o:opes) (k:kakkos) = case k of
(KakkoNode st en _) -> EKakko st : ENumber i : EKakko en : EOpe o : joinEx ints opes kakkos
gen range nums = do ints <- randomStream range
opes <- opeStream
kas <- kakkoStream
kos <- kokkaStream
print $ printsE $ joinEx (take nums ints) opes (knStream kas kos 0)
-- Print Utility
printE :: ExprNode -> [Char]
printE e = case e of
ENumber i -> show i
EOpe c -> return c
EKakko k -> case k of
Kak -> return '('
Kok -> return ')'
None -> []
printsE :: [ExprNode] -> [Char]
printsE [] = []
printsE (e:es) = printE e ++ printsE es
-- main function
main :: IO ()
main = gen 1000 10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment