i have some troubles here with this.
I'm trying to do something like that:
Prelude> func ["abacate", "aba", "baaba"]
["cate", "", "ba"]
this exercise, must return words without the substring aba.
elimLetras :: String -> String
elimLetras [] = []
elimLetras (x:y:z:xs)
| elem x "aA" || elem y "bB" || elem z "aA" = elimLetras xs
| otherwise = x : elimLetras (x:xs)
| otherwise = y : elimLetras (y:xs)
| otherwise = z : elimLetras (z:xs)
elimLetras (x:xs) = x:xs
this code it's not working right.
On ghci, i'ts return:
prelude> elimLetras "abacate"
output: "cce"
Any tips?
So you are trying to remove the case insensitive substring aba from a String. Your method of checking for a substring isn't bad. It wouldn't scale very well but you can keep it like this if you want. The main issue is with the multiple otherwise statements. You should only ever have one otherwise statement, as only the first one will ever be reached.
Here is a rewrite of your function with a couple of helper function:
import Data.Char (toLower)
elimLetras :: String -> String
elimLetras (x:y:z:xs)
| stringEquals "aba" [x,y,z] = elimLetras xs
| otherwise = x : elimLetras (y:z:xs)
elimLetras xs = xs -- anything that has fewer than 3 letters is returned "as is".
-- Check if two strings are the same (case insensitive)
stringEquals :: String -> String -> Bool
stringEquals a b = stringToLower a == stringToLower b
stringToLower :: String -> String
stringToLower [] = []
stringToLower (x:xs) = toLower x : stringToLower xs
If you know about the map function, here is how I would probably write it:
elimLetras' :: String -> String
elimLetras' (x:y:z:xs)
| "aba" == map toLower [x,y,z] = elimLetras' xs
| otherwise = x : elimLetras' (y:z:xs)
elimLetras' xs = xs
Related
This question already has answers here:
Non exhaustive pattern in function noThirds
(3 answers)
Closed 5 years ago.
I'm not sure what I'm missing here, but I have been unable to get the pattern matching on checkDiff to work in the code below. GHCi report "non-exhaustive patterns in function checkDiff. The code is:
import Data.Array.Unboxed
primes :: [Int]
primes = 2 : oddprimes ()
where
oddprimes () = 3 : sieve (oddprimes ()) 3 []
sieve (p:ps) x fs = [i*2 + x | (i,True) <- assocs a]
++ sieve ps (p*p) ((p,0) :
[(s, rem (y-q) s) | (s,y) <- fs])
where
q = (p*p-x)`div`2
a :: UArray Int Bool
a = accumArray (\ b c -> False) True (1,q-1)
[(i,()) | (s,y) <- fs, i <- [y+s, y+s+s..q]]
takePrimes :: [Int] -> [(Int,Int)]
takePrimes [] = []
takePrimes [x] = []
takePrimes (x:y:zs) = if y - x > 2 then (x,y) : takePrimes (y:zs) else takePrimes (y:zs)
checkDiff :: [(Int,Int)] -> Int
checkDiff [] = 0
checkDiff [(0,_)] = 0
checkDiff [(_,0)] = 0
checkDiff [(a,b)] = sum $ [x | x <- [(a + 1)..(b - 1)], totalFactors a == totalFactors (a + 1)]
totalFactors :: Int -> Int
totalFactors n = length $ [x | x <- [2..(div n 2)], rem n x == 0]
Please help.
checkDiff only handles lists of length zero and one. It is probably called with a longer list, triggering the non-exhaustiveness error.
You should turn on warnings with the -Wall flag. If you do, GHC will report such problems at compile time instead.
I am trying to solve a simple problem on HackerRank and am receiving the error in the title. The problem asks to take in a string and reduce it by removing adjacent pairs of letters. So "aabcdd" => "bc" for example. Here's my code:
main :: IO()
main = do
line <- getLine
putStrLn (reduce' line)
reduce' :: String -> String
reduce' [] = []
reduce' (x0:x1:xs)
| x1:xs == [] = [x0]
| x0 == x1 = reduce' xs
| otherwise = x0 : x1 : reduce' xs
I am confused because I think I have the edge cases covered. I don't want an answer to the problem, I just want to know why I am getting the error. Thanks!
You are not matching the case where you have only one element in the list
reduce' :: String -> String
reduce' [] = []
reduce' [x] = [x]
reduce' (x0:x1:xs)
| x0 == x1 = reduce' xs
| otherwise = x0 : x1 : reduce' xs
This | x1:xs == [] = [x0] is the pattern matching added, so there is no need to check in the guards.
New to Haskell:
Hi can't seem to figure this out.
What I am trying to do is take a string, turn it in to a [Int] (with map ord)
Change some numbers that fulfils something (in this case x mod 3 == 0).
afterwards I'd like to turn the unchanged numbers back to char, and changed numbers still numbers. Combine this into a string again..
This is my problem:
*Main> fromStringToList "hihello"
[104,105,104,101,108,108,111]
*Main> changeB3 [104,105,104,101,108,108,111]
"'h'210'h''e'216216222"
What I want is:
"h210he216216222"
I'm stuck figuring out how to use show and map to get this to work without the '_' from Char. Thanks.
My Code:
import Data.Char
fromStringToList :: String -> [Int]
fromStringToList "" = []
fromStringToList myString = map ord myString
{-
changeB3
PRE: True
POST: every Int that can be divided by 3 is multiplied by 2 and
kept as int, otherwise transformed to char
-}
changeB3 :: [Int] -> String
changeB3 [] = ""
changeB3 (x:xs)
| x `mod ` 3 == 0 = show map (x * 2 ) ++ changeB3 xs
|otherwise = map chr x ++ changeB3 xs
I will comment your code.
fromStringToList :: String -> [Int]
fromStringToList "" = []
fromStringToList myString = map ord myString
The second line is redundant: when myString is empty, map returns [] anyway. You should remove it.
changeB3 :: [Int] -> String
changeB3 [] = ""
changeB3 (x:xs)
| x `mod ` 3 == 0 = show map (x * 2 ) ++ changeB3 xs
|otherwise = map chr x ++ changeB3 xs
You seem to be confused here. You use a recursive function, but want to use map. You use either recursion or map here, not both.
Assuming you want to use map, you should start by defining how to handle a single Int.
changeB3Single :: Int -> String
changeB3Single x | x `mod` 3 == 0 = ...
| otherwise = ...
Then you map that over the whole list. A first attempt might be
changeB3 :: [Int] -> String
changeB3 xs = map changeB3Single xs -- type error!
but this won't work, since map here returns a list of strings, rather than a single string. We just need to concatenate them.
changeB3 xs = concat (map changeB3Single xs)
Indeed, concat (map ...) is so commonly found that it has its own function in the libraries:
changeB3 xs = concatMap changeB3Single xs
(One could make that pointfree, but there's no need to -- especially for a beginner.)
movex [] a s = []
movex (x:xs) a s
| elem a x = moveNow x a s
| otherwise = x : (movex xs a s)
where
moveNow x a s
| s == 'l' = moveNow2 x a
where
moveNow2 [] _ = []
moveNow2 (x:y:xs) a
| x == ' ' && y == a = a : x : moveNow2 (y:xs) a
| otherwise = x : moveNow2 (y:xs) a
<- This is what I got right now
I am trying to make a function that iterates through [string], finds the right string and then mutates it.
given input
func ["abc", "dfg"] f l -- move f in this list 1 space left --
expected output
["abc", "fdg"]
Right now I am stuck at movex function that gives me error
Couldn't match expected type `Char' with actual type `[Char]'
In the first argument of `(:)', namely `x'
In the expression: x : (movex xs a s)
Direct solution to the error is to replace the line
| elem a x = moveNow x a s
With
| elem a x = moveNow x a s : movex xs a s
Or, probably
| elem a x = moveNow x a s : xs
Depending on what you want to do after the first match: continue looking for certain character, or leave other strings untouched.
Your moveNow function has return type String, or [Char], while movex has [String], or [[Char]], that's why compiler complains.
To avoid such problems(or fix them easier) consider writing explicit type signatures, like so:
movex :: [String]->String->String->[String]
I can remove the vowels without a recursive function like this:
NoVowels:: String -> String
NoVowels xs = filter f xs where f x = not (x == ’a’ || x == ’e’ || x == ’i’ || x == ’o’ || x == ’u’)
But how may I do that with a recursive function ?
I tried something like this but of course did not work (parse Error):
NoVowels :: String -> String
NoVowels "" = error "Empty String!!"
NoVowels (x:xs)
| x in (x == 'a'|| x == 'e' || x == 'i' || x == 'o' || x == 'u') = NoVowels (tail x)
If the head is a vowel then I CUT it from the string and pass recursively the tail, if its not a vowel how may I verify the other string without removing it.
Update obs: I want to return the function without the vowels.
I thins it makes sense to define a function isVowel :: Char->Bool and after that write something like this :
noVowels :: String -> String
noVowels [] = []
noVowels (x:xs)
|isVowel x = noVowels xs
|otherwise = x : noVowels xs
If you don't want to define one more function you can try next code :
noVowels :: String ->String
noVowels [] = []
noVowels (x:xs)
|not( x `elem` "aeiou") = x: noVowels xs
|otherwise = noVowels xs
Here's a bit of an improvement on the code. Just in case you missed out on preserving the cases involved.
module Disemvowel where
disemvowel :: String -> String
disemvowel [] = []
disemvowel " " = " "
disemvowel (x:xs)
| x `elem` "aeiouAEIOU" = disemvowel xs
| otherwise = [x] ++ disemvowel xs