Program is still in infinite recursion - wolfram-mathematica

I am trying to create a Merge Sort using Wolfram Mathematica, but I am still getting this recursion error and I have no idea, where I made a misstake. I rewrite this code from Java, where it works just fine, so I guess it is some special thing for Wolfram. Do you have any idea, what could be wrong with my code?
Thanks a lot!
Heer is my code:
mergeSort[x_, left_, right_] :=
Module[{array = x, middle, n1, n2, L, R, i, j, k},
If[left < right,
middle = (left + right) / 2;
mergeSort[array, left, middle];
mergeSort[array, middle + 1, right];
n1 = middle - left + 1;
n2 = right - middle;
L = {};
R = {};
For[i = 1, i < n1, ++i,
L[[i]] = array[[left + 1]];
];
For[j = 1, j < n2, ++j,
R[[j]] = array[[middle + 1 + j]];
];
i = 0;
j = 0;
k = left;
While[i < n1 && j < n2,
If[L[[i]] <= R[[j]],
array[[k]] = L[[i]];
i++;
,
array[[k]] = R[[j]];
j++;
];
k++;
];
While[i < n1,
array[[k]] = L[[i]];
i++;
k++;
];
While[j < n2,
array[[k]] = R[[j]];
j++;
k++;
];
Return[array];
];
]
Here is my function call - mergeSort[{58, 3, 98}, 0, 3];

You have three main problems in your code.
The GfG code you are trying to adapt is passing the array arr by reference, so each recursion is operating on the same object. This doesn't ordinarily happen in Mathematica. I have added HoldFirst to pass array by reference. An alternative would be to simply leave array out of the function calls altogether and modify it directly as a global variable. E.g.
mergeSort[left_, right_] := Module[{},
If[left < right,
middle = Floor[(left + right)/2];
mergeSort[left, middle];
mergeSort[middle + 1, right];
...
Where the GfG code does int m = (l + r) / 2 the result is rounded down. This needs to be done explicitly in Mathematica: middle = Floor[(left + right)/2]. Otherwise you get infinite recursion.
The GfG code uses zero-based arrays. Mathematica uses one-based lists, so code such as for (int i = 0; i < n1; ++i) can be changed to For[i = 1, i <= n1, ++i, ...
You also had a typo from this line in the GfG code: L[i] = arr[l + i], and finally you do not need to use Return in Mathematica to return values at the end of a function.
Attributes[mergeSort] = HoldFirst;
mergeSort[array_Symbol, left_Integer, right_Integer] :=
Module[{middle, n1, n2, L, R, i, j, k},
If[left < right,
middle = Floor[(left + right)/2];
mergeSort[array, left, middle];
mergeSort[array, middle + 1, right];
n1 = middle - left + 1;
n2 = right - middle;
L = ConstantArray[Null, n1];
R = ConstantArray[Null, n2];
For[i = 1, i <= n1, ++i,
L[[i]] = array[[left + i - 1]];
];
For[j = 1, j <= n2, ++j,
R[[j]] = array[[middle + j]];
];
i = 1;
j = 1;
k = left;
While[i <= n1 && j <= n2,
If[L[[i]] <= R[[j]],
array[[k]] = L[[i]];
i++;
,
array[[k]] = R[[j]];
j++;
];
k++;
];
While[i <= n1,
array[[k]] = L[[i]];
i++;
k++;
];
While[j <= n2,
array[[k]] = R[[j]];
j++;
k++;
];
array
]
]
array = {58, 3, 98};
mergeSort[array, 1, Length[array]]
{3, 58, 98}
Note this has changed the contents of array.
array
{3, 58, 98}
Alternative Version
A version much more in the Mathematica idiom is this, by Wellin, Gaylord & Kamin.
merge[lis_List, {}] := lis
merge[{}, lis_List] := lis
merge[{a_, ra___}, {b_, rb___}] :=
If[a <= b,
Join[{a}, merge[{b}, {ra, rb}]],
Join[{b}, merge[{a, ra}, {rb}]]]
MergeSort[{}] := {}
MergeSort[{x_}] := {x}
MergeSort[lis_List] := Module[{div = Floor[Length[lis]/2]},
merge[MergeSort[Take[lis, div]], MergeSort[Drop[lis, div]]]]
MergeSort[{58, 3, 98}]
{3, 58, 98}

Related

Does rearranging the outerloop in Floyd-Warshall algorithm as most inner loop change the algorithm

The following code is for Floyd-Warshall algorithm
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
I propose to rewrite the code as follows
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
In the new code, I put the original outer loop into the most inner loop. I find that the new code is easy to understand solving all pair shortest path problem.
My question is: is the new code equivalent to the original code for Floyd-Warshall algorithm?
No, that will in general not work. At the very heart of the Floyd–Warshall algorithm is the idea to find shortest paths that go via a smaller subset of nodes: 1..k, and to then increase the size of this subset.
It is essential that pairs of nodes will have their distance adapted to the subset 1..k before increasing the size of that subset.
As an example, take the example graph used on Wikipedia:
Let's focus on the path that exists from node 3 to node 1, which has a least-weight path of 2 + -1 + 4 = 5.
Let's run the original algorithm and your variant to see if it identifies this distance:
Original (Correct) Algorithm
let d = [
[0, Infinity, -2, Infinity],
[4, 0, 3, Infinity],
[Infinity, Infinity, 0, 2],
[Infinity, -1, Infinity, 0]
];
let n = d.length;
for (let k = 0; k < n; ++k) {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < n; ++j) {
d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
}
}
}
console.log("distance from 3 to 1 = ", d[2][0]); // 5 -- correct
Your Suggested Algorithm
let d = [
[0, Infinity, -2, Infinity],
[4, 0, 3, Infinity],
[Infinity, Infinity, 0, 2],
[Infinity, -1, Infinity, 0]
];
let n = d.length;
for (let i = 0; i < n; ++i) {
for (let j = 0; j < n; ++j) {
for (let k = 0; k < n; ++k) {
d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
}
}
}
console.log("distance from 3 to 1 = ", d[2][0]); // Infinity -- wrong
If you turn the outer loop into the inner loop you get matrix multiplication over the tropical semiring (i.e. the one with min as addition and sum as multiplication) instead of Floyd Warshall.
It will compute the lowest-weight path with up to or exactly two steps. You can exponentiate the matrix by repeated squaring to get the same result as Floyd Warshall of course (with complexity O(V^3 log(V)), and it'll handle negative weight cycles better

Is it possible to limit the size of parts in the linear partitioning problem?

I have an engineering problem that requires me to partition a set of positive numbers to k parts, without changing the ordering of the numbers in the set, so that the sums of the parts are as equal as possible. I have understood that there are solutions to this 'linear partitioning problem'. In fact, I have successfully tried the dynamic programming solution already and it works.
Now the question: What if there is a maximum size limitation for the parts? ("No part can have more than m items") Can it be added e.g. to the DP solution or can some other technique be used for solving this.
Appreciate all comments, links and suggestions.
Edit: I added a crude sketch of the original algorithm below
// Partition number array seq to k parts with max number of m items in each part
public void LinearPartition(double[] seq, int k, int m)
{
double[,] table;
int[,] solution;
int n = seq.Length - 1;
linearPartitionTable(seq, k, m, out table, out solution);
k = k - 2;
while (k >= 0)
{
Console.WriteLine(solution[n - 1, k] + 1);
n = solution[n - 1, k];
k--;
}
}
private void linearPartitionTable(double[] seq, int k, int m,
out double[,] table, out int[,] solution)
{
int n = seq.Length;
table = new double[n, k];
solution = new int[n - 1, k - 1];
table[0, 0] = 0;
for (int i = 1; i < n; i++)
table[i, 0] = seq[i] + table[i - 1, 0];
for (int j = 0; j < k; j++)
table[0, j] = seq[0];
for (int i = 1; i < n; i++)
{
for (int j = 1; j < k; j++)
{
double currentMin = double.MaxValue;
int minX = 0;
for (int x = 0; x < i; x++)
{
double cost = Math.Max(table[x, j - 1], table[i, 0] - table[x, 0]);
if (cost < currentMin)
{
currentMin = cost;
minX = x;
}
}
table[i, j] = currentMin;
solution[i - 1, j - 1] = minX;
}
}
}

Print all combination of a set after pairing consecutive numbers

Question is such that given a set of numbers we have to write a recursive program which prints all possible combination after pairing consecutive numbers or leaving them single.
<div>
Ex set 1,2,3,4,5,6
Output
<ul>
<li>1,2,3,4,5,6</li>
<li>12,3,4,5,6</li>
<li>1,23,4,5,6</li>
<li>1,2,34,5,6</li>
<li>1,2,3,45,6</li>
<li>1,2,3,4,56</li>
<li>12,34,5,6</li>
<li>12,3,45,6</li>
<li>12,3,4,56</li>
<li>1,23,45,6</li>
<li>1,23,4,56</li>
<li>1,2,34,56</li>
<li>12,34,56</li>
</div>
I use c++ to code.
Suppose the given set is a(a[0], a[1], ..., a[n - 1]), and the length of a is n
And the current answer is saved in b
void dfs(int pos, int depth)
{
if(pos >= n)
for(int i = 0; i < depth; ++i)
printf("%d%c", b[i], i == depth - 1 ? '\n' : ',');
else
{
b[depth] = a[pos];
dfs(pos + 1, depth + 1);
if(pos + 1 < n)
{
int c = 1, x = a[pos];
while(x) c *= 10, x /= 10;
b[depth] = a[pos] * c + a[pos + 1];
dfs(pos + 2, depth + 1);
}
}
}

Maximum span in two arrays with equal sum

This is programming puzzle. We have two arrays A and B. Both contains 0's and 1's only.
We have to two indices i, j such that
a[i] + a[i+1] + .... a[j] = b[i] + b[i+1] + ... b[j].
Also we have to maximize this difference between i and j. Looking for O(n) solution.
I found O(n^2) solution but not getting O(n).
Best solution is O(n)
First let c[i] = a[i] - b[i], then question become find i, j, which sum(c[i], c[i+1], ..., c[j]) = 0, and max j - i.
Second let d[0] = 0, d[i + 1] = d[i] + c[i], i >= 0, then question become find i, j, which d[j + 1] == d[i], and max j - i.
The value of d is in range [-n, n], so we can use following code to find the answer
answer = 0, answer_i = 0, answer_j = 0
sumHash[2n + 1] set to -1
for (x <- 0 to n) {
if (sumHash[d[x]] == -1) {
sumHash[d[x]] = x
} else {
y = sumHash[d[x]]
// find one answer (y, x), compare to current best
if (x - y > answer) {
answer = x - y
answer_i = y
answer_j = y
}
}
}
Here is an O(n) solution.
I use the fact that sum[i..j] = sum[j] - sum[i - 1].
I keep the leftmost position of each found sum.
int convertToPositiveIndex(int index) {
return index + N;
}
int mostLeft[2 * N + 1];
memset(mostLeft, -1, sizeof(mostLeft));
int bestLen = 0, bestStart = -1, bestEnd = -1;
int sumA = 0, sumB = 0;
for (int i = 0; i < N; i++) {
sumA += A[i];
sumB += B[i];
int diff = sumA - sumB;
int diffIndex = convertToPositiveIndex(diff);
if (mostLeft[diffIndex] != -1) {
//we have found the sequence mostLeft[diffIndex] + 1 ... i
//now just compare it with the best one found so far
int currentLen = i - mostLeft[diffIndex];
if (currentLen > bestLen) {
bestLen = currentLen;
bestStart = mostLeft[diffIndex] + 1;
bestEnd = i;
}
}
if (mostLeft[diffIndex] == -1) {
mostLeft[diffIndex] = i;
}
}
cout << bestStart << " " << bestEnd << " " << bestLen << endl;
P.S. mostLeft array is 2 * N + 1, because of the negatives.
This is a fairly straightforward O(N) solution:
let sa = [s1, s2, s3.. sn] where si = sum(a[0:i]) and similar for sb
then sum(a[i:j]) = sa[j]-sa[i]
and sum(b[i:j]) = sb[j] - sb[i]
Note that because the sums only increase by 1 each time, we know 0 <= sb[N], sa[N] <=N
difference_array = [d1, d2, .. dn] where di = sb[i] - sa[i] <= N
note if di = dj, then sb[i] - sa[i] = sb[j] - sa[j] which means they have the same sum (rearrange to get sum(b[i:j]) and sum(a[i:j]) from above).
Now for each difference we need its max position occurrence and min position occurrence
Now for each difference di, the difference between max - min, is an i-j section of equal sum. Find the maximum max-min value and you're done.
sample code that should work:
a = []
b = []
sa = [0]
sb = [0]
for i in a:
sa.append(sa[-1] + i)
for i in b:
sb.append(sb[-1] + i)
diff = [sai-sbi for sai, sbi in zip(sa, sb)]
min_diff_pos = {}
max_diff_pos = {}
for pos, d in enumerate(diff):
if d in min_diff_pos:
max_diff_pos[d] = pos
else:
min_diff_pos[d] = pos
ans = min(max_diff_pos[d] - min_diff_pos[d] for d in diff)
Basically, my solution goes like this.
Take a variable to take care of the difference since the beginning.
int current = 0;
for index from 0 to length
if a[i] == 0 && b[i] == 1
current--;
else if a[i] == 1 && b[i] == 0
current++;
else
// nothing;
Find the positions where the variable has the same value, which indicates that there are equal 1s and 0s in between.
Pseudo Code:
Here is my primary solution:
int length = min (a.length, b.length);
int start[] = {-1 ... -1}; // from -length to length
start[0] = -1;
int count[] = {0 ... 0}; // from -length to length
int current = 0;
for (int i = 0; i < length; i++) {
if (a[i] == 0 && b[i] == 1)
current--;
else if (a[i] == 1 && b[i] == 0)
current++;
else
; // nothing
if (start[current] == -1) // index can go negative here, take care
start[current] = current;
else
count[current] = i - start[current];
}
return max_in(count[]);

Puzzle.. solving product of values in array X

Can you please help me solving this one?
You have an unordered array X of n integers. Find the array M containing n elements where Mi is the product of all integers in X except for Xi. You may not use division. You can use extra memory. (Hint: There are solutions faster than O(n^2).)
The basic ones - O(n^2) and one using division is easy. But I just can't get another solution that is faster than O(n^2).
Let left[i] be the product of all elements in X from 1..i. Let right[i] be the product of all elements in X from i..N. You can compute both in O(n) without division in the following way: left[i] = left[i - 1] * X[i] and right[i] = right[i + 1] * X[i];
Now we will compute M: M[i] = left[i - 1] * right[i + 1]
Note: left and right are arrays.
Hope it is clear:)
Here's a solution in Python. I did the easy way with division to compare against the hard way without. Do I get the job?
L = [2, 1, 3, 5, 4]
prod = 1
for i in L: prod *= i
easy = map(lambda x: prod/x, L)
print easy
hard = [1]*len(L)
hmm = 1
for i in range(len(L) - 1):
hmm *= L[i]
hard[i + 1] *= hmm
huh = 1
for i in range(len(L) - 1, 0, -1):
huh *= L[i]
hard[i - 1] *= huh
print hard
O(n) - http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_3.28
two passes -
int main (int argc, char **argv) {
int array[] = {2, 5, 3, 4};
int fwdprod[] = {1, 1, 1, 1};
int backprod[] = {1, 1, 1, 1};
int mi[] = {1, 1, 1, 1};
int i, n = 4;
for (i=1; i<=n-1; i++) {
fwdprod[i]=fwdprod[i-1]*array[i-1];
}
for (i=n-2; i>=0; i--) {
backprod[i] = backprod[i+1]*array[i+1];
}
for (i=0;i<=n-1;i++) {
mi[i]=fwdprod[i]*backprod[i];
}
return 0;
}
Old but very cool, I've been asked this at an interview myself and seen several solutions since but this is my favorite as taken from
http://www.polygenelubricants.com/2010/04/on-all-other-products-no-division.html
static int[] products(int... nums) {
final int N = nums.length;
int[] prods = new int[N];
java.util.Arrays.fill(prods, 1);
for (int // pi----> * <----pj
i = 0, pi = 1 , j = N-1, pj = 1 ;
(i < N) & (j >= 0) ;
pi *= nums[i++] , pj *= nums[j--] )
{
prods[i] *= pi ; prods[j] *= pj ;
System.out.println("pi up to this point is " + pi + "\n");
System.out.println("pj up to this point is " + pj + "\n");
System.out.println("prods[i]:" + prods[i] + "pros[j]:" + prods[j] + "\n");
}
return prods;
}
Here's what's going on, if you write out prods[i] for all the iterations, you'll see the following being calculated
prods[0], prods[n-1]
prods[1], prods[n-2]
prods[2], prods[n-3]
prods[3], prods[n-4]
.
.
.
prods[n-3], prods[2]
prods[n-2], prods[1]
prods[n-1], prods[0]
so each prods[i] get hit twice, one from the going from head to tail and once from tail to head, and both of these iterations are accumulating the product as they
traverse towards the center so it's easy to see we'll get exactly what we need, we just need to be careful and see that it misses the element itself and that's where
it gets tricky. the key lies in the
pi *= nums[i++], pj *= nums[j--]
in the for loop conditional itself and not in the body which do not happen until the end of the
iteration. so for
prods[0],
it starts at 1*1 and then pi gets set to 120 after, so prods[0] misses the first elements
prods[1], it's 1 * 120 = 120 and then pi gets set to 120*60 after
so on and so on
O(nlogn) approach:
int multiply(int arr[], int start, int end) {
int mid;
if (start > end) {
return 1;
}
if (start == end) {
return arr[start];
}
mid = (start+end)/2;
return (multiply(arr, start, mid)*multiply(arr, mid+1, end));
}
int compute_mi(int arr[], int i, int n) {
if ((i >= n) || (i < 0)) {
return 0;
}
return (multiply(arr, 0, i-1)*multiply(arr, i+1, n-1));
}
Here is my solution in Python: Easy way but with high computational cost may be?
def product_list(x):
ans = [p for p in range(len(x))]
for i in range(0, len(x)):
a = 1
for j in range(0, len(x)):
if i != j:
a = a*x[j]
ans[i] = a
return ans

Resources