haskell - Handling complicated input (with nested values) -
there following task:
- first line number of cases
- for each case there line number of numbers add
- for each case there line numbers
- for each case have print summed numbers
example:
input: 2 5 1 2 3 4 5 2 -100 100 output: 15 0
this implementation
import control.monad main = linescount <- readln :: io int numbers <- replicatem linescount getcase mapm_ putstrln $ map (show.sum) numbers getcase :: io [int] getcase = numberscount <- readln :: io int -- don't need variable numbersstring <- getline let numbers = map read $ words numbersstring return numbers
it looks lot of code parsing input. there tricks "compress" it? :)
if merely want make code shorter check out stack exchange community code golfing. fun , games.
if thinking there code may not need make shorter rather need make clearer. achieving matter of experience , practice. want isolate simple concepts correct , combine them in correct ways. methodologies include top-down design (break solution smaller pieces) , bottom-up design (from smaller pieces build solution) , mixes thereof.
a bottom-up piece hits me straight away task of summing list of numbers. has definition in haskell's prelude called sum :: (num a, foldable t) => t -> a
. somewhere in final solution going use this.
another method simplify problem. can lead astray way problem phrased. upon closer inspection might find equivalent , simpler phrasing.
what information need input? lists of numbers. simplest way obtain lists of numbers? number of lists seems irrelevant because there no need have information before start looking @ lists. drop first line , left with:
5 1 2 3 4 5 2 -100 100
then, length of each list irrelevant because not need information before summing list. therefore lets drop every other line point:
1 2 3 4 5 -100 100
now have lists of numbers separated line returns each number separated space.
at point have clear way break apart solution in top-down manner. first simplify input. secondly parse lists of numbers. thirdly sum lists. fourthly print sums. therefore skeleton of our solution:
simplifyinput :: string -> [string] parsenumberlist :: string -> [integer] -- note can use `sum` prelude sum number lists. printsums :: [integer] -> io () main :: io () main = getcontents >>= printsums . fmap (sum . parsenumberlist) . simplifyinput
now matter of implementing each obvious piece of solution.
simplifyinput :: string -> [string] simplifyinput = dropeveryother . drop 1 . lines dropeveryother :: [a] -> [a]
in writing simplifyinput
discovered dropping every other line requires more work. okay, can break solution apart again.
dropeveryother :: [a] -> [a] dropeveryother [] = [] dropeveryother (x:y:xs) = y : dropeveryother xs
then continuing...
parsenumberlist :: string -> [integer] parsenumberlist = fmap read . words printsums :: [integer] -> io () printsums = putstr . unlines . fmap show
therefore, in totality:
simplifyinput :: string -> [string] simplifyinput = dropeveryother . drop 1 . lines dropeveryother :: [a] -> [a] dropeveryother [] = [] dropeveryother (_:y:xs) = y : dropeveryother xs parsenumberlist :: string -> [integer] parsenumberlist = fmap read . words printsums :: [integer] -> io () printsums = putstr . unlines . fmap show main :: io () main = getcontents >>= printsums . fmap (sum . parsenumberlist) . simplifyinput
the amount of code have has gone (compared first solution) in exchange code made obvious. should add documentation comments not forget our explanation solution.
Comments
Post a Comment