not getting the right output in simple code - javascript

I'm working on a small exercise that should print all the odd numbers when a button is clicked. An error is shown when you don't fill in a number etc. When I put a number between 0 - 50, I will get the error saying "Not a number". Can someone help me with this little problem?
I don't know if the problem is with my output box in html, my tags or if there is something wrong with the if/ else statement.
let inputGetal = document.getElementById("getalInput");
//inputNumber
let genereerButton = document.getElementById("genereerButton"); //generateButton
let outputVenster = document.getElementById("outputVenster");
//outputWindow
let getal = inputGetal.value;
let onevenGetallen = () => {
if(typeof getal == "number" && (getal >= 0 || getal <= 50)) {`enter code here`
for (let i = 1; i < getal; i + 2) {
outputVenster.value += i + '<tab>';
}
} else {
outputVenster.value += "Geen goed getal" //not the right number
}
};
genereerButton.addEventListener("click", onevenGetallen);
I want to see all the odd numbers starting from 1 untill the input number has been reached.

You need to move to get the number from the input inside of the function, otherwise you get the original value, not the actual.
You need to convert the string to an integer number by using parseInt with a radix of 10.
Take the check with a logical AND &&, because both conditions have to be true.
Finally you need an addition assignment += in the final-expression part of the for statement.
let inputGetal = document.getElementById("getalInput"),
genereerButton = document.getElementById("genereerButton"),
outputVenster = document.getElementById("outputVenster"),
onevenGetallen = () => {
let getal = parseInt(inputGetal.value, 10); // get value, take integer number
if (getal >= 0 && getal <= 50) { // logical AND &&
outputVenster.value = ''; // empty output
for (let i = 1; i <= getal; i += 2) { // comparison <=, addition assignment
outputVenster.value += i + ' '; // take space as separator
}
} else {
outputVenster.value = "Geen goed getal";
}
};
genereerButton.addEventListener("click", onevenGetallen);
<input type="text" id="getalInput"> <input type="text" id="outputVenster"> <button id="genereerButton">go</button>

Related

Page displays formula rather than result (but for only ONE of the cases)

I'm a student currently learning JavaScript. As practice, I wanted to make a cute reading randomizer for a friend with a simple form and a if else input validation process.
Both of my first two cases function as I expect them two, but the third, the one that actually does the calculation, does not send the result of the calculation to be displayed, but rather the formula. I'm not sure where I went wrong.
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = (minNumChosen, maxNumChosen) => {
return Math.floor(Math.random() * (max - min) + min);
};
reply = "Today, you should read fic number " + generateRandomNumber + "!";
}
document.getElementById("result").innerHTML = reply;
}
For the last case, the page displays : "Today, you should read fic number (minNumChosen, maxNumChosen) => { return Math.floor(Math.random() * (max - min) + min); }!"
You can find the codepen here.
EDIT: Turns out I found another bug, which is probably logic based. It seems that for my function, 2 is greater than 10. So it must be judging by the first digit...
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = (min, max) => {
return Math.floor(Math.random() * (max - min) + min);
};
reply = "Today, you should read fic number " + generateRandomNumber(parseInt(minNumChosen), parseInt(maxNumChosen)) + "!";
}
document.getElementById("result").innerHTML = reply;
}
<input id="minNum" placeholder="min">
<input id="maxNum" placeholder="max">
<div id="result"></div>
<button onclick=pickfic()>Click</button>
You had to add parenthesis to generateRandomNumber()
And also make the minNumChosen and maxNumChosen into integers with parseInt().
There was also another mistake where you didn't name the parameters of your generateRandomNumber function (min, max).
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = Math.floor(Math.random() * (maxNumChosen - minNumChosen) + minNumChosen);
reply = "Today, you should read fic number " + generateRandomNumber + "!";
}
document.getElementById("result").innerHTML = reply;
OR
You created a function which takes in values but you didn't provide the min and max value while calling the generateRandomNumber function
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = (min,max) => {
return Math.floor(Math.random() * (max - min) + min);
};
reply = "Today, you should read fic number " + generateRandomNumber(minNumChosen, maxNumChosen) + "!";
}
document.getElementById("result").innerHTML = reply;
}
I figured out the last bug thanks to #SchokokuchenBäcker's input on the first issue.
My conditional was comparing strings, which is why 20 was smaller than 5 !
Writing the first conditional like this:
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || parseInt(minNumChosen) >= parseInt(maxNumChosen) )
makes it functional!

Calculating the average of several function invocations using closures

I am doing a coding challenge that reads like this:
Create a function runningAverage() that returns a callable function object. Update the series with each given value and calculate the current average.
rAvg = runningAverage();
rAvg(10) = 10.0;
rAvg(11) = 10.5;
rAvg(12) = 11;
I got a working solution, yet they also want the results to be rounded like this:
rAvg(13) = 13.50678; => 13.50
rAvg(13) = 13.50; => 13.50
rAvg(13) = 13.5; => 13.5
rAvg(13) = 13; => 13
Here is my code:
function runningAverage() {
let number = 0;
let numbOfFunctionCalls = 0;
return function (y) {
number += y;
numbOfFunctionCalls ++;
let average = (number/numbOfFunctionCalls);
let averageArray = average.toString().split('.');
//to get the number of decimal places
//e.g 11.543 ==> ['11', '543']
if ((Array.from(averageArray[1]).length) >= 2) {
return average.toPrecision(2);
}
else if ((Array.from(averageArray[1]).length) = 1) {
return average.toPrecision(1);
}
else {
return average;
}
}
}
I tested parts of the function separately and it seems to work, yet when I invoke it I get the message 'cannot convert undefined or null to object'.
This sounds like a fun coding challenge!
In this case, you want toFixed(), not toPrecision(). toPrecision() essentially allows you determine how many digits TOTAL (including those on the left of the decimal point) should appear, whereas toFixed() focuses on the number of digits to the right of the decimal point. Feel free to look these two methods up on MDN. When you read that toPrecision() may return exponential notation, this should make you pause and think, "That's weird. Why does this happen? When does this happen?", rather than "this detail is unimportant."
Your .length = 1 comparison needs to be modified to a ===.
Your code currently fails if an integer is the first number provided to rAvg(). In your first conditional, Array.from(undefined) may run, which is not permissible in JavaScript. You should consider ways to only work with "the digits to the right of the decimal" only if "there are digits to the right of the decimal."
Here is a working solution including all the suggestions, in case someone is interested:
function runningAverage() {
let number = 0;
let numbOfFunctionCalls = 0;
return function (y) {
number += y;
numbOfFunctionCalls ++;
let average = (number/numbOfFunctionCalls);
let numIsDecimal = average.toString().includes('.');
if (numIsDecimal) {
let averageArray = average.toString().split('.');
//to get the number of decimal places
//e.g 11.543 ==> ['11', '543']
if ((Array.from(averageArray[1]).length) >= 2) {
return Number(average.toFixed(2));
}
if ((Array.from(averageArray[1]).length) === 1) {
return Number(average.toFixed(1));
}
}
else {
return Number(average);
}
}
}
Not sure if this works but try it
function runningAverage() {
let number = 0;
let numbOfFunctionCalls = 0;
return function (y) {
number += y;
numbOfFunctionCalls ++;
let average = (number/numbOfFunctionCalls);
let averageArray = average.toString().split('.');
if ((Array.from(averageArray[1]).length) >= 2) {
return Math.round(average.toPrecision(2) * 2) / 2;
} else if ((Array.from(averageArray[1]).length) == 1) {
return Math.round(average.toPrecision(1) * 2) / 2;
} else {
return Math.round(average * 2) / 2;
};
};
};

Simple number guessing game using Javascript

I'm trying to make a number guessing game on JS for a web dev training I'm on. The problem is that it always prints the keyInYNStrict without giving an another chance for the user. Ignore the fact that the strings and variables are not in English. Basically I want the keyInYNStrict to only come after the arvaus == arvattava is true and the game has ended.
const minLuku = 1;
const maxLuku = 30;
const readlineSync = require('readline-sync');
let arvaus, arvattava, arvaustenLkm
do {
arvaus = readlineSync.question('Ajattelen numeroa 1 ja 30 välillä. Arvaapa vaan');
arvaustenLkm = 1;
arvattava = Math.floor(Math.random() * (maxLuku + 1 - minLuku)) + minLuku
kelvollinen = !isNaN(arvaus) && arvaus > 0 && arvaus < 31;
if (!kelvollinen) {
console.log('Elä viitsi! Laita nyt jokin oikea numero.');
}
else if (arvaus < arvattava){
arvaustenLkm++;
console.log('Kokeile suurempaa lukua.');
} else if (arvaus > arvattava){
arvaustenLkm++;
console.log('Kokeile pienempää lukua.');
} else if (arvaus == arvattava){
console.log('Hienoa. arvasit oikein ' + arvaustenLkm + ' arvauksella.')
}
} while (readlineSync.keyInYNStrict('Haluatko arvata uudestaan?'))
You'll need two while loops nested. The first is to repeat the guessing until the number has been found, the second to ask if the user wished to play again. This becomes clearer if you break a single game into a function, and then wrap "Play again?" around that function.
The following is untested. Notice I also pulled out the "Invalid guess" check to separate it from the game logic. I think that also improves readability, and allows for the option of checking for some other exit condition should the user wish to end early.
EDIT: As I'm thinking about it, there's another problem: Do you want to reset the hidden number each guess? That's probably not consistent with expectations. I've modified the code to reflect.
const minLuku = 1; // Lower bound
const maxLuku = 30; // Upper bound
const readlineSync = require('readline-sync');
let arvaus, arvattava, arvaustenLkm
do {
// Number of guesses
arvaustenLkm = 1;
//Target number
arvattava = Math.floor(Math.random() * (maxLuku + 1 - minLuku)) + minLuku
do {
// User's guess
arvaus = readlineSync.question('Ajattelen numeroa 1 ja 30 välillä. Arvaapa vaan');
// Bad guess test
if (isNaN(arvaus) || arvaus < minLuku || arvaus > maxLuku) {
console.log('Elä viitsi! Laita nyt jokin oikea numero.');
continue;
}
if (arvaus < arvattava){
arvaustenLkm++;
console.log('Kokeile suurempaa lukua.');
} else if (arvaus > arvattava){
arvaustenLkm++;
console.log('Kokeile pienempää lukua.');
} else if (arvaus == arvattava){
console.log('Hienoa. arvasit oikein ' + arvaustenLkm + ' arvauksella.')
}
} while (arvaus != arvattava)
} while (readlineSync.keyInYNStrict('Play again?'))

Why does if statement not work and make my element disappear using display: none?

I am building a tip calculator and I couldn't make the if statement in my function work it just skips to calculating.
function calculate() {
var bill = parseInt(document.getElementById("bill").value);
var tip = parseInt(document.getElementById("tip").value) * .01;
var persons = parseInt(document.getElementById("persons").value);
if (bill == "" || tip == "") {
alert("Please enter value");
return;
};
if (persons == "" || persons <= 1) {
persons = 1;
document.getElementById("perPerson").style.display = "none";
} else {
}
let totalTipPer = (bill * tip) / persons;
let totalPer = (bill + (tip * 100)) / persons;
let totalTip = bill * tip;
let total = bill + (tip * 100);
totalTipPer = totalTipPer.toFixed(2);
totalPer = totalPer.toFixed(2);
total = total.toFixed(2);
totalTip = totalTip.toFixed(2);
document.getElementById("total-tip/person").innerHTML = totalTipPer;
document.getElementById("total-price/person").innerHTML = totalPer;
document.getElementById("total-tip").innerHTML = totalTip;
document.getElementById("total-price").innerHTML = total;
}
document.getElementById("calculate").onclick = function () {
calculate();
document.getElementById('results').style.display = 'block';
}
I expect the div encapsulating Tip Amount per person and total per person and to not appear when the input value of persons is empty.
Function parseInt returns 'An integer number parsed from the given string. If the first character cannot be converted to a number, NaN is returned.'
if you rpovide an empty value ('') it will return
NaN which is not equal to anything, even itself.
there are several ways to fix this:
check if it is a NaN with Number.isNaN(var)
use an intermediate value like var personsValue and check if it is equal to empty string ''.
use Hybrid suggested solution and assign a 0
value for falsy value('', undefined, n
ull etc...)
The issue is that persons becomes NaN, since if the value is left blank, "" becomes NaN when it is run through parseInt().
The way to fix this is by defaulting it to 0 if the field is left blank.
var persons = parseInt(document.getElementById("persons").value || 0);
as others pointed out parseInt is returning NaN if the field is blank, but this will also happen if the user inputs $5.00 for example.
Here's one way to make sure the value can be converted to a number before doing so.
// This function determines if a JavaScript String can be converted into a number
function is_numeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function calculate() {
// first put the input values into separate variables
billValue = document.getElementById("bill").value;
tipValue = document.getElementById("tip").value;
personsValue = document.getElementById("persons").value;
// use the is_numeric() function above to check if the values can be converted to numeric
if (!is_numeric(billValue) || !is_numeric(tipValue)) {
alert("Please enter values for bill and tip");
return;
}
// the rest of your code here
}
Hope this helps.

Advice on how to code Luhn Credit Card validation with Javascript?

I'm pretty awful at Javascript as I've just started learning.
I'm doing a Luhn check for a 16-digit credit card.
It's driving me nuts and I'd just appreciate if someone looked over it and could give me some help.
<script>
var creditNum;
var valid = new Boolean(true);
creditNum = prompt("Enter your credit card number: ");
if((creditNum==null)||(creditNum=="")){
valid = false;
alert("Invalid Number!\nThere was no input.");
}else if(creditNum.length!=16){
valid = false;
alert("Invalid Number!\nThe number is the wrong length.");
}
//Luhn check
var c;
var digitOne;
var digitTwo;
var numSum;
for(i=0;i<16;i+2){
c = creditNum.slice(i,i+1);
if(c.length==2){
digitOne = c.slice(0,1);
digitTwo = c.slice(1,2);
numSum = numSum + (digitOne + digitTwo);
}else{
numSum = numSum + c;
}
}
if((numSum%10)!=0){
alert("Invalid Number!");
}else{
alert("Credit Card Accepted!");
}
</script>
The immediate problem in your code is your for loop. i+2 is not a proper third term. From the context, you're looking for i = i + 2, which you can write in shorthand as i += 2.
It seems your algorithm is "take the 16 digits, turn them into 8 pairs, add them together, and see if the sum is divisible by 10". If that's the case, you can massively simplify your loop - you never need to look at the tens' place, just the units' place.
Your loop could look like this and do the same thing:
for (i = 1; i < 16; i +=2) {
numSum += +creditNum[i];
}
Also, note that as long as you're dealing with a string, you don't need to slice anything at all - just use array notation to get each character.
I added a + in front of creditNum. One of the issues with javascript is that it will treat a string as a string, so if you have string "1" and string "3" and add them, you'll concatenate and get "13" instead of 4. The plus sign forces the string to be a number, so you'll get the right result.
The third term of the loop is the only blatant bug I see. I don't actually know the Luhn algorithm, so inferred the rest from the context of your code.
EDIT
Well, it would have helped if you had posted what the Luhn algorithm is. Chances are, if you can at least articulate it, you can help us help you code it.
Here's what you want.
// Luhn check
function luhnCheck(sixteenDigitString) {
var numSum = 0;
var value;
for (var i = 0; i < 16; ++i) {
if (i % 2 == 0) {
value = 2 * sixteenDigitString[i];
if (value >= 10) {
value = (Math.floor(value / 10) + value % 10);
}
} else {
value = +sixteenDigitString[i];
}
numSum += value;
}
return (numSum % 10 == 0);
}
alert(luhnCheck("4111111111111111"));
What this does is go through all the numbers, keeping the even indices as they are, but doubling the odd ones. If the doubling is more than nine, the values of the two digits are added together, as per the algorithm stated in wikipedia.
FIDDLE
Note: the number I tested with isn't my credit card number, but it's a well known number you can use that's known to pass a properly coded Luhn verification.
My below solution will work on AmEx also. I submitted it for a code test a while ago. Hope it helps :)
function validateCard(num){
var oddSum = 0;
var evenSum = 0;
var numToString = num.toString().split("");
for(var i = 0; i < numToString.length; i++){
if(i % 2 === 0){
if(numToString[i] * 2 >= 10){
evenSum += ((numToString[i] * 2) - 9 );
} else {
evenSum += numToString[i] * 2;
}
} else {
oddSum += parseInt(numToString[i]);
}
}
return (oddSum + evenSum) % 10 === 0;
}
console.log(validateCard(41111111111111111));
Enjoy - Mitch from https://spangle.com.au
#Spangle, when you're using even and odd here, you're already considering that index 0 is even? So you're doubling the digits at index 0, 2 and so on and not the second position, fourth and so on.. Is that intentional? It's returning inconsistent validations for some cards here compared with another algorithm I'm using. Try for example AmEx's 378282246310005.

Categories

Resources