Skip to content

Instantly share code, notes, and snippets.

@cleichner
Last active December 20, 2015 06:29
Show Gist options
  • Select an option

  • Save cleichner/6086604 to your computer and use it in GitHub Desktop.

Select an option

Save cleichner/6086604 to your computer and use it in GitHub Desktop.

Revisions

  1. cleichner revised this gist Apr 15, 2015. 9 changed files with 149 additions and 11 deletions.
    13 changes: 13 additions & 0 deletions LICENSE
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    Copyright 2014 Chas Leichner

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
    34 changes: 34 additions & 0 deletions RandomProblem1-desugared.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    -- First Haskell version, nothing tricky, no syntactic sugar around monad
    -- operations.
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    -- >> :: IO a -> IO b -> IO b
    -- >>= :: IO a -> (a -> IO b) -> IO b
    -- putStrLn :: String -> IO ()

    gameLoop :: [Int] -> Int -> Int -> IO ()
    gameLoop (x:y:values) right rounds =
    flushPut "Would you like to play? y/n: " >>
    getLine >>= \keepPlaying ->
    when (map toLower keepPlaying == "y") $
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2) in
    flushPut (unwords ["What is", show x, opStr, show y, "? "]) >>

    readLn >>= \response ->
    let (total, message) = if solution == response
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution]) in
    putStrLn (unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1)]) >>
    gameLoop values total (rounds + 1)
    where
    flushPut s = putStr s >> hFlush stdout

    main :: IO ()
    main =
    getStdGen >>= \gen ->
    gameLoop (randomRs (1, 100) gen) 0 0

    4 changes: 2 additions & 2 deletions RandomProblem1.hs
    Original file line number Diff line number Diff line change
    @@ -16,8 +16,8 @@ gameLoop (x:y:values) right rounds = do
    let (total, message) = if solution == response
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    putStrLn $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1)]
    gameLoop values total (rounds + 1)
    where
    flushPut s = putStr s >> hFlush stdout
    42 changes: 42 additions & 0 deletions RandomProblem2-5.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    -- Collected the game state into a Game record
    import Control.Applicative
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    data Game = Game { values :: [Int], right :: Int, rounds :: Int }

    updateGame :: Bool -> Game -> Game
    updateGame correct Game { values = (_:_:remaining)
    , right = score
    , rounds = total } =
    Game { values = remaining
    , right = if correct then score + 1 else score
    , rounds = total + 1 }

    gameLoop :: Game -> IO ()
    gameLoop gameState = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> getLine
    when keepPlaying $ do
    let (x:y:_) = values gameState
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    correct <- (solution ==) <$> readLn
    let gameState' = updateGame correct gameState
    putStrLn $ if correct
    then "Correct!"
    else unwords ["Sorry! the correct answer is:", show solution]
    putStr $ unwords
    ["You have solved", show $ right gameState', "out of",
    show $ rounds gameState', "\n"]
    gameLoop gameState'
    where
    flushPut = (>> hFlush stdout) . putStr

    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    gameLoop Game { values = randomValues, right = 0, rounds = 0 }
    6 changes: 3 additions & 3 deletions RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -12,13 +12,13 @@ gameLoop (x:y:values) right rounds = do
    when keepPlaying $ do
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]
    correct <- (solution ==) <$> readLn

    correct <- (solution ==) <$> readLn
    let (total, message) = if correct
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    putStrLn $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1)]
    gameLoop values total (rounds + 1)
    where
    flushPut = (>> hFlush stdout) . putStr
    10 changes: 6 additions & 4 deletions RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    -- Made state-passing explicit with StateT and record
    -- Made state passing implicit with StateT
    import Control.Applicative
    import Control.Monad
    import Control.Monad.State
    @@ -26,12 +26,14 @@ gameLoop = do
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    modify (updateGame correct)
    gameState' <- get
    liftIO . putStrLn $ if correct
    then "Correct!"
    else unwords ["Sorry! the correct answer is:", show solution]
    liftIO . putStr $ unwords
    ["You have solved", show $ right game, "out of", show $ rounds game, "\n"]
    liftIO . putStrLn $ unwords
    ["You have solved", show $ right gameState', "out of",
    show $ rounds gameState']
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    46 changes: 46 additions & 0 deletions RandomProblem4-desugared.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    -- Removed syntactic sugar around monad operations.
    import Control.Applicative
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data Game = Game { values :: [Int], right :: Int, rounds :: Int }

    updateGame :: Bool -> Game -> Game
    updateGame correct Game { values = (_:_:remaining)
    , right = score
    , rounds = total } =
    Game { values = remaining
    , rounds = total + 1
    , right = if correct then score + 1 else score }

    -- >> :: StateT Game IO a -> StateT Game IO b -> StateT Game IO b
    -- >>= :: StateT Game IO a -> (a -> StateT Game IO b) -> StateT Game IO b
    -- liftIO :: IO a -> StateT Game IO a
    -- liftIO . putStrLn :: String -> StateT Game IO ()

    gameLoop :: StateT Game IO ()
    gameLoop =
    flushPut "Would you like to play? y/n: " >>
    ("y" ==) . map toLower <$> liftIO getLine >>= \keepPlaying ->
    when keepPlaying $
    gets values >>= \(x:y:_) ->
    let (solution, opStr) = [(x + y, "+"), (x - y, "-")] !! (x `mod` 2) in
    flushPut (unwords ["What is", show x, opStr, show y, "? "]) >>

    (solution ==) <$> liftIO readLn >>= \correct ->
    modify (updateGame correct) >> get >>= \game ->
    (liftIO . putStrLn) (unwords [message solution correct,
    "\nYou have solved", show $ right game, "out of", show $ rounds game]) >>
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct!"
    message solution _ = unwords ["Sorry! the correct answer is:", show solution]

    main :: IO ()
    main =
    randomRs (1,100) <$> getStdGen >>= \randomValues ->
    evalStateT gameLoop (Game randomValues 0 0)
    3 changes: 2 additions & 1 deletion RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    -- Factored message into a function
    -- Factored message into a function, collapsed modification and state update
    -- using >>
    import Control.Applicative
    import Control.Monad
    import Control.Monad.State
    2 changes: 1 addition & 1 deletion RandomProblem8.hs
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    let (soln, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    putStr (unwords ["What is", show x, opStr, show y, "? "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) soln <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    putStrLn $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1)]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct!")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
  2. cleichner revised this gist Dec 3, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem9.hs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    -- Integrated updateGame into gameLoop using state update operators.
    -- Used the `Safe` library to be more robust when given invalid input
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
  3. cleichner revised this gist Dec 3, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem9.hs
    Original file line number Diff line number Diff line change
    @@ -32,7 +32,7 @@ gameLoop = do
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    correct <- liftM (solution ==) (getUserInput $ unwords
    ["What is", show x, opStr, show y ++ "? "])
  4. cleichner revised this gist Dec 3, 2013. 8 changed files with 10 additions and 18 deletions.
    3 changes: 1 addition & 2 deletions RandomProblem1.hs
    Original file line number Diff line number Diff line change
    @@ -9,10 +9,9 @@ gameLoop (x:y:values) right rounds = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- getLine
    when (map toLower keepPlaying == "y") $ do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    response <- readLn
    let (total, message) = if solution == response
    then (right + 1, "Correct!")
    5 changes: 2 additions & 3 deletions RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -10,11 +10,10 @@ gameLoop (x:y:values) right rounds = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> getLine
    when keepPlaying $ do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> readLn

    let (total, message) = if correct
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    3 changes: 1 addition & 2 deletions RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -22,10 +22,9 @@ gameLoop = do
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- gets values
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ if correct
    3 changes: 1 addition & 2 deletions RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -22,10 +22,9 @@ gameLoop = do
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- gets values
    let (op, opStr) = [((+),"+"), ((-),"-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+"), (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ unwords [message solution correct,
    3 changes: 1 addition & 2 deletions RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -23,10 +23,9 @@ gameLoop = do
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- use values
    let (op, opStr) = [((+),"+"), ((-),"-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ unwords [message solution correct,
    4 changes: 1 addition & 3 deletions RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -19,10 +19,8 @@ gameLoop = do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    numRight <- right <+= if correct then 1 else 0

    3 changes: 1 addition & 2 deletions RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -25,10 +25,9 @@ gameLoop = do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correctSolution <- (solution ==) <$> liftIO readLn
    past <- history <%= (History x y opStr correctSolution :)
    numRight <- right <+= if correctSolution then 1 else 0
    4 changes: 2 additions & 2 deletions RandomProblem8.hs
    Original file line number Diff line number Diff line change
    @@ -10,9 +10,9 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    let (soln, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    putStr (unwords ["What is", show x, opStr, show y, "? "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    (total, message) <- ap ((.) . updateGame right) (==) soln <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct!")
  5. cleichner revised this gist Dec 2, 2013. 1 changed file with 52 additions and 0 deletions.
    52 changes: 52 additions & 0 deletions RandomProblem9.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    -- Integrated updateGame into gameLoop using state update operators.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import Safe
    import System.IO
    import System.Random

    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int }
    makeLenses ''Game

    flushPut :: String -> StateT Game IO ()
    flushPut = liftIO . (>> hFlush stdout) . putStr

    getUserInput :: String -> StateT Game IO Int
    getUserInput prompt = do
    flushPut prompt
    line <- liftIO getLine
    case readMay line of
    Just value -> return value
    Nothing -> do
    liftIO . putStrLn $ unwords ["Error:", show line, "is not a valid number"]
    getUserInput prompt

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (solution, opStr) = [(x + y, "+") , (x - y, "-")] !! (x `mod` 2)
    correct <- liftM (solution ==) (getUserInput $ unwords
    ["What is", show x, opStr, show y ++ "? "])
    numRight <- right <+= if correct then 1 else 0
    liftIO . putStrLn $
    unwords [message solution correct, "\nYou have solved", show numRight,
    "out of", show numRounds]
    gameLoop
    where
    message _ True = "Correct!"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop (Game randomValues 0 0)

  6. cleichner revised this gist Nov 21, 2013. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    -- Added historical data for every problem asked.
    -- Added historical data for every problem asked to show flexibility of
    -- StateT with lens.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
  7. cleichner revised this gist Nov 21, 2013. 2 changed files with 2 additions and 2 deletions.
    2 changes: 1 addition & 1 deletion RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -28,7 +28,7 @@ gameLoop = do
    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ if solution == response
    liftIO . putStrLn $ if correct
    then "Correct!"
    else unwords ["Sorry! the correct answer is:", show solution]
    liftIO . putStr $ unwords
    2 changes: 1 addition & 1 deletion RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -29,7 +29,7 @@ gameLoop = do

    let solution = x `op` y
    correctSolution <- (solution ==) <$> liftIO readLn
    past <- history <%= (History x y opStr correctSolution :)
    past <- history <%= (History x y opStr correctSolution :)
    numRight <- right <+= if correctSolution then 1 else 0

    liftIO . putStrLn $ unwords [message solution correctSolution,
  8. cleichner revised this gist Nov 21, 2013. 2 changed files with 2 additions and 2 deletions.
    2 changes: 1 addition & 1 deletion RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ gameLoop (x:y:values) right rounds = do
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    correct <- (solution ==) <$> readLn
    let (total, message) = if correct
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    2 changes: 1 addition & 1 deletion RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ gameLoop = do
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> readLn
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ if solution == response
    then "Correct!"
  9. cleichner revised this gist Nov 21, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ gameLoop = do
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    correct <- (solution ==) <$> readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ if solution == response
    then "Correct!"
  10. cleichner revised this gist Nov 20, 2013. 2 changed files with 52 additions and 53 deletions.
    52 changes: 40 additions & 12 deletions RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,47 @@
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    -- Added historical data for every problem asked.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data History = History { _lhs :: Int, _rhs :: Int, _operator :: String,
    _correct :: Bool} deriving (Show)
    makeLenses ''History

    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int,
    _history :: [History] }
    makeLenses ''Game

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correctSolution <- (solution ==) <$> liftIO readLn
    past <- history <%= (History x y opStr correctSolution :)
    numRight <- right <+= if correctSolution then 1 else 0

    liftIO . putStrLn $ unwords [message solution correctSolution,
    "\nYou have solved", show numRight, "out of", show numRounds,
    show (past ^.. traverse.correct)]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct!"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords ["What is", show x, opStr, show y, "? "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct!")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop (Game randomValues 0 0 [])
    53 changes: 12 additions & 41 deletions RandomProblem8.hs
    Original file line number Diff line number Diff line change
    @@ -1,48 +1,19 @@
    -- Added historical data for every problem asked.
    {-# LANGUAGE TemplateHaskell #-}
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    import Control.Applicative
    import Control.Lens hiding (op)
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data History = History { _lhs :: Int, _rhs :: Int, _operator :: String,
    _correct :: Bool} deriving (Show)
    makeLenses ''History

    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int,
    _history :: [History] }
    makeLenses ''Game

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correctSolution <- (solution ==) <$> liftIO readLn
    past <- history <%= (History x y opStr correctSolution :)
    numRight <- right <+= if correctSolution then 1 else 0

    liftIO . putStrLn $ unwords [message solution correctSolution,
    "\nYou have solved", show numRight, "out of", show numRounds,
    show (past ^.. traverse.correct)]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct!"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop (Game randomValues 0 0 [])

    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords ["What is", show x, opStr, show y, "? "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct!")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
  11. cleichner revised this gist Nov 20, 2013. 2 changed files with 49 additions and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem.java
    Original file line number Diff line number Diff line change
    @@ -41,4 +41,4 @@ public static boolean keepPlaying(Scanner keyboard) {
    public static void printQuestion(int x, char op, int y) {
    System.out.print("What is " + x + " " + op + " " + y + "? ");
    }
    }
    }
    48 changes: 48 additions & 0 deletions RandomProblem8.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    -- Added historical data for every problem asked.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data History = History { _lhs :: Int, _rhs :: Int, _operator :: String,
    _correct :: Bool} deriving (Show)
    makeLenses ''History

    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int,
    _history :: [History] }
    makeLenses ''Game

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correctSolution <- (solution ==) <$> liftIO readLn
    past <- history <%= (History x y opStr correctSolution :)
    numRight <- right <+= if correctSolution then 1 else 0

    liftIO . putStrLn $ unwords [message solution correctSolution,
    "\nYou have solved", show numRight, "out of", show numRounds,
    show (past ^.. traverse.correct)]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct!"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop (Game randomValues 0 0 [])

  12. cleichner revised this gist Nov 20, 2013. 7 changed files with 7 additions and 7 deletions.
    2 changes: 1 addition & 1 deletion RandomProblem1.hs
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@ gameLoop (x:y:values) right rounds = do
    keepPlaying <- getLine
    when (map toLower keepPlaying == "y") $ do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    response <- readLn
    2 changes: 1 addition & 1 deletion RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ gameLoop (x:y:values) right rounds = do
    keepPlaying <- ("y" ==) . map toLower <$> getLine
    when keepPlaying $ do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    2 changes: 1 addition & 1 deletion RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@ gameLoop = do
    when keepPlaying $ do
    (x:y:_) <- gets values
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    2 changes: 1 addition & 1 deletion RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@ gameLoop = do
    when keepPlaying $ do
    (x:y:_) <- gets values
    let (op, opStr) = [((+),"+"), ((-),"-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -24,7 +24,7 @@ gameLoop = do
    when keepPlaying $ do
    (x:y:_) <- use values
    let (op, opStr) = [((+),"+"), ((-),"-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    2 changes: 1 addition & 1 deletion RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -20,7 +20,7 @@ gameLoop = do
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]
    flushPut $ unwords ["What is", show x, opStr, show y, "? "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    2 changes: 1 addition & 1 deletion RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    putStr (unwords ["What is", show x, opStr, show y, "? "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
  13. cleichner revised this gist Nov 20, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ makeLenses ''Game

    updateGame :: Bool -> Game -> Game
    updateGame correct =
    (values %~ (drop 2)) .
    (values %~ drop 2) .
    (rounds +~ 1) .
    (right +~ if correct then 1 else 0)

  14. cleichner revised this gist Nov 20, 2013. 2 changed files with 3 additions and 3 deletions.
    4 changes: 2 additions & 2 deletions RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -13,8 +13,8 @@ updateGame correct Game { values = (_:_:remaining)
    , right = score
    , rounds = total } =
    Game { values = remaining
    , right = if correct then score + 1 else score
    , rounds = total + 1 }
    , rounds = total + 1
    , right = if correct then score + 1 else score }

    gameLoop :: StateT Game IO ()
    gameLoop = do
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -13,8 +13,8 @@ makeLenses ''Game

    updateGame :: Bool -> Game -> Game
    updateGame correct =
    (rounds +~ 1) .
    (values %~ (drop 2)) .
    (rounds +~ 1) .
    (right +~ if correct then 1 else 0)

    gameLoop :: StateT Game IO ()
  15. cleichner revised this gist Nov 20, 2013. 4 changed files with 4 additions and 4 deletions.
    2 changes: 1 addition & 1 deletion RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ gameLoop = do
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message _ True = "Correct!"
    message solution _ = unwords ["Sorry! the correct answer is:", show solution]

    main :: IO ()
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@ gameLoop = do
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message _ True = "Correct!"
    message solution _ = unwords ["Sorry! the correct answer is:", show solution]

    main :: IO ()
    2 changes: 1 addition & 1 deletion RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -31,7 +31,7 @@ gameLoop = do
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message _ True = "Correct!"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    2 changes: 1 addition & 1 deletion RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -15,5 +15,5 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
    updateGame total _ True = (total + 1, "Correct!")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
  16. cleichner revised this gist Nov 20, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    -- Introduced Control.Lens and made significant use of state update operators.
    -- Integrated updateGame into gameLoop using state update operators.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
  17. cleichner revised this gist Nov 20, 2013. 4 changed files with 65 additions and 22 deletions.
    2 changes: 1 addition & 1 deletion RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -39,4 +39,4 @@ gameLoop = do
    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop Game { values = randomValues, right = 0, rounds = 0 }
    evalStateT gameLoop (Game randomValues 0 0)
    21 changes: 12 additions & 9 deletions RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    -- Introduced Control.Lens and made significant use of state update operators.
    -- Introduced Control.Lens
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
    @@ -11,28 +11,31 @@ import System.Random
    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int }
    makeLenses ''Game

    updateGame :: Bool -> Game -> Game
    updateGame correct =
    (rounds +~ 1) .
    (values %~ (drop 2)) .
    (right +~ if correct then 1 else 0)

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    (x:y:_) <- use values
    let (op, opStr) = [((+),"+"), ((-),"-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    numRight <- right <+= if correct then 1 else 0

    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ unwords [message solution correct,
    "\nYou have solved", show numRight, "out of", show numRounds]
    "\nYou have solved", show $ game ^. right, "out of", show $ game ^. rounds]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]
    message solution _ = unwords ["Sorry! the correct answer is:", show solution]

    main :: IO ()
    main = do
    45 changes: 33 additions & 12 deletions RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,40 @@
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    -- Introduced Control.Lens and made significant use of state update operators.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Applicative
    import Control.Lens hiding (op)
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int }
    makeLenses ''Game

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    numRight <- right <+= if correct then 1 else 0

    liftIO . putStrLn $ unwords [message solution correct,
    "\nYou have solved", show numRight, "out of", show numRounds]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop (Game randomValues 0 0)
    19 changes: 19 additions & 0 deletions RandomProblem7.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    import Control.Applicative
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    main :: IO ()
    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
  18. cleichner revised this gist Nov 20, 2013. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -21,7 +21,8 @@ gameLoop (x:y:values) right rounds = do
    putStr $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop values total (rounds + 1)
    where flushPut = (>> hFlush stdout) . putStr
    where
    flushPut = (>> hFlush stdout) . putStr

    main :: IO ()
    main = do
  19. cleichner revised this gist Nov 20, 2013. 2 changed files with 3 additions and 3 deletions.
    4 changes: 2 additions & 2 deletions RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -14,8 +14,8 @@ gameLoop (x:y:values) right rounds = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    response <- readLn
    let (total, message) = if solution == response
    correct <- (solution ==) <$> liftIO readLn
    let (total, message) = if correct
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    2 changes: 1 addition & 1 deletion RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ gameLoop = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    response <- liftIO readLn
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ if solution == response
    then "Correct!"
  20. cleichner revised this gist Nov 20, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ gameLoop (x:y:values) right rounds = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- readLn
    response <- readLn
    let (total, message) = if solution == response
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
  21. cleichner revised this gist Nov 19, 2013. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -10,8 +10,9 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    putStr (unwords [show x, ["+" , "-"] !! (x `mod` 2), show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (([(+),(-)] !! (x `mod` 2)) x y) <$> readLn
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
  22. cleichner revised this gist Nov 17, 2013. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -10,9 +10,8 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr (unwords [show x, ["+" , "-"] !! (x `mod` 2), show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (([(+),(-)] !! (x `mod` 2)) x y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
  23. cleichner revised this gist Nov 16, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -24,7 +24,7 @@ gameLoop = do

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    numRight <-right <+= if correct then 1 else 0
    numRight <- right <+= if correct then 1 else 0

    liftIO . putStrLn $ unwords [message solution correct,
    "\nYou have solved", show numRight, "out of", show numRounds]
  24. cleichner revised this gist Nov 16, 2013. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -17,17 +17,17 @@ gameLoop = do
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- show <$> (rounds <+= 1)
    numRounds <- rounds <+= 1

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    numRight <- show <$> (right <+= if correct then 1 else 0)
    numRight <-right <+= if correct then 1 else 0

    liftIO . putStrLn $ unwords [message solution correct,
    "\nYou have solved", numRight, "out of", numRounds]
    "\nYou have solved", show numRight, "out of", show numRounds]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
  25. cleichner revised this gist Nov 16, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    -- Introduced Control.Lens and made significant use of state update operators.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Lens hiding (op)
    import Control.Applicative
    import Control.Lens hiding (op)
    import Control.Monad
    import Control.Monad.State
    import Data.Char
  26. cleichner revised this gist Nov 16, 2013. 3 changed files with 54 additions and 14 deletions.
    4 changes: 2 additions & 2 deletions RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -28,8 +28,8 @@ gameLoop = do
    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStr $ unwords [message solution correct,
    "\nYou have solved", show $ right game, "out of", show $ rounds game, "\n"]
    liftIO . putStrLn $ unwords [message solution correct,
    "\nYou have solved", show $ right game, "out of", show $ rounds game]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    45 changes: 33 additions & 12 deletions RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,40 @@
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    -- Introduced Control.Lens and made significant use of state update operators.
    {-# LANGUAGE TemplateHaskell #-}
    import Control.Lens hiding (op)
    import Control.Applicative
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data Game = Game { _values :: [Int], _right :: Int, _rounds :: Int }
    makeLenses ''Game

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- values <<%= drop 2
    numRounds <- show <$> (rounds <+= 1)

    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    numRight <- show <$> (right <+= if correct then 1 else 0)

    liftIO . putStrLn $ unwords [message solution correct,
    "\nYou have solved", numRight, "out of", numRounds]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message soln _ = unwords ["Sorry! the correct answer is:", show soln]

    main :: IO ()
    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop (Game randomValues 0 0)
    19 changes: 19 additions & 0 deletions RandomProblem6.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    import Control.Applicative
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    main :: IO ()
    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])
  27. cleichner revised this gist Jul 28, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -25,5 +25,5 @@ gameLoop (x:y:values) right rounds = do

    main :: IO ()
    main = do
    gen <- getStdGen
    gameLoop (randomRs (1,100) gen) 0 0
    randomValues <- randomRs (1,100) <$> getStdGen
    gameLoop randomValues 0 0
  28. cleichner revised this gist Jul 28, 2013. 3 changed files with 5 additions and 5 deletions.
    2 changes: 1 addition & 1 deletion RandomProblem1.hs
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ gameLoop (x:y:values) right rounds = do

    let solution = x `op` y
    response <- readLn
    let (total, message) = if response == solution
    let (total, message) = if solution == response
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    4 changes: 2 additions & 2 deletions RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -14,8 +14,8 @@ gameLoop (x:y:values) right rounds = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) <$> readLn
    let (total, message) = if correct
    correct <- readLn
    let (total, message) = if solution == response
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    4 changes: 2 additions & 2 deletions RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -26,9 +26,9 @@ gameLoop = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) <$> liftIO readLn
    response <- liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ if correct
    liftIO . putStrLn $ if solution == response
    then "Correct!"
    else unwords ["Sorry! the correct answer is:", show solution]
    liftIO . putStr $ unwords
  29. cleichner revised this gist Jul 26, 2013. 5 changed files with 8 additions and 8 deletions.
    4 changes: 2 additions & 2 deletions RandomProblem1.hs
    Original file line number Diff line number Diff line change
    @@ -13,8 +13,8 @@ gameLoop (x:y:values) right rounds = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    response <- getLine
    let (total, message) = if read response == solution
    response <- readLn
    let (total, message) = if response == solution
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    2 changes: 1 addition & 1 deletion RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ gameLoop (x:y:values) right rounds = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) . read <$> getLine
    correct <- (solution ==) <$> readLn
    let (total, message) = if correct
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    6 changes: 3 additions & 3 deletions RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -26,12 +26,12 @@ gameLoop = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) . read <$> liftIO getLine
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ unwords if correct
    liftIO . putStrLn $ if correct
    then "Correct!"
    else unwords ["Sorry! the correct answer is:", show solution]
    liftIO . putStr $
    liftIO . putStr $ unwords
    ["You have solved", show $ right game, "out of", show $ rounds game, "\n"]
    gameLoop
    where
    2 changes: 1 addition & 1 deletion RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ gameLoop = do
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) . read <$> liftIO getLine
    correct <- (solution ==) <$> liftIO readLn
    game <- modify (updateGame correct) >> get
    liftIO . putStr $ unwords [message solution correct,
    "\nYou have solved", show $ right game, "out of", show $ rounds game, "\n"]
    2 changes: 1 addition & 1 deletion RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@ main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) ((. read) . (==)) (x `op` y) <$> getLine
    (total, message) <- ap ((.) . updateGame right) (==) (x `op` y) <$> readLn
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
  30. cleichner created this gist Jul 26, 2013.
    44 changes: 44 additions & 0 deletions RandomProblem.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    // Java code that started it all
    import java.util.Random;
    import java.util.Scanner;

    public class RandomProblem {
    public static void main(String[] args) {
    int right = 0;
    int rounds = 0;
    Scanner keyboard = new Scanner(System.in);
    Random rand = new Random();
    while (keepPlaying(keyboard)) {
    int x = rand.nextInt(100) + 1;
    int y = rand.nextInt(100) + 1;

    int solution = 0;
    if (rand.nextBoolean()) {
    solution = x + y;
    printQuestion(x, '+', y);
    } else {
    solution = x - y;
    printQuestion(x, '-', y);
    }

    rounds++;
    if (solution == keyboard.nextInt()) {
    System.out.println("Correct!");
    right++;
    } else {
    System.out.println("Sorry! the correct answer is: " + solution);
    }
    System.out.println("You have solved " + right + " out of " +
    rounds + " problems correctly.");
    }
    }

    public static boolean keepPlaying(Scanner keyboard) {
    System.out.print("Would you like to play? y/n: ");
    return keyboard.next().toLowerCase().equals("y");
    }

    public static void printQuestion(int x, char op, int y) {
    System.out.print("What is " + x + " " + op + " " + y + "? ");
    }
    }
    29 changes: 29 additions & 0 deletions RandomProblem1.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    -- First Haskell version, nothing tricky
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    gameLoop :: [Int] -> Int -> Int -> IO ()
    gameLoop (x:y:values) right rounds = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- getLine
    when (map toLower keepPlaying == "y") $ do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    response <- getLine
    let (total, message) = if read response == solution
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop values total (rounds + 1)
    where
    flushPut s = putStr s >> hFlush stdout

    main :: IO ()
    main = do
    gen <- getStdGen
    gameLoop (randomRs (1, 100) gen) 0 0
    29 changes: 29 additions & 0 deletions RandomProblem2.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    -- Introduced applicative and pointfree style
    import Control.Applicative
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    gameLoop :: [Int] -> Int -> Int -> IO ()
    gameLoop (x:y:values) right rounds = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> getLine
    when keepPlaying $ do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) . read <$> getLine
    let (total, message) = if correct
    then (right + 1, "Correct!")
    else (right, unwords ["Sorry! the correct answer is:", show solution])
    putStr $ unwords
    [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop values total (rounds + 1)
    where flushPut = (>> hFlush stdout) . putStr

    main :: IO ()
    main = do
    gen <- getStdGen
    gameLoop (randomRs (1,100) gen) 0 0
    43 changes: 43 additions & 0 deletions RandomProblem3.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    -- Made state-passing explicit with StateT and record
    import Control.Applicative
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data Game = Game { values :: [Int], right :: Int, rounds :: Int }

    updateGame :: Bool -> Game -> Game
    updateGame correct Game { values = (_:_:remaining)
    , right = score
    , rounds = total } =
    Game { values = remaining
    , right = if correct then score + 1 else score
    , rounds = total + 1 }

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- gets values
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) . read <$> liftIO getLine
    game <- modify (updateGame correct) >> get
    liftIO . putStrLn $ unwords if correct
    then "Correct!"
    else unwords ["Sorry! the correct answer is:", show solution]
    liftIO . putStr $
    ["You have solved", show $ right game, "out of", show $ rounds game, "\n"]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr

    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop Game { values = randomValues, right = 0, rounds = 0 }
    42 changes: 42 additions & 0 deletions RandomProblem4.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    -- Factored message into a function
    import Control.Applicative
    import Control.Monad
    import Control.Monad.State
    import Data.Char
    import System.IO
    import System.Random

    data Game = Game { values :: [Int], right :: Int, rounds :: Int }

    updateGame :: Bool -> Game -> Game
    updateGame correct Game { values = (_:_:remaining)
    , right = score
    , rounds = total } =
    Game { values = remaining
    , right = if correct then score + 1 else score
    , rounds = total + 1 }

    gameLoop :: StateT Game IO ()
    gameLoop = do
    flushPut "Would you like to play? y/n: "
    keepPlaying <- ("y" ==) . map toLower <$> liftIO getLine
    when keepPlaying $ do
    (x:y:_) <- gets values
    let (op, opStr) = [((+),"+"), ((-),"-")] !! (x `mod` 2)
    flushPut $ unwords [show x, opStr, show y, "= "]

    let solution = x `op` y
    correct <- (solution ==) . read <$> liftIO getLine
    game <- modify (updateGame correct) >> get
    liftIO . putStr $ unwords [message solution correct,
    "\nYou have solved", show $ right game, "out of", show $ rounds game, "\n"]
    gameLoop
    where
    flushPut = liftIO . (>> hFlush stdout) . putStr
    message _ True = "Correct"
    message solution _ = unwords ["Sorry! the correct answer is:", show solution]

    main :: IO ()
    main = do
    randomValues <- randomRs (1,100) <$> getStdGen
    evalStateT gameLoop Game { values = randomValues, right = 0, rounds = 0 }
    19 changes: 19 additions & 0 deletions RandomProblem5.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    -- Went golfing. Applied all of the above refactorings, but only to shrink code.
    import Control.Applicative
    import Control.Monad
    import Data.Char
    import System.IO
    import System.Random

    main :: IO ()
    main = getStdGen >>= gameLoop 0 0 . randomRs (1, 100) where
    gameLoop right rounds (x:y:values) = do
    putStr "Would you like to play? y/n: " >> hFlush stdout
    ("y" ==) . map toLower <$> getLine >>= flip when (do
    let (op, opStr) = [((+), "+") , ((-), "-")] !! (x `mod` 2)
    putStr (unwords [show x, opStr, show y, "= "]) >> hFlush stdout
    (total, message) <- ap ((.) . updateGame right) ((. read) . (==)) (x `op` y) <$> getLine
    putStr $ unwords [message, "\nYou have solved", show total, "out of", show (rounds + 1), "\n"]
    gameLoop total (rounds + 1) values)
    updateGame total _ True = (total + 1, "Correct")
    updateGame total solution _ = (total, unwords ["Sorry! the correct answer is:", show solution])