why is outer variable not available in if conditional - javascript

function NumStuff(num) {
this.num = num;
this.multipleOfFour = function() {
//if multiple of 4
if (this.num % 4 === 0) {
console.log(this.num + " is a multiple of Four");
console.log("the structure of the given integer " +
this.num + " is ");
for (let i = 0; i < this.num; i++) {
if (4 * i === this.num) { //why is this.num outside of
//lexical scope
console.log(this.num + " = " + i + " x 4");
break;
}
}
//if not a multiple of 4
} else {
console.log(this.num + " isn't a multiple of 4 but here is the integer's structure:");
let remainder = this.num % 4;
let tempNum = this.num - remainder;
for (let i = 0; i < tempNum; i++) {
if (4 * i === tempNum) {
console.log(this.num + " = " + i + " x 4 + " + remainder);
break;
}
}
}
};
}
let num = prompt("Enter an integer:");
let n = new NumStuff(num);
n.multipleOfFour();
Say we enter 20 as our num. It passes through the multipleOfFour() and hits the first if conditional. This.num(20) % 4 is equal to 0 so it passes.Then we loop through i to find what number times 4 is equal to 20. This.num is in the scope of the for statement but not in the scope of the inner if conditional of the for statement. Why is that so?

It is in the scope. That's not the issue.
But this.num is a string (that's what prompt always returns) while 4 * i is a number. And 4 * i === this.num will always be false, regardless of what you enter when prompted.
Try this (here):
for (let i = 0; i < this.num; i++) {
console.log('x', 4 * i, this.num, 4 * i === this.num);
An easy fix is let num = parseInt(prompt("Enter an integer:"));.

Related

How to generate unique random numbers

I’m trying to generate 5 unique random numbers between two numbers. The sixth number is a random number between another set of numbers but it doesn’t have to be unique. I tried to ensure the uniqueness of each number by placing the first randomly generated number in an array.
Then each subsequent randomly generated number is checked against the numbers in this array. Any generated number matching a number in the array will be discarded and a new one is generated until one that doesn’t match any in the array is is found. My code doesn’t work because occasionally it produces duplicates.
How is this fixed?
https://jsfiddle.net/L3h0rf5q/
var btnGen = document.getElementById('generate');
var fiveNum = document.getElementById('fiveNums');
var lastNum = document.getElementById('lastNum');
btnGen.addEventListener('click', function () {
let ranNum;
let firstFive = "";
let pb = "";
let oldNum;
ranNum = GenerateNumbers();
ranNum.sort(
(a, b) => {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
);
for(let i=0; i<ranNum.length; i++){
if(i<ranNum.length - 1){
if(ranNum[i].toString().length<2){
firstFive += "0" + ranNum[i].toString() + " " + " " + " " + " " + " " + " "
}else{
firstFive += ranNum[i].toString() + " " + " " + " " + " " + " " + " "
}
}else{
if(ranNum[i].toString().length<2){
pb = "0" + ranNum[i].toString();
}else {
pb = ranNum[i].toString();
}
}
fiveNum.innerHTML = firstFive;
lastNum.innerHTML = pb;
}
});
function GenerateNumbers() {
let randomNums = [];
let selectedNums = [];
let newNum = undefined;
for (let i = 0; i < 6; i++) {
if (i == 0) {
newNum = Math.floor(Math.random() * 75) + 1
randomNums[i] = newNum;
selectedNums.push(newNum);
}
if (i >0 && i < 5){
while (selectedNums.includes(newNum)) {
newNum = Math.floor(Math.random() * 75) + 1
}
randomNums[i] = newNum;
//add to an array
selectedNums.push(newNum);
}
if (i == 5) {
randomNums[i] = Math.floor(Math.random() * 42) + 1
}
}
return randomNums;
}
<div style="margin-left:20%; width:500px; font-weight:bold; font-size:30px;">
<button id="generate" style="margin-left:36%">Generate Numbers</button>
<br><br>
<div>
<label style="margin-left:20%">Generate Numbers</label>
<br>
<div style="background-color:black">
<span id="fiveNums" style="margin-left: 10%; width:80%; color:blue;"></span>
<span id="lastNum" style="color:blue;"></span>
</div>
</div>
the approach is to make an array with all possible values, shuffle it, and then grab 5 of them (and for that extra value you want, just calculate it separately). you can do this with plain javascript if you want:
function shuffle(arr) {
let i = arr.length;
while(i != 0) {
let j = Math.floor(Math.random() * i--);
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
//fill arr with all possible values
var arr = [];
for(var i = 50; i <= 100; i++) arr.push(i);
//shuffle
shuffle(arr);
//grab 5
console.log(arr.slice(-5));
//and the extra one
console.log(Math.floor(Math.random() * 76) + 75);
But doing it with rando.js is a lot nicer:
console.log(randoSequence(50, 100).slice(-5));//first five
console.log(rando(75, 150));//the other one
<script src="https://randojs.com/2.0.0.js"></script>

Only accept whole numbers, no decimals

I need my code to only accept whole numbers, no decimals and should prompt an error when a decimal gets entered. I don't want a new function , I'm hoping I can just add lines to my function but I don't know what I need to add.
function number_function() {
number = parseInt(prompt('Enter a positive integer:'));
if (number < 0) {
alert('Error! Factorial for negative number does not exist. But I will show you the positive number');
number = number * -1;
let n = 1;
for (i = 1; i <= number; i++) {
n *= i;
}
alert("The factorial of " + number + " is " + n + ".");
} else if (number === 0) {
alert("Please enter a number greater than 0");
} else {
let n = 1;
for (i = 1; i <= number; i++) {
n *= i;
}
alert("The factorial of " + number + " is " + n + ".");
}
}
number_function();
You can do this to check if the number has decimals
const val = 10.7 % 1;
if (val !== 0) {
console.log('has decimals');
} else {
console.log('has no decimal');
}
JavaScript provides the built-in function Number.isInteger(n)

How to find the average in javascript?

So I'm fairly new to JavaScript but I cannot seem to find the average in my code. I want to understand why my average is not working. Any help you guys?
function getEvenOdd() {
var oddSum = 0;
var evenSum = 0;
var num = 0;
var evenAvg = 0;
var oddAvg = 0;
while (true) {
num = parseInt(prompt("Enter a number(-1 to exit)"));
if (num == -1) {
break;
}
if (num % 2 == 0) {
evenSum += num;
} else {
oddSum += num;
}
evenAvg = evenSum / num;
oddAvg = oddSum / num;
}
alert("Sum of all even numbers is: " + evenSum);
alert("Sum of all odd numbers is: " + oddSum);
alert("Average of all even numbers is : " + evenAvg);
alert("Average of all odd numbers is: " + oddAvg);
}
On your code, to calculate the oddAvg and evenAvg, you have divided evenSum and oddSum by num variable (which is input from prompt).
And as you know, average = total sum / total count, so it's not right to divide the sum by the input number variable.
Instead of that, you need to calculate the count of odd and even numbers and divide the even and odd sum by the even and odd number counts as follows.
function getEvenOdd() {
var oddSum = 0;
var evenSum = 0;
var num = 0;
var evenAvg = 0;
var oddAvg = 0;
var evenCount = 0;
var oddCount = 0;
while (true) {
num = parseInt(prompt("Enter a number(-1 to exit)"));
if (num == -1) {
break;
}
if (num % 2 == 0) {
evenSum += num;
evenCount ++;
} else {
oddSum += num;
oddCount ++;
}
}
evenAvg = evenSum / evenCount;
oddAvg = oddSum / oddCount;
alert("Sum of all even numbers is: " + evenSum);
alert("Sum of all odd numbers is: " + oddSum);
alert("Average of all even numbers is : " + evenAvg);
alert("Average of all odd numbers is: " + oddAvg);
}
getEvenOdd();
These operations are dividing the evenSum or oddSum by the last input num.
evenAvg = evenSum / num;
oddAvg = oddSum / num;
You should divide the sum by the number of even or odd inputs.
Instead of evenSum / num use evenSum/Count of Numbers entered.
How about this solution? It is aiming to store odd and even numbers into oddList and evenList.
function getEvenOdd() {
var evenAvg = 0;
var oddAvg = 0;
var oddList = [];
var evenList = [];
var num = 0;
while (true) {
num = parseInt(prompt("Enter a number(-1 to exit)"));
if (num == -1) {
break;
}
if (num % 2 == 0) {
evenList.push(parseInt(num));
} else {
oddList.push(parseInt(num));
}
evenAvg = evenList.reduce((p, c) => p + c, 0) / evenList.length;
oddAvg = oddList.reduce((p, c) => p + c, 0) / oddList.length;
}
alert("Sum of all even numbers is: " + evenList.length);
alert("Sum of all odd numbers is: " + oddList.length);
alert("Average of all even numbers is : " + evenAvg);
alert("Average of all odd numbers is: " + oddAvg);
}
getEvenOdd();

Unlimited 6 sided dice roller

Need help with a JavaScript assignment from School but don't know how I should do it and was hoping for some tips?
We're supposed to create a 6 sided dice roller program and the user will have the option to choose between how many dices should be rolled, min 1 and max 5 dices.
The sum of the amount of dices used should always be displayed on the page. But if a number 6 is thrown, then this should make the program disregard it to the sum and instead throw two new dices, there should be an error message displaying this when it happens.
When all the dices are thrown the total sum of all the dices should be displayed and how many times you threw the dices.
I've managed to create this so far but I'm not sure how I should do regarding the number 6 or even if I'm on the right path here?
JS
function rollDice() {
var numDice = document.getElementById("diceNum").value;
var container = document.getElementById("dieContainer");
container.innerHTML = "";
for (var i = 0; i < numDice; i++) {
var diceRoll = Math.floor(Math.random() * 6) + 1;
container.innerHTML += '<div class="dice">' + diceRoll + '</div>';
};
var x, text;
x = document.getElementById("diceNum").value;
if (isNaN(x) || x < 1 || x > 5) {
window.alert('Input not valid');
document.getElementById("dieContainer").style.display = "none";
} else {
document.getElementById("dieContainer").style.display = "block";
}
};
EDIT
I updated it to this now
let diceThrows = numDice;
let sum = 0;
while(diceThrows > 0) {
var diceRoll = Math.floor(Math.random() * 6) + 1;
if(diceRoll == 6) {
diceThrows += 2;
console.log("You got a 6 och two new dices were thrown");
document.getElementById("msg").innerHTML = "You got a 6 och two new dices were thrown";
} else {
sum += diceRoll;
console.log(sum);
document.getElementById("msg").innerHTML = "Result: " + sum;
}
container.innerHTML += '<div class="dice">' + diceRoll + '</div>';
diceThrows -= 1;
}
I managed to display the results, but wondering now if there is a way display the results without them getting reset every time you use the function?
Replace loop for by loop while:
let diceThrows = 6;
let sum = 0;
while(diceThrows > 0) {
var diceRoll = Math.floor(Math.random() * 6) + 1;
if(diceRoll == 6) {
diceThrows += 2;
} else {
sum += diceRoll;
}
container.innerHTML += '<div class="dice">' + diceRoll + '</div>';
diceThrows -= 1;
}
You can do something like this:
function rollDice() {
var numDice = Number(document.getElementById("diceNum").value);
if (isNaN(numDice) || numDice < 1 || numDice > 5) {
window.alert('Input not valid');
return
}
var container = document.getElementById("dieContainer");
container.innerHTML = "";
var total = 0
for (var i = 0; i < numDice; i++) {
var diceRoll = Math.floor(Math.random() * 6) + 1;
container.innerHTML += '<div class="dice">' + diceRoll + '</div>';
if(diceRoll === 6) {
//Increase the maximum by 1 (because ignore 6: -1; add two: +2)
numDice++
//Decrease the current by 1 (to ignore the 6)
i--
continue
}
total += diceRoll
};
document.getElementById("diceTotal").innerText = total
document.getElementById("diceCount").innerText = numDice
}
<input type="number" id="diceNum">
<button onclick="rollDice()" >Roll Dice</button><br>
Total (without 6s): <span id="diceTotal" ></span><br>
Count of rolls (without 6s): <span id="diceCount" ></span><br>
<div id="dieContainer" ></div>

Function call using a for loop to cycle through array not working, Help please

I'm very new to Javascript but I have a problem which I have spent all day trying to research and solve, like to do it myself but i'm very stuck.
My code is simple, I have created 5 functions, 1 tests for letters, one tests for numbers, 1 for an open bracket and 1 for a closed bracket, and the fifth spots a full stop. These functions return true.
I then created a function to call all of these functions when required to produce a numerical output depending on what is found in a text string.
Back to the top, I have a string, I created an array using split to place each of the characters in the string into the separate addresses in the array. The idea is that I use a for loop to scroll through the array and output the type into identity, which is then outputted in a list.
The issue is it will do the loop once then crash, and i can't find the problem, the issue lies in the line:
identity = isWhat(ModCompound[x],ModCompound[y]);
removing it with // and the for loop runs fine.
I would like to know why? what is the mistake?
code: (raw FORM)
<!DOCTYPE html>
<!--
Sjb 19/03/2015
-->
<html>
<head>
<title></title>
</head>
<body>
Chemicals
</br>
Compound: <input id="compound" value="NaCl.2(H20)">
<script>
var identity;
var x;
Compound = document.getElementById('compound').value;
ModCompound = Compound;
ModCompound = ModCompound.split('');
for (i = 0; i < Compound.length; i++){
x = i;
y = i;
document.write(i);
identity = isWhat(ModCompound[x],ModCompound[y]);
document.write(Math.random() + " : " + identity + "</p>");
}
ModCompound= ModCompound.join('');
// Custom Functions
function isWhat(n1,c1) //OUTPUT 1,2,9,0,8
{
if (isLetter(n1,c1) === true) {
return isWhat = 1;
//document.write = "L";
} //OUTPUT 1
if (isNumber(n1,c1) === true) {
return isWhat = 2;
//document.write = "N";
} //OUTPUT 2
if (isOpenBracket(n1,c1) === true){
return isWhat = 9;
//document.write("OB");
} //OUTPUT 9
if (isClosedBracket(n1,c1) === true) {
return isWhat = 0;
//document.write = "CB";
} //OUTPUT 0
if (isFullStop(n1,c1) === true) {
return isWhat = 8;
//document.write = "FS";
} //OUTPUT 8
}
function isNumber(n, c) //OUTPUT(s) TRUE
{
if (n >= 0 || n <= 9 ) {
//document.write(n + " N " + c + "</p>");
return isNumber = true;
}
}
function isLetter(n, c)
{
n = n.charCodeAt(0);
if (((n >= 65) && (n <= 90)) || ((n >= 97) && (n <= 122))) {
//document.write(n + " L " + c + "</p>");
return isLetter = true;
}
}
function isOpenBracket(n,c)
{
if (n === "(") {
//document.write(n + " OB " + c + "</p>");
return isOpenBracket = true;
}
}
function isClosedBracket(n,c)
{
if (n === ")") {
//document.write(n + " CB " + c + "</p>");
return isClosedBracket = true;
}
}
function isFullStop(n,c)
{
if (n === ".") {
//document.write(n + " F " + c + "</p>");
return isFullStop = true;
}
}
</script>
</body>
</html>
Your return statements should just be like this:
return 1;
You're writing this:
return isWhat = 1;
That's setting the variable isWhat to 1, then returning it. isWhat is a function, though, so setting it to 1 makes is so you can't call it (because now it's a number, not a function). Also, there's no need to type var===true, because if the variable is true, then var will evaluate to true and the if statement will run.

Categories

Resources