Skip to content

Instantly share code, notes, and snippets.

@nobsun
Last active June 18, 2017 06:01
Show Gist options
  • Save nobsun/d1db0372ec685b7d577db83fa3771e4c to your computer and use it in GitHub Desktop.
Save nobsun/d1db0372ec685b7d577db83fa3771e4c to your computer and use it in GitHub Desktop.
type Score = Int
data Grade = A | B | C | D
instance Show Grade where
show A = "優"
show B = "良"
show C = "可"
show D = "不可"
grade :: Score -> Maybe Grade
grade x
| outRange x = Nothing
| x < 60 = Just D
| x < 70 = Just C
| x < 80 = Just B
| otherwise = Just A
outRange :: Score -> Bool
outRange = not. inRange
inRange :: Score -> Bool
inRange x = 0 <= x && x <= 100
data Count = Count { nA, nB, nC, nD :: Int }
instance Show Count where
show (Count a b c d) = printf "優:%4d名 良:%4d名 可:%4d名 不可:%4d名" a b c d
zero :: Count
zero = Count 0 0 0 0
incA, incB, incC, incD :: Count -> Count
incA c = c { nA = nA c + 1 }
incB c = c { nB = nB c + 1 }
incC c = c { nC = nC c + 1 }
incD c = c { nD = nD c + 1 }
main :: IO ()
main = loop zero
loop :: Count -> IO ()
loop c = do
{ prompt "得点? "
; input <- getLine
; let score = read input
; let judge = grade score
; maybe (print c)
(printCountUpLoop c)
judge
}
printCountUpLoop :: Count -> Grade -> IO ()
printCountUpLoop c g = print g >> loop (countUp g c)
countUp :: Grade -> (Count -> Count)
countUp A = incA
countUp B = incB
countUp C = incC
countUp D = incD
prompt :: String -> IO ()
prompt s = putStr s >> hFlush stdout
countAndGrades :: [Score] -> (Count, [Grade])
countAndGrades = mapAccumL countGrade zero . unfoldr phi
where
phi [] = Nothing
phi (x:xs) = bool Nothing (Just (x,xs)) (inRange x)
countGrade c s = case grade s of
Just g -> (countUp g c, g)
serialize :: (Count, [Grade]) -> String
serialize ~(c,gs)
= promptStr ++ concatMap (followedByPrompt . shows) gs ++ shows c "\n\n"
followedByPrompt :: ShowS -> String
followedByPrompt ss = ss promptStr
promptStr :: String
promptStr = "\n得点? "
main :: IO ()
main = hSetBuffering stdout NoBuffering
>> interact (serialize . countAndGrades . map read . lines)
module Main where
import Data.Bool
import Data.List
import System.IO
import Text.Printf
type Score = Int
data Grade = A | B | C | D
instance Show Grade where
show A = "優"
show B = "良"
show C = "可"
show D = "不可"
grade :: Score -> Maybe Grade
grade x
| outRange x = Nothing
| x < 60 = Just D
| x < 70 = Just C
| x < 80 = Just B
| otherwise = Just A
outRange :: Score -> Bool
outRange = not . inRange
inRange :: Score -> Bool
inRange x = 0 <= x && x <= 100
data Count = Count { nA, nB, nC, nD :: Int }
instance Show Count where
show (Count a b c d) = printf "| 優:%4d名 | 良:%4d名 | 可:%4d名 | 不可:%4d名 |" a b c d
zero :: Count
zero = Count 0 0 0 0
incA, incB, incC, incD :: Count -> Count
incA c = c { nA = nA c + 1 }
incB c = c { nB = nB c + 1 }
incC c = c { nC = nC c + 1 }
incD c = c { nD = nD c + 1 }
countUp :: Grade -> (Count -> Count)
countUp A = incA
countUp B = incB
countUp C = incC
countUp D = incD
countAndGrades :: [Score] -> (Count, [Grade])
countAndGrades = mapAccumL countGrade zero . unfoldr phi
where
phi [] = Nothing
phi (x:xs) = bool Nothing (Just (x,xs)) (inRange x)
countGrade c s = case grade s of Just g -> (countUp g c, g)
selialize :: (Count, [Grade]) -> String
selialize ~(c,gs) = promptStr ++ concatMap (followedByPrompt . shows) gs ++ shows c "\n\n"
followedByPrompt :: ShowS -> String
followedByPrompt ss = ss promptStr
promptStr :: String
promptStr = "\n得点? "
main :: IO ()
main = hSetBuffering stdout NoBuffering
>> interact (serialize . countAndGrades . map read . lines)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment