How do I add the content of the string?
I am making a function that compares two strings to see if it is a rearrangement of the other. for example, "hhe" and "heh" will return true, but "hhe" and "hee" will be false. I thought I could do this by summing the elements of the string and seeing if they are the same. I know haskell, so I don't know if I can sum characters like in C. Code:
comp :: String -> String-> Bool
comp x y = (sum x) == (sum y)
This results in a compilation error.
source to share
Taking your example code at face value, the problem with it is that it Char
doesn't implement Num
, so it's sum :: Num a => [a] -> a
incompatible.
We can fix this, however, by using fromEnum
to convert Char
to Int
s:
isPermutationOf :: String -> String-> Bool
isPermutationOf x y = hash x == hash y
where hash = sum . map fromEnum
And this will work in your example:
λ isPermutationOf "hhe" "heh"
True
The downside is that it also has some false positives:
λ isPermutationOf "AAA" "ab"
True
We can try to reduce them a little by making sure that the lengths, maxes and mins of the inputs are the same:
isPermutationOf :: String -> String-> Bool
isPermutationOf x y = hash x == hash y && maximum x == maximum y && minimum x == minimum y
where hash = sum . map fromEnum
But although it catches some cases
λ isPermutationOf "AAA" "ab"
False
He won't catch them all
λ isPermutationOf "abyz" "acxz"
True
To do this, we really need to make sure that we have the same amount of each Char
on both inputs. We could solve this problem by using Data.Map.Map
the storage of samples for each Char
or use Data.List.sort
for sorting each of the inputs, but if we only want to use Prelude
, we will need to turn our own decision.
There's any number of examples of writing quicksort
in haskell out there , so I won't tell you how to do it. So, here's a dumb isPermutationOf
one that uses math instead.
isPermutationOf xs ys = all (\k -> powsum k as == powsum k bs) [0..n]
where as = map fromEnum xs
bs = map fromEnum ys
n = length xs
powsum k zs = sum (map (^k) zs)
Basically, we can view the n
-length string as a collection of n
unknowns. isPermutationOf
checks the equations n+1
:
- eq 0: x 00 + x 10 + ... + x n-10 = y 00 + y 10 + ... + y m-1 0
- eq 1: x 01 + x 11 + ... + x n-11 = y 01 + y 11 + ... + y m-1 1
- eq 2: x 02 + x 12 + ... + x n-12 = y 02 + y 12 + ... + y m-1 2
- ...
- eq n: x 0n + x 1n + ... + x n-1n = y 0n + y 1n + ... + y m-1 n
eq0
is essentially a length check. Considering xs
other equations n
develop equations n
for n
unknowns, which will give us a solution for a ys
unique one up to permutation.
But actually you should use a (bucket) sort because the above algorithm O(n^2)
is slow for this type of check.
source to share
if you don't want to use a standard library function (learning target) you can quickly concatenate both strings and check for string equality (bonus: quickSort)
isEqual :: String -> String -> Bool
isEqual a b = sortString a == sortString b
where
sortString :: String -> String
sortString [] = []
sortString (x:xs) = sortString (filter (<x) xs) ++ [x] ++ sortString (filter (>=x) xs)
source to share