Strings differing by only one character - string

So, I'm kinda new to Haskell (and programming generally) and I've been trying to solve a problem for a while. I want to make a function, that has as an input 2 alphanumerics (type String) and that returns True ONLY if both alphanumerics have the same length AND have only 1 different char. So, for example, if the inputs were block and black, I would get True, but if the inputs were black and brake, i would get false. I tried to do this with recursion, but i failed miserably. I need this function, because I wanτ to use it for checking some inputs in a program that I'm working on.
Any help is appreciated, thanks for your time.

If I understand you right, the different Chars should occur on the same position?
Then I think a straight-forward definition would be:
oneDifferent xs ys =
length xs == length ys &&
1 == length (filter (==False) (zipWith (==) xs ys))
... or ...
oneDifferent xs ys =
length xs == length ys &&
1 == foldr ((+) . fromEnum) 0 (zipWith (/=) xs ys) where
A recursive solution would be
oneDifferent (x:xs) (y:ys)
| x /= y = xs == ys
| otherwise = oneDifferent xs ys
oneDifferent _ _ = False

Related

separate even and odd elements of list haskell

I am trying to separate elements of a list into to further lists, one for the odd and one for even numbers.
For Example,
input: [1,2,3,4,10]
output: ([2,4,10],[1,3])
sepList :: [Int]->([Int],[Int])
sepList [] = ([],[])
sepList (x:xs) | (x mod 2) ==0 = (([x],[]) ++ sepList xs)
| (x mod 2) /=0 = (([],[x]) ++ sepList xs)
| otherwise = ([],[])
It gives error on ...++ sepList xs
anyone could guide me here?
The operator++ is used to concatenate 2 lists and neither of your arguments to ++ is a list,
([x],[]) ++ sepList xs
both ([x],[]) and sepList xs are pairs of lists. So what you want is to pattern match on sepList xs e.g. using a let binding,
let (ys,zs) = sepList xs in
and then return,
(x:ys,zs)
You aren't concatenating two lists; you want to add a single element to a list, selected from the tuple output of the recursive call. Don't use (++); use (:).
sepList (x:xs) = let (evens, odds) = sepList xs
in if even x
then (x:evens, odds)
else (evens, x:odds)
More simply, though, sepList = partition even. (partition can be found in Data.List.)
There are two answers so far which suggest basically doing this by hand (by pattern-matching on the result of the recursive call), but there is actually an operator already defined for the types that you're working with that does exactly what you want! Lists form a monoid with (<>) = (++), but you don't have two lists: you have two pairs of lists. Happily, the type of pairs are also a monoid if each element of the pair is a monoid: (a,b) <> (c,d) = (a <> c, b <> d). So, you can simply replace your ++ call with <>, which will result in concatenating the corresponding lists in your pairs.
For enthusiasts, following one line will also work for separating list in even and odd.
sepList xs = (filter even xs , filter odd xs)
import Data.List
sepList :: [Int]->([Int],[Int])
sepList = partition even
sepList [1,2,3,4,10]
In this case i would use an accumulator to create the tuple containing the two lists.In our case the accumulator is ([],[]).
split::[Int]->([Int],[Int])
split ls= go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
As you can see the elements need to be reversed since we are pushing on top of our lists with the : operator.
I do not know if this is optimal but i would write it like this with reverse:
module Split where
split::[Int]->([Int],[Int])
split ls=let rev tupl=(reverse . fst $ tupl ,reverse .snd $ tupl) in
rev $ go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs

Base case for not going out of the list?

Im very new to haskell and would like to know if theres a basic case for not going out of the list when going threw it!
For example in this code im trying to make a list where it compares the number on the right, and it if its bigger it stays on the list, otherwise we remove it, but it keeps giving me Prelude.head:empty list, since its comparing to nothing in the end im assuming. I've tried every base case i could think off... can anyone help me?
maiores:: [Int]->[Int]
maiores [] = []
maiores (x:xs) | x > (head xs) = [x] ++ [maiores xs)
| otherwise = maiores xs
If your function is passed a list with one element, it will match (x:xs), with xs matching []. Then you end up with head [] and thus your error. To avoid this, add an additional base case maiores (x:[]) = ... between your two existing cases, and fill it in appropriately.
Also: you can write [x] ++ maiores xs as x : maiores xs, which is more natural because you deconstruct a : and then immediately reconstruct it with the modified value, as opposed to indirectly using ++.
Never use head or tail in your code, unless you can't avoid it. These are partial functions, which will crash when their input is empty.
Instead, prefer pattern matching: instead of
foo [] = 4
foo (x:xs) = x + head xs + foo (tail xs)
write
foo [] = 4
foo (x1:x2:xs) = x1 + x2 + foo xs
Now, if we turn on warnings with -Wall, GHC will suggest that the match in not exhaustive: we forgot to handle the [_] case. So, we can fix the program accordingly
foo [] = 4
foo [x] = x
foo (x1:x2:xs) = x1 + x2 + foo xs
Just make pattern matching more specific. Since (:) is right associative:
maiores:: [Int]->[Int]
maiores [] = []
maiores (x : y : xs) | x > y = [x] ++ maiores (y:xs)
maiores (_ : xs) = maiores xs

How to implement this using map/filter

I'm supposed to come up with a function and::[Bool]->Bool, where (and xs) is True only if xs containst no False elements.
I am perfectly able to write this using recursion. I even tried it using map, BUT map ALWAYS return a list, which conflicts my return type.
Here's my code using recursion: (it works just fine)
isTrue::[Bool]->Bool
isTrue [] =True
isTrue (x:xs)
| (x == True) =isTrue(xs)
| otherwise =False
I tried doing this with map: (this will never work)
and::[Bool]->Bool
and xs = map (True ==) xs
So how in the world can I use map, filter or foldr to implement this crazy function? Thanks
Consider also takeWhile in a similar fashion as filter, yet halting the filtering once the first False is encountered, as follows,
and' :: [Bool] -> Bool
and' xs = xs == takeWhile (== True) xs
Filter True values and check if the result is an empty list:
and' :: [Bool] -> Bool
and' = null . filter (== False)
More classic approach using foldr:
and'' :: [Bool] -> Bool
and'' = foldr (&&) True
foldr is the way to go:
There are various ways to get to that. The first is to think about folding as inserting a binary operation between pairs of elements:
foldr c n [x1,x2,x3,...,xn] =
x1 `c` (x2 `c` (x3 `c` (... `c` (xn `c` n))))
So in this case,
foldr (&&) True [x1,x2,x3,...,xn] =
x1 && x2 && x3 && ... && xn && True
Note that && is right associative, so we don't need the parentheses there.
Another approach is to figure out how to convert the recursive form you gave into a fold. The thing to read to see how this works in general is Graham Hutton's "A Tutorial on the Universality and Expressiveness of Fold".
Start with your recursive form:
and::[Bool]->Bool
and [] =True
and (x:xs)
| (x == True) = and (xs)
| otherwise = False
Now there's no reason to ask if x==True because that's actually just the same as testing x directly. And there's no need for extra parentheses around a function argument. So we can rewrite that like this:
and [] = True
and (x:xs)
| x = and xs
| otherwise = False
Now let's see if we can write this as a fold:
and xs = foldr c n xs
Because and [] = True we know that n = True:
and xs = foldr c True xs
Now look at the recursive case:
and (x:xs)
| x = and xs
| otherwise = False
You can see that this depends only on x and on and xs. This means that we will be able to come up with a c so the fold will work out right:
c x r
| x = r
| otherwise = False
r is the result of applying and to the whole rest of the list. But what is this c function? It's just (&&)!
So we get
and xs = foldr (&&) True xs
At each step, foldr passes (&&) the current element and the result of folding over the rest of the list.
We don't actually need that xs argument, so we can write
and = foldr (&&) True

Haskell: Double every 2nd element in list

I just started using Haskell and wanted to write a function that, given a list, returns a list in which every 2nd element has been doubled.
So far I've come up with this:
double_2nd :: [Int] -> [Int]
double_2nd [] = []
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)
Which works but I was wondering how you guys would write that function. Is there a more common/better way or does this look about right?
That's not bad, modulo the fixes suggested. Once you get more familiar with the base library you'll likely avoid explicit recursion in favor of some higher level functions, for example, you could create a list of functions where every other one is *2 and apply (zip) that list of functions to your list of numbers:
double = zipWith ($) (cycle [id,(*2)])
You can avoid "empty list" exceptions with some smart pattern matching.
double2nd (x:y:xs) = x : 2 * y : double2nd xs
double2nd a = a
this is simply syntax sugar for the following
double2nd xss = case xss of
x:y:xs -> x : 2 * y : double2nd xs
a -> a
the pattern matching is done in order, so xs will be matched against the pattern x:y:xs first. Then if that fails, the catch-all pattern a will succeed.
A little bit of necromancy, but I think that this method worked out very well for me and want to share:
double2nd n = zipWith (*) n (cycle [1,2])
zipWith takes a function and then applies that function across matching items in two lists (first item to first item, second item to second item, etc). The function is multiplication, and the zipped list is an endless cycle of 1s and 2s. zipWith (and all the zip variants) stops at the end of the shorter list.
Try it on an odd-length list:
Prelude> double_2nd [1]
[1,*** Exception: Prelude.head: empty list
And you can see the problem with your code. The 'head' and 'tail' are never a good idea.
For odd-lists or double_2nd [x] you can always add
double_2nd (x:xs) | length xs == 0 = [x]
| otherwise = x : (2 * head xs) : double_2nd (tail xs)
Thanks.
Here's a foldr-based solution.
bar :: Num a => [a] -> [a]
bar xs = foldr (\ x r f g -> f x (r g f))
(\ _ _ -> [])
xs
(:)
((:) . (*2))
Testing:
> bar [1..9]
[1,4,3,8,5,12,7,16,9]

Why my two codes work so differently? (Haskell, Merge Sort)

I was writing a code for merge sort (Haskell).
I have a question on the function that puts two lists together according to the order.
( i.e. [1,4,7] [2,5,6] -> [1,2,4,5,6,7])
This is my original code. (xs, ys are the parameters and zs is an accumulator.)
msort4 [] ys zs = zs ++ ys
msort4 xs [] zs = zs ++ xs
msort4 allx#(x:xs) ally#(y:ys) zs
| x <= y = msort4 xs ally (zs ++ [x])
| otherwise = msort4 allx ys (zs ++ [y])
This is my second code which I wrote after referring a code I found online.
msort4 [] ys = ys
msort4 xs [] = xs
msort4 allx#(x:xs) ally#(y:ys)
| x <= y = x :msort4 xs ally
| otherwise = y : msort4 allx ys
Just with this small difference, my code improved a lot.
I was sorting a list of around 500 words and my original code needs around 2.5 seconds but the new one sorts it average of within 0.4 second.
I am wondering why mine is so slow while the one online is much faster even though they look pretty similar. (I even thought mine would be faster because mine does not need to go back and forth.)
Thanks in advance.
prepending (:) to a list is O(1), (++) is O(n) where n is a length of a left list
as zs get larger you have to traverse the whole list every time just to add one element [x]

Resources