Unbound value length on mergesort algorithm - ocaml

I have the following task:
Complete the algorithm
let rec mergeSort (a, i, b, j, c, k) =
if i = (length a) && j = (length b) || k = (length c) then
()
else if i = (length a) then
(c.(k) <- b.(j);
mergeSort (a, i+1, b, j+1, c, k+1))
else if j = (length b) then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else if a.(i) < b.(j) then
...
else
...
where I suppose the answer would be:
let rec mergeSort (a, i, b, j, c, k) =
if i = (length a) && j = (length b) || k = (length c) then
()
else if i = (length a) then
(c.(k) <- b.(j);
mergeSort (a, i+1, b, j+1, c, k+1))
else if j = (length b) then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else if a.(i) < b.(j) then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else
(c.(k) <- b.(j);
mergeSort (a, i, b, j+1, c, k+1))
So that it gives the in- and output as follows:
let a = [|1; 4; 7; 9|];;
let b = [|2; 3; 4; 5; 6|];;
let c = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0|]
mergesort(a, 0, b, 0, c, 0) ->
[|1; 2; 3; 4; 4; 5; 6; 7; 9; 0; 0; 0|]
However, I am getting an unbound value length error on the first line. I thought length was a part of the ocaml-library and the part of the error is the actual task, not the answer. How would I change this so that the function compiles?

As per comments, the name length has to come from somewhere. Given that you're working with arrays, you almost certainly want Array.length. You could prepend your code with open Array but that's perhaps an overreaction.
You could also bind the name length to Array.length with let length = Array.length.
You could modify your code to explicitly specify which length you want:
let rec mergeSort (a, i, b, j, c, k) =
if i = (Array.length a) && j = (Array.length b) || k = (Array.length c) then
()
else if i = (Array.length a) then
(c.(k) <- b.(j);
mergeSort (a, i+1, b, j+1, c, k+1))
else if j = (Array.length b) then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else if a.(i) < b.(j) then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else
(c.(k) <- b.(j);
mergeSort (a, i, b, j+1, c, k+1))
But I might be more inclined to bind names for the length of each array, and only locally open Array.
let rec mergeSort (a, i, b, j, c, k) =
let a_len, b_len, c_len = Array.(length a, length b, length c) in
if i = a_len && j = b_len || k = c_len then
()
else if i = a_len then
(c.(k) <- b.(j);
mergeSort (a, i+1, b, j+1, c, k+1))
else if j = b_len then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else if a.(i) < b.(j) then
(c.(k) <- a.(i);
mergeSort (a, i+1, b, j, c, k+1))
else
(c.(k) <- b.(j);
mergeSort (a, i, b, j+1, c, k+1))
As an aside:
let c = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0|]
Could be:
let c = Array.init 10 (fun _ -> 0)
And it doesn't feel very idiomatic to have your function mutate that array as an existing value and return unit. It would feel more idiomatic to have mergeSort return a merged, sorted array. We can actually use your existing code as a baseline local function. We'll rename it to mergeSort'.
let mergeSort (a, i, b, j) =
let c = Array.(init (length a + length b) (fun _ -> 0)) in
let rec mergeSort' (a, i, b, j, c, k) =
let a_len, b_len, c_len = Array.(length a, length b, length c) in
if i = a_len && j = b_len || k = c_len then
()
else if i = a_len then
(c.(k) <- b.(j);
mergeSort' (a, i+1, b, j+1, c, k+1))
else if j = b_len then
(c.(k) <- a.(i);
mergeSort' (a, i+1, b, j, c, k+1))
else if a.(i) < b.(j) then
(c.(k) <- a.(i);
mergeSort' (a, i+1, b, j, c, k+1))
else
(c.(k) <- b.(j);
mergeSort' (a, i, b, j+1, c, k+1))
in
mergeSort' (a, i, b, j, c, 0);
c
Now:
utop # mergeSort(a, 0, b, 0);;
- : int array = [|1; 2; 3; 4; 4; 5; 6; 7; 9|]
Heck, we can even make it simpler than that by hiding the i and j.
let a = [|1; 4; 7; 9|]
let b = [|2; 3; 4; 5; 6|]
let c = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0|]
let mergeSort (a, b) =
let c = Array.(init (length a + length b) (fun _ -> 0)) in
let rec mergeSort' (a, i, b, j, c, k) =
let a_len, b_len, c_len = Array.(length a, length b, length c) in
if i = a_len && j = b_len || k = c_len then
()
else if i = a_len then
(c.(k) <- b.(j);
mergeSort' (a, i+1, b, j+1, c, k+1))
else if j = b_len then
(c.(k) <- a.(i);
mergeSort' (a, i+1, b, j, c, k+1))
else if a.(i) < b.(j) then
(c.(k) <- a.(i);
mergeSort' (a, i+1, b, j, c, k+1))
else
(c.(k) <- b.(j);
mergeSort' (a, i, b, j+1, c, k+1))
in
mergeSort' (a, 0, b, 0, c, 0);
c
And use it like so:
utop # mergeSort (a, b);;
- : int array = [|1; 2; 3; 4; 4; 5; 6; 7; 9|]
Lets optimize that a bit more and curry the arguments:
let a = [|1; 4; 7; 9|]
let b = [|2; 3; 4; 5; 6|]
let mergeSort a b =
let (a_len, b_len) = Array.(length a, length b) in
let c_len = a_len + b_len in
let c = Array.init c_len (fun _ -> 0) in
let rec append x i k =
if k = c_len
then ()
else (k -> c.(k) <- x.(i); append x (i + 1) (k + 1))
in
let rec mergeSort' i j =
if i = a_len
then append b j (i + j)
else if j = b_len
then append a i (i + j)
else
let (i', j') =
if a.(i) < b.(j)
then (c.(i + j) <- a.(i); (i+1, j))
else (c.(i + j) <- b.(j); (i, j+1))
in
mergesort' i' j'
in
mergeSort' 0 0;
c

This is so much simpler if you do it with lists:
# let mergeSort a b =
let rec mergeSort' ?(acc=[]) = function
| ([], []) -> List.rev acc
| (a, []) -> List.rev_append acc a
| ([], b) -> List.rev_append acc b
| ((x::xs as a), (y::ys as b)) ->
if x < y
then mergeSort' ~acc:(x::acc) (xs, b)
else mergeSort' ~acc:(y::acc) (a, ys)
in
Array.of_list (mergeSort' (Array.to_list a, Array.to_list b));;
val mergeSort : 'a array -> 'a array -> 'a array = <fun>
# let a = [|1; 4; 7; 9|]
let b = [|2; 3; 4; 5; 6|]
let c = mergeSort a b;;
val a : int array = [|1; 4; 7; 9|]
val b : int array = [|2; 3; 4; 5; 6|]
val c : int array = [|1; 2; 3; 4; 4; 5; 6; 7; 9|]

Related

In miller rabin algorithm in check function in while loop why we use " x = mod(x, x, n) " this?

code full link : Full Code link
bool check(ll a, ll d, ll n)
{
ll x = power(a, d, n);
if (x == 1 || x == n - 1)
return true;
while (d != n - 1)
{
x = mod(x, x, n);
d = (d << 1); /*** d = d * 2 ***/
if (x == 1)
return false;
if (x == n - 1)
return true;
}
return false;
}
The mod function is badly named -- it should be called mul or mulmod -- mod(a, b, n) computes a*b modulo n.
So mod(x, x, n) is just squaring x.

cubic function root bisection search time limit exceeded

I have implemented this solution for finding a root of a cubic function
f(x) = ax3 + bx2 + cx + d
given a, b, c, and d, ensuring it's being monotonic.
After submitting the solution to an online judge without being shown the test cases, I am being faced by a time limit error. a, b, c, and d guarantee that the function is monotonic and we know it is being continuous. The code first finds the interval [A, B] such that f(A) * f(B) < 0; then the code moves to implement the bisection search.
What I want to know is if there is some possibility to minimize the time complexity of my code so it passes the online judge. The input is a, b, c, d, and the output should be the root with an error 0.000001.
Code:
#include <iostream>
#include <algorithm>
//#include <cmath>
//#include <string>
using namespace std;
int f(double a, double b, double c, double d, double x) {
return x*(x*(a*x + b) + c) + d;
}
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
double a, b, c, d, A, B, x = 1, res;
cin >> a >> b >> c >> d;
//determinning the interval
double f_x = f(a, b, c, d, x);
if (a > 0) { // strictly increasing
if (f_x > 0) { B = 0;
while (f(a, b, c, d, x) >= 0) { x -= x; }
A = x; }
else { A = 0;
while (f(a, b, c, d, x) <= 0) { x += x; }
B = x; }
}
else { //strictly decreasing
if (f_x > 0) { A = 0;
while (f(a, b, c, d, x) >= 0) { x += x; }
B = x; }
else { B = 0;
while (f(a, b, c, d, x) <= 0) { x -= x; }
A = x; }
}
// Bisection Search
double l = A;
while ((B - A) >= 0.000001)
{
// Find middle point
l = (A + B) / 2;
// Check if middle point is root
if (f(a, b, c, d, l) == 0.0)
break;
// Decide the side to repeat the steps
else if (f(a, b, c, d, l)*f(a, b, c, d, A) < 0)
B = l;
else
A = l;
}
res = l;
cout.precision(6);
cout << fixed << " " << res;
return 0;
}
There is no need to determine the initial interval, just take [-DBL_MAX, +DBL_MAX]. The tolerance can be chosen to be 1 ULP.
The following code implements these ideas:
// This function will be available in C++20 as std::midpoint
double midpoint(double x, double y) {
if (std::isnormal(x) && std::isnormal(y))
return x / 2 + y / 2;
else
return (x + y) / 2;
}
int main() {
...
const auto fn = [=](double x) { return x * (x * (x * a + b) + c) + d; };
auto left = -std::numeric_limits<double>::max();
auto right = std::numeric_limits<double>::max();
while (true) {
const auto mid = midpoint(left, right);
if (mid <= left || mid >= right)
break;
if (std::signbit(fn(left)) == std::signbit(fn(mid)))
left = mid;
else
right = mid;
}
const double answer = left;
...
}
Initially, fn(x) can overflow and return inf. No special handling of this case is needed.

Crossword game: read 2d given array and search diagonally c++

This is a crossword game. I wanna read an array diagonally.
I should find some word in all over the 2d given array
this array read from a given file
and it is n*m size; m not always = n
How can I read 2d given diagonally like this:
Example:
m = 4
n = 4
b o o k
z a k o
s l l e
x y z l
ball: found
[b] o o k
z [a] k o
s l [l] e
x y z [l]
foo: not found
Here is the code:
char ReadArray(char* array, int r, int c, int n, int m)
{
return (r > 0 && r <= n && c > 0 && c <= m) ?
array[n * (r - 1) + (c - 1)] : '\0';
}
char readrc(char* array, int r, int c, int n, int m)
{
return (r > 0 && r <= n && c > 0 && c <= m) ?
array[n * (r - 1) + (c - 1)] : '\0';
}
void read_down_right(char* array, int n, int m, vector<string>& list)
{
for (int sc = 2 - n; sc <= m - 1; sc++)
{
string str = "";
for (int r = 1, c = sc; r <= n; r++, c++)
{
char chr = readrc(array, r, c, n, m);
if (chr != '\0')
str += chr;
}
list.push_back(str);
}
}
void read_down_left(char* array, int n, int m, vector<string>& list)
{
for (int sc = 2; sc <= m + n - 2; sc--)
{
string str = "";
for (int r = 1, c = sc; r <= n; r++, c--)
{
char chr = readrc(array, r, c, n, m);
if (chr != '\0')
str += chr;
}
list.push_back(str);
}
}
pass a reference to a blank list each time. list contains all possible strings afterwards, do a linear search.

Prolog. Error occurs in the compilation of "if-else"

I have a small problem - I did not get to write "if - else." Need to check on the long side if it is a triangle or not.
Here is my code, but the compiler indicates an error in the comparison sign "<" in "A < B + C" - "E;Test_Goal, pos: 465, 406 ')' or ',' expected"
I would be very grateful for the help.
PREDICATES
equal(integer,integer,integer)
isTriangle(integer,integer,integer)
CLAUSES
/*isTriangle(A,B,C):-
( A < B + C ->
( B < A + C ->
( C < A + B ->
writeln("It is triangle"),
fail
; C >= A + B ->
write("It is not triangle!")
)
fail
; B >= A + C ->
write("It is not triangle!")
)
fail
; A >= B + C ->
write("It is not triangle!")
)*/
isTriangle(A,B,C):-
( (A < B + C; B < A + C; C < A + B) -> writeln("It is triangle")
; (A >= B + C; B >= A + C; C >= A + B) -> write("It is not triangle!")
)
equal(A,B,C):-
isTriangle(A,B,C),
A = B,
B = C,
C = A.
GOAL
equal(3,0,3).
I don't believe Visual Prolog supports the ISO Prolog operator, ->/2. You can try refactoring your predicate from this:
isTriangle(A,B,C):-
( (A < B + C; B < A + C; C < A + B) -> writeln("It is triangle")
; (A >= B + C; B >= A + C; C >= A + B) -> write("It is not triangle!")
)
To this:
isTriangle(A, B, C):-
(A < B + C; B < A + C; C < A + B),
write("It is not triangle!").
isTriangle(A, B, C):-
(A >= B + C; B >= A + C; C >= A + B),
write("It is not triangle!").
But isn't it true that, for any triangle ABC that all of the inequalities must hold? So it really should be:
isTriangle(A, B, C):-
A < B + C,
B < A + C,
C < A + B,
write("It is not triangle!").
isTriangle(A, B, C):-
(A >= B + C; B >= A + C; C >= A + B),
write("It is not triangle!").
Alternatively, you could use a cut. I prefer the above approach to using a cut, but in case Visual Prolog (which deviates from standard Prolog in many ways) doesn't like parenthetical statement groupings:
isTriangle(A, B, C):-
A < B + C,
B < A + C,
C < A + B, !,
write("It is not triangle!").
isTriangle(A, B, C):-
write("It is not triangle!").

Return from Recursion (c/c++)

I'm having trouble returning a desired value in a recursive call. I want it to always return 0 unless a certain condition is met, in that case it should return 1 and exit.
int check = recursion(a, b, c, d, e, f);
int recursion(int *a, int *b, int c, int d, int e, int f){
int k, dX, dY;
for(k=0;k<=b[1]-1;k++){
dX = b[k*4+3] - e;
dY = b[k*4+2] - f;
if(((dX == 1 || dX == -1) && (dY == 0))){
if(b[k*4+4] == 1) return 1;
e = b[k*4+3];
f = b[k*4+2];
b[k*4+2] = b[k*4+3] = 0;
recursion(a, b, c, d, e, f);
}
if(((dY == 1 || dY == -1) && (dX == 0))){
if(b[k*4+4] == 1) return 1;
e = b[k*4+3];
f = b[k*4+2];
b[k*4+2] = b[k*4+3] = 0;
recursion(a, b, c, d, e, f);
}
}
return 0;
}
A lot of irrelevant information has been removed, but as you can see if b[k*4+4] == 1 at anypoint, check should then equal 1. Otherwise, return 0 and check will = 0. It completes a basic traversal, which I know is completing correctly and is even stopping at the terminating condition (b[k*4+4] == 1) but it isn't returning the correct value.
Currently, it is ALWAYS returning 0. Check always equals 0, although it is stopping once the condition is met. I also tried removing the ending return 0; although check still equals zero...
You just need to check the return values of your recursive calls, i.e.,
return recursion(a, b, c, d, e, f);
You need to do return recursion(a, b, c, d, e, f); instead of just recursion(a, b, c, d, e, f);. Otherwise, the result of those recursive calls will be lost.
edit: to not prematurely exit your loop, you can do this:
int check = recursion(a, b, c, d, e, f);
int recursion(int *a, int *b, int c, int d, int e, int f){
int k, dX, dY;
for(k=0;k<=b[1]-1;k++){
dX = b[k*4+3] - e;
dY = b[k*4+2] - f;
if(((dX == 1 || dX == -1) && (dY == 0))){
if(b[k*4+4] == 1) return 1;
e = b[k*4+3];
f = b[k*4+2];
b[k*4+2] = b[k*4+3] = 0;
if(recursion(a, b, c, d, e, f) == 1)
return 1;
}
if(((dY == 1 || dY == -1) && (dX == 0))){
if(b[k*4+4] == 1) return 1;
e = b[k*4+3];
f = b[k*4+2];
b[k*4+2] = b[k*4+3] = 0;
if(recursion(a, b, c, d, e, f) == 1)
return 1;
}
}
return 0;
}