Haskell Mini Function Implementation - haskell

I have been trying to take this function and make small implementation using iterate and takeWhile. It doesn't have to be using those functions, really I'm just trying to turn it into one line. I can see the pattern in it, but I can't seem to exploit it without basically making the same code, just with iterate instead of recursion.
fun2 :: Integer -> Integer
fun2 1 = 0
fun2 n
| even n = n + fun2 (n `div` 2)
| otherwise = fun2 (3 * n + 1)
Any help would be great. I've been struggling with this for hours.
Thanks

If you want to do this with iterate, the key is to chop it up into smaller logical parts:
generate a sequence using the rule
ak+1 = ak/2 if ak even
ak+1 = 3ak+1 if ak odd
stop the sequence at aj = 1 (which all do, if the collatz conjecture is true).
filter out the even elements on the path
sum them
So then this becomes:
f = sum . filter even . takeWhile (>1) . iterate (\n -> if even n then n `div` 2 else 3*n + 1)
However, I do think this would be clearer with a helper function
f = sum . filter even . takeWhile (>1) . iterate collatz
where collatz n | even n = n `div` 2
| otherwise = 3*n + 1
This may save you no lines, but transforms your recursion into the generation of data.

Firstly, I agree with tom's comment that there is nothing wrong with your four line version. It's perfectly readable. However, it's occasionally a fun exercise to turn Haskell functions into one liners. Who knows, you might learn something!
At the moment you have
fun 1 = 0
fun n | even n = n + fun (n `div` 2)
| otherwise = fun (3 * n + 1)
You can always convert an expression using guards into an if
fun 1 = 0
fun n = if even n then n + fun (n `div` 2) else fun (3 * n + 1)
You can always convert a series of pattern matches into a case expression:
fun n = case n of
1 -> 0
_ -> if even n then n + fun (n `div` 2) else fun (3 * n + 1)
And finally, you can convert a case expression into a chain of ifs (actually, in general this would require an Eq instance for the argument of your function, but since you're using Integers it doesn't matter).
fun n = if n == 1 then 0 else if even n then n + fun (n `div` 2) else fun (3 * n + 1)
I think you'll agree that this is far less readable than what you started out with.

One liner ;)
fun2 n = if n==1 then 0 else if even n then n + fun2 (n `div` 2) else fun2 (3 * n + 1)
My sense is that short of look-up tables, this function cannot be implemented without recursion because the argument passed in the recursion seems unpredictable (except for n as powers of 2).
On the other hand, rampion helped me learn something new.

Related

Reverse function behavior in Haskell

digits :: Int -> [Int]
digits n = reverse (x)
where x
| n < 10 = [n]
| otherwise = (mod n 10) : (digits (div n 10))
*ghci> digits 1234 = [3,1,2,4]*
digits' :: Int -> [Int]
digits' n = (x)
where x
| n < 10 = [n]
| otherwise = (mod n 10) : (digits' (div n 10))
*ghci>digits' 1234 = [4,3,2,1]*
As per my understanding the evaluation of digits 1234 should be [1,2,3,4]. But it seems that I am missing something. Can anyone explain this?
The problem is that digits reverses the string in each recursive call, not just once at the outer level. Try digits x = reverse (digits' x) (or, equivalently, digits = reverse . digits'), and see if you can explain the difference.
Notwithstanding the excellent answer by amalloy, here is a way of getting the digits in the expected order without involving the reverse library function.
We use the common trick of accumulating the result in some extra argument of the recursive call, (the “accumulator”) noted here as dgs.
We also use the divMod library function, which returns a pair containing both the quotient and the remainder.
digits :: Int -> [Int]
digits n = go [] n
where
base = 10
go dgs k = if (k < base) then (k:dgs)
else let (q,r) = divMod k base
in go (r:dgs) q
The accumulator grows by successive prepending operations, in such a way that the digits end up in the appropriate order.

ruby while loop translated to haskell

I've just started learning a bit of Haskell and functional programming, but I find it very difficult getting a hang of it :)
I am trying to translate a small piece of ruby code to Haskell (because I like the concept functional programming and Haskell proposes and even more because I come from a mathematics field and Haskell seems very mathematical):
class Integer
def factorial
f = 1; for i in 1..self; f *= i; end; f
end
end
boundary = 1000
m = 0
# Brown Numbers - pair of integers (m,n) where n factorial is equal with square root of m
while m <= boundary
n = 0
while n <= boundary
puts "(#{m},#{n})" if ((n.factorial + 1) == (m ** 2))
n += 1
end
m += 1
end
I could only figure out how to do factorials:
let factorial n = product [1..n]
I cannot figure out how to do the while loops or equivalent in Haskell, even though I found some examples that were far to confusing for me.
The idea is that the loops start from 0 (or 1) and continue (with an increment of 1) until it reaches a boundary (in my code is 1000). The reason there is a boundary is because I was thinking of starting parallel tasks that do the same operation but on different intervals so the results that I expect are returned faster (one operation would be done on 1 to 10000, another on 10000 to 100000, etc.).
I would really appreciate it if anyone could help out with this :)
Try this:
let results = [(x,y) | x <- [1..1000], y <- [1..1000] ,1 + fac x == y*y]
where fac n = product [1..n]
This is a list comprehension. More on that here.
To map it to your Ruby code,
The nested loops in m and n are replaced with x and y. Basically there is iteration over the values of x and y in the specified ranges (1 to 1000 inclusive in this case).
The check at the end is your filter condition for getting Brown numbers.
where allows us to create a helper function to calculate the factorial.
Note that instead of a separate function, we could have computed the factorial in place, like so:
(1 + product[1..x]) == y * y
Ultimately, the (x,y) on the left side means that it returns a list of tuples (x,y) which are your Brown numbers.
OK, this should work in your .hs file:
results :: [(Integer, Integer)] --Use instead of `Int` to fix overflow issue
results = [(x,y) | x <- [1..1000], y <- [1..1000] , fac x == y*y]
where fac n = product [1..n]
To add to shree.pat18's answer, maybe an exercise you could try is to translate the Haskell solution back into Ruby. It should be possible, because Ruby has ranges, Enumerator::Lazy and Enumerable#flat_map. The following rewritten Haskell solution should perhaps help:
import Data.List (concatMap)
results :: [(Integer, Integer)]
results = concatMap (\x -> concatMap (\y -> test x y) [1..1000]) [1..1000]
where test x y = if fac x == y*y then [(x,y)] else []
fac n = product [1..n]
Note that Haskell concatMap is more or less the same as Ruby Enumerable#flat_map.

Haskell, memoization, stack overflow

I'm working on problem 14 of Project Euler (http://projecteuler.net/problem=14). I'm trying to use memoization so that I save the length of the sequence for a given number as a partial result. I'm using Data.MemoCombinators for that. The program below produces a stack overflow.
import qualified Data.MemoCombinators as Memo
sL n = seqLength n 1
seqLength = Memo.integral seqLength'
where seqLength' n sum = if (n == 1) then sum
else if (odd n) then seqLength (3*n+1) (sum+1)
else seqLength (n `div` 2) (sum+1)
p14 = snd $ maximum $ zip (map sL numbers) numbers
where numbers = [1..max]
max = 999999
The stack overflow should be due to sum+1 being evaluated lazily. How can I force it to be evaluated before each call to seqLength? BTW, is memoization well implemented? I'm more interested in pointing out my Haskell mistakes than in solving the exercise.
The most common ways of forcing evaluation are to use seq, $! or a bang pattern. However sum+1 is not the culprit here. maximum is. Replacing it with the stricter foldl1' max fixes the stack overflow error.
That taken care of, it turns out that your memoization here is no good. Memo.integral only memoizes the first argument, so you're memoizing partial applications of seqLength', which doesn't really do anything useful. You should get much better results without tail recursion so that you're memoizing the actual results. Also, as luqui points out, arrayRange should be more efficient here:
seqLength = Memo.arrayRange (1, 1000000) seqLength'
where seqLength' 1 = 1
seqLength' n | odd n = 1 + seqLength (3*n+1)
| otherwise = 1 + seqLength (n `div` 2)
I'm not familiar with Data.MemoCombinators, so the generic advice is: try seqLength (3*n+1) $! (sum+1) (the same for even n, of course).
Why use MemoCombinators when we can exploit laziness? The trick is to do something like
seqLength x = lengths !! x - 1
where lengths = map g [1..9999999]
g n | odd n = 1 + seqLength (3 * n + 1)
| otherwise = 1 + seqLength (n `div` 2)
which should work in a memoized way. [Adapted from the non-tail-recursive solution by #hammar]
Of course, then seqLength is O(n) for the memoized case so it suffers less performance. However, this is remediable! We simply take advantage of the fact that Data.Vector is streamed and has O(1) random access. The fromList and map will be done at the same time (as the map will simply produce thunks instead of the actual values because we are using a boxed vector). We also fallback on a non-memoized version since we can't possibly memoize every possible value.
import qualified Data.Vector as V
seqLength x | x < 10000000 = lengths V.! x - 1
| odd x = 1 + seqLength (3 * n + 1)
| otherwise = 1 + seqLength (n `div` 2)
where lengths = V.map g $ V.fromList [1..99999999]
g n | odd n = 1 + seqLength (3 * n + 1)
| otherwise = 1 + seqLength (n `div` 2)
Which should be comparable or better to using MemoCombinators. Don't have haskell on this computer, but if you want to figure out which is better, there's a library called Criterion which is excellent for this sort of thing.
I think using Unboxed Vectors could actually give better performance. It would force everything at once when you evaluate one item (I think) but you need that anyway. Hence you could then just run a foldl' max to get a O(n) solution that should have less constant overhead.
If memory serves, for this problem you don't need memoization at all. Just use foldl' and bang patterns:
snd $ foldl' (\a n-> let k=go n 1 in if fst a < ....
where go n !len | n==1 = ....
Compile with -O2 -XBangPatterns . It's always better to run stadalone as running compiled code in ghci can introduce space leaks.

Trouble using map in Haskell

I am attempting to make an algorithm to solve Project Euler Problem 255
I came up with this solution:
roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1)
| rem n 2 == 1 = n : floor ( ((2*10^((d-1) `div` 2)) + ceiling (n `div` (2*10^((d-1) `div` 2)) )) `div` 2 )
| otherwise = n : floor ( ((7*10^((d-2) `div` 2)) + ceiling (n `div` (7*10^((d-2) `div` 2)) )) `div` 2 )
where
d = length (map (digitToInt) (show (n)))
average a = (sum a) `div` (length a)
answer = average [map roundedSq [10E13..10E14]]
main = do
print answer
But every time I try to load, it comes with an error for the answer calculating function.
What have I done wrong and will this even give me a correct solution or will it just get stick in a loop??
answer = average [map roundedSq [10E13..10E14]]
You've put the mapped list into a list of one element here. I think perhaps you mean:
answer = average (map roundedSq [10E13..10E14])
There is a problem with your average.
average a = (sum a) `div` (length a)
sum uses the entire list. length also uses the entire list. This means that the whole list will be generated and held in memory while one of these functions traverses it, and will not be garbage collected until the other function traverses it.
You pass average a very large list, so you will run out of memory.
Solution: rewrite average as a function that only traverses the list once, so that the list can be garbage collected as it is generated.
Example (untested):
average a = sum `div` length
where (sum, length) = foldl' f (0, 0) a
f (sum, length) i = (sum + i, length + 1)
Note that this uses foldl', from Data.List, not foldl. foldl has its own space issues (which someone more knowledgeable than me may wish to comment on).
And as Tobias Wärre has pointed out,
roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1)
will result in an endless loop:
we want to evaluate roundedSq n
if (roundedSq n) == roundedSq (n-1) is true, we will return n : roundedSq (n+1) as the answer
we need to evaluate (roundedSq n) == roundedSq (n-1)
we need to evaluate roundedSq n
goto 1.
If you want average to return a Fractional number you'll need to use this definition:
average a = (sum a) / (fromIntegral $ length a)
(/) is the Fractional division operator whereas div is the Integral division operator. Note you also need to use fromIntegral because length returns an Int which is not a part of the Fractional type class.
You'll get stuck in an infinite loop due to
roundedSq n | (roundedSq n) ...
Edit: Sometimes it seems like I have a hole in my head. Of course average is ok.
However, since you don't decrement or increment all recursive calls to roundedSq you will never hit the "bottom" and terminate.

Printing a result during a recursion in haskell

I am beginning to learn Haskell and am making a program to do the iterative process:
n -> n/2 (for even n)
n -> 3n+1 (for odd n)
So I got this far:`
chain n | n == 0 = error "What are you on about?"
| n == 1 = error "Finished"
| rem n 2 == 0 = chain (n `div` 2)
| rem n 2 /= 0 = chain (3 * n + 1)
`
Will this work?
But it only does the calculations behind the scenes, is there any way to make it display or export as list the result for n on each iteration until it reaches 1 so I can find the length of the list later?
On a side note, is there any way to make GHCi begin in a specific folder ?(I'm using windows)
You could have it return a list of the results in the "chain" like this:
chain n | n == 0 = error "What are you on about?"
| n == 1 = []
| rem n 2 == 0 = (n `div` 2) : chain (n `div` 2)
| otherwise = (3 * n + 1) : chain (3 * n + 1)
Now you'll get results like these:
*Main> chain 3
[10,5,16,8,4,2,1]
*Main> chain 7
[22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]
Yes, certainly. There's even a function from the Data.List module that captures this usage pattern.
import Data.List (unfoldr)
chain 0 = []
chain n = unfoldr f n
where
f 1 = Nothing
f n = let n' | even n = n `div` 2
| otherwise = 3 * n + 1
in Just (n', n')
The type of unfoldr is: (b -> Maybe (a, b)) -> b -> [a]
b is the state variable that used to generate the list. The function supplied as the first argument to unfoldr should either returns Nothing (which means terminate the list) or Just (b, a) where a is the element to add to the list, and b is the new state variable.
is there any way to make it display or export as list the result for n on each iteration until it reaches 1
You can use the Debug.Trace.trace to print logging messages to stdout as values are evaluated. Good for quick debugging.
You will notice that the two earlier answers use the paradigm of "build the whole list, and then output it at the end" rather than "output one element at a time". This is the functional way of doing things.
If you really want to do it in an imperative style, you have to use monadic programming, which is a more advanced topic. Here's an example (don't worry if you can't understand everything that's going on ... monads are quite mysterious and magical):
import Control.Monad.Writer
chain :: Int -> (String, [Int])
chain = runWriter . chain'
where
chain' 0 = return "Failure"
chain' 1 = do
tell [1] -- write 1
return "Success" -- finished
chain' n = do
-- write n
tell [n]
-- calculate next n and recurse
if even n
then chain' $ n `div` 2
else chain' $ 3 * n + 1
Which gives results like:
*Main> chain 3
("Success",[3,10,5,16,8,4,2,1])
But, as you can see, the writer monad still just generates the list behind the scenes.
This might seem inefficient. What if you want to print a list of 1,000,000 elements? Do you really have to generate the whole list upfront? In fact, Haskell's lazy semantics mean that, whenever possible, Haskell will compile your "build the whole thing upfront and then print it out" code into "only generate and output one element at a time" code.
The function should just return the list of found elements. This list can be inspected further later on:
chain 0 = error "No no no."
chain 1 = [1]
chain n
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
Here [1] is a list containing just 1 and : is a list constructor that adds the element on the left to the list on the right.
The list constructed by chain can then be displayed or used with other functions:
*Main> chain 5
[5,16,8,4,2,1]
*Main> length (chain 31)
107

Resources