简体   繁体   中英

Haskell - Decode message with pattern

I am new to Haskell and I am currently learning it in school. I got a school task where I have to decode a message that contain certain patterns but I have got no idea how to do this.

The pattern looks something like this: If a letter has a consonant followed by the character 'o' and then once again followed by the same consonant as before it should replace that substring ("XoX" where X is a consonant) with only the consonant. For example if I decode the string "hohejoj" it should return "hej". Sorry if I am explaining this poorly but I think you understand.

This is the code I have so far (but it doesn't work):¨

karpsravor :: String->String
karpsravor s = karpsravor_help s ""
    where karpsravor_help s res
           |s == "" && (last res) == 'o' = (init res)
           |s==""=res
           |otherwise = karpsravor_help (drop 3 s) (res ++ (consDecode (take 3 s)))

consDecode :: String->String
consDecode a
    |(length a) < 3 = ""
    |a == [(head a)]++"o"++[(head a)] = [(head a)]
    |otherwise = a

The code is completely broken and poorly written (dumb method) but I have no other idea for how to solve this. Please help!

Pattern match to find occurrences of 'o'. Ie, use

karpsravorhelp (a:'o':b:rest) res = ...

You can't have a:'o':a:rest in the above, you can't pattern match for equality; you'll need to use a guard to make sure that a == b :

karpsravorhelp (a:'o':b:rest) res | a == b = ... | otherwise = ...

You'll also have to make sure a and b are consonants, which will just be an 'and' condition for the first guard. For the otherwise condition, make sure that the recursive call calls (b:rest) since you could have something like a:'o':b:'o':b:... .

Also make sure to match for two other patterns:

  1. Empty List, []
  2. x:rest , which must go after the above pattern; this way, it will first attempt to match on the a:'o':b:rest pattern, and if that's not there, just take the next letter.

One way to do it would be with unfoldr from Data.List . You can use a case expression to pattern match on a : 'o' : b : rest , and then check that a and b are equal and not vowels using a guard | . Then just include the base cases for when the pattern doesn't match.

notVowel :: Char -> Bool
notVowel = (`notElem` "aeiouAEIOU")

karpsravor :: String -> String
karpsravor = unfoldr $ \str -> case str of
    a : 'o' : b : rest
        | a == b && notVowel a -> Just (a, rest)
    a : rest                   -> Just (a, rest)
    ""                         -> Nothing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM