I want to learn a bit of OCaml, just to get a taste of a programming language other than C++ and Java. I will be very greatful if you help me with the following program: basically the user inputs a positive integer. The sum of all integers from N to 0 is printed.
Obviously you create an integer N, let the user enter its value. Create a variable sum of type int. Have a for loop which will add N to sum and then decrement N's value by one. The loop will run while N is greater than 1. I have no idea how to do this in OCaml's syntax though.
Any help would be highly appreciated.
The way you describe your algorithm is how you would typically implement it in C++ or in Java. You can write it the same way in OCaml, but the idiomatic way would be a recursive function that does not mutate variables, as follows:
let rec print_sum acc n =
if n <= 0
then Printf.printf "Sum: %d\n" acc
else print_sum (acc + n) (n - 1)
Invoke with: print_sum 0 11 ;;
To write a recursive function:
First think of the base case when it is not necessary to recurse. This will save you from forgetting it (here, it's the case n <= 0)
The general case: how can you get one step closer to the base case already written? Here it's by invoking the function with n-1.
Related
I am making a simple program that sums all the numbers to n. I am curious why I get a stack overflow when I don't use parentheses on n-1 and I don't when I use them.
let rec summing n=
if n=0
then 0
else n+ summing n-1;; (*(n-1)*)
summing 5;;
I suspect that without the parentheses the order of operations for this:
n+ summing n-1
Is implied as this:
(n) + (summing n) - (1)
Which means the same value of n is always recursively passed until the stack overflows. Explicitly using the parentheses allows you to pass n - 1 recursively.
Can anybody explain how the following code works. The code was given as a fast recursive implementation of a function returning n-th Fibonacci number. I have a general idea of how recursive functions work. I can fully understand the direct recursive implementation of such function, using the definition of Fibonacci numbers, which, however, is not efficient.
The main thing I cannot grasp is what does fib(n – 1, prev0) return when we have garbage stored in prev0.
int fib(int n, int &prev1) {
if (n < 2) {
prev1 = 0;
return n;
}
int prev0;
prev1 = fib(n – 1, prev0);
return prev0 + prev1;
}
I am a beginner, so, please, be as specific as you can.
You probably missed the fact that this function returns two results: One as its return value and one in the "input" parameter passed by reference.
The severe inefficiency of the simple recursive definition of fib is that at each recursive level you must make two different calls to lower levels, even though one of them includes all the work of the other.
By allowing the one that includes all the work of the "other" to also return the result of the "other", you avoid doubling the work at each level.
In the mathematical sense it is no longer a "function" (because of the side effect). But as a function in the programming sense, it sidesteps the efficiency problem of fib by returning two values from one call.
I think it appropriate to mention that in C++, there are more elegant ways to return a pair of values as the result of a function. (Even in C you could return a struct by value).
Edit (in response to your edit):
The main thing I cannot grasp is what does fib(n – 1, prev0) return
when we have garbage stored in prev0.
The trick is that prev0 is an output from the function, not an input.
I am a beginner, so, please, be as specific as you can.
The parameter declaration of int & in the function signature lets the function use that parameter as input or output or both as it chooses. This particular function uses it as output.
If you understand the basics of recursive functions, you understand how each level of the recursion has its own copy of the parameter n and of the local variable prev0. But prev1 is not a separate variable. It is effectively an alias for the higher level's prev0. So any read or write of the current level's prev1 really happens to the higher level's prev0.
This level's n is passed "by value" meaning it is a copy of the value of the passed expression (the higher level's n-1 ). But this level's prev1 is passed by reference so it is not a copy of the value of the higher level's prev0, it is an alias of the higher level's prev0.
Note that prev1 is never read from. Only written to. Let's think about the function this way:
std::pair<int,int> fib_pair(int n) {
if (n < 2) {
return std::make_pair(n, 0);
}
std::pair<int, int> prev = fib_pair(n-1);
return std::make_pair(prev.first + prev.second, prev.first);
}
Now it's clearer - there's the one recursive call, and fib(n) returns the two previous numbers, instead of just the one. As a result, we have a linear function instead of an exponential one. We can then rewrite the original version in terms of this one to help us understand both:
int fib(int n, int &prev1) {
std::pair<int, int> pair = fib_pair(n);
prev1 = pair.second;
return pair.first;
}
Let's look at four different functions that compute the nth fibonacci number, using pseudocode instead of restricting the program to a single language. The first follows the standard recursive definition:
function fib(n) # exponential
if n <= 2 return 1
return fib(n-1) + fib(n-2)
This function requires exponential time, O(2n), because it recomputes previously-computed fibonacci numbers at each step. The second function requires linear time, O(n), by working from 1 to n instead of n to 1 and keeping track of the two previous fibonacci numbers:
function fib(n) # linear
if n <= 2 return 1
prev2 = prev1 = 1
k := 3
while k <= n
fib := prev2 + prev1
prev2 := prev1
prev1 := fib
return fib
That's the same algorithm your program uses, though yours disguises what's going on by operating recursively and passing one of the parameters by a pointer to a variable in an outer scope.
Dijkstra described an algorithm for computing the n fibonacci number in logarithmic time, O(log n), using matrices and the exponentiation by squaring algorithm. I won't give the full explanation here; Dijkstra does it better than I could (though you should beware his convention that F0 = 1 instead of F0 = 0 as we have been doing it). Here's the algorithm:
function fib(n) # logarithmic
if n <= 2 return 1
n2 := n // 2 # integer division
if n % 2 == 1 return square(fib(n2+1)) + square(fib(n2))
return fib(n2) * (2*fib(n2-1) + fib(n2))
The fourth algorithm operates in constant time, O(1), provided you have floating-point numbers with sufficient precision, using the mathematical definition of the fibonacci numbers:
function fib(n) # constant
sqrt5 := sqrt(5)
p := (1 + sqrt5) / 2
q := 1 / p
return floor((p**n + q**n) / sqrt5 + 0.5)
For most languages this last algorithm isn't very useful, because for fibonacci numbers of any size you need some kind of unlimited-precision decimal arithmetic library, and although it's constant time it will probably take longer in practice than the simple logarithmic-time algorithm operating on unlimited-precision integers, at least until n is very large.
The obvious (non efficient) implementation of finding a Fibonacci number would be:
int fib(int n) {
if (n<2) return n;
return fib(n-2) + fib(n-1);
}
This implementation is inefficient you are doing the same calculations twice.
For example if n is 6, you the algorithm would tell you to add fib(4) and fib(5). To find fib(5), you need to add fib(4) and fib(3). And there you go calculating fib(4) for the second time. As n becomes larger, this will become more inefficient.
The example you provided avoids this inefficiency by remembering the previous fibonacci sequence.
Pretty much what the title says. I just started learning SML and am having trouble with my first project. I understand this is a very basic question and it would be incredibly easy for me to do in something like java, but I'm having difficulty understanding SML. I need to write a function intsFromTo. It should take a pair of integers, low and high, and return a list of consecutive integers in ascending order, namely all those that are greater than or equal to low and less than or equal to high.
Here's what I have so far
fun intsFromTo (low,high) = val intList = []
if low >= high then nill
else intList::low intsFromTo(low+1,high);
and I'm getting the following errors which I'm also having difficulty understanding.
http://i.imgur.com/QZ0WT6j.png
Any and all help to get me going would be greatly appreciated.
Note: The code could be mode more compact for style but might not so clearly illustrate the basic concepts.
Typical Recursion
fun intsFromTo(low, high) =
let
val out = []
in
if
low <= high
then
low :: intsFromTo2(low + 1, high)
else
out
end
Alternative Approach
An alternative way to produce the list is using map-reduce style semantics on a list.
fun intsFromTo(low, high) =
if high > low
then (* the list will contain at least one value *)
if
high >= 0
then
List.tabulate((high + 1) - low,
fn k => k + low)
else
List.rev(
List.tabulate((~low + 1) + high,
fn k => ~k + high))
else
[] (* list empty: low >= high *)
Why an Alternative?
Just out of curiosity.
Performance
Anecdotal timing indicates that the first version is about twice as fast as the second version using:
fun time() =
let
val t = Timer.startCPUTimer();
in
intsFromTo(~1000000,1000000);
Time.toReal(#usr(Timer.checkCPUTimer(t)))
end
At least on my computer while it is being used for other things.
Several issues in your code, just reveal the hidden segments to see the answers, but I'm just giving hints first to help you work it out by yourself.
what is the syntax for a function body?
Recall that a function body requires a let ... in ... end when defining local values, as you are doing there with intList:
what is the value nill?
You probably meant nil, or []
what are you trying to express with intList::low intsFromTo(low+1,high)?
You've got that part almost right: your goal is to return the list made of the current low element, followed by the list of element from its successor to the highest. This is written : low :: intsFromTo (low+1,high). The long explanation: you actually wrote 2 different expressions side by side (intList::low and the recursive call to intsFromTo), the first of which is not a function, so it cannot be applied to the second (remember that this is the same principle as in lambda calculus).
And then?
After these changes, the resulting program should compile, but its implementation could be improved (hint: intList?). This is left as an exercise for the reader.
Late answer, but here's a lovely compact recursive definition of this.
fun intList a b = if (a = b) then [b]
else a::intList (a+1) b;
I'll use a simple example for what I'm trying to do.
Say I have the list:
nums = []
Now I have the function:
allNums n = nums.append(n)
So if I run the function:
allNums 6
The list nums should have the values
[6]
I know nums.append doesn't work, but what code could replace that.
Simple Answer:
You can't do that. Haskell is a pure, functional language, that means:
A function does not have any side effect.
A function does always return the same result when called with the same parameters.
A function may or may not be called, but you don't have to care about that. If it wasn't called, it wasn't needed, but because the function does not have any side effects, you won't find out.
Complex answer:
You could use the State Monad to implement something that behaves a bit like this, but this is probably out of reach for you yet.
I'm suggesting to use an infinite list instead of appending to global variable.
It's true haskell is pure functional. But also it's lazy. Every part of data is not calculated until is really needed. It also applies to collections. So you could even define a collection with elements based on previous elements of same collection.
Consider following code:
isPrime n = all (\p -> (n `mod` p) /= 0 ) $ takeWhile (\p ->p * p <= n) primes
primes = 2 : ( filter isPrime $ iterate (+1) 3 )
main = putStrLn $ show $ take 100 primes
definition of isPrime is trivia when primes list is defined. It takes pack of primes which is less or equivalent to square root of examining number
takeWhile (\p ->p * p <= n) primes
then it checks if number have only non-zero remainders in division by all of these numbers
all (\p -> (n `mod` p) /= 0 )
the $ here is an application operator
Next using this definition we taking all numbers starting from 3:
iterate (+1) 3
And filtering primes from them.
filter isPrime
Then we just prepending the first prime to it:
primes = 2 : ( ... )
So primes becomes an infinite self-referred list.
You may ask: why we prepending 2 and just no starting filtering numbers from it like:
primes = filter isPrime $ iterate (+1) 2
You could check this leads to uncomputable expression because the isPrime function needs at least one known member of primes to apply the takeWhile to it.
As you can see primes is well defined and immutable while it could have as many elements as you'll need in your logic.
According to the book this is how its done, but I am not able to get this to work. It gives me an error Not in scope: 'ld'. I'm guessing I should be importing some package but not sure which one. Also the book uses GS module at the prompt but I'm using WinGHCi that has Prelude. What am I missing here?
factors :: Int -> [Int]
factors n | n < 1 = error "not positive"
| n == 1 = []
| otherwise = p : factors (div n p)
where p = ld n
I guess this can also be done using map and filter functions? How?
I suppose the aim of the assignment is to teach you about list comprehensions, filter and similar constructs, and not to have you write functions that test for primality or create the list of divisors in any sensible way. Therefore what you need is a predicate divides,
divides :: Int -> Int -> Bool
a `divides` b = ???
Then you use that predicate for the argument to filter or in a list comprehension to find the list of divisors, and use the divisors function for your isPrime test.
You want to inspect all numbers from 1 to n, and keep them only if they divide n. The filter function can help you:
divisors n = filter ??? [1..n]
So what condition you need to put in place of ??? ?
For the isPrime function you could reuse the divisors function, you already mentioned how.
Break it down into simpler steps.
Write a function, divides :: Int -> Int -> Bool such that
x `divides` n
is true when x is a divisor of n. So, first, think about what it means for x to be a divisor of n.
Now that you have a way to check if a single number x is a divisor of n, you need to check a certain range of numbers less than n to see which ones are divisors.
Hint: In Haskell, you can generate a list of numbers from 1 to n like so: [1..n]
This is where that filter function you mention would be useful. Check its type:
filter :: (a -> Bool) -> [a] -> [a]
Just replace the a above with Int.
As far as the isPrime function, just think about what it means for a number to be prime... if you've calculated your divisors correctly, you can check the list to make sure that it matches with that property.
If this is a homework related question, you should definitely tag it with homework, then people don't feel as timid about helping out :)