Having trouble counting iterations of different outputs in my javascript code - javascript

Trying to set up code to take inputted numbers, determine whether they are negative or positive, displaying this, and then when 0 is put in the code displays the amount of positive numbers put in and the amount of negative numbers put in and then terminates. Having trouble with the counting part and I am not sure how to set this up better. I am also not sure how to set this up to terminate after 0 is put in.
function mapping() {
var num = parseInt(document.getElementById("num1").value);
var countp = 0;
var countn = 0;
if (num !== 0) {
if (num > 0) {
document.getElementById("output").innerHTML = "positive";
countp += 1;
} else {
document.getElementById("output").innerHTML = "negative";
countn += 1;
}
} else {
document.getElementById("output").innerHTML = "countp: " + countp;
document.getElementById("output").innerHTML = "countn: " + countn;
}
}
Thank you.

Two problems with the code.
1st: You need to move countp and countn outside of the function to make them global.
2nd: You are writing the positive number counts to output's html and then you are overriding it by negative count.
This should do the trick;
var countp = 0;
var countn = 0;
function mapping() {
var num = parseInt(document.getElementById("num1").value);
if (num !== 0) {
if (num > 0) {
document.getElementById("output").innerHTML = "positive";
countp += 1;
} else {
document.getElementById("output").innerHTML = "negative";
countn += 1;
}
} else {
var html = "countp: " + countp + ", countn: " + countn;
document.getElementById("output").innerHTML = html;
// this line added
countp = 0, countn = 0;
}
}
<input type="text" id="num1">
<button onclick="mapping()">Test</button>
<div id="output">
</div>

The main issue with the code is that countp and countn are local variables. Thus they are created and initialized to 0 every time the function is called. Move the two lines outside the function to fix this bug!
Another bug is the code in the last else part. There you set innerHTML twice, so the div ends up with only countn. To fix this bug, replace the last innerHTML = by innerHTML +=.
Finally, if I understand you correctly, you want that no more updates occur once 0 has been entered. To achieve this, you could add another variable like isFinal that is set to true when the user enters 0, and add a check to your function.
Some more suggestions:
Instead of if (num!==0), it is considered good practice to start with positive conditions such as if (num === 0). That way, you will also avoid some nesting in the conditions.
What happens if the user does not enter a valid number? In your code, this will be treated as negative number. Add a test for "NaN" to fix this.
You repeat the document.getElementById... many times. Use a temporary variable to fix this.
In modern JavaScript, it is recommended to use let or const instead of var.
Be consistent in your use of semicolons at the end of lines.
Thus the code ends up as:
let countp = 0;
let countn = 0;
let isFinal = false;
function mapping() {
if (isFinal) {
return;
}
const num = parseInt(document.getElementById("num1").value);
let html = "";
if (Number.isNaN(num)) {
html = "invalid";
} else if (num === 0) {
html = "countp: " + countp + "<br>";
html += "countn: " + countn;
isFinal = true;
} else if (num > 0) {
html = "positive";
countp += 1;
} else {
html = "negative";
countn += 1;
}
document.getElementById("output").innerHTML = html;
}

Related

In Javascript can you use a set of document.write's and store them as one variable?

Just a quick question which is basically to do with document.write.
Again new to this so apologies in advance if it is a daft question.
Are you able to convert document.write into a variable if all the document.write's was nested in a for loop?
For example existing code is:
for (loop = number; loop >0; loop--)
{
factorial = factorial*loop ;
if (loop!=1)
{
document.write (loop +"x");
}
else
{ //otherwise put in the loop = string
document.write (loop+"=");
}
}
document.write (factorial +"<br>");
So you would then have document.write the full answer as '4x3x2x1=24' which works when the program ends and displays.
Could you store that whole set of document.write's as a variable to display in javascript as an alert.
So it would look something like:
var fullFactorial = all document.write
alert (fullFactorial);
I'm just not sure if its do-able and any help would be ace.
document.write expects a string as an argument, so you can build up the string in your loop and then do a single call to document.write; see *** comments:
const number = 10;
let factorial = 1;
let str = ""; // *** The string we'll build; starts empty
for (let loop = number; loop > 0; loop--) {
factorial = factorial * loop;
if (loop != 1) {
str += loop + "x"; // *** Add to the string
} else {
//otherwise put in the loop = string
str += loop + " = "; // *** Add to the string
}
}
str += factorial; // *** Add to the string
document.write(str + "<br>"); // Output the string and a <br>
That said, I strongly urge you not to use document.write. Use the DOM instead. For instance:
const number = 10;
let factorial = 1;
let steps = "";
for (let loop = number; loop > 0; loop--) {
factorial = factorial * loop;
if (loop != 1) {
steps += loop + "x";
} else {
steps += loop;
}
}
document.getElementById("steps").textContent = steps;
document.getElementById("result").textContent = factorial;
<span id="steps"></span> = <span id="result"></span>
First, document.write is very much obsolete, please use something else.
But to answer your question, just build a variable first by concatenating everything you want to concatenate, and then insert it into the DOM. Then you'll still have it in a variable.
Concatenation
var output = '';
output += ' ...'
output += ' ...'
document.write(output);

Luhn Check Javascript

I am attempting to have someone input there credit card number and validate if it is a valid number by doing the Luhn Check. I want to be able to check it if they input the whole card number as one big string or if they put spaces in it. In my function validate though I keep getting an error message that there is an illegal return statement for my total variable. Here is my current code.
<script type="text/javascript">
function validate(numbers) {
var sum;
var sum1;
var total;
for (i = 0; i < numbers.length; i++) {
if (numbers.length % 2 == 0) {
sum += numbers[i];
}
else
if ((numbers[i] * 2) >= 10) {
sum1 += numbers[i] - 9;
}
else
sum1 += numbers[i];
}
total = sum + sum1;
return total;
}
function cardnumber() {
var cardnumber = document.getElementById("input").value;
var numbers = cardnumber.split(" ");
var out = "";
for (i = 0; i < numbers.length; i++) {
out += validate(numbers[i]);
if (out % 10 == 0)
return true;
}
}
function getOutput() {
if (cardnumber()) {
alert("You card is valid.");
}
}
</script>
<body>
<h1>I will validate a credit card number</h1>
Card Type:
<input type="radio" id="c1" value="Visa">Visa</input>
Card number: <textarea id="input" style="vertical-align: middle;"></textarea></br>
<input type="button" value="Submit" onclick="getOutput()" /></br></br>
</body>
Your function validate is missing an opening curly brace after the for loop. This made your return statement outside of your function and since a return statement is invalid outside of a function it was an invalid return statement.
function validate(numbers){
var sum;
var sum1;
var total;
for (i=0; i<numbers.length; i++) { // this previous curly brace `{` was missing
if (numbers.length%2==0){
sum += numbers[i];
}
else
if ((numbers[i]*2)>=10){
sum1 += numbers[i] -9;
}
else
sum1 +=numbers[i];
}
total = sum + sum1;
return total;
}
EDIT WITH MORE CORRECTIONS:
There is quite a bit more wrong with the formatting of you functions you also need to include opening and closing curly braces around your other else statements. I would suggest getting a code editor like VS Code and downloading an extension similar to Bracket pair colorizer 2. It will highlight paired brackets together. This will help you with your formatting.
function validate(numbers){
var sum;
var sum1;
var total;
for (i=0; i<numbers.length; i++) {
if (numbers.length%2==0){
sum += numbers[i];
}
else {
if ((numbers[i] * 2) >= 10) {
sum1 += numbers[i] - 9;
}
else {
sum1 += numbers[i];
}
}
}
total = sum + sum1;
return total;
}
function cardnumber(){
var cardnumber= document.getElementById("input").value;
var numbers = cardnumber.split(" ");
var out ="";
for (i = 0; i < numbers.length; i++) {
out += validate(numbers[i]);
}
if (out %10==0)
return true;
}
function getOutput() {
if (cardnumber()) {
alert("You card is valid.");
}
}
These are all the changed lines (the left is new code and the right side is the old code):
Tips for completion
validate function
So, currently if you console.log your numbers are strings when they pass into the validate function. This is fine when they are sent into validate, but when you add the numbers at index i (i.e. numbers[i]) you should use parseInt(numbers[i], 10) to turn them into numbers, so for example sum += parseInt(numbers[i], 10); the same applies when adding to sum1. The other thing to note is that saying var sum will make sum equal the undefined value. When you add a number or string to an undefined value some unexpected things will probably happen, so since you need your sums and totals to be numbers you should instead initialize your sums and totals at 0. Like so:
var sum = 0;
var sum1 = 0;
var total = 0;
The only other thing wrong with your validate function is that your are checking if numbers.length%2==0 which instead you should be checking if i%2==0. You may have to think about why for a moment, but one thing you may notice is the length of numbers never changes during the iteration of the loop where as i does change at each step.
cardnumber function
Your out variable needs to be initialized to zero. Your cardnumber can instead be split by spaces and then joined by the empty string. This handles if the user accidentally types multiple spaces. Then since you join your split array you no longer would need a for loop.
var numbers = cardnumber.split(" ").join('');
var out =0;
out += validate(numbers);
Lines that need changing somehow
Here's a difference of the lines of the old code that where incorrect and need to be changed somehow. I'm not giving you the completed code, but hopefully this will be sufficient to help you figure out the rest on your own (I feel I shouldn't give you all of the solution due to some degree of academic integrity. I would feel I robbed you the opportunity to learn more if I don't at least let you think through and type it out on your own.). If you are wondering what needs to be changed on a specific line that is highlighted red all of it should be above, so best of luck.

Removing alert from code forces it to enter infinite loop

I have a piece of code that has a few window alert messages. It works fine. However, if I remove the alert statements, the program enters into an infinite loop. This is weird for me.
Can someone help me identify the problem with the code?
function countSwaps(arr) {
let notVisited = {}, swaps = 0;
for (let i = 0; i < arr.length; i++) {
notVisited[i] = true;
}
while (Object.keys(notVisited).length) {
alert("main pass");
let nextPos, currentPos = Object.keys(notVisited)[0];
while (arr[currentPos] !== parseInt(currentPos+1)) {
nextPos = arr[currentPos] - 1;
[arr[currentPos], arr[nextPos]] = [arr[nextPos], arr[currentPos]];
swaps+= 1;
alert("Swap " + arr[currentPos] + " and " + arr[nextPos] + "\n");
delete notVisited[nextPos];
}
delete notVisited[currentPos];
}
return swaps;
}
console.log(countSwaps([2,3,4,1,5]));
Well, it runs an infinite loop for me without the alerts as well.
It seems like the problem is the following expression: parseInt(currentPos+1)
The addition happens before the conversion from a string to a number, so for example:
currentPos = '4';
currentPos + 1 == '41';
parseInt(currentPos + 1) == 41
What you want is probably parseInt(currentPos) + 1. Now:
currentPos = '4';
parseInt(currentPos) + 1 == 5
With this the loop seems to quit and I get the result of 3 swaps out of it.
This is cause of infinite loop.
while (Object.keys(notVisited).length)
It should be something like
while (Object.keys(notVisited).length > 0)
That is a property, it will always return true

How to fix this "if" statement

I don't really know the correct format to this if statement. I want it to count the frequency each word in my txt file was used.
function countWords(array, word, index) {
var count = 0;
var value = " "
for (var i = 0; i < array.length; i++) {
if (array[i] == 0 && value == word)
count++;
}
}
if (getUserSelectionForm.problem.value == "pay") {
countWords(working2DArray, "pay", 0)
if (getUserSelectionForm.problem.value == "staffing") {
countWords(working2DArray, "staffing", 0)
if (getUserSelectionForm.problem.value == "hours") {
countWords(working2DArray, "hours", 0)
if (getUserSelectionForm.problem.value == "management") {
countWords(working2DArray, "management", 0)
console.log(countWords)
document.getElementById('section2').innerHTML = "The selected word appears " + countWords + " times in the array."
}
Try not to use multiple IF statements and use a switch statement instead. Makes code much clearer and cleaner.
E.g.
switch(expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch
So:
var p = getUserSelectionForm.problem.value;
switch (p) {
case 'pay':
countWords(working2DArray, "pay", 0);
break;
case 'staffing':
countWords(working2DArray, "staffing", 0);
}
You are making three mistakes in code:
You are missing some of the closing curly braces } of you if blocks.
You do not return anything from function. You should return count.
countWords is a function you don't need to display that. You need to display its result.
You can make your code much simpler. You don't need these if statements at all because you are passing the same value of getUserSelectionForm.problem.value to the function so directly pass it.
function countWords(array, word, index) {
var count = 0;
var value= " "
for(var i = 0; i < array.length; i++){
if(array[i] == 0 && value == word)
count++;
}
return count;
}
let word = getUserSelectionForm.problem.value
document.getElementById('section2').innerHTML = `The selected word appears ${countWords(working2DArray,word,0)} times in array`
If you want to only check for few items then use create a array of "pay","staffing"... and use includes() on it
let word = getUserSelectionForm.problem.value
if(["pay","staffing","hours","management"].includes(word)){
document.getElementById('section2').innerHTML = `The selected word appears ${countWords(working2DArray,word,0)} times in array`
}
In my understanding , you want to trigger the function whenever problem.value ==='pay'||'staffing'||'hours'||'management' ,here is clearer version for your reference:
var problemValue = getUserSelectionForm.problem.value;
var isProblemValueMatch = ["pay", "staffing" ,"hours", "management"].includes(problemValue);
if (isProblemValueMatch ) {
var countWords = working2DArray.filter(function(v) {
return v === problemValue;
}).length;
console.log(countWords)
document.getElementById('section2').innerHTML = "The selected word appears " + countWords + " times in the array."
}

How do I use innerHTML inside a loop using JavaScript?

Here is the code and snippet:
var amount = prompt("How many list items would you like?");
if(isNaN(amount) || amount < 1) {
alert("Please enter a positive whole number");
} else {
for(i = 0; i <= amount; i++) {
document.getElementById("content").innerHTML = "Loop: " + i + "<br>";
}
}
<div id="content"></div>
Hi, I'm a new to Javascript and I can't figure this out. How can I write into the div tag "content" using the loop to display values inside the div tag per loop?
Change to += instead of = and start the for loop with 1 unless you want to print out as loop 0, loop 1 and so on...
document.getElementById("content").innerHTML += "Loop: " + i + "<br>";
var amount = prompt("How many list items would you like?");
if(isNaN(amount) || amount < 1) {
alert("Please enter a positive whole number");
} else {
for(i = 1; i <= amount; i++) {
document.getElementById("content").innerHTML += "Loop: " + i + "<br>";
}
}
<div id="content"></div>
Your code looks basically correct but you need to understand the context in which a browser executes javascript. For a given computation (event), the browser usually executes all of that computation before it does any redraws of the actual page. What this means in your case is that only the last value of innerHTML will be used. One approach to this is to accumulate the entire innerHTML value before returning (I see IsabelHM just posted that). The second would be to use something like setTimeout to spread the computation out over multiple "sessions" - something like
var i = 0;
count = function() {
document.getElementById("content").innerHTML = "Loop: " + i + "<br>";
i++;
if (i < amount) {
window.setTimeout(count, 100);
}
};
count();
Note - I haven't run that but the idea is there. I basically count at 100ms intervals.

Categories

Resources