I have a function in Haskell that has two parameters and I want to calculate the sum of this function.
module Main where
fact 0 = 1
fact n = n * fact (n - 1)
combination n p = fact n / fact (n - p)
combSum p = combination p p / foldr1 (\p-> \x -> combination p x) [p,(p-1)..0]
prob p = combination p p / combSum p
That not seems to work. The combSum function. How can I write that function?
Just correcting the function... Sorry...
x must vary from p to 0.
First,
combination p p
is the same thing as:
fact p
Next, I am not entirely sure what your combSum does. Especially the denominator. foldr takes a function, an initial value, and a list. I dont see your initial value. Are you just trying to sum a series of values? like
fact 0 = 1
fact n = n * fact (n - 1)
combination n p = fact n / fact (n - p)
combSum p = sum $ map (\x -> combination p x) [p, p-1 .. 0]
prob p = fact p / combSum p
Not sure if that is what you want ...
Related
In Unison, functions are identified by the hashes of their ASTs instead of by their names.
Their documentation and their FAQs have given some explanations of the mechanism.
However, the example presented in the link is not clear to me how the hashing actually works:
They used an example
f x = g (x - 1)
g x = f (x / 2)
which in the first step of their hashing is converted to the following:
$0 =
f x = $0 (x - 1)
g x = $0 (x / 2)
Doesn't this lose information about the definitions.
For the two following recursively-defined functions, how can the hashing distinguish them:
# definition 1
f x = g (x / 2)
g x = h (x + 1)
h x = f (x * 2 - 7)
# definition 2
f x = h (x / 2)
g x = f (x + 1)
h x = g (x * 2 - 7)
In my understanding, brutally converting all calling of f g and h to $0 would make the two definitions undistinguishable from each other. What am I missing?
The answer is that the form in the example (with $0) is not quite accurate. But in short, there's a special kind of hash (a "cycle hash") which is has the form #h.n where h is the hash of all the mutually recursive definitions taken together, and n is a number from 0 to the number of terms in the cycle. Each definition in the cycle gets the same hash, plus an index.
The long answer:
Upon seeing cyclical definitions, Unison captures them in a binding form called Cycle. It's a bit like a lambda, but introduces one bound variable for each definition in the cycle. References within the cycle are then replaced with those variables. So:
f x = g (x - 1)
g x = f (x / 2)
Internally becomes more like (this is not valid Unison syntax):
$0 = Cycle f g ->
letrec
[ x -> g (x - 1)
, x -> f (x / 2) ]
It then hashes each of the lambdas inside the letrec and sorts them by that hash to get a canonical order. Then the whole cycle is hashed. Then these "cycle hashes" of the form #h.n get introduced at the top level for each lambda (where h is the hash of the whole cycle and n is the canonical index of each term), and the bound variables get replaced with the cycle hashes:
#h.0 = x -> #h.1 (x - 1)
#h.1 = x -> #h.0 (x / 2)
f = #h.0
g = #h.1
let rec f (l: int list) : int * int =
begin match l with
| [] -> (0,0)
| [x] (x,x)
| x::y::tl -> let (a,b) = f tl in
(x + a, y + b)
end
let r = f [2;3;4;5;6]
I'm thinking that the answer would compute to r = (6,6) because if you keep calling the recursive function on the tail, you'll end up with the last item in the list, thus it will match to the second case but I have no idea if this is correct or why this is the case. Really, I don't understand the use of let (a,b) = f tl in (x + a, y + b).
I'll try to explain let (a, b) = f tl in (x + a, y + b). Maybe that will help.
The pattern for this case is x :: y :: tl. So this means that tl represents the tail of the tail of the list. I.e. it represents the list after you remove the two elements at the front.
Along these same lines, x represents the first element of the list and y represents the second element.
The recursive call to f is going to return whatever f returns for tl, which is what you're trying to figure out. This will be a pair of numbers, as you can tell from the pattern (a, b).
The result of the whole expression (which is the result of f except when the list is very short) is (x + a, y + b). In other words, it adds the first element of the list to the first number of the pair and the second element of the list to the second element of the pair.
XYZ(a, b, c, m, n){
For p = 1 to m do
For q=p to n do
c[p,q] = a[p,q] + b[p,q];}
I think it is n + n-1 + n-2 +.....+(n-m+1). But I am not sure. Is it this or m*n?
Let's simplify your code :
For p from 1 to m
For q from p to n
Do something
Assuming the Do something part is done in constant time, what determines the time complexity of the code are the two loops. The outer loop runs m times, while the inner loop runs n-p, with p going from 1 to m.
If m >= n, the Do something part is repeated n+(n-1)+...+1 = n*(n+1)/2 = n²/2 + n/2 = O(n²) times.
Otherwise, if n > m, it's repeated n+(n-1)+...+(n-m+1) = (n*(n+1) - (n-m)*(n-m+1))/2 = 1/2 * (n² + n - n² + 2*n*m - n - m² + m) = O(2*n*m - m²) = O(n²) times.
In any case, O(n²) is a right answer, but if n >> m, a more precise answer is O(n*m).
For my homework assignment in ML I have to use the fold function and an anonymous function to turn a list of integers into the alternating sum. If the list is empty, the result is 0. This is what I have so far. I think what I have is correct, but my biggest problem is I cannot figure out how to write what I have as an anonymous function. Any help would be greatly appreciated.
fun foldl f y nil = y
| foldl f y (x::xr) =
foldl f(f(x,y))xr;
val sum = foldl (op -) ~6[1,2,3,4,5,6];
val sum = foldl (op -) ~4[1,2,3,4];
val sum = foldl (op -) ~2[1,2];
These are just some examples that I tested to see if what I had worked and I think all three are correct.
There are two cases: one when the list length is even and one when the list length is odd. If we have a list [a,b,c,d,e] then the alternating sum is a - b + c - d + e. You can re-write this as
e - (d - (c - (b - a)))
If the list has an even length, for example [a,b,c,d] then we can write its alternating sum as
- (d - (c - (b - a))).
So to address these two cases, we can have our accumulator for fold be a 3-tuple, where the first entry is the correct value if the list is odd, the second entry is the correct value if the list is even, and the third value tells us the number of elements we've looked at, which we can use to know at the end if the answer is the first or second entry.
So an anonymous function like
fn (x,y,n) => (x - #1 y, ~(x + #2 y), n + 1)
will work, and we can use it with foldl with a starting accumulator of (0,0,0), so
fun alternating_sum xs =
let
(v1, v2, n) = foldl (fn (x,y,n) => (x - #1 y, ~(x + #2 y), n + 1)) (0,0,0) xs
in
if n mod 2 = 0 then v2 else v1
end
Eventually what I want is what x represents:
let x = (something, (myfunc1 para1));;
so that when calling x, I get a tuple, but when calling (snd x) para, I will get a return value of myfunc1 para.
What I'm trying is like this:
let myfunc2 para1 para2 =
let myfunc1 para2 = ... in
( (fst para1), (myfunc1 para2) );;
And I want to call myfunc2 like this:
let x = myfunc2 para1 to get what I described above. However, what I get is just a function which when called with para1 will return a regular tuple, not a (something, function) tuple
You have a useless para2 parameter in your definition. The correct way is:
let myfunc2 para1 =
let x = ... in
let myfunc1 para2 = ... in
( x, myfunc1 );;
But it would help if we could speak about a concrete example. You are misunderstanding something obvious, but I do not know what.
Here is a concrete example. Suppose we want a function f which accepts a number n and returns a pair (m, g) where m is the square of n and g is a function which adds n to its argument:
let f n =
let m = n * n in
let g k = n + k in
(m, g)
Or shorter:
let f n = (n * n, fun k => n + k)
Now to use this, we can do:
let x = f 10 ;;
fst x ;; (* gives 100 *)
snd x ;; (* gives <fun> *)
snd x 5 ;; (* gives 15, and is the same thing as (snd x) 5 *)
Now let us consider the following bad solution in which we make the kind of mistake you have made:
let f_bad n k =
let m = n * n in
let g k = n + k in
(m, g k)
Now f_bad wants two arguments. If we give it just one, we will not get a pair but a function expecting the other argument. And when we give it that argument, it will return a pair of two integers because (m, g k) means "make a pair whose first component is the integer m and the second component is g applied to k, so that is an integer, too."
Another point worth making is that you are confusing yourself by calling two different things para2. In our definition of f_bad we also confuse ourselves by calling two different things k. The k appearing in the definition of g is not the same as the other k. It is better to call the two k's different things:
let f_bad n k1 =
let m = n * n in
let g k2 = n + k2 in
(m, g k1)
Now, does that help clear up the confusion?