hello we have to create a code with turns for example "1T3e1s1t" into [(1,'T'),(3,'e'),(1,'s'),(1,'t')]
here is my code
unformat :: String -> [(Int, Char)]
unformat [] = []
unformat (x:xs) = [(unformat' 1, x)] unformat xss
where
unformat' = length (takeWhile (== x)xs)
xss = drop unformat' xs
it works but the output is "1T3e" -> [(1,'1'),(1,'T'),(1,'3'),(1,'e')] other than the takeWhile - drop function i get errors. The usage of the function replicate ive tried as well but with the wrong output again
unformat :: String -> [(Int, Char)]
unformat [] = []
unformat (x:xs) = (replicate (fst x) (snd x)) unformat xs
id appreciate any kind of help sincerely
CodePudding user response:
You can pattern-match also by multiple elements at the beginning of a list (like a:b:xs
):
module Main where
import Data.Char
main = print $ unformat "1T3e1s1t" -- [(1,'T'),(3,'e'),(1,'s'),(1,'t')]
unformat :: String -> [(Int, Char)]
unformat (i:c:xs) = (digitToInt i, c) : unformat xs
unformat _ = []
Data.Char.digitToInt
converts '0'
to 0
and 'f'
to 15
, for example.
CodePudding user response:
Here my solution with foldl
. In each step we remember prev chars as a Jsut c
if it's the first item of tuple or Nothing
if it's second item of tuple.
module Main where
import Data.Char
main :: IO ()
main = print $ unformat "1T3e1s1t"
unformat :: String -> [(Int, Char)]
unformat s = snd $ foldl opr (Nothing , []) s
where
opr (prev, acc) c = case prev of
Just n -> (Nothing, acc [(digitToInt n, c)])
Nothing -> (Just c, acc)
The output will be:
[(1,'T'),(3,'e'),(1,'s'),(1,'t')]