How to recursively compare the digits in a number in Haskell - haskell

I am doing problem 112 on Project Euler and came up with the following to test the example case (I'll change the number in answer to 0.99 to get the real answer):
isIncre x | x == 99 = False
| otherwise = isIncre' x
where
isIncre' x = ???
isDecre x = isIncre (read $ reverse $ show x :: Int)
isBouncy x = (isIncre x == False) && (isDecre x == False)
bouncers x = length [n|n<-[1..x],isBouncy n]
nonBouncers x = length [n|n<-[1..x],(isBouncy n) == False]
answer = head [x|x<-[1..],((bouncers x) / (nonBouncers x)) == 0.5]
But what I don't know how to do is define a function isIncre' which tests to see if the digits in a number are greater than or equal to the one on their left. I know it needs to be done recursively but how?
On a side note, I know I can only use / on two floating point numbers but how can I make the output of bouncers to be floating point number instead of an integer?
Edit:
Thanks for the help, but it didn't like the = when I changed isIncre to:
isIncre x | x <= 99 = False
| otherwise = isIncre' (mshow x)
where
isIncre' (x:y:xs) = (x <= y) && (isIncre' (y:xs))
isIncre' _ = True

The number 0.99 cannot be represented exactly in base 2. Hence you may want to avoid the use of floating point numbers for this assignment. Instead, to see whether exactly 99% of the numbers <= x are bouncers, test whether
100 * (x - bouncers x) == x
This works because it is (mathematically) the same as (x - bouncers x) == x / 100, which is true if (x - bouncers x) (the number of non-bouncy numbers) is 1% of x. Observe that there is thus no need to define nonBouncers.
Also, another way to define bouncers is
bouncers x = length $ filter isBouncy [1..x]
However, you should reconsider your design. Currently you are recalculating the number of bouncy numbers up to x, for every x that you try. So a lot of work is being done over and over. What you may instead want to do, is generate a sequence of tuples (x, n), where n is the number of bouncy numbers <= x. Observe that if there are n bouncy numbers <= x, then there are either n or n + 1 bouncy number <= x + 1.
More specifically, to calculate (x + 1, n'), all you need is (x, n) and the output of isbouncy (x + 1).

If you have a string representation of an integer number, you could write the isIncre function like this (ord converts a character to an integer and string is just a list of chars):
isIncre (x:y:xs) = ord x <= ord y && isIncre (y:xs)
isIncre _ = True
It could be even nicer to write the isIncre function without ord, working on any ordered type, then combine it with "map ord" when you call it instead. The implementation would then be just:
isIncre (x:y:xs) = x <= y && isIncre (y:xs)
isIncre _ = True
That could be called like this, if x is an integer number
isIncre (map ord (show x))

I would use really nice functional version of isIncre if you have string representation of intetger.
isIncre :: (Ord a) => [a] -> Bool
isIncre list = and $ zipWith (<=) list (tail list)
If not, just compose it with show.
isIncreNum :: Integer -> Bool
isIncreNum = isIncre . show

Related

Is it possible to store a removed value in haskell

Hi I am new to haskell and I was just wondering whether it was possible to store a value that has already been removed:
This is my code
input :: Integer -> String
input x = checklength $ intolist x
intolist 0 = []
intolist x = intolist (x `div` 10) ++ [x `mod` 10]
checklength x = if length(x) >= 13 && length(x) <= 16 then doubleall
(init(x)) else "Not valid length of credit card number"
doubleall x = finalcheck $ final $ double (reverse (x))
double x = case x of
[] -> []
[x] -> if (x*2 < 10) then [x*2] else [x*2 `div` 10 + x*2 `mod` 10]
x:y:xs -> (if (x*2 < 10) then [x*2] else [x*2 `div` 10 + x*2 `mod` 10]) ++
y:double xs
final x = (sum x) * 9
finalcheck x = if (x `mod` 10 == ...... ) then "True" else "False"
My code basically takes an input as an integer such as 987564736264535. then makes this integer into a list of number such as [9,8,7..5]. Then it checks the length has to between 13 to 16 digits. If not you get an error statement. If the digits are between the required amount it will go into the doubeall function and remove the last number using (init). the number removed is 5 in which it will double the numbers and reverse the list order. It will then sum the numbers together and multiple by 9. The final step that I have done part of is taking the last digit of the number that has already been summed together and multiplied by 9. So lets give and example lets say I get 456 then I use mod 10 to take the last number which is 6. **Now here is where I am having a problem in which I want to check whether this 6 is equal to the same number that was removed originally in the checklength function when I used init. So in the checklength function I removed the number 5 **
Thanks
Once you remove data, you can't access it again. You need a function that preserves the final checkdigit that you're stripping off.
Since order is (mostly) irrelevant, consider:
validate :: Integer -> Bool
validate x = let digits = toDigits x
in if checkLength digits
then doesMatch . splitCheckdigit $ digits
else False
where
toDigits 0 = [0]
toDigits x = go x
where
go 0 = []
go x = let (d, m) = x `divMod` 10
in m : toDigits d
-- reverses order
checkLength x = let l = length x
in 13 <= l && l <= 16
splitCheckdigit (checkdigit:rest) = (checkdigit, rest)
-- remember we reversed in toDigits, so the *first* digit is the checkdigit!
doesMatch (checkdigit, rest) = let total = (*9) . sum . reduce $ rest
shouldBe = total `mod` 10
in checkdigit == shouldBe
where
reduce (x:y:xs) = (sum . toDigits $ x) : y : reduce xs
reduce [x] = [sum . toDigits $ x]
reduce [] = []
-- note how #toDigits# is reused here rather than redefined.
If you prefer Arrows, validate can be written as:
toDigits >>> ((doesMatch <<< splitCheckdigit) &&& checkLength) >>> uncurry (&&)

Writing a Between Numbers Function in Haskell

I'm currently working through The Craft of Functional Programming 2nd Edition and I have been presented with a task to write a between function which has stumped me.
The function takes three numbers as arguments and returns a boolean result i.e.
between :: Int -> Int -> Int -> Bool
It is defined so that between m n p is true if n is between n and p. For the sake of simplicity given between 2 2 2, the function would return true, also between 3 3 5 would return true.
Mathematically, x<=y and y<=z
The question also recommended that I could write a weakAscendingOrder function which checks that the number sequence doesn't go down at any point. I have written this function and my code is shown below:
weakAscendingOrder :: Int -> Int -> Int -> Bool
weakAscendingOrder x y z = (x <= y) && (y <= z)
How can I write a between function, either with or without using weakAscendingOrder, while preserving the function signatures since they have been provided by the book?
Comment two is exactly right. The weakAscendingOrder function behaves exactly like you want between to behave. Here are some additional flavors of implementation:
between x y z --using guards
|x <= y = y <= z
|otherwise = False
between x y z = if (x <= y) then (y <= z) else False --using if
between x y z = case (x <= y) of True -> (y <= z) --using case syntax
False -> False
however the (x<=y)&&(y<=z) is in my opinion very readable and does the job nicely.

Check for an element in the rest of the list (lx)

i recently picked up Haskell and i am having trouble putting in code the way to look if an element is in the rest of the list (x:lx) in this case in lx.
My code:
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y
| (x==y) && (`lx` == y) = False
| otherwise = True
The way it is now checks for the first element (x==y) but i don't know how to check if the element y exists in lx. The thing i am actually trying to accomplish is to find out if in the list of Intigers lx the number y contains 0 or 1 times and return True otherwise return False
There are several implementations you could use for this, one that I see which avoids applying length to a potentially infinite list is
atmostonce xs y
= (<= 1)
$ length
$ take 2
$ filter (== y) xs
This removes all elements from xs that are not equal to y, then takes at most 2 of those (take 2 [1] == [1], take 2 [] == []), calculates the length (it's safe to use here because we know take 2 won't return an infinite list), then checks if that is no more than 1. Alternatively you could solve this using direct recursion, but it would be best to use the worker pattern:
atmostonce = go 0
where
go 2 _ _ = False
go n [] _ = n <= 1
go n (x:xs) y =
if x == y
then go (n + 1) xs y
else go n xs y
The n <= 1 clause could be replaced by True, but ideally it'll short-circuit once n == 2, and n shouldn't ever be anything other than 0, 1, or 2. However, for your implementation I believe you are looking for the elem function:
elem :: Eq a => a -> [a] -> Bool
atmostonce [] y = True
atmostonce (x:ls) y
| (x == y) && (y `elem` ls) = False
| otherwise = True
But this won't return you the value you want, since atmostonce [1, 2, 2, 2] 2 would return True. Instead, you'd need to do recursion down the rest of the list if x /= y:
atmostonce (x:ls) y
| (x == y) && (y `elem` ls) = False
| otherwise = atmostonce ls y
You can do this using the elem function:
atmostonce:: [Int] -> Int -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
You better first check if the element x is not equal to y. If that is the case, you simply call the recursive part atmostonce lx y: you thus search further in the list.
In case x == y, (the otherwise case), you need to check if there is another element in lx (the remainder of the list), that is equal to x. If that is the case, you need to return False, because in that case there are multiple instances in the list. Otherwise you return True.
Furthermore you can generalize your function further:
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce [] y = True
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
Eq is a typeclass, it means that there are functions == and /= defined on a. So you can call them, regardless of the real type of a (Int, String, whatever).
Finally in the first case, you can use an underscore (_) which means you don't care about the value (although in this case it doesn't matter). You can perhaps change the order of the cases, since they are disjunct, and this makes the function syntactically total:
atmostonce:: (Eq a) => [a] -> a -> Bool
atmostonce (x:lx) y | x /= y = atmostonce lx y
| otherwise = not $ elem y lx
atmostonce _ _ = True
The existing answers are good, but you can use dropWhile to do the part that's currently done via manual recursion:
atMostOnce xs y =
let afterFirstY = drop 1 $ dropWhile (/= y) xs
in y `notElem` afterFirstY

How do I add the contents of a string?

Im am making a function which compares two strings to see if one is a rearrangement of the other. for example "hhe" and "heh" would produce true but "hhe" and "hee" would be false. I thought I could do this by summing the elements of the string and seeing if they are the same. I am knew to haskell, so I dont know if I can sum chars like in C. Code so far:
comp :: String -> String-> Bool
comp x y = (sum x) == (sum y)
This produces an error when compiling.
You can first sort, then compare the strings
import Data.List
import Data.Function
comp = (==) `on` sort
which can then be used like this
"abcd" `comp` "dcba" --yields True
It doesn't make sense to "sum" two strings. Use permutations instead:
comp :: String -> String -> Bool
comp x = (`elem` permutations x)
Live demo
Though there are problems with your implementation, as suggested by others, the direct answer to your question is that you can first convert characters to Int (a type that supports arithmetic) with fromEnum.
> sum . map fromEnum $ "heh"
309
Taking your example code at face value, the problem with it is that Char doesn't implement Num, so sum :: Num a => [a] -> a is incompatible.
We can fix that, however, by using fromEnum to convert the Chars to Ints:
isPermutationOf :: String -> String-> Bool
isPermutationOf x y = hash x == hash y
where hash = sum . map fromEnum
And this will work on your example case:
λ isPermutationOf "hhe" "heh"
True
The downside is that it also has some false positives:
λ isPermutationOf "AAA" "ab"
True
We can try to reduce those somewhat 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 though that catches some cases
λ isPermutationOf "AAA" "ab"
False
It doesn't catch them all
λ isPermutationOf "abyz" "acxz"
True
To do that, we really need to make sure we've got the same number of each Char in both inputs. We could solve this by using a Data.Map.Map to store the counts of each Char or by using Data.List.sort to sort each of the inputs, but if we only want to use the Prelude, we'll need to roll our own solution.
There's any number of examples on how to write quicksort in haskell out there, so I'm not going to tell you how to do that. So here's a dumb isPermutationOf 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 an n-length string as a set of n unknowns. isPermutationOf checks the n+1 equations:
eq0: x00 + x10 + ... + xn-10 = y00 + y10 + ... + ym-10
eq1: x01 + x11 + ... + xn-11 = y01 + y11 + ... + ym-11
eq2: x02 + x12 + ... + xn-12 = y02 + y12 + ... + ym-12
...
eqn: x0n + x1n + ... + xn-1n = y0n + y1n + ... + ym-1n
eq0 is essentially a length check. Given xs, the other n equations work out to n equations for n unknowns, which will give us a solution for ys unique up to permutation.
But really, you should use a (bucket) sort instead, because the above algorithm is O(n^2), which is slow for this kind of check.
if you do not want to use standard library(learning purpose) function, you can quickSort both string and check for equality of string (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)

Convert Negative-base binary to Decimal in Haskell: "Instances of .. required"

I have to write two functions converting decimal numers into a (-2)adian number system (similar to binary only with -2) and vice versa.
I already have managed to get the decimal -> (-2)adian running.
But with (-2)adian -> decimal I have a problem and just don't know where to begin.
Hope you can Help me
type NegaBinary = String
-- Function (-2)adisch --> decimal
negbin_dezi :: NegaBinary -> Integer -> Integer
negbin_dezi (xs:x) n
| (x == 0) = if ([xs] == "") then 0 else (negbin_dezi [xs] (n+1))
| (x == 1) = if ([xs] == "") then (-2)**n else (-2)**n + (negbin_dezi [xs] (n+1))
It always throws:
"Instances of (Num [Char], Floating Integer) required for definition of negbin_dezi.
Anyone an idea why it wont work?
Please please please :)
You have your list pattern-matching syntax backwards. In _ : _ the first argument is the head of the list (one element), and the second is the tail of the list (another list). e.g. x:xs matched with "abc" gives x = 'a' xs = "bc". So xs:x should be x:xs. The reason for GHC asking for an instance of Num [Char], is the comparison x == 0 (and x == 1). In this, it is trying to match the type of x (String == [Char]) with the type of 0 (Num a => a), and to do this, it requires a Num instance for String.
The fix is: negbin_dezi (x:xs) n
The problem asking for an Floating Integer instance is because (**) has type Floating a => a -> a -> a, where as you want (^) which has type (Num a, Integral b) => a -> b -> a (i.e. it is restricted to integer powers.)
Once you've done this, you'll find that your algorithm doesn't work for a few reasons:
The number 0 is different to the character '0', you should be comparing x with the characters '0' and '1' rather than the numbers 0 and 1.
xs is already a string, so [xs] is a list containing a string, which isn't what you want. This is fixed by removing the square brackets.
Possibly the ordering of the reduction is wrong.
On a different note, the duplicated if statement suggests that there is some optimisations that could happen with your code. Specifically, if you handle the empty string as part of negbin_dezi then you won't have to special case it. You could write it something like
negbin_dezi "" _ = 0
negbin_dezi (x:xs) n
| n == '0' = negbin_dezi xs (n+1)
| n == '1' = (-2)^n + negbin_dezi
(This has the bonus of meaning that the function is "more total", i.e. it is defined on more inputs.)
A few more things:
The code is "stringly-typed": your data is being represented as a string, despite having more structure. A list of booleans ([Bool]) would be much better.
The algorithm can be adapted to be cleaner. For the following, I'm assuming you are storing it like "01" = -2 "001" = 4, etc. If so, then we know that number = a + (-2) * b + (-2)^2 * c ... = a + (-2) * (b + (-2) * (c + ...)) where a,b,c,... are the digits. Looking at this, we can see the stuff inside the brackets is actually the same as the whole expression, just starting at the second digit. This is easy to express in Haskell (I'm using the list-of-bools idea.):
negbin [] = 0
negbin (x:xs) = (if x then 1 else 0) + (-2) * negbin xs
And that's the whole thing. If you aren't storing it in that order, then a call to reverse fixes that! (Being really tricky, one could write
negbin = foldr (\x n -> (if x then 1 else 0) + (-2)*n) 0
)
Some problems:
x == 0 or x == 1, but x is a Char, so you mean x == '0'.
You write (xs:x). There's no pattern for matching at the end of a list. Perhaps use a helper function that reverses the list first.
[xs] has one element, and will never be "". Use a base case instead.
Pattern matching is more helpful than equality checking.
** is for floating point powers, ^ is for integer powers
You often use [xs] where you mean xs. You don't need to put square brackets to make a list.
Here's a rewrite that works:
negbin_dezi1 :: NegaBinary -> Integer
negbin_dezi1 xs = negbin (reverse xs) 0
negbin [] _ = 0
negbin (x:xs) n
| x == '0' = negbin xs (n+1)
| x == '1' = (-2)^n + (negbin xs (n+1))
It would be nicer to use pattern matching:
negbin_dezi2 :: NegaBinary -> Integer
negbin_dezi2 xs = negbin (reverse xs) 0 where
negbin [] _ = 0
negbin ('0':xs) n = negbin xs (n+1)
negbin ('1':xs) n = (-2)^n + negbin xs (n+1)
But maybe it would be nicer to convert '0' to 0 and '1' to 1 and just multiply by that:
val :: Char -> Int
val '0' = 0
val '1' = 1
negbin_dezi3 :: NegaBinary -> Integer
negbin_dezi3 xs = negbin (reverse xs) 0 where
negbin [] _ = 0
negbin (x:xs) n = val x * (-2)^n + negbin xs (n+1)
I'd not write it that way, though:
A completely different approach is to think about the whole thing at once.
"10010" -rev> [0,1,0,0,1] -means> [ 0, 1, 0, 0, 1 ]
[(-2)^0, (-2)^1, (-2)^2, (-2)^3, (-2)^4]
so let's make both lists
powers = [(-2)^n | n <- [0..]]
coefficients = reverse.map val $ xs
and multiply them
zipWith (*) powers coefficients
then add up, giving:
negbin_dezi4 xs = sum $ zipWith (*) powers coefficients
where powers = [(-2)^n | n <- [0..]]
coefficients = reverse.map val $ xs
You could rewrite powers as map ((-2)^) [0..],
or even nicer: powers = 1:map ((-2)*) powers.
(It's nicer because it reuses previous calculations and is pleasantly clean.)
this
convB2D::NegaBinary->Integer
convB2D xs|(length xs)==0 =0
|b=='0' = convB2D(drop 1 xs)
|b=='1' = val+convB2D(drop 1 xs)
|otherwise= error "invalid character "
where b=head xs
val=(-2)^((length xs)-1)
worked for me.
I on the other hand have problems to convert dec->nbin :D

Resources