I am writing a JavaScript program that is supposed to generate a number (2 90% of the time, 4 for the other 10%). This works fine, however the number is then supposed to randomly replace one of the spots in the array that had previously had a value of zero. As far as I can tell, my code that should work but it does not and I get this error message:
Cannot read property '0' of undefined
I've included my code below but it may look weird because I am using Khan Academy's JavaScript teaching tool which might not be the same as normal JavaScript (I am not sure about this since I am new to the language).
var M=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
var NewTile=function(M){
var open=0; // checks all tiles to see whitch ones are 0's
var available=[]; // while recorfing the number of zeros and
for (var p=0; p<=3; p+=1){ // thier positions
for (var q=0; q<=3; q+=1){
var i=M[p][q];
if (i===0){
open=open+1;
available.push([p,q]);
}
}
}
var TwoOrFour=random(1,10);
var NewValue;
if (TwoOrFour===10){ // generates the new value
NewValue=4;
}else{
NewValue=2;
}
var NewPos;
if (open===0){ // decides whether the game is lost
var over=true;
return over;
}else{ // replaces the correct spot in the array
var GetPos=random(0,open);
var NewPos=available[GetPos];
M[NewPos[0]][NewPos[1]]=NewValue; // THIS IS WHERE THE ERROR SEEMS TO CAUSE AN ISSUE
}
return M;
};
var M=NewTile(M);
println(M[0]);
println(M[1]);
println(M[2]);
println(M[3]);
Can anyone tell me what I am doing wrong and why I am getting this error?
Related
I am wondering how should I implement KCL using JavaScript. I have several current meter that to detect the value of current along a line.
I came out with a simple program but was unable to think about how to implement KCL efficiently.
var currentPointsDBA = new Array(); // Data from electricity meter will be captured and store in this array
var totalCurrentMDB = new Array(); // Total current from adding will be stored in array. Each index represents 1 distribution board.
const totalBusBar = 5;
for (z=0; z<currentPointsDBA.length(); z++){
totalCurrent += currentPoints[z];
}
totalCurrentMDB[0] = totalCurrent;
var currentCheck = [
{
name: DBA, number: 0, threshold: 0
}];
for(i=0; i<totalBusBar; i++){
var totalCurrentCheck = currentCheck[i];
if(totalCurrentMDB[totalCurrentCheck.number] != 0){
//DO SOMETHING
}
}
I realized with this, the condition will never be met as I am adding the current without using the concept of current entering the node is equals to current exiting a node.
Another difficulty that I was facing was to have an algorithm that can be used to calculate positively and negatively for KCL.
Inputs would be a power line that will be connected to a transducer(meter to measure current). Output is also current that is connected to a meter.
For the Point 1,2,3,4,5 it will be replaced with the meters. Basically, I would want an algorithm to have Sum of DBA = Point 1+2+3+4+5. However, point 1 is bi-directional. It can act as input or output. The issue will be to figure out how the current direction is and use that to determine as input or output.
I am a "new" developer into the foray of Web Development and I have come across an issue I was hoping that you fine people on Stack Overflow would be able to help me with. I have asked several Cadre and Instructors in my class and we are all stumped by it.
To start with I have decided to put all of my code on a Gitlab repo so if you want to look at the whole thing (or if you want to add to it let me know): Link to Github Repo. I fiqured you guys don't want the whole thing posted as a wall of text and rather some snip-its of what in the file I specifically. But it is relitively small file
I am useing simple JavaScript as well as Node.Js to be able to build a working calculator in the back end that I can use as a template for any other project I will need to work on in the future. For now I am trying to just get it working by imputing things via the console.
I have made a way for what is imputed in Node and to an imputArray var I have set up and the Array goes something like this:
[(command), (num1), (num2), (num3), ...]
I set up a switch function that runs a block of code based on what command was given (add, subtract, divide, etc..). As well as separating the command from the number and putting them inside another array.
The part I need some help with is with getting the block of code to work for what I want it to do. I have got it set up to run rather easily on two numbers but I want it to handle as many numbers as I want to throw at it. I tried various forms of for loops as well as forEach loops and I cant seem to get it working.
case 'divide':
for (i = 1; i < numArray.length; i++) { // If any number besides the first is 0 spit out this
if (numArray[i] === 0) {
consol.log("You canot divide by zero!");
}
else {
var previousTotal = numArray[0]; //Inital number in array
for (i = 1; i < numArray.length; i++) {
previousTotal = previousTotal / numArray[i]; // for each number in array divide to the previous number
}
}
result = previousTotal // Pushes end total to result
}
break;
I have gone through several different versions of the above code (such as using for loops instead) but this is pretty much what I ended up with. I'm sure there is an easier way and more sane way to do what I am trying to do, but if I knew how I wouldn't be here.
Essentially this is the ideal thing I want to do but I cant find a way to do it: I want to run a small block of code the index of the number array, minus one. In this case it is dividing the previous number by the next number in the array.
So it only runs if there are more then one in the array and it does the function to the previous number, or total from the last one in the array.
This is pretty much the only thing holding me back from finishing this so if someone can take the time to look at my crapy code and help it do what I want it to do that would be awesome.
Your code is reseting result each time the outer loop iterates so it will just equal what ever the last prev Total is. Basically every loop but the last is irrelevant. Do you want to add them to result? If so you want:
result += previousTotal
Or if you want an array of the answers you want:
result.push(reviousTotal)
Sorry not 100% what you want. Hope this helps!
You just need one loop, and you probably want to stop iterating if a 0 occurs:
result = numArray[0]; //no need for another variable
for (var i = 1; i < numArray.length; i++) { // declare variables!
if (numArray[i] === 0) {
console.log("You canot divide by zero!"); // typo...
break; // exit early
}
result = result / numArray[i];
}
For sure that can be also written a bit more elegantly:
const result = numArray.reduce((a, b) => a / b);
if(isNaN(result)) {
console.log("Can't divide by zero!");
} else {
console.log(`Result is ${result}`);
}
I assume you want the divide command to do ((num1/num2)/num3)/...
There are couple of issues in the code you posted, I will post a version that does the above. You can inspect and compare it your version to find your mistakes.
// divide, 10, 2, 5
case 'divide':
if (numArray.length < 2) {
console.log("no numbers in array")
break;
}
// previousTotal starts with 10
var previousTotal = numArray[1];
// start from the second number which is 2
for (i = 2; i < numArray.length; i++) {
if (numArray[i] === 0) {
console.log("You canot divide by zero!");
}
else {
previousTotal = previousTotal / numArray[i]; // for each number in array divide to the previous number
}
}
result = previousTotal;
// result will be (10/2)/5 = 1
break;
Our JavaScript application fails in very strange ways when running on iOS 10 beta 2 and beta 3 (running on iPhone 6). When looking at logs I can see that arrays contain NaN's and 0x00's in unexpected places. I managed to produce a test program that can quite reliably reproduce the behavior.
I have filled a bug report with Apple but haven't heard back so I am a bit concerned whether this will be fixed or not. So as a first thing, I would like to hear if someone can reproduce it and at least confirm there is a bug (and not just a misunderstanding on my part etc.). I'm fairly sure of this myself, but always good to be on the safe side! Could also be others have encountered it and found a workaround or maybe if some WebKit developers run into it, they might be able to help.
Test program showing bug
Here's the test progarm. The problem doesn't occur every time but the JavaScript code in the page can detect when it occurred and will keep refreshing the page until it occurs. On a non-affected browser, this means the page will keep refreshing. On an affected browser (such as Safari on iOS 10 beta 2 and beta 3 running on an iPhone 6) the refreshing will stop after some iterations (typically 5-10) and the display error.
The program operates by creating an uint8array of size 8192 (it seems smaller array sizes causes the error to be more rare). It will fill this array with dummy values, then call "toStr" which first allocates a new plain Array, then copies the contents of the uint8array to the plain array, narrowing each element along the way. While doing this it builds up a string containing the original value and the copied value. When the error occurs, the element in the target array turns out to be NaN which should not be able to occur since it by construction contains only integers. The doTest() function tests for whether such a NaN value is contained in the resulting string which shows that the error has occurred.
Note that within each refresh, the program runs 20 iterations and here it is also random which iteration that fails. However, I have observed that if the error doesn't occur among the first 20 of iterations, it is not likely to occur at all within this page load even if one ran an indefinite number of iterations, and this is the reason why I added the reload page logic.
Note that the program logic itself is completely deterministic so every run should be the same, which is also the case on other browsers. More detail can be seen by removing the comments from the log() statement in the doTest() function so it prints out the array.
Note that the problem seems to go away if the function "narrow" is inlined rather than being a separate function (even though these two programs should of course be semantically equivalent). Also, if one omits the shift from "state >> 8" the error also seemingly goes away so either the exact array values are significant or this rewrite somehow affects how the JIT operates. Hence, it is critical the exact program structure is used when testing for the problem.
<html>
<head>
<title>Array test page</title>
<script>
log = function(s) {
var ta = document.getElementById("ta");
ta.value += s + "\n";
}
function narrow(x_0) {
return x_0 << 24 >> 24;
}
function toStr(i8bytes) {
var bytes, i, str;
bytes = new Array(i8bytes.length);
str = '';
for (i = 0; i < 16; i++) {
bytes[i] = narrow(i8bytes[i]);
str += '*** (' + i8bytes[i] + ' - ' + bytes[i] + ')';
}
return str;
}
function doTest() {
var sz = 8192;
state = 0;
var i;
var fnd = false;
for (i = 0; i < 20; i++) {
var arr = new ArrayBuffer(sz);
var i8bytes = new Uint8Array(arr, 0, sz);
for (j = 0; j < i8bytes.length; j++) {
state = state + 1;
var v = state >> 8;
i8bytes[j] = narrow(v);
}
var str = toStr(i8bytes);
// log(str); <-- REMOVE COMMENT to show results
if (str.indexOf("NaN") !== -1) {
log("Found NaN at iteration" + i);
log(str);
fnd = true;
break;
}
}
return fnd;
}
function start() {
log("Starting: " + new Date());
if (!doTest()) {
location.reload(true); // <--- REMOVE THIS LINE TO PREVENT RELOAD
}
};
</script>
</head>
<body onload="start()">
<h1>Array test page</h1>
<p>Note that on a non-affected browser this page will reload indefinitely. On an affected browser, it
will stop reloading once the problem is detected.
<p>
<textarea id="ta" rows="10" cols="40"></textarea>
</body>
</html>
As far as I understand topojson.presimplify(JSON) in D3 adds Z coordinate to each point in the input topojson shape based on its significance, which then allows to use it for the dynamic simplification like in http://bl.ocks.org/mbostock/6245977
This method topojson.presimplify() takes quite a long time to execute on complicated maps, especially in Firefox which makes the browser unresponsive for few seconds.
Can it be baked directly into the topojson file via the command line as it is done with projections:
topojson --projection 'd3.geo.mercator().translate([0,0]).scale(1)' -o cartesian.topo.json spherical.topo.json
I found a workaround for this which is not completely as simple as I wanted but still achieves the same result.
After the topojson.presimplify(data) is called, data already holds the pre simplified geometry with added Z axis values.
Then I convert it to the JSON string and manually copy it to a new file with JSON.stringify(data)
Nevertheless these conversion to a JSON string has a problem with Infinity values which often occur for Z and with JSON.stringify method are converted to null. Also when there is a value for Z coordinate it is usually too precise and writing all decimal points takes too much space.
For that reason before converting data to a JSON string I trim the numbers:
// Simplifying the map
topojson.presimplify(data);
// Changing Infinity values to 0, limiting decimal points
var arcs = data.arcs;
for(var i1 = arcs.length; i1--;) {
var arc = arcs[i1];
for(var i2 = arc.length; i2--;) {
var v = arc[i2][2];
if(v === Infinity) arc[i2][2] = 0;
else {
arc[i2][2] = M.round(v * 1e9)/1e9;
}
}
}
This makes Infinity values to appear as exactly 0 and other values are trimmed to 9 decimal points which is enough for dynamic simplification to work properly.
Since such string is too long to easily print it for copying to the new json file it is much easier to store it in the localStorage of the browser:
localStorage.setItem(<object name>, JSON.stringify(data))
Then in Safari or Chrome open the developer console and in the tab Resources -> Local Storage -> <Website URL> the stored object can be found, copied and then pasted into a text editor.
Usually it is pasted as a <key> <value> pair, so one needs to remove from the beginning of the pasted string so that it starts from {.
Since Infinity values have been converted to 0, in the dynamic simplification function it should be taken into account so that points with Z = 0 are treated as Z = Infinity and are always plotted with any simplification area:
point: function(x, y, z) {
if (z===0 || z >= simplificationArea) {
this.stream.point(x, y);
}
}
I have a javascript that calculates the percentage from two fields (retail and network) and then dumps that percentage into another field (markup).
As I am relatively new to the world of JS I have ended up reusing the code for several rows of fields. This goes against DRY and KISS principles so I was wondering if you could give me some input on how to optimise my code so that it can handle any two fields and then dump a value to a third field.
Here is a screenshot of my form segment that is using it.
http://i.imgur.com/FHvDs.png
Here is my code I am using, I have had to reuse it four times and place the code in four functions e.g. (percentage1, percentage2, percentage3, percentage4) each one of these functions deals with a row of fields show in the screenshot.
function percentage1()
{
//the dividee
x = document.getElementById('tariff_data');
//the divider
y = document.getElementById('network_data');
//if the first value is lower than the second, append a "-" sign
if (x.value < y.value)
{
z = "-"+(x.value/y.value)*100;
document.getElementById('markup_data').value = z;
}
//not a negative percentage
else
{
z = (x.value/y.value)*100;
document.getElementById('markup_data').value = z;
}
}
function percentage2()
{
//the dividee
x = document.getElementById('tariff_rental');
//the divider
y = document.getElementById('network_rental');
//if the first value is lower than the second, append a "-" sign
if (x.value < y.value)
{
z = "-"+(x.value/y.value)*100;
document.getElementById('markup_rental').value = z;
}
//not a negative percentage
else
{
z = (x.value/y.value)*100;
document.getElementById('markup_data').value = z;
}
}
etc etc....
These functions are called using the onchange HTML attribute
Also when I divide by a decimal number it gives the wrong value, any Ideas how to make it calculate the correct percentage of a decimal number?
My code also gives out these strange outputs:
NaN , Infinity
Thanks
Rather than optimization, let's focus on correctness first =)
Note that the HTMLInputElement.value property has type "string", so your arithmetic operators are doing implicit type conversion which means you are likely often doing string concatenation instead of the numeric operations you expect.
I strongly recommend explicitly converting them to numbers first and checking for invalid input, also, don't forget to declare your variables first using var so they don't potentially clobber globals, e.g.:
var x = Number(document.getElementById('tariff_data'));
var y = Number(document.getElementById('network_data'));
if (!isFinite(x) || !isFinite(y)) {
// Handle non-numerical input...
}
You can also use the parseFloat function if you prefer, e.g.:
var x = parseFloat(document.getElementById('tariff_data'), 10);
I highly recommend doing some formal learning about the JavaScript language; it is full of pitfalls but if you stick to the "good parts" you can save yourself a lot of hassle and headache.
With regard to DRYing your code out; remember that you can:
Pass parameters to your functions and use those arguments within the function
Return values using the return keyword
In your case, you've got all your multiplication code repeated. While trying to fix the string vs. number problems maerics has already mentioned, you could do something like this:
// We're assuming 'dividee' and 'divider' are numbers.
function calculatePercentage(dividee, divider) {
var result;
// Regardless of the positive/negative result of the calculation,
// get the positive result using Math.abs().
result = Math.abs((dividee.value / divider.value) * 100);
// If the result was going to be negative...
if (dividee.value < divider.value) {
// Convert our result to negative.
result = result * -1;
}
// Return our result.
return result;
}
Then, in your percentage functions, you can just call this code like so:
function percentage1() {
var tariff, network, markup;
tariff = parseFloat(document.getElementById('tariff_data').value, 10);
network = parseFloat(document.getElementById('network_data').value, 10);
markup = document.getElementById('markup_data');
markup.value = calculatePercentage(tariff, network);
}
Obviously, you could take this further, and create a function which takes in the IDs, extracts the values from the elements etc., but you should try and build that yourself based on these tips.
Maerics also makes a very good point which you should take note of; learn more about the Good Parts of JavaScript. Douglas Crockford's book is excellent, and should be read and understood by all JS developers, IMHO.
Hope this helps you clean your code up!