Working with 2-D arrays in JS - javascript

I know that multi-dimensional arrays are not natively supported in JS, but I would like to shoehorn them in a calculation I'm doing. For example, I have:
amn1 = new Array(4);
for (j = 0; j < amn1.length; j = j + 1) {
amn1[j] = new Array(4);
}
amn1[0][0] = -8.72500;
amn1[0][1] = 1.88000;
amn1[0][2] = 0.741900;
amn1[0][3] = 0.752000;
amn1[1][0] = 0.83090;
amn1[1][1] = 0.11140;
amn1[1][2] = -0.528800;
amn1[1][3] = -0.555890;
amn1[2][0] = -0.13396;
amn1[2][1] = -0.06481;
amn1[2][2] = 0.126423;
amn1[2][3] = 0.128431;
amn1[3][0] = 0.01262;
amn1[3][1] = 0.00540;
amn1[3][2] = -0.009341;
amn1[3][3] = -0.009306;
for (u = 0; u < 4; u = u + 1) {
for (n = 0; n < 4; n = n + 1) {
amn1[u][n] = amn1[u][n] * logt + amn1[u][n];
}
loglambda = loglambda + amn1[u][n];
loglambda = loglambda * logi;
}
Assume my script is linted and all variables are properly declared and initialized. Now, checking to see if JS understands the contents of amn1 in the inner loop, it does. However, in the outer loop a check of the console output reveals undefined. Keeping the logic the same, this works in a procedural language, but not here (I have a working version of this in Fortran).
Why does this not work?

dead simple :
loglambda = loglambda + amn1[u][n];
on that line your N will always be 4.
Keeping in mind the size of your array : you have only j = [0,1,2,3] for each amn1[i][j].

Related

Using for loops to define global variables

I am defining some global arrays at the top of my JS file. There are for loops to populate the arrays. I have done very similar things that have worked but for some reason, this is having issues. The first for loop runs through only one time and the code below that never gets ran.
var group = 'a';
var RoofVar = 1;
var TrimVar = 1;
var BBVar = 1;
var imageArrayGroup0 = [];
var floatingButtonArrayGroup0 = [];
var labelArrayGroup0 = [];
for (a = 1; a < 3; a++) {
labelArrayGroup0[a] = document.createElement("Label");
labelArrayGroup0[a].type = "Label";
floatingButtonArrayGroup0[a] = document.getElementById('floatingButton0' + (100 + a));
floatingButtonArrayGroup0[a].style.textAlign = "center";
floatingButtonArrayGroup0[a].style.paddingTop = "5px";
labelArrayGroup0[a] = document.getElementById('floatingButton0' + (100 + x));
}
var imageArray0 = [];
var floatingButtonArray0 = [];
var labelArray0 = [];
for (b = 1; b < 5; b++) {
imageArray0[b] = document.createElement("img");
imageArray0[b].type = "image";
floatingButtonArray0[b] = document.getElementById('floatingButton0' + (b));
floatingButtonArray0[b].style.paddingLeft = "15px";
floatingButtonArray0[b].style.paddingTop = "5px";
labelArray0[b] = document.getElementById('floatingButton0' + b);
}
var imageArray1 = [];
var floatingButtonArray1 = [];
var labelArray1 = [];
for (c = 1; c < 3; c++) {
imageArray1[c] = document.createElement("img");
imageArray1[c].type = "image";
floatingButtonArray1[c] = document.getElementById('floatingButton1' + (c));
floatingButtonArray1[c].style.paddingLeft = "15px";
floatingButtonArray1[c].style.paddingTop = "5px";
labelArray1[c] = document.getElementById('floatingButton1' + c);
}
You have other issues than just "(100 + x) instead of (100 + a).
First, arrays in JavaScript are "zero-based" but your loops start at 1.
This means you're putting things in but leaving spot '0' undefined, which will probably break things later.
Next. at the beginning of the loop you set labelArrayGroup0[a] to a new blank label, but you never do anything to put it on the page. At the end the loop, you overwrite labelArrayGroup0[a] to a floatingButton element you pull from the page.
In fact, you do this in every loop - the last line resets the value of the 1st line.
It's not clear what you're trying to accomplish. Presumably you intend to append labelArrayGroup0[a] to the page instead?
Also, in the middle, you set floatingButtonArrayGroup0[a] = document.getElementById('floatingButton0' + (100 + a)); which is the same element you grab in the last line of the loop...
Paul had my answer. I forgot to switch out the "x" for an "a".

c pointers and javascript

I have been working on a conversion of a C code into javascript. But they just don't return the same data.
I have an idea on how to handle the pointers. In javascript I'll create an array.
Note: This are not the full code, only partials
Origin:
// file.h
unsigned char m_aucState0[256];
unsigned char m_aucState[256];
unsigned char m_ucI;
unsigned char m_ucJ;
unsigned char* m_pucState1;
unsigned char* m_pucState2;
// file.c
unsigned char *pucKeyData
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256);
Javascript:
// buffer or array???
this.m_aucState0 = new Buffer(256)
this.m_aucState = new Buffer(256)
this.m_ucI
this.m_ucJ
this.m_pucState1 = []
this.m_pucState2 = []
for (var i = 0; i < 256; i++)
{
this.m_pucState1 = this.m_aucState0 + i
this.m_ucJ += this.m_pucState1[0] + (pucKeyData[0] + this.m_ucI)
this.m_pucState2 = this.m_aucState0 + this.m_ucJ
//Swaping
this.m_ucTemp = this.m_pucState1[0]
this.m_pucState1[0] = this.m_pucState2[0]
this.m_pucState2[0] = this.m_ucTemp
this.m_ucI = (this.m_ucI + 1) % iKeyLen
}
this.m_aucState.copy(this.m_aucState0, 0, 0, 256)
So my idea is because a pointer returns an address, that address contains the first byte of the pointer data. So if in an array I could just also point to the first index of the array right?
Is what I did above right?
Just for context let me add 1 function:
Javascript:
Crypt.prototype.setup = function(pucKeyData, iKeyLen) {
if (iKeyLen < 1)
throw new Error("Key Length should be at least 1")
var i;
for (i = 0; i < 256; i++)
this.m_aucState0[i] = i
this.m_ucI = 0
this.m_ucJ = 0
for (var i = 0; i < 256; i++)
{
this.m_pucState1 = this.m_aucState0 + i
this.m_ucJ += this.m_pucState1[i] + (pucKeyData[i] + this.m_ucI)
this.m_pucState2 = this.m_aucState0 + this.m_ucJ
//Swaping
this.m_ucTemp = this.m_pucState1[i]
this.m_pucState1[i] = this.m_pucState2[i]
this.m_pucState2[i] = this.m_ucTemp
this.m_ucI = (this.m_ucI + 1) % iKeyLen
}
this.m_aucState.copy(this.m_aucState0, 0, 0, 256)
//Initialize Indexes
this.m_ucI = 0
this.m_ucJ = 0
//Initialization Finished
this.m_bInit = true
}
CPP:
void CArcfourPRNG::SetKey(unsigned char *pucKeyData, int iKeyLen)
{
if(iKeyLen < 1)
throw exception("Key Length should be at least 1");
int i;
for(i=0; i<256; i++)
m_aucState0[i] = i;
m_ucI = 0;
m_ucJ = 0;
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256);
//Initialize Indexes
m_ucI = 0;
m_ucJ = 0;
//Initialization Finished
m_bInit = true;
}
What is the difference of m_pucState1 and *m_pucState1 in this:
m_pucState1 = m_aucState + m_ucI;
m_ucJ += *m_pucState1;
In Javascript, there are typed buffer objects: http://www.javascripture.com/ArrayBuffer
You will also find something about the ctypes collection, but in my understanding they are used only for native OS library calls.
Also, I don't know a native JS Buffer object like you mention it. There is one in NodeJS, but I don't know its features.
If you insist of translating your code one-by-one, then these typed buffer objects may greatly support you. I think it's not a good way as while translating from C to Javascript, your terminology alters anyway. It alters from adding long pointer values to forming array indices.
Here is one problem example in your translation:
In C, you write:
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
In Javascript, you write:
this.m_ucJ += this.m_pucState1[0] + (pucKeyData[0] + this.m_ucI);
The brackets in the C term make m_ucI altering the address. So in Javascript this should rather be in the square brackets, somehow like this:
this.m_ucJ += this.m_pucState1[0] + pucKeyData[0 + this.m_ucI];
and then you can skip the "0 +". This shows how one-by-one translation between such different languages is full of traps.
So let's assume that we will use the simplest Javascript object, which is the array []. Then this is my suggestion. It's a draft, but it should give you a thorough idea:
// Define arrays
var aState0 = []; // m_aucState0
var aState = []; // m_aucState
// Define helpers
var state1Index; // *m_pucState1
var state2Index; // *m_pucState2
var i; // m_uci. There is no such thing as "uc" in Javascript.
var j; // m_ucj
var iLoop; // i in loop.
// It's readable to have this constant.
var bufferLength = 255;
// Somewhere we need:
var keyData;
var temp;
var iKeyLen;
// Just for here, give the array a size. So it's done in Javascript.
// Alternatively, fill it with 256 values from anywhere.
aState0[bufferLength] = 0;
// console.log(state0.length) will now print 256
// ...
// init i, j, iKeyLen ...
// ...
for (iLoop = 0; iLoop <= bufferLength; iLoop++) {
// This:
// m_pucState1 = m_aucState0 + i;
// m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
// becomes:
state1Index = iLoop;
j += aState0[state1Index] + keyData[i];
// This:
// m_pucState2 = m_aucState0 + m_ucJ;
// becomes:
state2Index = j;
// This:
// m_ucTemp = *m_pucState1;
// *m_pucState1 = *m_pucState2;
// *m_pucState2 = m_ucTemp;
// becomes:
temp = aState0[state1Index];
aState0[state1Index] = aState0[state2Index];
aState0[state2Index] = temp;
// This:
// m_ucI = (m_ucI + 1) % iKeyLen;
// becomes:
i = (i+1) % iKeyLen;
}
// this:
// memcpy(m_aucState, m_aucState0, 256);
// would be a clone. So you'd need jQuery or else. But you can simply write:
for (index in state0) {
state[index] = state0[index];
}
Finally, you can drop j as it is equal to state2Index, and state1Index equal to iLoop.
But this is a puzzle where you will probably have to use paper and pencil and to draw some boxes and arrows to get clear with.
Hth :-)

JavaScript syntax issue

I'm doing "fifteen puzzle" game. I'm only a beginner, so I chose this project to implement. My problem is shuffle algorithm :
function shuffle() {
$('td').empty();
var p = 0;
var f = 0;
do {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var rand = arr[Math.floor(Math.random() * arr.length)];
if ($('#' + rand).is(':empty')) {
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
} else {}
} while (f < 15)
That works cool, but I've heard that almost 50% of all random shuffle like mine is unsolvable. So I found math formula at wikipedia.org for this game, explaining how you can avoid that.
Here's modified algorithm that doesn't work either. The way I know it is alert stuff: it launches only 2 times instead of 31.
array = [];
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
array[i] = new Array();
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array[i].push(j)
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
The question is the same:
What's wrong? Two-dimensional array doesn't work.If you've got any questions - ask.
Just to make it clear: 2 for loops with i and j should make a 2-dimensional array like this [ this is " var i" -->[1,3,4,5,7], this is "var i" too-->[5,7,9,14,15]]. Inside each i there's j. The for loop with var a should count the number of js inside each i. if the number of js is even, the code is finished and shuffle's accomplished, otherwise shuffle should be made once again.
var nextId = cerIdNum + j;
in that fiddle, I don't see this cerIdNum declared & defined neither as local nor as global variable, I suppose that is curIdNum
Please use the below definition of algorithm and let us know if this works. Basically, the alert messages would come only twice, since there were usages of undefined variables. For the purpose of illustration, I have placed comments at where the problem points occured. Due to these problems, your script would stop executing abruptly thereby resulting in the behavior you described.
Oh and by the way - I did not have time to go through the Wiki link provided - hence you will have to verify your logic is correct. However, I have definitely resolved the errors causing the behavior you observed.
As an aside - consider using jQuery, your code will be a lot cleaner...
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array.push(j) //array[i].push does not make sense
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array.length; //array[1].length does not make sense
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
I found the solution by totally rewriting the code. Thank everyone for help!
Here's what do work:
function shuffle (){
press = 1;
$('td').empty().removeClass();
p=0;
var f;
do {
var arr=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var rand=arr[Math.floor(Math.random()*arr.length)];
if ($('#'+ rand).is(':empty')){
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
}
else{}
}while(f < 15){
winChance();
}
}
function winChance (){
array = [];
for (i=1;i<16;i++){
array[i]= new Array();
var currentId = $('#' + i).attr('id');
var currentIn = $('#' + i).html()
var currentIdNum = parseInt(currentId, 10);
var currentInNum = parseInt(currentIn, 10);
for (j=1;j<16;j++){
var nextId = currentIdNum + j;
if (nextId < 16){
var nextIn = $('#' + nextId).html();
var nextInNum = parseInt(nextIn, 10);
if (currentInNum > nextInNum){
array[i].push(j);
}
}
}
}
checkSum();
}
function checkSum(){
var sum = 0;
for (var a=1; a<16; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){}
else {
shuffle();
}
}

How to make calculations in Javascript?

i = 3;
j = 2;
function domath(x) {
i = 4;
j = 1;
return i*x + j;
}
j = domath(i) - j;
alert(j); //expected result = 11
k = domath(i) + j;
alert(k); //expected result = 15
The above JavaScript code does not return the expected results (as indicated by the comments in the code). Please correct the code for me anyone ?
As you're not using var , the variables i and j you're defining in the first lines are actually the same variable as you define in your domath() function...
try this :
i = 3;
j = 2;
function domath(x) {
var i = 4;
var j = 1;
return i*x + j;
}
j = domath(i) - j;
alert(j); //expected result = 11
k = domath(i) + j;
alert(k); //expected result = 15
P.S : it could be a good idea to vary your variable name in order to make your code more readable
Declare your variables using var:
var i = 3;
var j = 2;
function domath(x) {
var i = 4;
var j = 1;
return i * x + j;
}
It seems to be a really nasty way to do things.
I would personally do something like:
var v1;
var v2;
function math(x){ //do math here then return}
alert(math(1))
If you really have to use the same varible every where at least do it like:
var i = 3;
var j = 2;
function domath(x) {
var i = 4;
var j = 1;
return i*x + j;
}
Also meaningful varibles names will keep you on a good track and using var and not global will also help you!
var i = 3;
var j = 2;
function domath(x) {
var i = 4;
var j = 1;
return i*x + j;
}
var x = domath(i) - j; // overwriting J will change your next expected result
alert(x); //expected result = 11
var k = domath(i) + j;
alert(k); //expected result = 15
The problem is you're overwriting global variables, i.e. screwing up your math:
j = domath(i) - j;
This expression is evaluated from left to right. The call to domath() will assign new values to i and j, so the effective code here would be this:
j = (i = 4) * 3 + 1 - 1;
So once this is done, j will be set to 12, which is indeed not 11. In addition, i will have a value of 4.
To use local variables within your function, you'll have to redeclare them, essentially hiding the global variables being outside this scope:
function domath(x) {
var i = 4;
var j = 1;
return i * x + j;
}
This time, the first assignment will be resolved to this, because domath() won't touch i and j assigned outside:
j = 4 * 3 + 1 - 2
Once this i done, j will be set to 11, just as expected.
To avoid such issues, it's good practice to always use var when defining new variables (which you'll have to do when wanting to write strict code anyway), and not to use such short, not-telling variable names. I'd consider limiting the use of one-character variable names to iterators and other things with very limited scope. Never for something being global.

Javascript Random problem?

var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
alert(swf[i]); // swf[1] >> 2.swf
This case ,Random output One number.
How to Random output two different numbers ?
var swf = ['1.swf', '2.swf', '3.swf'],
// shuffle
swf = swf.sort(function () { return Math.floor(Math.random() * 3) - 1; });
// use swf[0]
// use swf[1]
Even though the above should work fine, for academical correctness and highest performance and compatibility, you may want to shuffle like this instead:
var n = swf.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = swf[i];
swf[i] = swf[j];
swf[j] = tmp;
}
Credits to tvanfosson and Fisher/Yates. :)
You can use splice to remove the chosen element, then simply select another randomly. The following leaves the original array intact, but if that's not necessary you can use the original and omit the copy. Shown using a loop to demonstrate how to select an arbitrary number of times upto the size of the original array.
var swf=["1.swf","2.swf","3.swf"];
var elementsToChoose = 2;
var copy = swf.slice(0);
var chosen = [];
for (var j = 0; j < elementsToChoose && copy.length; ++j) {
var i = Math.floor(Math.random()*copy.length);
chosen.push( copy.splice(i,1) );
}
for (var j = 0, len = chosen.length; j < len; ++j) {
alert(chosen[j]);
}
I would prefer this way as the bounds are known (you are not getting a random number and comparing it what you already have. It could loop 1 or 1000 times).
var swf = ['1.swf', '2.swf', '3.swf'],
length = swf.length,
i = Math.floor(Math.random() * length);
firstRandom = swf[i];
// I originally used `delete` operator here. It doesn't remove the member, just
// set its value to `undefined`. Using `splice` is the correct way to do it.
swf.splice(i, 1);
length--;
var j = Math.floor(Math.random() * length),
secondRandom = swf[j];
alert(firstRandom + ' - ' + secondRandom);
Patrick DW informed me of delete operator just leaving the value as undefined. I did some Googling and came up with this alternate solution.
Be sure to check Tvanfosson's answer or Deceze's answer for cleaner/alternate solutions.
This is what I would do to require two numbers to be different (could be better answer out there)
var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
var j;
do {
j = Math.floor(Math.random()*swf.length);
} while (j === i);
alert(swf[i]);
alert(swf[j]);
Edit: should be j===i

Categories

Resources