Using javascript vars as array key names - javascript

I'm making a grid of 18 x 9 and want to calculate the sizes for all possible boxes that could be placed on the grid.
I'm placing them in objects, but the line
var template_sizes_site[x + 'x' + y] = {};
Is failing. it seems I can't use variables AND a string to name key?
I want basically to say array['2x9']['width'] = 42; etc
What am I missing?
var template_sizes = {};
var site_width = 70;
var site_height = 70;
var site_margin = 20;
for (var y = 1; y <= 9; y++)
{
for (var x = 1; x <= 18; x++)
{
var template_sizes_site[x + 'x' + y] = {};
template_sizes_site[x + 'x' + y]['width'] = ((site_width * x) + (x > 1 ? site_margin * (x - 1) : 0));
template_sizes_site[x + 'x' + y]['height'] = ((site_height * y) + (y > 1 ? site_margin * (y - 1) : 0));
}
}

Remove the var from your first line in the body of your nested for loop:
var template_sizes = {};
var site_width = 70;
var site_height = 70;
var site_margin = 20;
for (var y = 1; y <= 9; y++)
{
for (var x = 1; x <= 18; x++)
{
template_sizes_site[x + 'x' + y] = {};
template_sizes_site[x + 'x' + y]['width'] = ((site_width * x) + (x > 1 ? site_margin * (x - 1) : 0));
template_sizes_site[x + 'x' + y]['height'] = ((site_height * y) + (y > 1 ? site_margin * (y - 1) : 0));
}
}
var is only for variables, not for properties:
var template = {}; // OK
var template_sizes_site[x + 'x' + y] = {}; // not allowed, no need
Also you'll need to initialise template_sizes_site if that wasn't a typo.

You did not initialize your variable template_sizes_site (is this meant to be template_sizes ?). Also you could shorten your initialization code a little like shown below.
var template_sizes = {},
template_sizes_site = {},
site_width = 70,
site_height = 70,
site_margin = 20;
for (var y = 1; y <= 9; y++) {
for (var x = 1; x <= 18; x++) {
template_sizes_site[x + 'x' + y] = {
'width': ((site_width * x) + (x > 1 ? site_margin * (x - 1) : 0)),
'height': ((site_height * y) + (y > 1 ? site_margin * (y - 1) : 0))
};
}
}

You need to change var template_sizes_site[x + 'x' + y] = {}; into template_sizes_site[x + 'x' + y] = {}; because your way creates local variable in scope and after leaving it (when loop goes to next time) data is becomes lost.
Also template_sizes_site is not initialized if it is all your code.

Related

Why won't setMatrix([...matrix, [[x][y]]]) work?

I want to add the coordinates x and y (from the loop) to the state (matrix) like you can see in my example but it won't work. Can someone help me?
const [matrix, setMatrix] = useState([[], []] as any)
for (let j = 0; j < imgHeight * scale; j += props.gridsize.height) {
for (let i = 0; i < imgWidth * scale; i += props.gridsize.width) {
console.log('x: ' + x + ' ===== ' + 'y: ' + y)
drawImgRectangles(ctx, [{ x: x, y: y, width: props.gridsize.width, height: props.gridsize.height }])
x += props.gridsize.height
}
x = 0
y += props.gridsize.height
}
setMatrix([...matrix, [[x][y]]])
console.log(matrix[[0][0]]) **
The problem is in expression [x][y] which evaluates to undefined.
[x] defines an array containing one element x
[x][y] tries to index the [x] array, taking y-th element. If y is anything other than 0, the result is undefined
console.log([3][0]); // 3
console.log([3][1]); // undefined
You probably meant one of:
const x = 1;
const y = 2;
var matrix1: number[][] = [];
matrix1 = [...matrix1, [x, y]];
var matrix2: number[][][] = [];
matrix2 = [...matrix2, [[x], [y]]];

How to convert between Lat Long and MGRS using javascript without dependence on libraries

I have a mapping app running in a browser than needs to be able to convert between latitude longitude and MGRS. I need to keep the load time of the app fast so I do not want to include any libraries with additional functions I do not need.
I solved this by developing the following two functions combining bits from two primary sources plus others on the internet. I have optimised them for speed not understanding!
My two primary sources were:
http://www.movable-type.co.uk/scripts/latlong-utm-mgrs.html
http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html
Example usage : MGRSString (51.172,-1.779) returns
"30U WB 85358 69660"
function MGRSString (Lat, Long)
{
if (Lat < -80) return 'Too far South' ; if (Lat > 84) return 'Too far North' ;
var c = 1 + Math.floor ((Long+180)/6);
var e = c*6 - 183 ;
var k = Lat*Math.PI/180;
var l = Long*Math.PI/180;
var m = e*Math.PI/180;
var n = Math.cos (k);
var o = 0.006739496819936062*Math.pow (n,2);
var p = 40680631590769/(6356752.314*Math.sqrt(1 + o));
var q = Math.tan (k);
var r = q*q;
var s = (r*r*r) - Math.pow (q,6);
var t = l - m;
var u = 1.0 - r + o;
var v = 5.0 - r + 9*o + 4.0*(o*o);
var w = 5.0 - 18.0*r + (r*r) + 14.0*o - 58.0*r*o;
var x = 61.0 - 58.0*r + (r*r) + 270.0*o - 330.0*r*o;
var y = 61.0 - 479.0*r + 179.0*(r*r) - (r*r*r);
var z = 1385.0 - 3111.0*r + 543.0*(r*r) - (r*r*r);
var aa = p*n*t + (p/6.0*Math.pow (n,3)*u*Math.pow (t,3)) + (p/120.0*Math.pow (n,5)*w*Math.pow (t,5)) + (p/5040.0*Math.pow (n,7)*y*Math.pow (t,7));
var ab = 6367449.14570093*(k - (0.00251882794504*Math.sin (2*k)) + (0.00000264354112*Math.sin (4*k)) - (0.00000000345262*Math.sin (6*k)) + (0.000000000004892*Math.sin (8*k))) + (q/2.0*p*Math.pow (n,2)*Math.pow (t,2)) + (q/24.0*p*Math.pow (n,4)*v*Math.pow (t,4)) + (q/720.0*p*Math.pow (n,6)*x*Math.pow (t,6)) + (q/40320.0*p*Math.pow (n,8)*z*Math.pow (t,8));
aa = aa*0.9996 + 500000.0;
ab = ab*0.9996; if (ab < 0.0) ab += 10000000.0;
var ad = 'CDEFGHJKLMNPQRSTUVWXX'.charAt (Math.floor (Lat/8 + 10));
var ae = Math.floor (aa/100000);
var af = ['ABCDEFGH','JKLMNPQR','STUVWXYZ'][(c-1)%3].charAt (ae-1);
var ag = Math.floor (ab/100000)%20;
var ah = ['ABCDEFGHJKLMNPQRSTUV','FGHJKLMNPQRSTUVABCDE'][(c-1)%2].charAt (ag);
function pad (val) {if (val < 10) {val = '0000' + val} else if (val < 100) {val = '000' + val} else if (val < 1000) {val = '00' + val} else if (val < 10000) {val = '0' + val};return val};
aa = Math.floor (aa%100000); aa = pad (aa);
ab = Math.floor (ab%100000); ab = pad (ab);
return c + ad + ' ' + af + ah + ' ' + aa + ' ' + ab;
};
To convert back from mgrs to lat long use the following function. The input string must have metre (i.e. 5 digit) easing and northing resolution and have spaces as output by the above function.
function LatLongFromMGRSstring (a)
{
var b = a.trim();
b = b.match(/\S+/g);
if (b == null || b.length != 4) return [false,null,null];
var c = (b[0].length < 3) ? b[0][0] : b[0].slice(0,2);
var d = (b[0].length < 3) ? b[0][1] : b[0][2];
var e = (c*6-183)*Math.PI / 180;
var f = ["ABCDEFGH","JKLMNPQR","STUVWXYZ"][(c-1) % 3].indexOf(b[1][0]) + 1;
var g = "CDEFGHJKLMNPQRSTUVWXX".indexOf(d);
var h = ["ABCDEFGHJKLMNPQRSTUV","FGHJKLMNPQRSTUVABCDE"][(c-1) % 2].indexOf(b[1][1]);
var i = [1.1,2.0,2.8,3.7,4.6,5.5,6.4,7.3,8.2,9.1,0,0.8,1.7,2.6,3.5,4.4,5.3,6.2,7.0,7.9];
var j = [0,2,2,2,4,4,6,6,8,8,0,0,0,2,2,4,4,6,6,6];
var k = i[g];
var l = Number(j[g]) + h / 10;
if (l < k) l += 2;
var m = f*100000.0 + Number(b[2]);
var n = l*1000000 + Number(b[3]);
m -= 500000.0;
if (d < 'N') n -= 10000000.0;
m /= 0.9996; n /= 0.9996;
var o = n / 6367449.14570093;
var p = o + (0.0025188266133249035*Math.sin(2.0*o)) + (0.0000037009491206268*Math.sin(4.0*o)) + (0.0000000074477705265*Math.sin(6.0*o)) + (0.0000000000170359940*Math.sin(8.0*o));
var q = Math.tan(p);
var r = q*q;
var s = r*r;
var t = Math.cos(p);
var u = 0.006739496819936062*Math.pow(t,2);
var v = 40680631590769 / (6356752.314*Math.sqrt(1 + u));
var w = v;
var x = 1.0 / (w*t); w *= v;
var y = q / (2.0*w); w *= v;
var z = 1.0 / (6.0*w*t); w *= v;
var aa = q / (24.0*w); w *= v;
var ab = 1.0 / (120.0*w*t); w *= v;
var ac = q / (720.0*w); w *= v;
var ad = 1.0 / (5040.0*w*t); w *= v;
var ae = q / (40320.0*w);
var af = -1.0-u;
var ag = -1.0-2*r-u;
var ah = 5.0 + 3.0*r + 6.0*u-6.0*r*u-3.0*(u*u)-9.0*r*(u*u);
var ai = 5.0 + 28.0*r + 24.0*s + 6.0*u + 8.0*r*u;
var aj = -61.0-90.0*r-45.0*s-107.0*u + 162.0*r*u;
var ak = -61.0-662.0*r-1320.0*s-720.0*(s*r);
var al = 1385.0 + 3633.0*r + 4095.0*s + 1575*(s*r);
var lat = p + y*af*(m*m) + aa*ah*Math.pow(m,4) + ac*aj*Math.pow(m,6) + ae*al*Math.pow(m,8);
var lng = e + x*m + z*ag*Math.pow(m,3) + ab*ai*Math.pow(m,5) + ad*ak*Math.pow(m,7);
lat = lat*180 / Math.PI;
lng = lng*180 / Math.PI;
return [true,lat,lng];
}

Paradoxical Javascript Variable Defining

I am trying to calculate a maths question. It requires the use of variables within variables that loop around.
Here is my JavaScript Code:
var a = m+1;
var b = n+1;
var c = o+1;
var d = p+1;
var e = q+1;
var f = r+1;
var g = s+1;
var h = t+1;
var i = u+1;
var j = v+1;
var l = w+1;
var m = (1+b)/2;
var n = (a+c)/2;
var o = (b+d)/2;
var p = (c+e)/2;
var q = (d+f)/2;
var r = (e+g)/2;
var s = (f+h)/2;
var t = (g+i)/2;
var u = (h+j)/2;
var v = (i+l)/2;
var w = (j+12)/2;
function CalculateA() {
alert(a);
}
The HTML is just a button calling CalculateA() Function.
This results with undefined. Is there a way to properly calculate this or is it not possible with javascript or coding.
Edit
I relize now that this isn't working very well.
Also I ran it through excel with looping calculations and found the answer.
Thanks for all your help anyway.
https://drive.google.com/open?id=0B9I2lCue4HpLZEh3X0NGTUE4YXM
The Excel Calculation ^
You could give all variables a start value of zero to prevent NaN and then call the operations again until a is converging to 12.916666666666651.
function calc() {
a = m + 1;
b = n + 1;
c = o + 1;
d = p + 1;
e = q + 1;
f = r + 1;
g = s + 1;
h = t + 1;
i = u + 1;
j = v + 1;
l = w + 1;
m = (1 + b) / 2;
n = (a + c) / 2;
o = (b + d) / 2;
p = (c + e) / 2;
q = (d + f) / 2;
r = (e + g) / 2;
s = (f + h) / 2;
t = (g + i) / 2;
u = (h + j) / 2;
v = (i + l) / 2;
w = (j + 12) / 2;
console.log(a);
}
var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0,
ii, letter;
for (ii = 0; ii < 1000; ii++) {
calc();
}
for (ii = 1; ii <= 23; ii++) {
letter = (ii + 9).toString(36);
letter === 'k' || console.log(letter, window[letter]); // k is missing ...
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nothing is impossible in coding. it is returning undefined because 'a' is declared on top where m is not defined and it is "NaN" error -- Not a Number.
The variables end up depending onto each other, which means that your result will always be NaN.
Javascript tries to give you an exact result for the formula, which it can't. What you need for this math issue, is to replace the variables in each term with each other, to get to a result with only 1 variable - I don't think there's a way for you to do that in Javascript with less effort than doing it manually.

How to add two big numbers in javascript?

I have two text boxes. Each will take input up to thousand digits.
Now i want to add these two numbers. My question is what data type should i use to store the result?
I have tried this:
<script>
var x = 'Thousand digit of number'
var y = 'Thousand digit of number'
var z = x + y
</script>
but i am getting result in exponential form. How to store the result and display it?
Yet another solution, because it's faster and cleaner.
function add(A, B) {
const AL = A.length
const BL = B.length
const ML = Math.max(AL, BL)
let carry = 0, sum = ''
for (let i = 1; i <= ML; i++) {
let a = +A.charAt(AL - i)
let b = +B.charAt(BL - i)
let t = carry + a + b
carry = t/10 |0
t %= 10
sum = (i === ML && carry)
? carry*10 + t + sum
: t + sum
}
return sum
}
> add(
'9999999999999999999999999999999999999999999999999999999999999999999999999999',
'999999999999999999999999999999999999999'
)
> "10000000000000000000000000000000000000999999999999999999999999999999999999998"
Use BigInt as described here: https://stackoverflow.com/a/56370672/641913
const z = BigInt(x) + BigInt(y);
console.log(z.toString());
Here is another solution not so different from others you can find in the internet (consider that it doesn't work with negative numbers!):
function sums(arg1, arg2) {
var sum = "";
var r = 0;
var a1, a2, i;
// Pick the shortest string as first parameter and the longest as second parameter in my algorithm
if (arg1.length < arg2.length) {
a1 = arg1;
a2 = arg2;
}
else {
a1 = arg2;
a2 = arg1;
}
a1 = a1.split("").reverse();
a2 = a2.split("").reverse();
// Sum a1 and a2 digits
for (i = 0; i < a2.length; i++) {
var t = ((i < a1.length) ? parseInt(a1[i]) : 0) + parseInt(a2[i]) + r;
sum += t % 10;
r = t < 10 ? 0 : Math.floor(t / 10);
}
// Append the last remain
if (r > 0)
sum += r;
sum = sum.split("").reverse();
// Trim the leading "0"
while (sum[0] == "0")
sum.shift();
return sum.length > 0 ? sum.join("") : "0";
}
// Test
function testEquals(expected, actual) {
if (expected == actual)
console.log("OK: " + expected);
else
console.error("ERROR: " + expected + " != " + actual);
}
testEquals("100", sums("99", "1"));
testEquals("100", sums("00099", "0001"));
testEquals("10000000000", sums("9999999999", "1"));
testEquals("10000010101", sums("9999999999", "10102"));
testEquals("0", sums("0", "0"));
testEquals("1", sums("0", "1"));
testEquals("9", sums("8", "1"));
testEquals("9", sums("1", "8"));
testEquals("10000000000000000000000000000000000000000", sums("9999999999999999999999999999999999999999", "1"));
Input the numbers as string and add each characters each other as array something like this:
function add() {
document.getElementById("demo").innerHTML = "";
var x = document.getElementById("txt1").value;
var y = document.getElementById("txt2").value;
var len;
var lenx = x.length;
var leny = y.length;
var x1,y1,rem,div=0;
if(lenx>leny) len = lenx; else len = leny;
for(var i=0;i<len;i++){
if(i>=lenx) x1 = 0;
else x1 = parseInt(x[lenx-i-1]);
if(i>=leny) y1 = 0;
else y1 = parseInt(y[leny-i-1]);
rem = (x1+y1+div)%10;
div = Math.floor((x1 + y1+div)/10);
document.getElementById("demo").innerHTML = rem + document.getElementById("demo").innerHTML;
}
if(div>0){
document.getElementById("demo").innerHTML = div + document.getElementById("demo").innerHTML;
}
}
Here the code: https://jsfiddle.net/mtsL1k2x/5/
Note: this is only for natural numbers. You can modify depending on your inputs
Either use a big number library like https://mathjs.org/docs/datatypes/bignumbers.html , or you can use something lighter weight (but easy to understand) like http://www.discoversdk.com/knowledge-base/arbitrary-length-integer-addition-in-javascript
Well, if you want to do this without using BigInt or any third-party Library, then I don't think you need to convert to an array, you can use the charAt() function to add the individual characters at each point in the string. You would have to use the for loop starting from its maximum value and reducing till its lowest. The code snippet is below;
function add(a, b) {
let sum='';
let z,x;
let r=0;
if (a.length>=b.length){
z=a;
x=b;
}
else{
z=b;
x=a;
};
let p=x.length;
for (let i=z.length;i>0;i--){
let t=((p>0)?parseInt(x.charAt(p-1)):0)+parseInt(z.charAt(i-1))+r;
sum=(t%10)+sum;
r=t<10?0:Math.floor(t/10);
p=p-1;
};
if (r>0){sum=r+sum};
return sum;
};
function add(a, b) {
a = a.split("").reverse();
b = b.split("").reverse();
let maxLen=Math.max(a.length, b.length);
let sum = [];
let remainder = 0;
for (let i = 0; i < maxLen; i++) {
let x = parseInt(a[i]) ? parseInt(a[i]) : 0;
let y = parseInt(b[i]) ? parseInt(b[i]) : 0;
let digit = (x + y + remainder) % 10;
remainder = Math.floor((x + y + remainder) / 10);
sum.unshift(digit);
}
if (remainder) {sum.unshift(remainder)}
return sum.join("");
}
function add(x, y) {
//this function adds two extremely large numbers, negative and/or positive
var temp, borrow=false, bothNeg=false, oneNeg=false, neg=false;
if (x < 0 && y < 0) { bothNeg = true; x = -x; y = -y; }
else if (x < 0 || y < 0) {
oneNeg = true;
if (Math.abs(x) == Math.abs(y)) { x = 0; y = 0; }
else if (x < 0 && Math.abs(x) > Math.abs(y)) { neg = true; x = -x; y = -y; }
else if (x < 0 && Math.abs(x) < Math.abs(y)) { temp = y; y = x; x = temp; }
else if (y < 0 && Math.abs(x) < Math.abs(y)) { neg = true; temp = y; y = -x; x = -temp; }
}
x = parseInt(x*1000000000/10).toString();
y = parseInt(y*1000000000/10).toString();
var lenx=x.length, leny=y.length, len=(lenx>leny)?lenx:leny, sum="", div=0, x1, y1, rem;
for (var i = 0; i < len; i++) {
x1 = (i >= lenx) ? 0 : parseInt(x[lenx-i-1]);
y1 = (i >= leny) ? 0 : parseInt(y[leny-i-1]);
y1 = (isNaN(y1)) ? 0 : y1;
if (oneNeg) y1 = -y1;
if (borrow) x1 = x1 - 1;
if (y < 0 && x1 > 0 && Math.abs(x1) >= Math.abs(y1)) { borrow=false; div=0; }
if (y < 0 && y1 <= 0 && (x1 < 0 || Math.abs(x1) < Math.abs(y1))) { borrow=true; rem=(x1+y1+div+10)%10; div=10; }
else { rem=(x1+y1+div)%10; div=Math.floor((x1+y1+div)/10); }
sum = Math.abs(rem).toString() + sum;
}
if (div > 0) sum = div.toString() + sum;
sum = parseFloat(sum*10/1000000000);
if (bothNeg || neg) sum = -sum;
return sum;
}
<body>
<p>Click the button to calculate x.</p>
<button onclick="myFunction()">Try it</button>
<br/>
<br/>Enter first number:
<input type="text" id="txt1" name="text1">Enter second number:
<input type="text" id="txt2" name="text2">
<p id="demo"></p>
<script>
function myFunction() {
var y = document.getElementById("txt1").value;
var z = document.getElementById("txt2").value;
var x = +y + +z;
document.getElementById("demo").innerHTML = x;
}
</script>
https://jsfiddle.net/Sanjeevgaut/mtsL1k2x/

Uncaught TypeError: Cannot set property '1' of undefined

Now this is wierd, I basically calling the function "sortTiles()" twice, the first time, it loops through, and returns a beautiful array, just as it's supposed to do. But the second time I call it, it doesn't work, and throws the error as stated in the title to a specific line: tiles[y][x] = tile;.
The first time around, the returned array from "sortTiles()" is put into a global array called "solution". The second time the function is called, it will get the tiles X and Y coordinate from the solution array.
What I'm doing here is it basically scans a sliding puzzle, with the help of a html5 canvas and prnt_scrn+paste into the website. And as said, first time you do it, you take a screenshot of the solution, paste it in, and it marks out all the coordinates just fine. The second time, it throws an error :(
function getTile(x, y) {
var id = 0;
for (i = 0; i < 2; i++) {
for (i2 = 0; i2 < 2; i2++) {
var data = context.getImageData(x + i * 48 + 5 - (i * 10), y + i2 * 48 + 5 - (i2 * 10), 1, 1).data;
id += data[0] + data[1] + data[2];
}
}
return id;
}
function findTile(number) {
for (y = 0; y < 5; y++) {
for (x = 0; x < 5; x++) {
if (solution[y][x] == number) {
return [x, y];
}
}
}
}
function sortTiles() {
context.font = "20px Georgia";
var tiles = [];
tiles.length = 0;
for (y = 0; y < 5; y++) {
tiles[y] = [];
for (x = 0; x < 5; x++) {
var tile = getTile(108 + x * 56, 34 + y * 56);
tiles[y][x] = tile;
if (solution.length != 0) {
var coordinate = findTile(tile);
context.fillText(coordinate[0] + ", " + coordinate[1], 108 + x * 56 + 12, 34 + y * 56 + 36);
} else {
context.fillText(x + ", " + y, 108 + x * 56 + 12, 34 + y * 56 + 36);
}
}
}
return tiles;
}
Your x and y variables are global and are conflicting between sortTiles and findTile. Make them local using var.
function getTile(x, y) {
var id = 0;
for (var i = 0; i < 2; i++) {
for (i2 = 0; i2 < 2; i2++) {
var data = context.getImageData(x + i * 48 + 5 - (i * 10), y + i2 * 48 + 5 - (i2 * 10), 1, 1).data;
id += data[0] + data[1] + data[2];
}
}
return id;
}
function findTile(number) {
for (var y = 0; y < 5; y++) {
for (var x = 0; x < 5; x++) {
if (solution[y][x] == number) {
return [x, y];
}
}
}
}
function sortTiles() {
context.font = "20px Georgia";
var tiles = [];
tiles.length = 0;
for (var y = 0; y < 5; y++) {
tiles[y] = [];
for (var x = 0; x < 5; x++) {
var tile = getTile(108 + x * 56, 34 + y * 56);
tiles[y][x] = tile;
if (solution.length != 0) {
var coordinate = findTile(tile);
context.fillText(coordinate[0] + ", " + coordinate[1], 108 + x * 56 + 12, 34 + y * 56 + 36);
} else {
context.fillText(x + ", " + y, 108 + x * 56 + 12, 34 + y * 56 + 36);
}
}
}
return tiles;
}

Categories