How to generate unique random numbers - javascript

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>

Related

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();

JavaScript arr.indexOf() always gives -1

I have a random number generator and a pick of one of the numbers inside. I'm trying to get the position of the number, So I used index.of() but it always shows '-1'.
I thought this would be the most direct way of finding the location of a particular number within an array. Am I wrong?
const shuffle = arr => {
let a = arr.slice(0); // take a copy
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
};
var arr = [];
var UserNumber = 10;
var BallNumber = 4;
var RandomNumber = Math.floor(Math.random() * UserNumber) + 1;
while (arr.length < BallNumber) {
var r = Math.floor(Math.random() * UserNumber) + 1;
if (arr.indexOf(r) === -1) {
arr.push(r);
}
console.log(r);
}
var selected = shuffle(arr).slice(0, 1);
document.write("<p> The random Number to choose is " + selected + "</p>");
document.write("<p> The Random Numbers are " + arr + "</p>");
document.write("<p> The position is " + arr.indexOf(selected) + "</p>");
Array.prototype.slice returns an array:
var selected = shuffle(arr).slice(0, 1)
Here, selected is now an array with a single element. But objects are never === to anything besides themselves, and since indexOf uses === to determine indicies, it'll always return -1.
Extract the first value from the shuffled array instead:
var selected = shuffle(arr)[0]
const shuffle = arr => {
let a = arr.slice(0); // take a copy
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
};
var arr = [];
var UserNumber = 10;
var BallNumber = 4;
var RandomNumber = Math.floor(Math.random() * UserNumber) + 1;
while (arr.length < BallNumber) {
var r = Math.floor(Math.random() * UserNumber) + 1;
if (arr.indexOf(r) === -1) {
arr.push(r);
}
}
var selected = shuffle(arr).slice(0, 1)[0];
document.write("<p> The random Number to choose is " + selected + "</p>");
document.write("<p> The Random Numbers are " + arr + "</p>");
document.write("<p> The position is " + arr.indexOf(selected) + "</p>");
slice returns an array, so you'll have to grab the first element, something like:
const shuffle = (arr) => {
let a = arr.slice(0); // take a copy
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
};
var arr = [];
var UserNumber = 10;
var BallNumber = 4;
var RandomNumber = Math.floor(Math.random() * UserNumber) + 1;
while (arr.length < BallNumber) {
var r = Math.floor(Math.random() * UserNumber) + 1;
if (arr.indexOf(r) === -1) {
arr.push(r);
}
console.log(r);
}
var selected = shuffle(arr).slice(0, 1);
document.write("<p> The random Number to choose is " + selected + "</p>");
document.write("<p> The Random Numbers are " + arr + "</p>");
document.write("<p> The position is " + arr.indexOf(selected[0]) + "</p>");

why is outer variable not available in if conditional

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:"));.

while loop. can't hardcode the while statement

function start() {
var output = "";
var index = 0;
var total = 0;
var average = 0;
var arr = []
while(arr.length < 12){
var randomnumber = Math.ceil(Math.random()*20)
if(arr.indexOf(randomnumber) > -1) continue;
arr[arr.length] = randomnumber;
}
output = output + "List of all values in the array: " + arr;
output = output + "<br/>" + "Total number of values in the array: " + arr.length + "<br/>";
while(index < arr.length) {
total = total + arr[index];
index++;
}
average = total / index;
output = output + "Total of all values: " + total + "<br/>";
output = output + "Average of all values: " + average;
document.getElementById("msg").innerHTML = output;
}
I was told I am not allowed to hardcode the statement, how to I go about changing the 'while' statement so I am not hardcoding?
Probably they mean
var arr = new Array(12);
var randIndex=0;
while(randIndex < arr.length){
var randomnumber = Math.ceil(Math.random()*20)
if(arr.indexOf(randomnumber) > -1) continue;
arr[randIndex] = randomnumber;
randIndex++;
}
Looks like a school assignment. If you are not supposed to hardcode the number of elements in array (currently 12) then you will need to get that number from user in some way. Or alternatively use a random number as shown below.
Note: there is a catch if you let the user specify the number of elements. I'll keep it for you to explore and fix.
function start(len) {
var output = "";
var index = 0;
var total = 0;
var average = 0;
var arr = []
while(arr.length < len){
var randomnumber = Math.ceil(Math.random()*20)
if(arr.indexOf(randomnumber) > -1) continue;
arr[arr.length] = randomnumber;
}
output = output + "List of all values in the array: " + arr;
output = output + "<br/>" + "Total number of values in the array: " + arr.length + "<br/>";
while(index < arr.length) {
total = total + arr[index];
index++;
}
average = total / index;
output = output + "Total of all values: " + total + "<br/>";
output = output + "Average of all values: " + average;
document.getElementById("msg").innerHTML = output;
}
// start(10); // you can get the number of elements in array from user and pass it here. I'm passing hardcoded 10 for now.
start(Math.ceil(Math.random()*20)); // alternatively passing a random number
<div id='msg'>
</div>

How can I numerically sort an array in Javascript when the number is the first part of each entry?

I am creating a list of words from a String. I then split that string into individual words, gather a count of how many times each word is repeated, and display it. Everything there works perfectly. However, the result displays the words and counts in no specific order. I will want to display them with the highest number first. I have generated the following code:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to display the array values after the split.</p>
<button onclick="analyze()">Analyze</button>
<p id="displayText"></p>
<script>
function analyze() {
var str = "This this is is is is is is is is is is is is is is is just just a test test test";
var res = str.split(" ");
document.getElementById("displayText").innerHTML = res;
document.getElementById("displayText").innerHTML += "<br/><br/>The amount of words is: " + res.length + "<br/><br/><br/>";
document.getElementById("displayText").innerHTML += "The list of words:<br/><br/>";
var words = [];
var wordsWithCount = [];
for (i = 0; i < res.length; i++) {
words.push(res[i]);
document.getElementById("displayText").innerHTML += words[i] + "<br/><br/>";
}
var current = null;
var cnt = 0;
for (var i = 0; i < words.length; i++) {
if (words[i] != current) {
if (cnt > 0) {
document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
wordsWithCount.push(cnt + " - " + current);
}
current = words[i];
cnt = 1;
} else {
cnt++;
}
}
if (cnt > 0) {
document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
wordsWithCount.push(cnt + " - " + current);
}
wordsWithCount.sort();
document.getElementById("displayText").innerHTML += "<br/><br/><br/><br/><br/>The list of SORTED words:<br/><br/>";
for (i = 0; i < wordsWithCount.length; i++) {
document.getElementById("displayText").innerHTML += wordsWithCount[i] + "<br/><br/>";
}
}
</script>
</body>
</html>
This is the last bit of the output. As you can see, it's being sorted, but only by first digit. Thus, 15 is displayed before 2. Any thoughts?
The list of SORTED words:
1 - This
1 - a
1 - this
15 - is
2 - just
3 - test
I will most likely need to break this into two arrays at some point, because I will want the user to be able to copy and paste all of the words, without the numbers. However, I assume that will need to be the last step, because if I break the frequency of each word into it's own array of numbers, and keep the words in their own array, then the sort function will sort one array, and the other array will not follow.
Using a parseInt() method and the solution found here (How to sort an array of integers correctly) to the mix it works!
replace wordsWithCount.sort(); with:
function sortNumber(a,b) {
return parseInt(a) - parseInt(b);
}
wordsWithCount.sort(sortNumber);
Live here: https://www.w3schools.com/code/tryit.asp?filename=FFGXRIN0VZWO
Do it using Intl.Collator. Like this:
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var test = ['1 - this', '3 - this', '14 - this'];
test.sort(collator.compare);
Outputs ["1 - this", "3 - this", "14 - this"]
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var test = ['1 - this', '3 - this', '14 - this'];
console.log(test.sort(collator.compare));
You can just add a custom compare function to pass into your wordsWithCount.sort() call. Here I declared a function called compareWordCount and used the sugfested method by #Pointy; using parseInt to ignore all non integer parts appended to array value. Take a look at this working snippet:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to display the array values after the split.</p>
<button onclick="analyze()">Analyze</button>
<p id="displayText"></p>
<script>
function compareWordCount(a,b) {
if (parseInt(a) < parseInt(b))
return -1;
return 1;
}
function analyze() {
var str = "This this is is is is is is is is is is is is is is is just just a test test test";
var res = str.split(" ");
document.getElementById("displayText").innerHTML = res;
document.getElementById("displayText").innerHTML += "<br/><br/>The amount of words is: " + res.length + "<br/><br/><br/>";
document.getElementById("displayText").innerHTML += "The list of words:<br/><br/>";
var words = [];
var wordsWithCount = [];
for (i = 0; i < res.length; i++) {
words.push(res[i]);
document.getElementById("displayText").innerHTML += words[i] + "<br/><br/>";
}
var current = null;
var cnt = 0;
for (var i = 0; i < words.length; i++) {
if (words[i] != current) {
if (cnt > 0) {
document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
wordsWithCount.push(cnt + " - " + current);
}
current = words[i];
cnt = 1;
} else {
cnt++;
}
}
if (cnt > 0) {
document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
wordsWithCount.push(cnt + " - " + current);
}
wordsWithCount.sort(compareWordCount);
document.getElementById("displayText").innerHTML += "<br/><br/><br/><br/><br/>The list of SORTED words:<br/><br/>";
for (i = 0; i < wordsWithCount.length; i++) {
document.getElementById("displayText").innerHTML += wordsWithCount[i] + "<br/><br/>";
}
}
</script>
</body>
</html>

Categories

Resources