Haskell: last digit of a very large number - haskell

I'm trying to work out the last digit of a very large number. The challenge is that I'm getting the error
*** Exception: Prelude.!!: negative index
which I don't think should be possible. This happens when I try:
lastDigit [27,15,14]
Here is my code, which is based on https://brilliant.org/wiki/finding-the-last-digit-of-a-power/:
In this case, n becomes 7 and modList 7 gives the recurring sequence [1,7,9,3,1,7,9,3...], which is the first argument of (!!) in the relevant guard. The second argument of (!!) gives 1 because (y:ys) is (15,14) and rem (powers (15 ^ 14)) 4 is 1. Please help.
lastDigit :: [Integer] -> Integer
lastDigit [] = 1
lastDigit [x] = x `mod` 10
lastDigit [x,y] = x ^ y `mod` 10
lastDigit (x:y:ys)
| y == 0 && head ys /= 0 = 1
| n == 0 = 0
| n == 9 || n == 4 = (!!) (modList n) (rem (fromIntegral $ powers (y:ys)) 2)
| n == 2 || n == 3 || n == 7 || n == 8 = (!!) (modList n) (rem (fromIntegral $ powers (y:ys)) 4)
| otherwise = n
where n = mod x 10
powers xs = foldr1 (^) xs
modList n = drop 3 . take 30 $ cycle [mod x 10| x <- map (n^) $ take 4 [1..]]

You should be very specific about the types, otherwise they might get implicit converted during calculations. If you add Int type to your algorithm, ghc will not complain and run into an negative index exception
(fromIntegral $ powers (y:ys)) 2 :: Int)
but if you provide
(fromIntegral $ powers (y:ys)) 2 :: Integer)
it will result in
• Couldn't match expected type ‘Int’ with actual type ‘Integer’
• In the second argument of ‘(!!)’, namely
‘(rem (fromIntegral $ powers (y : ys)) 2 :: Integer)’
As you can see you have an implicit Int conversion there. Try to split up your function into smaller ones and provide a type signature, then you should be able to successfully align the types and calculate with Integers instead of Int.

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 (&&)

FP101x Lab 2 sumDigits

I'm stuck on Lab 2 of the Functional Programming course on edX taught by Erik Meijer. I will copy paste the assignment here:
In this lab, you will implement a validation algorithm for credit cards. The algorithm follows these steps:
Double the value of every second digit beginning with the rightmost.
Add the digits of the doubled values and the undoubled digits from the original number.
Calculate the modulus of the sum divided by 10.
If the result equals 0, then the number is valid. Here is an example of the results of each step on the number 4012888888881881.
In order to start with the rightmost digit, we produce a reversed list of digits. Then, we double every second digit.
Result: [1,16,8,2,8,16,8,16,8,16,8,16,2,2,0,8].
We sum all of the digits of the resulting list above. Note that we must again split the elements of the list into their digits (e.g. 16 becomes [1, 6]).
Result: 90.
Finally, we calculate the modulus of 90 over 10.
Result: 0.
Since the final value is 0, we know that the above number is a valid credit card number. If we make a mistake in typing the credit card number and instead provide 4012888888881891, then the result of the last step is 2, proving that the number is invalid.
My code:
toDigits :: Integer -> [Integer]
toDigits n = if 0 <= n && n <= 10 then [n] else toDigits ((n - n `mod` 10) `quot` 10) ++ [n `mod` 10]
toDigitsRev :: Integer -> [Integer]
toDigitsRev n = reverse (toDigits n)
doubleSecond :: [Integer] -> [Integer]
doubleSecond xs | length xs <= 1 = xs
| 1 < length xs && length xs < 4 = [fst (splitAt 2 xs) !! 0 ,(*2) (fst (splitAt 2 xs) !! 1 )] ++ snd (splitAt 2 xs)
| otherwise = doubleSecond (fst (splitAt 2 xs)) ++ doubleSecond (snd (splitAt 2 xs))
sumDigits :: [Integer] -> Integer
sumDigits xs | xs == [] = 0
| otherwise = sum (toDigits (head xs)) + sumDigits (tail xs)
isValid :: Integer -> Bool
isValid n | sumDigits (doubleSecond (toDigitsRev n)) `mod` 10 == 0 = True
| otherwise = False
Next, they give you this code:
numValid :: [Integer] -> Integer
numValid xs = sum . map (\_ -> 1) $ filter isValid xs
creditcards :: [Integer]
creditcards = [ 4716347184862961,
4532899082537349,
4485429517622493,
4320635998241421,
4929778869082405,
5256283618614517,
5507514403575522,
5191806267524120,
5396452857080331,
5567798501168013,
6011798764103720,
6011970953092861,
6011486447384806,
6011337752144550,
6011442159205994,
4916188093226163,
4916699537435624,
4024607115319476,
4556945538735693,
4532818294886666,
5349308918130507,
5156469512589415,
5210896944802939,
5442782486960998,
5385907818416901,
6011920409800508,
6011978316213975,
6011221666280064,
6011285399268094,
6011111757787451,
4024007106747875,
4916148692391990,
4916918116659358,
4024007109091313,
4716815014741522,
5370975221279675,
5586822747605880,
5446122675080587,
5361718970369004,
5543878863367027,
6011996932510178,
6011475323876084,
6011358905586117,
6011672107152563,
6011660634944997,
4532917110736356,
4485548499291791,
4532098581822262,
4018626753711468,
4454290525773941,
5593710059099297,
5275213041261476,
5244162726358685,
5583726743957726,
5108718020905086,
6011887079002610,
6011119104045333,
6011296087222376,
6011183539053619,
6011067418196187,
4532462702719400,
4420029044272063,
4716494048062261,
4916853817750471,
4327554795485824,
5138477489321723,
5452898762612993,
5246310677063212,
5211257116158320,
5230793016257272,
6011265295282522,
6011034443437754,
6011582769987164,
6011821695998586,
6011420220198992,
4716625186530516,
4485290399115271,
4556449305907296,
4532036228186543,
4916950537496300,
5188481717181072,
5535021441100707,
5331217916806887,
5212754109160056,
5580039541241472,
6011450326200252,
6011141461689343,
6011886911067144,
6011835735645726,
6011063209139742,
379517444387209,
377250784667541,
347171902952673,
379852678889749,
345449316207827,
349968440887576,
347727987370269,
370147776002793,
374465794689268,
340860752032008,
349569393937707,
379610201376008,
346590844560212,
376638943222680,
378753384029375,
348159548355291,
345714137642682,
347556554119626,
370919740116903,
375059255910682,
373129538038460,
346734548488728,
370697814213115,
377968192654740,
379127496780069,
375213257576161,
379055805946370,
345835454524671,
377851536227201,
345763240913232
]
You are supposed to run numValid creditcards and get 94, I'm getting 39.
I suspect my mistake is in sumDigits but can't really find it, any help is much appreciated.
Let's try to find those errors. We're going to use QuickCheck to test several properties. Let's start with some properties for toDigits:
toDigits_prop n = n >= 0 ==> length (toDigit n) === length (show n)
It will fail after some tests with something like this:
*Main> quickCheck toDigits_prop
*** Failed! Falsifiable (after 24 tests):
10
1 /= 2
This means that we got only one digit on 10, where we originally expected two. Let's check the result of toDigits on 10:
*Main> toDigits 10
[10]
Aha. There's a logic error on toDigits, the behaviour on the bounds is wrong, 10 isn't a digit. So change that to <= 9 instead <= 10. While we're at it let's simplify that function, since there is quotRem to get both the reminder and quot at the same time:
toDigits :: Integer -> [Integer]
toDigits n = case n `quotRem` 10 of
(0, m) -> [m] -- only one digit was left
(q, m) -> toDigits q ++ [m]
Note that this function is somewhat inefficient, we can make it faster if we reverse the digits at the same time:
toDigitsRev :: Integer -> Integer
toDigitsRev n = case n `quotRem` 10 of
(0, m) -> [m] -- only one digit was left
(q, m) -> m : toDigitsRev q -- add current digit left
Either way, let's check whether the new version of toDigits holds:
*Main> quickCheck toDigits_prop
+++ OK, passed 100 tests.
Allright. Let's check whether this passes all tests:
*Main> numValid creditcards
94
Seems like now everything is fine. So the key is to check properties of your functions. Note that several functions can be written easier, e.g.
doubleSecond :: Num a => [a] -> [a]
doubleSecond xs = zipWith ($) (cycle [id, (2*)]) xs
-- or
doubleSecond (x:y:xs) = x : 2 * y : doubleSecond xs
doubleSecond xs = xs
sumDigits :: [Integer] -> Integer
sumDigits xs = sum (concatMap toDigits xs)

Check whether an integer (or all elements of a list of integers) be prime

I'm doing a simple Haskell function using recursion. At the moment, this seems to work but, if I enter 2, it actually comes up as false, which is irritating. I don't think the code is as good as it could be, so, if you have any advice there, that'd be cool too!
I'm pretty new to this language!
EDIT: Ok, so I understand what a prime number is.
For example, I want to be able to check 2, 3, 5, 7, etc and have isPrime return true. And of course if I run the function using 1, 4, 6, 8 etc then it will return false.
So, my thinking is that in pseudo code I would need to do as follows:
num = 2 -> return true
num > 2 && num = even -> return false
After that, I'm struggling to write it down in any working code so the code below is my work in process, but I really suck with Haskell so I'm going nowhere at the minute.
module Recursion where
isPrime :: Int -> Bool
isPrime x = if x > 2 then ((x `mod` (x-1)) /= 0) && not (isPrime (x-1)) else False
Ok,
let's do this step by step:
In math a (natural) number n is prime if it has exactly 2 divisors: 1 and itself (mind 1 is not a prime).
So let's first get all of the divisors of a number:
divisors :: Integer -> [Integer]
divisors n = [ d | d <- [1..n], n `mod` d == 0 ]
then get the count of them:
divisorCount :: Integer -> Int
divisorCount = length . divisors
and voila we have the most naive implementation using just the definition:
isPrime :: Integer -> Bool
isPrime n = divisorCount n == 2
now of course there can be quite some impprovements:
instead check that there is no divisor > 1 and < n
you don't have to check all divisors up to n-1, it's enough to check to the squareroot of n
...
Ok just to give a bit more performant version and make #Jubobs happy ;) here is an alternative:
isPrime :: Integer -> Bool
isPrime n
| n <= 1 = False
| otherwise = not . any divides $ [2..sqrtN]
where divides d = n `mod` d == 0
sqrtN = floor . sqrt $ fromIntegral n
This one will check that there is no divisor between 2 and the squareroot of the number
complete code:
using quickcheck to make sure the two definitions are ok:
module Prime where
import Test.QuickCheck
divisors :: Integer -> [Integer]
divisors n = [ d | d <- [1..n], n `mod` d == 0 ]
divisorCount :: Integer -> Int
divisorCount = length . divisors
isPrime :: Integer -> Bool
isPrime n
| n <= 1 = False
| otherwise = not . any divides $ [2..sqrtN]
where divides d = n `mod` d == 0
sqrtN = floor . sqrt $ fromIntegral n
isPrime' :: Integer -> Bool
isPrime' n = divisorCount n == 2
main :: IO()
main = quickCheck (\n -> isPrime' n == isPrime n)
!!warning!!
I just saw (had something in the back of my mind), that the way I did sqrtN is not the best way to do it - sorry for that. I think for the examples with small numbers here it will be no problem, but maybe you really want to use something like this (right from the link):
(^!) :: Num a => a -> Int -> a
(^!) x n = x^n
squareRoot :: Integer -> Integer
squareRoot 0 = 0
squareRoot 1 = 1
squareRoot n =
let twopows = iterate (^!2) 2
(lowerRoot, lowerN) =
last $ takeWhile ((n>=) . snd) $ zip (1:twopows) twopows
newtonStep x = div (x + div n x) 2
iters = iterate newtonStep (squareRoot (div n lowerN) * lowerRoot)
isRoot r = r^!2 <= n && n < (r+1)^!2
in head $ dropWhile (not . isRoot) iters
but this seems a bit heavy for the question on hand so I just remark it here.
Here are two facts about prime numbers.
The first prime number is 2.
An integer larger than 2 is prime iff it's not divisible by any prime number up to its square root.
This knowledge should naturally lead you to something like the following approach:
-- primes : the infinite list of prime numbers
primes :: [Integer]
primes = 2 : filter isPrime [3,5..]
-- isPrime n : is positive integer 'n' a prime number?
isPrime :: Integer -> Bool
isPrime n
| n < 2 = False
| otherwise = all (\p -> n `mod` p /= 0) (primesPrefix n)
where primesPrefix n = takeWhile (\p -> p * p <= n) primes
As a bonus, here is a function to test whether all items of a list of integers be prime numbers.
-- arePrimes ns : are all integers in list 'ns' prime numbers?
arePrimes :: [Integer] -> Bool
arePrimes = all isPrime
Some examples in ghci:
ghci> isPrime 3
True
ghci> isPrime 99
False
ghci> arePrimes [2,3,7]
True
ghci> arePrimes [2,3,4,7]
False
You can get a recursive formulation from the "2 divisors" variant by step-wise refinement:
isPrime n
= 2 == length [ d | d <- [1..n], rem n d == 0 ]
= n > 1 && null [ d | d <- [2..n-1], rem n d == 0 ]
= n > 1 && and [ rem n d > 0 | d <- takeWhile ((<= n).(^2)) [2..] ]
= n > 1 && g 2
where
g d = d^2 > n || (rem n d > 0 && g (d+1))
= n == 2 || (n > 2 && rem n 2 > 0 && g 3)
where
g d = d^2 > n || (rem n d > 0 && g (d+2))
And that's your recursive function. Convince yourself of each step's validity.
Of course after we've checked the division by 2, there's no need to try dividing by 4,6,8, etc.; that's the reason for the last transformation, to check by odds only. But really we need to check the divisibility by primes only.

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

Haskell program that gives pretty prime numbers

I've made a haskell program that computes pretty prime numbers. Pretty primes are primes that are very close to a power of 2. You give 2 numbers for example: 10 and 20 then it returns 17 because 17 is the closest to a power of 2. 17 - 16 = 1 so it is the closest.
I've made this:
EDIT: I've rewrote the primefunction like this and e verw function but still getting -1.
-- Geeft priemgetallen terug tussen de 2 grenzen
-- English: Gives primenumbers between 2 numbers
priemgetallen :: Int->[Int]
priemgetallen b = take b (zeef [2..])
where zeef (p:xs) = p : zeef [x | x<-xs, (mod x p) /= 0]
-- Geeft machten terug tussen de 2 grenzen
-- English: Gives powers of 2 between 2 numbers
machten :: Int->Int->[Int]
machten a b
| a <= 2 = 2:[2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
| otherwise = [2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
-- English: the start of the function
prettyprime :: Int->Int->Int
prettyprime a b = vergelijk ( verw a (priemgetallen b)) (machten a b)
-- Filter the list
verw :: Int->[Int]->[Int]
verw _ [] = []
verw k (x:xs)
| x > k = [x] ++ verw k xs
| otherwise = verw k xs
-- Vergelijkt alle priemgetallen en geeft welke korste bij het ander ligt
-- English this function must see what primenumber is the closest to a power of 2 but I can't fix it
vergelijk :: [Int]->[Int]->Int
vergelijk [] _ = -1
vergelijk _ [] = -1
vergelijk (x:xs) (y:ys)
| x - y < vergelijk (x:xs) ys = x
| x - y > vergelijk (x:xs) ys = vergelijk xs (y:ys)
| x - y == vergelijk (x:xs) ys = x
main = do
print $ prettyprime 14 20
Can someone help me?
Kind regards,
The incomplete pattern is because you've omitted the case when x - y == vergelijk (x:xs) ys. The compiler is capable of warning you about this if you add -fwarn-incomplete-patterns and convert your guards into a real case:
vergelijk (x:xs) (y:ys) = case compare (x - y) (vergelijk (x:xs) ys) of
LT -> x
-- you will get a warning about having no case for EQ
GT -> vergelijk xs (y:ys)
As a bonus, this version is much less likely to recompute the recursive call, especially on low optimization levels.

Resources