Function that returns the median? (OCaml) - ocaml

In OCaml how would I write a median function that takes 5 arguments and returns the median. For example med5 2 5 7 4 3 would return 4.
I managed to write a med3 function (returns the median of 3 arguments) using if and else statements but this would be ridiculously complex if I attempted the same technique for 5 arguments :(
let med3 a b c =
if ((b<=a && c>=a) || (c<=a && b>=a)) then a
else if ((a<=b && c>=b) || (c<=b && a>=b)) then b else c;;
For the med5 function, I would like to be able to use the min and max functions (built in to OCaml) to discard the highest and lowest values from the set of 5 arguments. Then I could use the med3 function that I have already written to return the median of the remaining 3 arguments, but how do I discard the minimum and maximum arguments!?!?!?!?
Any help would be much appreciated :)

If you can use Array, then just put your 5 entries in an array, sort it, and return a[2]. If it's also forbidden in your assignment, you can use a poor-man's bubble sort to select the max, then the min:
let med5 a b c d e =
(* move the max towards 'e' *)
let a,b = if a<=b then a,b else b,a in
let b,c = if b<=c then b,c else c,b in
...
(* then move the min towards 'd', don't forget to reverse the comparisons *)
...
in med3 a b c

You could put those 5 arguments into a list, then removing an element from a list is easy.

If lists and arrays are forbidden, you can have three variables storing the three greatest elements among the five:
let med5 a b c d e =
let first = ref min_int in
let second = ref min_int in
let third = ref min_int in
if a >= !first then (third := !second; second := !first; first := a)
else if a >= !second then (third := !second; second := a)
else if a >= !third then (third := a);
if b >= !first then (third := !second; second := !first; first := b)
else if b >= !second then (third := !second; second := b)
else if b >= !third then (third := b);
(* you guess what to do for c, d, e ;-) *)
(* return the third largest element: *)
!third

Related

Writing power function in Standard ML with a predefined compound function

Having trouble writing a power function inStandard Ml. Im trying to write a function called exp of type int -> int -> int.
The application exp b e, for non-negative e, should return b^e.
For example, exp 3 2 should return 9. exp must be implemented with the function compound provided below. exp should not directly calls itself. Here is the compound function, it takes in a value n, a function, and a value x. All it does is it applies the function to the value x n number of times.
fun compound 0 f x = x
| compound n f x = compound (n-1) f (f x);
Im having trouble figuring out how to write this function without recursion, and with the restraint of having to use a function that only can use a function with one parameter. Anyone have any ideas of where to start with this?
This is what I have:
fun exp b 0 = 1
| exp b e = (compound e (fn x => x*x) b)
I know that this doesn't work, since if i put in 2^5 it will do:
2*2, 4*4, 16*16 etc.
You are extremely close. Your definition of exp compounds fn x => x*x which (as you noticed) is not what you want, because it is repeatedly squaring the input. Instead, you want to do repeated multiplication by the base. That is, fn x => b*x.
Next, you can actually remove the special case of e = 0 by relying upon the fact that compound "does the right thing" when asked to apply a function 0 times.
fun exp b e = compound e (fn x => b*x) 1
You could just do this instead I believe
fun exp 0 0 = 1
| exp b 0 = 1
| exp b e = (compound (e - 1) (fn x => b * x ) b);
this may not be exactly 100% proper code. I sort of just now read a bit of Standard ML documentation and took some code and reworked it for your example but the general idea is the same for most programming languages.
fun foo (num, power) =
let
val counter = ref power
val total = 1
in
while !counter > 0 do (
total := !total * num
counter := !counter - 1
)
end;
To be more clear with some pseudo-code:
input x, pow
total = 1
loop from 1 to pow
total = total * x
end loop
return total
This doesn't handle negative exponents but it should get you started.
It basically is a simple algorithm of what exponents truly are: repeated multiplication.
2^4 = 1*2*2*2*2 //The 1 is implicit
2^0 = 1

Trouble in Making an isPrime Function

This is a homework. OCaml seems to be made by a psychopath.
let prime : int -> bool
= fun n ->
if n > 2 then
let a = n - 1 in
let rec divisor n a =
if a > 1 && n mod a = 0 then false
else if a = 2 && n mod a <> 0 then true
else divisor n a-1 ;;
else if n = 2 then true
else if n = 1 then false
I am not good at coding and I know that my isPrime algorithm is wrong.
But I wonder where in my code is the mistake that produces the syntax error.
Also is there any way to define the isPrime function in a recursive form?
Example:
let rec prime n = ~
You'll get better responses from experts if you don't gratuitously insult their language :-) But I'm an easygoing guy, so I'll take a stab at your syntax error.
There are quite a few problems in this code. Here are 3 that I see right off:
The symbol ;; is used to tell the interpreter that you've entered a full expression that you want it to evaluate. It's definitely out of place in the middle of a function declaration.
Your second let doesn't have an associated in. Every let must have an in after it. The only exception is for defining values at the top level of a module (like your prime function).
The expression divisor n a-1 is parsed as (divisor n a) - 1. You want parentheses like this: divisor a (n - 1).

Ocaml, why this code does not work?

let rec prime : int -> bool
= fun n -> let rec f a = if (a = 1) then 1
else if (n mod a) = 0 then 0
else if ((f a-1) = 1) then 1
else 0
in
if ((f n-1) = 1) then true
else false
As you can see from my code, I want to implement a function which can tell given number is prime or not.
I can compile and run this code, but for all X function tell "false".
Why this happens?
Thanks in advance. :)
The expression:
f n-1
is parsed like this:
(f n) - 1
You need to write this:
f (n - 1)
((f n-1) = 1)
f n-1 is equivalent to (f n) - 1, not f (n - 1). So you're taking a number that's either 0 or 1, then subtract 1 from (yielding either -1 or 0) and then seeing whether it's 1, which it can never be.
Note that this wouldn't even have compiled had you made f return a boolean rather than an integer (you can't subtract from a boolean).

How does that recursive function work?

Might be a very basic question but I just got stuck with it. I am trying to run the following recursive function:
//If a is 0 then return b, if b is 0 then return a,
//otherwise return myRec(a/2, 2*b) + myRec(2*a, b/2)
but it just gets stuck in infinite loop. Can anybody help me to run that code and explain how exactly that function works? I built various recursive functions with no problems but this one just drilled a hole in my head.
Thanks.
Here is what I tried to do:
#include<iostream>
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
else return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
int main()
{
if (46 == myRec(100, 100)) {
std::cout << "It works!";
}
}
Well, let us mentally trace it a bit:
Starting with a, b (a >= 2 and b >= 2)
myRec(a/2, 2*b) + something
something + myRec(2*a', b'/2)
Substituting for a/2 for a' and 2*b for b', we get myRec(2*(a/2), (b*2)/2), which is exactly where we started.
Therefore we will never get anywhere.
(Note that I have left out some rounding here, but you should easily see that with this kind of rounding you will only round down a to the nearest even number, at which point it will be forever alternating between that number and half that number)
I think you are missing on some case logic. I last program in C ages ago so correct my syntax if wrong. Assuming numbers less than 1 will be converted to zero automatically...
#include<iostream>
int myRec(int a, int b){
// Recurse only if both a and b are not zero
if (a!=0 && b!=0) {
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
// Otherwise check for any zero for a or b.
else {
if (a==0){
return b;
}
if (b==0){
return a;
}
}
}
UPDATE:
I have almost forgot how C works on return...
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
VBA equivalent with some changes for displaying variable states
Private Function myRec(a As Integer, b As Integer, s As String) As Integer
Debug.Print s & vbTab & a & vbTab & b
If a = 0 Then
myRec = b
End If
If b = 0 Then
myRec = a
End If
If a <> 0 And b <> 0 Then
myRec = myRec(a / 2, 2 * b, s & "L") + myRec(2 * a, b / 2, s & "R")
End If
End Function
Sub test()
Debug.Print myRec(100, 100, "T")
End Sub
Running the test in Excel gives this (a fraction of it as it overstacks Excel):
T: Top | L: Left branch in myRec | R: Right branch in myRec
The root cause will be the sum of the return which triggers more recursive calls.
Repeating of the original values of a and b on each branch from level 2 of the recursive tree...
So MyRec(2,2) = MyRec(1,4) + MyRec(4,1)
And MyRec(1,4) = MyRec(.5,8) + MyRec(2,2)
So MyRec(2,2) = MyRec(.5,8) + MyRec(2,2) + MyRec(4,1)
Oops.
(The .5's will actually be zeroes. But it doesn't matter. The point is that the function won't terminate for a large range of possible inputs.)
Expanding on gha.st's answer, consider the function's return value as a sum of expressions without having to worry about any code.
Firstly, we start with myRec(a,b). Let's just express that as (a,b) to make this easier to read.
As I go down each line, each expression is equivalent, disregarding the cases where a=0 or b=0.
(a,b) =
(a/2, 2b) + (2a, b/2) =
(a/4, 4b) + (a, b) + (a, b) + (4a, b/4)
Now, we see that at a non-terminating point in the expression, calculating (a,b) requires first calculating (a,b).
Recursion on a problem like this works because the arguments typically tend toward a 'base case' at which the recursion stops. A great example is sorting a list; you can recursively sort halves of the list until a list given as input has <= 2 elements, which is trivial without recursion. This is called mergesort.
However, your myRec function does not have a base case, since for non-zero a or b, the same arguments must be passed into the function at some point. That's like trying to sort a list, in which half of the list has as many elements as the entire list.
Try replacing the recursion call with:
return myRec(a/2, b/3) + myRec(a/3, b/2);

Advice for POUR1 on SPOJ?

I need help with this problem POUR1. I think
it can be solved with bruteforce approach, but I read that it is a graph problem (BFS). I solved problems like ABCPATH, LABYR1, PT07Y, PT07Z, BITMAP, ...
But I don't know how to approach POUR1 in BFS manner.
Can someone give me some advice?
Problem statement:
Given two vessels, one of which can accommodate a litres of water and the other - b litres of water, determine the number of steps required to obtain exactly c litres of water in one of the vessels.
At the beginning both vessels are empty. The following operations are counted as 'steps':
emptying a vessel,
filling a vessel,
pouring water from one vessel to the other, without spilling, until one of the vessels is either full or empty.
Input:
An integer t, 1<=t<=100, denoting the number of testcases, followed by t sets of input data, each consisting of three positive integers a, b, c, not larger than 40000, given in separate lines.
Output:
For each set of input data, output the minimum number of steps required to obtain c litres, or -1 if this is impossible.
Example:
Sample input:
2
5
2
3
2
3
4
Sample output:
2
-1
This question has a simpler solution. No need for BFS. Ad-hoc would do good.
method 1 - fill A, empty it into B. whenever A becomes empty fill it back, whenever B becomes full empty it. (all the above-mentioned actions count as individual moves). Continue this process until you arrive at the required amount of water in any one of the vessels. Get the number of moves here. (say C1).
method 2 - fill B, empty it into A. whenever B becomes empty fill it back, whenever A becomes full empty it. Continue this until you arrive at the required amount. Get the number of moves say C2).
The answer is min(C1,C2).
Source code in C++:
#include < cstdio >
#include < algorithm >
using namespace std;
int pour(int A, int B, int C) {
int move = 1, a = A, b = 0, tfr;
while (a != C && b != C) {
tfr = min(a, B - b);
b += tfr;
a -= tfr;
move++;
if (a == C || b == C)
break;
if (a == 0) {
a = A;
move++;
}
if (b == B) {
b = 0;
move++;
}
}
return move;
}
/** Reason for calculating GCD of a,b is to check whether an integral solution of
* equation of form ax + by = c exist or not, to dig deeper read Diophantine Equations
*/
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
int main() {
int t, a, b, c;
scanf("%d", & t);
while (t--) {
scanf("%d%d%d", & a, & b, & c);
if (c > a && c > b)
printf("-1\n");
else if (c % gcd(a, b) != 0)
printf("-1\n");
else if (c == a || c == b)
printf("1\n");
else
printf("%d\n", min(pour(a, b, c), pour(b, a, c)));
}
return 0;
}
Consider the set of all a priori possibles states (eg [3, 7] meaning Vessel1 contains 3 litters and vessel2 contains 7 litters). You have a directed graph whose vertices are those states and whose edges are the possible moves. The question is to find a path in the graph joining the state [0, 0] to either a state of type [c, ?] or a state of type [?, c]. Such a path is typically searched by a BFS.