I am trying to practice some recursive functions in haskell. The following random functions show some different forms of recursions and iterations. I have problems understanding which form of recursion or iteration is connected to a function. I know the recursion forms tail recursion, linear recursion and tree recursion and the regular iteration. Is there any strategy to assign one of the four different forms i know every function?
f1 x y z = if x > y then f1 (x+2) (y-1) z else y
f2 x y z = if z /= 0 then y + x + f2 (x-1) (y-1) (z-2) else 1
f3 x y z = if y < 0 then True
else (f3 (f3 (x-2) (y-4) (z-6)) (4*y) (z-2)) + (f3 6 (y-2) (z*2))
f4 x y z = if z > 0 then (f4 (x-y) (y+1) (x-z)) + (f4 2 x z) else y+x-
(2*z)
The strategy is to look at how the return value of each recursive call is used:
In f1, the return value is itself returned immediately
In f2, the return value of a single recursive call is used to compute the return value of the original call.
In f3 and f4, the return values of multiple recursive calls are used to compute the return value of the original call.
(The fact that you need to make a recursive call to f3 in order to compute an argument for another recursive call doesn't, I think, affect any classification you are asked to make.)
I'm trying to write Karatsuba Algorithm using the divide and conquer approach in Haskell. I did it with merge sort algorithm but can't figure it out here and it's a little bit embarrassing at this point.
My main function looks like this:
dz test end divide combine x =
if test x then end x
else combine(map(dz test end divide combine) (divide x))
I test it for values 1234 and 5678: dz test end divide combine [1234, 5678,2].
So I have to write test, end, divide and combine functions.
lengthNumb x = length . show $ x
test (x:x1:xs) = (lengthNumb x) < 4 || (lengthNumb x1) < 4
end (x:y:z:xs) = [x * y, z]
This is pretty straightforward. I just check if both numbers that I want to multiply are at least 4 digits long. If not I just use simple multiplication and carry m value. I know that Karatsuba works better for bigger numbers but this is just for testing purposes.
divide [] = []
divide (x:x1:x2:xs) =
let y1 = x `div` 10^x2
y2 = x `mod` 10^x2
y3 = x2 `div` 2
z1 = x1 `div` 10^x2
z2 = x1 `mod` 10^x2
in [[y1,y2,y3],[z1,z2,y3],[y1+y2, z1+z2, y3]]
combine [[x, x1],[y,y1],[z,z1]] = x * 10^(2*x1) + y + (z - x - y) * 10^x1
I was told that combine function should only do the final multiplication. So I guess it should get three numbers as an input (each with their m value) and then also do the necessary subtraction ( z-x-y ) because I couldn't do it in divide.
But this is wrong. I get an error:
Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [[a]] -> [a]
Actual type: [[[a]]] -> [a]
I think it is a problem with the parameters of combine function but I don't know how to fix it. I also think that there could be a problem with how combine and divide work together because in one of the previous iterations the final result of multiplication was wrong.
I am new to Haskell and learning how to properly use recursion.
The following function (which uses a formula to calculate central binomial coefficients) is extremely slow; for instance, grid (20,20) crashes my laptop. Can you help me understand why?
grid::(Integer,Integer)->Integer
grid (1, x) = 1 + x
grid (x, 1) = 1 + x
grid (x, y) = grid ((x-1),y) + grid ((x),(y-1))
Notably, there's not caching or memoization in your algorithm. GHC does not do magic and will not optimize away problems like that. For a 5x5 grid you're calling grid 139 times, for a 6x6 503, for a 7x7 it's 1847, and for 10x10 it's 97239 times. By the time you get to 20x20 you're making so many recursive calls that it's just not feasible. It's the same concept as doing
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
You're going to have an exponential number of calls as you increase n, slowing you down. Instead, you can approach this problem similarly to how it's solved in the case of the Fibonacci sequence, using lists and memoization:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Except here you want it to calculate the binomial coefficients. As for the implementation of such an algorithm, you'll have to figure that out yourself ;) I can point you at a previous answer of mine that solved the problem for generating Pascal's triangle.
The reason why the execution of this function grinds to a crawl is that it utilizes multiple recursion e.g. the function calls itself twice upon each recursive call. That means that there are repeated computations taking place during the execution of this recursive function, and that the time complexity of the computation increases exponentially as the size of the inputs increase.
The effects of this are more noticeable with larger input values like 20.
Let's look at a call to grid(5, 5).
This expands as follows.
grid(5, 5)
grid(4, 5) + grid(5, 4)
(grid(3, 5) + grid(4, 4)) + (grid(4, 4) + grid(5, 3))
((grid(2, 5) + grid(3, 4)) + (grid(4, 3) + grid(3, 4))) +
((grid(3, 4) + grid(4, 3)) + (grid(4, 3) + grid(5, 2)))
...and so on
As you can see things get out of hand quickly even with small values of x and y, grid(3, 4) and grid(4, 3) are calculated multiple times. As stated previously, a solution that utilizes zipWith will be much more efficient.
As explained in the other answers, the problem with your implementation is that the number of recursive calls is exponential, even though the number of distinct values of grid (x,y) that need to be computed is just quadratic.
The solution to the problem is called memoization, which basically means caching values that have been computed before. I definitely recommend you to write your own implementation based on lists, as recommended by #bheklilr.
There is however a quick solution offered by existing libraries such as MemoTrie:
import Data.MemoTrie
grid :: (Integer, Integer) -> Integer
grid = memo grid'
grid' :: (Integer, Integer) -> Integer
grid' (1, x) = 1 + x
grid' (x, 1) = 1 + x
grid' (x, y) = grid (x - 1, y) + grid (x , y - 1)
Notice that now grid is defined as a value - it's not polymorphic and it takes no arguments (although it's value is a function). The call to memo creates a single instance of a trie that caches all values and uses grid' to compute values not present in the cache.
Alternative to memoization is generating rows iteratively, reducing the number of computations.
central :: [Integer] -> [Integer]
central x = zipWith (+) x (0:central x)
For example, to generate the next row from previous
> central [1,2,3]
[1,3,6]
or for your grid function
grid x y = (iterate central [1..]) !! x !! y
and for zero based index
> grid 2 4
35
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.
I am doing project euler question 136, and came up with the following to test the example given:
module Main where
import Data.List
unsum x y z n = (y > 0) && (z > 0) && (((x*x) - (y*y)- (z*z)) == n) && ((x - y) == (y - z))
answer = snub $ takeWhile (<100) [n|x<-[1..],d<-[1..x`div`2],n<-[x..100],y<-[x-d],z<-[y-d], unsum x y z n ]
where
snub [] = []
snub (x:xs) | elem x xs = snub (filter (/=x) xs)
| otherwise = x : snub xs
snub will remove any numbers that are duplicates from a list.
The example is supposed to give 25 solutions for n where x^2 - y^2 - z^2 == n and all numbers are positive (or so I gather from the question) and are an arithmetic progression such that x-y == y-z. But when I use the code, a list of 11 solutions for n are returned.
What have I done wrong in my list comprehension and are there any optimisations I have missed out?
point 1
I made an attempt at this question and found that this was the sequence of ns that I came up with
[4,3,16,12,7,20,11,48,28,19,80,44,23,52,112,31,68,76,1156,43,176,559...
which potentially means that your takeWhile (<100) is the wrong filtering function to use to determine when to stop. On a related note, I tried running this:
answer = snub $ filter (<=100) $ takeWhile (<200) [...listcomprehension...]
But i gave up because it was taking too long. Which leads me to point 2.
point 2
In terms of optimisations, look at what your list comprehension produces in terms of raw output.
Main> take 30 [(x,y,z,n) | x<-[1..], d<-[1..x`div`2], n<-[x..100], y<-[x-d], z<-[y-d]]
[(2,1,0,2),(2,1,0,3),(2,1,0,4),(2,1,0,5),(2,1,0,6),(2,1,0,7),(2,1,0,8),(2,1,0,9),
(2,1,0,10),(2,1,0,11),(2,1,0,12),(2,1,0,13),(2,1,0,14),(2,1,0,15),(2,1,0,16),(2,1,0,17),
(2,1,0,18),(2,1,0,19),(2,1,0,20),(2,1,0,21),(2,1,0,22),(2,1,0,23),(2,1,0,24),(2,1,0,25),
(2,1,0,26),(2,1,0,27),(2,1,0,28),(2,1,0,29),(2,1,0,30),(2,1,0,31)]
This means that unsum is being called on each combination of x y z and n, which is a little bit redundant since we know that 2^2 - 1^2 - 0^2 = 3.
It is also much simpler and much less redundant to move the calculation of n from the list comprehension (slow because of above) to a function and merely list comprehend the (x,y,z) combinations that are valid.
ns = map nsum [(x, x-d, x-d-d) | x <- [1..], d <- [1..x`div`2]]
nsum (x,y,z) = x^2 - y^2 - z^2
Then it is possible to calculate the answer from this infinite list, but beware of using takewhile.