I have the following pair of Integers:
maxCollatz :: (Integer, Integer)
maxCollatz = (head $ maximum (map collatzList [1..500]), length $ maximum (map collatzList [1..500]))
Since I am a newbie, I don't know how to use either fromIntegral or toInteger to convert length to Integer. I know that length must be finite, but since the range of the "function" can be quite big, I am inclined to use (Integer, Integer).
Again, my question is - how to convert length to Integer from Int using fromIntegral or toInteger?
There are two problems : first your code doesn't do what you think it does, second just converting the length to an integer is completely useless...
1) Your code is erroneous since maximum doesn't select the longest list. maximum works with Ord instances and select the greatest according to the compare method for this type. For Int and Integer, the order may be obvious but for lists it is not so. The traditional way to order list is the lexicographic order (which is used in dictionaries if you consider words to be list of characters) : "[] < y:_" and "x:xs < y:ys" iff x < y or (x == y and xs < ys).
So your code will simply give you the collatzList that start with the biggest number, that is [500, 250, ...].
2) Converting your length to Integer is nice but it's too late : if it was computed with an Int, it won't restore the correct value, a list of length (maxBound :: Int) + 1 will get a computed length of (minBound :: Int) then this Int will be converted to an Integer of the same value...
What you want is to compute the length directly with Integers which you can do with Data.List.genericLength.
That said, you really don't need to use Integer, especially if you're on a 64-bit GHC (very likely, check with ghc -e "maxBound :: Int" on the CLI). Collatz won't go over a 64-bit Int for reasonable starting numbers.
As for maximum, I suggest you investigate maximumBy, comparing and zip to get code that do what you want.
I have found it:
maxCollatz :: (Integer, Integer)
maxCollatz = (head $ maximum (map collatzList [1..500]), toInteger $ length $ maximum (map collatzList [1..500]))
Just add toInteger $ before length.
Related
I need to convert a string of chars to a list of binary numbers in Haskell. I've written two functions to do this, but I'm not sure how to combine them into one. So far I have
dec[]=[]
dec(x:xs) = ord(x): dec xs
to convert every char in the list into a decimal number. The next function
bin 0 = [0]
bin n| n `mod` 2 == 1 = bin (n `div` 2) ++ [1]
| n `mod` 2 == 0 = bin (n `div` 2) ++ [0]
converts a decimal number to its binary equivalent. I'm not sure how to apply the second function to every element in the list, in order to convert every char to its equivalent in binary. I tried to use the where clause:
where n = dec(x:xs) = ord(x): dec xs
but this is not valid as there are two equals signs on the same line. How can I achieve the correct functionality?
You can be pretty certain that an Int will be stored in binary. It only appears to be in decimal because it is converted to decimal when you print it. So, the name dec is a misnomer, that function is converting a String into a sequence of numbers that represent the Unicode value of each character. You can avoid explicit recursion by using map:
toUnicode :: String -> [Int]
toUnicode = map ord
Note that this function uses so-called point-free style. The expected argument is missing, but will be passed to map when supplied by the caller.
The Bin function will not compile because it starts with an upper case character, making it a data constructor. You should name the function starting with a lower case character. According to your example output, you want leading zeros in your binary representations, so you can't stop conversion when the value becomes zero. You need to continue until you have converted the desired number of digits, which appears to be 8. It is also inefficient to keep appending to a list. It is better to prepend, and then reverse the result.
toBinary :: Int -> [Int]
toBinary = go 8 [] where
go 0 acc _ = reverse acc
go n acc x = go (n-1) (bit:acc) x' where
(x', bit) = x `divMod` 2
Here, we use a helper function, go which counts down the number of remaining digits as it builds up the list of 1's and 0's.
So, now we have a function to convert a String into a list of Ints, and a function to convert an Int into a list of 0/1 Ints, and we want to glue them together to make a function that converts a String to a list of 0/1 Ints. If we map our toBinary function over the result of toUnicode, we will get a list of lists, which must be concatenated to form a single list. This is such a common pattern that there's a function for that called, concatMap:
stringToBinary :: String -> [Int]
stringToBinary = concatMap toBinary . toUnicode
Here we use function composition to first apply toUnicode to the String, and then concatMap the toBinary over the result.
What we want is a function of type String -> String (decimal -> binary). What you have now is
dec :: String -> [Int]
bin :: Int -> [Int] -- use *lowercase*
So it seems impossible to compose a function of type String -> String only with these two. Besides, ord is not what you want.
*Main> dec "123"
[49,50,51]
*Main> bin 123
[0,1,1,1,1,0,1,1]
From what you have now, the possible solution would be:
*Main Data.Char> toBinary = map intToDigit . bin . read
*Main Data.Char> toBinary "123"
"01111011"
I guess your intention may be dec :: String -> Int, then bin . dec :: String -> [Int]. You can follow the type signature and retry.
(product (take 9 [1000,999..])) `div` (product (map (\j-> product [1..j]) (map (\j->length(j)) (group [2,2,2,2,2,2,2,2,2]))))
The above code is of the form X div Y, with X=product (take 9 [1000,999..]) & Y=(product (map (\j-> product [1..j]) (map (\j->length(j)) (group [2,2,2,2,2,2,2,2,2]))))
If I copy and paste the code in ghci, it gives me -12740133310672 as an answer,
but if I count X & Y individually, I get 964541486381834014456320000 & 362880, then dividing them gives me 2658017764500203964000 as an answer.
I think this incoherence might be because the number is too large, but since the computer can calculate X and Y correctly individually, how come it can't also divide them combined?
Prelude Data.List> let x = product $ take 9 [1000,999..]
Prelude Data.List> x
964541486381834014456320000
Prelude Data.List> :t x
x :: (Enum a, Num a) => a
Observe that x has the type of a generic number: you calculated it with just operations that work for any number type. When you evaluate such a number in GHCi, it defaults to the “safest” concrete type, which is Integer, an arbitrary-precision type which has no problem with big numbers. However, you can enforce the calculation to be done with any other numerical type:
Prelude Data.List> x :: Integer
964541486381834014456320000
Prelude Data.List> x :: Float
9.645414e26
Prelude Data.List> x :: Double
9.645414863818342e26
Prelude Data.List> x :: Int
-4623139575776374784
The floating point versions are inaccurate but still close, whereas Int (a machine-size fixed precision number) simply overflows and gives complete bogus.
Normally this won't bother you, because huge calculations are by default done with the safe Integer type.
That is, unless something else prevents it.
Prelude Data.List> let y = product (map (\j-> product [1..j]) $ map length (group [2,2,2,2,2,2,2,2,2]))
Prelude Data.List> y
362880
Prelude Data.List> :t y
y :: Int
Unlike x, the type of y is already concrete: it must be Int, because that's the result type of length. (The rationale being: a list that's so big that you couldn't measure its length with an Int would not be able to fit in memory anyway.)
Now, div, like most numeric functions in Haskell, requires that the arguments and result have all the same type. For this reason, x`div`y will as a whole be calculated as Int instead of Integer, including x. And as we've seen, calculating x as Int gives bogus.
OTOH, if you use 362880 as a literal, then this isn't connected to length. It's just a generic number, like x, hence GHCi will again default to safe Integer, i.e. you get
Prelude Data.List> x `div` 362880
2658017764500203964000
The same result can be achieved if you just allow conversion of y:
Prelude Data.List> x `div` fromIntegral y
2658017764500203964000
Using Integer instead of Int helps:
let r :: Integer ; r = (product (take 9 [1000,999..])) `div` (product (map (\j-> product [1..j]) (map (\j->fromIntegral $ length(j)) (group [2,2,2,2,2,2,2,2,2]))))
gets me: 2658017764500203964000
I don't fully understood your code, but I assume if you calculate them individually you get smaller intermediate results - so Int won't overflow.
So yes - the incoherence is because of large numbers (Int is limited in it's width, so it will just overflow (negative numbers). If you operate with such large numbers you should probably use Integer, which has unlimited width.
I am trying to return the length of a list as an Integer type, but applying length xs returns the length as an Int type. How can I work around this issue?
This is what I am trying to achieve: (it does not work)
sizeList :: [Integer] -> Integer
sizeList xs = length xs
It works as soon as I change the return to sizeList :: [Integer] -> Int but I don't want to do so.
You can either call genericLength from Data.List, or call length and use fromIntegral to convert the result.
There is also one trick I've seen in Learn You a Haskell for Great Good! that could be applied:
sum [1 | _ <- list]
Could be useful in some cases, perhaps.
I currently have the Haskell function below which converts an integer into a list of digits taken from the original integer. My question is thus: Is there a way to do this without using mod and div? For example, if I wanted to do the same thing with a string I could create a function utilising other functions such as head and tail etc.
I struggled with this problem for a while before finally come to SO and finding the answer in another post. What got me asking this question is the fact that I would have never thought of using mod and div myself!
toDigits :: Integer -> [Integer]
toDigits n
| n < 1 = []
| otherwise = toDigits (n `div` 10) ++ [n `mod` 10]
You mentioned that you could do the same thing on strings with list operations. Indeed, that would be another way. You could convert the integer to a string and then convert each character to an integer:
import Data.Char (digitToInt)
toDigits :: Int -> [Int]
toDigits = map digitToInt . show
Here I used Int rather than Integer, but you can use Integer if you really want with a little more trouble:
toDigits :: Integer -> [Integer]
toDigits = map (fromIntegral . digitToInt) . show
#icktoofay's answer uses show, a generic way to convert some value to a String (in other words, get its string representation). A value should be of a type that is an instance of a typeclass Show. For example, Int is an instance of Show (enter :i Int in ghci and seek for a string instance Show Int -- Defined in `GHC.Show'). But a function isn't an instance of Show, so let f n = n in f will throw an error, because how would you convert a function to a string? (See also: If functions as instances of the Show typeclass). Anyway, using show function is idiomatic, so you can stick to it.
There is however a way to extract a digit from a number using logarithms, powers and integer divisions. Remember that you can remove digits from the left by finding a remainder, and remove digits from the right by integer division. In both cases, the right operand is some power of 10. For example:
*Main> 123 `mod` 10
3
*Main> 123 `div` 100
1
But how do you know, which power of 10 you should use to divide by? By finding a logarithm base 10: #digits of N = log10N + 1, e.g. log1012345 = 4. Unfortunately you can't use logBase, because it uses floating point arithmetic, which is inaccurate. For example:
*Main> logBase 10 1000
2.9999999999999996
You can use custom function iLogBase for integers—copy the code from the link into your source code. This way to find a first digit of a number I use the following code:
firstDigit :: (Integral a) => a -> a
firstDigit n = n `div` (10^log)
where log = fst $ iLogBase 10 n
Creating a more general function of finding an arbitrary digit of a number and converting a number into a list of digits is left to you as an exercise :).
Also, the code in your question is inefficient. List concatenation (++) operation has the complexity of O(n), that is, every time you want to append an element to and end of list, it has to add the left list to the right list one by one, until you have a resulting list. Check out the source for (++), basically [1,2,3] ++ [4] becomes 1 : 2 : 3 : [4], which is terribly inefficient, as it takes 3 cons (:) operations just to add a list. And as you append numbers to the end multiple times, it has to repeat the same process each time, therefore overall complexity of your function is O(n^2).
On the other hand (:) is instant, that is, has complexity of O(1). No matter how long is your list, prepending an element to the beginning is cheap. So instead of adding an element to the end, I would recommend, adding it to the beginning and an the end simply reversing the list once (for information, Lisp people call this push/nreverse idiom):
reverse $ (n `mod` 10) : toDigits (n `div` 10)
I'm new in Haskell and try to solve 3 problem from http://projecteuler.net/.
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My solution:
import Data.List
getD :: Int -> Int
getD x =
-- find deviders
let deriveList = filter (\y -> (x `mod` y) == 0) [1 .. x]
filteredList = filter isSimpleNumber deriveList
in maximum filteredList
-- Check is nmber simple
isSimpleNumber :: Int -> Bool
isSimpleNumber x = let deriveList = map (\y -> (x `mod` y)) [1 .. x]
filterLength = length ( filter (\z -> z == 0) deriveList)
in
case filterLength of
2 -> True
_ -> False
I try to run for example:
getD 13195
> 29
But when i try:
getD 600851475143
I get error Exception: Prelude.maximum: empty list Why?
Thank you #Barry Brown, I think i must use:
getD :: Integer -> Integer
But i get error:
Couldn't match expected type `Int' with actual type `Integer'
Expected type: [Int]
Actual type: [Integer]
In the second argument of `filter', namely `deriveList'
In the expression: filter isSimpleNumber deriveList
Thank you.
Your type signature limits the integer values to about 2^29. Try changing Int to Integer.
Edit:
I see that you already realised that you need to use Integer instead of Int. You need to change the types of both getD and isSimpleNumber otherwise you will get a type mismatch.
Also in general, if you are having trouble with types, simply remove the type declarations and let Haskell tell you the correct types.
Main> :t getD
getD :: Integral a => a -> a
Main> :t isSimpleNumber
isSimpleNumber :: Integral a => a -> Bool
After you found the error, may I point out that your solution is quite verbose? In this case a very simple implementation using brute force is good enough:
getD n = getD' n 2 where
getD' n f | n == f = f
| n `mod` f == 0 = getD' (n `div` f) f
| otherwise = getD' n (succ f)
this question is easy enough for brute-force solution, but it is a bad idea to do so because the whole idea of project euler is problems you need to really think of to solve (see end of answer)
so here are some of your program's flaws:
first, use rem instead of mod. it is more efficient.
some mathematical thinking should have told you that you don't need to check all numbers from 1 to x in the isprime function and the getD function, but checking all numbers from the squareroot to one (or reversed) should be sufficient. note that in getD you will actually need to filter numbers between x and the square root, because you search for the biggest one.
why do you use the maximum function in getD? you know the list is monotonically growing, so you may as well get the last one.
despite you only need the biggest divisor (which is prime) you compute the divisors list from small to big making the computer check for each value if it is a divisor or not although discarding the result once a bigger divisor is found. it should be fixed by filtering the list of numbers from x to 1, not from 1 to x. this will cause the computer to check divisibility (how should I say that?) for the biggest possible divisor, not throwing to the trash the knowledge of previous checks. note that this optimization takes effect only if the previous point is optimized, because otherwise the computer will compute all divisors anyway.
with the previous points mixed, you should have filtered all numbers [x,x-1 .. squareroot x] and taken the first.
you don't use an efficient isPrime function. if I were you, I would have searched for an isprime library function, which is guaranteed to be efficient.
and there are more..
with this kind of code you will never be able to solve harder project euler problems. they are designed to need extra thinking about the problem (for instance noticing you don't have to check numbers greater from the square root) and writing fast and efficient code. this is the purpose of project euler; being smart about programming. so don't skip it.