How to define a var in an array? - javascript

Building my first real app with JS: Black Jack. I was just wondering why my j, q, k, and a var are coming back as undefined.
window.onload = init;
var cards = [2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,j,j,j,j,q,q,q,q,k,k,k,k,a,a,a,a];
var j = 10;
var q = 10;
var k = 10;
var a = 11;
function init() {
var button = document.getElementById("doIt");
button.onclick = processIt;
}
function processIt() {
var cpu1 = document.getElementById("cpu1");
cpu1.innerHTML = cards[37];
}
Any help would be greatly appreciated.

Because at the moment when you declare cards, those variables (or, rather, their values) are still undefined. Reorder the declarations.
var j = 10;
var q = 10;
var k = 10;
var a = 11;
var cards = [2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,j,j,j,j,q,q,q,q,k,k,k,k,a,a,a,a];

You're defining them after you use them... You have to define variables before you use them, not after.

In javascript, declarations are processed first but assignment occurs in order. Your code is effectively:
var cards, j, q, k, a;
// Here, all variables exist but none have a value
// When cards is assigned an array, the values of j, q, k and a
// are still undefined.
cards = [2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,
8,9,9,9,9,10,10,10,10,j,j,j,j,q,q,q,q,k,k,k,k,a,a,a,a];
// Now the rest are given values
j = 10;
q = 10;
k = 10;
a = 11;

Related

Altering find and replace Google Sheets script

I have the following script, though I would like to change it to only find and replace on a specific sheet (Sheet4!A:AB).
How would I go about doing this:
function fandr() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var s=ss.getActiveSheet();
var r=s.getDataRange();
var vlst=r.getValues();
var i,j,a,find,repl;
find="abc";
repl="xyz";
for (i in vlst) {
for (j in vlst[i]) {
a=vlst[i][j];
if (a==find) vlst[i][j]=repl;
}
}
r.setValues(vlst);
}
I think that pnuts's comment is helpful for your situation. If you are still looking for your solution, how about this answer? You want to find and replace the values in Sheet4!A:AB. If my understanding is correct, I would like to propose 2 patterns. I think that there are several solution for your situation. So please think of this as one of them.
Pattern 1
This modification is a simple modification. It modified the range for retrieving values to Sheet4!A:AB.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var r = ss.getRange("Sheet4!A:AB");
var vlst = r.getValues();
var i, j, a, find, repl;
find = "abc";
repl = "xyz";
for (var i = 0; i < vlst.length; i++) {
for (var j = 0; j < vlst[i].length; j++) {
a = vlst[i][j];
if (a == find) vlst[i][j] = repl;
}
}
r.setValues(vlst);
Pattern 2
In the case of pattern 1, the values retrieved by getRange("Sheet4!A:AB") includes the empty rows. By this, the search speed becomes slow. So in this pattern 2, the data range of "A1:AB" is retrieved using getLastRow().
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Sheet4");
var r = s.getRange("A1:AB" + s.getLastRow());
var vlst = r.getValues();
var i, j, a, find, repl;
find = "abc";
repl = "xyz";
for (var i = 0; i < vlst.length; i++) {
for (var j = 0; j < vlst[i].length; j++) {
a = vlst[i][j];
if (a == find) vlst[i][j] = repl;
}
}
r.setValues(vlst);
References :
getSheetByName()
getRange(a1Notation)
getLastRow()
If I misunderstand what you want, please tell me. I would like to modify it.

Generate consecutive variables and set equal to function

In javascript, how would one generate a sequence of vars and set them all equal to a specific function?
for example, I want to create 20 variables that increment by one consecutive integer:
var color1 = getRandomColor()
var color2 = getRandomColor()
var color3 = getRandomColor()...
and so on, and then set each equal to the same function
I understand generating variables could be done with the function below but how would one set search these output variables to the getRandomColor() function within a function?
function createVariables() {
var colors = [];
for (var i = 0; i <= 20; ++i) {
colors[i] = "color" + i;
}
return colors;
}
You can create properties dynamically using Bracket notation.
//Define a object
window.colors = {}
for (var i = 0; i < 20; ++i) {
window.colors["color" + i] = i; //getRandomColor();
}
console.log(window.colors.color0, window.colors)
However I would recommend you to create an array and use its index
var colors = [];
for (var i = 0; i < 20; ++i) {
colors[i] = i; //getRandomColor();
}
console.log(colors[0], colors)

Array equals itself plus number = NaN

I must be doing something stupid. The array newArea needs to add up data from all regions, i.e. be global. Regions are represented by variable p. But when I try to get newArea array to add to itself, e.g. newArea[p] += otherArray, it outputs NaNs. Even newArea[p] += 1 outputs NaNs.
Can anyone spot what I'm doing wrong? It's driving me mad and I'm working to a deadline.
mm=0
var maxVolume = 0;
var tempCAGR = 0;
var maxCAGR = 0;
var newArray = [];
var newRegions = [];
var newConsValues = [];
var newArea = [];
for (var p=0; p<arrayRef[mm].length; p++) {//9 regions
newArray[p] = [];
for (var q=0; q<arrayRef[mm][p].length; q++) {//4 scenarios
newArea[q] = [];
if (q==0) {
newRegions.push(arrayRef[mm][p][q][0]);
newConsValues.push(arrayRef[mm][p][q][1]);
}
for (var r=0; r<dates.length; r++) {//time
//console.log('p: '+p+', q: '+q+', r: '+r);
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
}
arrayRef[mm][p][q].shift();
tempCAGR = Math.pow(( arrayRef[mm][p][q][len] / arrayRef[mm][p][q][1] ),(1/len))-1;
//console.log(newRegions[p]+', num: '+arrayRef[mm][p][q][len-1]+', denom: '+arrayRef[mm][p][q][0]+', len: '+len+', cagr: '+tempCAGR);
newArray[p][q] = tempCAGR;
maxCAGR = Math.max(maxCAGR,tempCAGR);
}
}
console.log(newArea);
You are cleaning the array in newArea everytime you loop through it:
...loop q ...
newArea[q] = []; // <-- resets the array at q pos
... loop r ...
if (p==0) {
newArea[q][r] = 1;
} else {
newArea[q][r] += 1;
}
So when p === 0 it will fill an array at q pos of your newArea array. However, next iteration of p will clear them out, so there's nothing there to sum.
You probably want to keep the old array or create a new one if there isn't one.
newArea[q] = newArea[q] || [];
It looks like you do not have the variable initialised. With adding something to undefined, you get NaN.
You can change the art of incrementing with a default value:
if (p == 0) {
newArea[q][r] = 1;
} else {
newArea[q][r] = (newArea[q][r] || 0) + 1;
}

Variable scope within methods

I was teaching myself how to make a binary genetic algorithm the other day. The goal was to make it so that it would match a randomly generated 35 length binary string. I ran into a problem where methods were editing variables that I did not think were in its scope. This caused my solution to slowly degrade in fitness instead of increase! After I found out where this was happening I fixed it by newP[0].join('').split('') so that newP[0] itself would not be edited. For convenience I've marked where the problem was happening below in comments.
While I have fixed this problem I'd like to hopefully get an understanding as to why this happens and also prevent without doing the join/split silliness.
Here is the code:
var GeneticAlgorithm = function () {};
GeneticAlgorithm.prototype.mutate = function(chromosome, p) {
for(var i = 0; i < chromosome.length; i++) {
if(Math.random() < p) {
chromosome[i] = (chromosome[i] == 0) ? 1 : 0;
}
}
return chromosome;
};
GeneticAlgorithm.prototype.crossover = function(chromosome1, chromosome2) {
var split = Math.round(Math.random() * chromosome1.length);
var c1 = chromosome1;
var c2 = chromosome2;
for(var i = 0; i < split; i++) {
c1[i] = chromosome2[i];
c2[i] = chromosome1[i];
}
return [c1, c2];
};
// fitness = function for finding fitness score of an individual/chromosome (0-1)
// length = length of string (35)
// p_c = percentage chance of crossover (0.6)
// p_m = percentage change of mutation (0.002)
GeneticAlgorithm.prototype.run = function(fitness, length, p_c, p_m, iterations) {
var iterations = 100;
var size = 100;
// p = population, f = fitnesses
var p = [];
var f = [];
for(var i = 0; i < size; i++) {
p.push(this.generate(length));
f.push(fitness(p[i].join('')));
}
while( iterations > 0 && Math.max.apply(Math, f) < 0.999 ) {
var mates = [];
var newP = [];
var newF = [];
mates = this.select(p, f);
newP.push(mates[0], mates[1]);
while(newP.length < size) {
/*-------------------> Problem! <-------------------*/
mates = [newP[0].join('').split(''), newP[1].join('').split('')];
/*
* If I passed newP[0] when mates[0] changed newP[0] would also change
*/
if(Math.random() < p_c) {
mates = this.crossover(mates[0], mates[1]);
}
mates[0] = this.mutate(mates[0], p_m);
mates[1] = this.mutate(mates[1], p_m);
newP.push(mates[0], mates[1]);
}
for(var i = 0; i < size; i++) {
newF.push(fitness(newP[i].join('')));
}
p = newP;
f = newF;
iterations--;
}
return p[f.indexOf(Math.max.apply(Math, f))].join('');
};

Passing a calculated variable from one function to another

...not sure "calculated" was the right word...I have written two functions, the second of which needs the output of a variable from the first. I cant seem to get it to pass...my guess is that I am calling it wrong, but can't seem to get it right...might have something to do with the time I've spent staring at the whole thing..
The variable I need passed is subset I am trying to use it on the last line of the second function.
If it matters, the getPos function is getting its value from an input box.
The javascript:
<script>
var alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
function getPos(value)
{
var letterPosition = alphabet.indexOf(value);
var subset = alphabet.slice(letterPosition+1, 26);
document.getElementById('theRest').value = subset;
}
function appendTable(id)
{
var tbody = document.getElementById(id).getElementsByTagName("tbody")[0];
var i = 0;
for (var r = 0; r < 4; r++) {
var row = tbody.insertRow(r);
for (var c = 0; c < 4; c++) {
var cell = row.insertCell(c);
cell.appendChild(document.createTextNode(subset[i++]));
}
}
}
</script>
<script>
var alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var subset;
function getPos(value)
{
var letterPosition = alphabet.indexOf(value);
subset = alphabet.slice(letterPosition+1, 26);
document.getElementById('theRest').value = subset;
}
function appendTable(id)
{
var tbody = document.getElementById(id).getElementsByTagName("tbody")[0];
var i = 0;
for (var r = 0; r < 4; r++) {
var row = tbody.insertRow(r);
for (var c = 0; c < 4; c++) {
var cell = row.insertCell(c);
cell.appendChild(document.createTextNode(subset[i++]));
}
}
}
</script>
That should do the trick.
Declaring subset before the functions makes it a global var, if you define it with var subset within a function it becomes tied to that function, removing the var makes it use the global var.

Categories