Two-Dimensional Recursive JavaScript

W

wgarner

I am trying to implement a two-dimensional recursive formula, g(x,y).
It is sort of like multiplication.

g(x,y) = 0 if either x or y is 0. g(1, y) = y and g(x, 1) = x.

Those are the base cases.

In general, though, g(x, y) = h[g(x,b) XOR g(a,y) XOR g(a,b): 0 <= a <
x, 0 <= b < y], where h is another function which I have already
written a script for. (The XOR refers to binary addition and can be
implemented via " ^ ", so that is all right.)

The problem I am having is preventing stack overflows and making the
script run in a reasonable amount of time.

I looked online and found that for a Fibonaci sequence, one code used
push() and shift() to reduce the processing time and to reuse the
previous calculuations.

The code is as follows:

function fastfib(n){
var i;
var fibs = new Array();
fibs.push(0);
fibs.push(1);
for(i=0; i<n; i++){
fibs.push(fibs[0] + fibs[1]);
fibs.shift();
}
return fibs[0];
}


Something like that would be ideal here, as it would be quite helpful
to save these function values and use them to build more complicated
ones.

My thought was to create a two-dimensional array, but I got stuck.
Here is the code that I have so far:


<html>
<head>
<title> Nim Multiplication </title>
</head>
<body>

<script language="JavaScript">

function nim_mult(a,b) {

var g = new Array(a+1);
for(i=0; i<=a;i++) {
g = new Array(b+1);
}

for(i=0;i<=a;i++) {
g[0] = 0;
if(b>0)
g[1] = i;
}
for(j=0;j<=b;j++) {
g[0][j] = 0;
if(a>0)
g[1][j] = j;
}


if(a=="0" || b=="0") {
return 0;
} else if (a=="1") {
return b;
} else if(b=="1") {
return a;
} else {

nim_mult_str="";

for(i=0; i<a; i++) {
for(j=0; j<b; j++) {
nim_mult_str+= "," + nim_mult(i,b) + ",";
}
}
g[a] = h(nim_mult_str);

return g[a];
}

}
</script>


<form name=nimmulti>

<input type="text" name="a"> <font face="Symbol">Ä</font> <input
type="text" name="b"> <br><br>

<input type="button" value="Multiply"
onclick="multval.value=nim_mult(a.value,b.value)"><br><br>

Multiplication value: <input type="text" name="multval">

</form>

</body>
</html>


I should mention that the h() function I have written takes a string
of numbers, parses out the commas, and then returns a value.


Any help would be greatly appreciated.
 
T

Tom de Neef

I am trying to implement a two-dimensional recursive formula, g(x,y).
It is sort of like multiplication.

g(x,y) = 0 if either x or y is 0. g(1, y) = y and g(x, 1) = x.

Those are the base cases.
function nim_mult(a,b) {

var g = new Array(a+1);
for(i=0; i<=a;i++) {
g = new Array(b+1);
}

Every time you enter this function it will create the g array and fill it.
And the function is called recursively, so it doesn't meet your objective.
Instead, you want to declare and fill it once. That should thus happen in an
'outer' function. The recursion should than be placed in an inner function.
See later.
for(i=0;i<=a;i++) {
g[0] = 0;
if(b>0)
g[1] = i;
}
for(j=0;j<=b;j++) {
g[0][j] = 0;
if(a>0)
g[1][j] = j;
}

I'm not sure that it is sensible to fille the elements [0,j] and [i,0]. Will
they ever be accessed ?
if(a=="0" || b=="0") {
return 0;
} else if (a=="1") {
return b;
} else if(b=="1") {
return a;
} else {
NB: why do you compare a and b here to a string, wheras before you compared
them to numbers. The following code will achieve the same:
if (a==0 || b==0) return 0;
if (a==1) return b;
if (b==1) return a;
nim_mult_str="";

for(i=0; i<a; i++) {
for(j=0; j<b; j++) {
nim_mult_str+= "," + nim_mult(i,b) + ",";
}
I don't understand why you loop thru j. Part of the formula is missing ?
}
g[a] = h(nim_mult_str);

return g[a];
}


I think that your idea of storing results in the 2d array could be
implemented as follows.
function nim_mult(a,b) {
if (a==0 || b==0) return 0;
if (a==1) return b;
if (b==1) return a;
var i,g = []
for (i=0;i<a;i++) {g = []}; // create g and make it available to inner
function
function inner(a,b) {
var i,j,result
if (a==0 || b==0) return 0;
if (a==1) return b;
if (b==1) return a;
result=g[a]
if (result) return result;
result="";
for(i=0; i<a; i++) {
for(j=0; j<b; j++) {
result+="," + inner(i,b) + ","+inner(a,j); // ???
}}
g[a]=result;
return result
}
return inner(a,b)
}

Tom
 
D

Dr J R Stockton

In comp.lang.javascript message <2ff17b21-198a-4f08-9652-6511d2c74dd7@a8
g2000prf.googlegroups.com>, Wed, 13 Aug 2008 19:56:51, (e-mail address removed)
posted:
I am trying to implement a two-dimensional recursive formula, g(x,y).
The problem I am having is preventing stack overflows and making the
script run in a reasonable amount of time.


There, ISTM that x & y are integers. Given g(x, y), one can produce a
faster G(x, y), something like :-

var K = [] // Cache

function G(X, Y) { var T
T = K[X] ; if (!T) T = K[X] = [] // if X new, create X sub-array
T = T[Y] ; if (!T) T = T[Y] = g(X, Y) // if X Y new, fill element
return T }

With that, G(X, Y) will be calculated only once for each (X, Y), saving
time. If the range of X, or an upper bound, is known, then a little
time will be saved by first filling K with empty arrays K[J] = [] and
omitting the first test.

If the first calculation is of a non-small X, Y, then that will save
time (for likely g) but may not reduce the depth of recursion. But if
you start calling with (X, Y) small and work up, it probably will reduce
the maximum depth needed for the larger (X, Y).

Note that there is an assumption that the number of combinations (X, Y)
is not to great to be cached. In that case, it *might* help to cache
only the values for which X, Y, or both are small - that depends on the
details of g.

One can test G by checking that G(X, Y) == g(X, Y) for various (X, Y).

One could make G more general by passing g in as a third argument?


See <http://www.merlyn.demon.co.uk/js-misc1.htm#Cash> for 1-D examples.



ASIDE I now have an even faster (slightly) Easter routine, by Knuth
via McClendon; but I cannot trace it back to Bull or Act.
Anyone got the relevant part of Knuth "Art" vol 1 pp 155-156?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top