generate random numbers in specific range and using specific numbers? - javascript

How to generate random numbers in specific range and using specific numbers?
Example
given numbers [7,8];
given range [100-900];
output must be one of them 777, 787, 788, 878, 877, 888 etc...
Help me
const randomGenerateNumber = (maxRange:number, minRange:number, numbers:number[]) => {
//...what should i do in there??? Help me? Any Idea?
}

I think you don't want random numbers. It seems that you want a set of numbers based on some rules. Random means something else.
If I understand well your question you want to generate all possible numbers containing only a set of digits from a range of numbers. Is this an accurate description?
If so, this is similar with what you want: Generate random numbers only with specific digits
Edit:
You are right, so you want only one number.
In javascript you could do something like this:
I edited the algorithm to take into account min and max in probably the most lazy way. I didn't take into account cases where numbers can't be generated, it will return undefined.
There are so many ways to do this. Your algorithm can work too and maybe more efficient but it seems to have an issue with 0, it will generate numbers with 0 even if it's not in the digits array.
function randomGenerateNumber(minRange, maxRange, digits){
noTries = 0;
while(noTries++ < 100000)
{
var num = 0;
//get a random number from your range
len = Math.floor(Math.random() * (maxRange - minRange) + minRange);
//get the lenght of that random number
len = len.toString().length;
//generate a number with that length using only your set of digits
while(len--)
{
num = num * 10 + digits[Math.floor(Math.random() * digits.length)];
}
if(num >= minRange && num<= maxRange)
{
return num;
break;
}
}
}
//your testing cases
console.log(randomGenerateNumber(100,900,[7,8]))
console.log(randomGenerateNumber(299,300,[1,2,3,4,5,6,7,8,9]));

i did it. Is there any improvement. Little bit messy.
const getRandomNumber = (min: number, max: number, numbers: number[]): number => {
if (numbers.length === 9) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
let result = '';
//split maxDigits 100 => [1, 0, 0]
const maxDigits = max
.toString()
.split('')
.map(i => parseInt(i, 10));
//split minDigits 100 => [1, 0, 0]
const minDigits = min
.toString()
.split('')
.map(i => parseInt(i, 10));
//length of random number [minDigit, maxDigit] inclusive
const randomDigit = Math.floor(Math.random() * (maxDigits.length - minDigits.length + 1) + minDigits.length);
let alreadyHigh = false;
let alreadyLow = false;
let equal = true;
//4 conditions
//1. minDigits.length === maxDigits.length
//2. randomDigit === minDigits.length
//3. randomDigit === maxDigits.length
//4. randomDigit > minDigits.length && randomDigit < maxDigits.length
for (let i = 0; i < randomDigit; i++) {
const numbersToUse = i === 0 ? numbers : [...numbers, 0];
let availableNumbers = [];
if (minDigits.length === maxDigits.length) {
if (equal) {
for (let k = 0; k < numbersToUse.length; k++) {
if (minDigits[i] > maxDigits[i]) {
if (numbersToUse[k] >= 0 && numbersToUse[k] <= maxDigits[i]) {
availableNumbers.push(numbersToUse[k]);
}
} else if (numbersToUse[k] >= minDigits[i] && numbersToUse[k] <= maxDigits[i]) {
availableNumbers.push(numbersToUse[k]);
} else {
availableNumbers.push(maxDigits[i]);
}
}
} else {
if (!alreadyHigh) {
for (let k = 0; k < numbersToUse.length; k++) {
if (numbersToUse[k] >= minDigits[i]) {
availableNumbers.push(numbersToUse[k]);
}
}
} else {
availableNumbers = numbersToUse;
}
}
} else if (randomDigit === minDigits.length) {
if (!alreadyHigh) {
for (let k = 0; k < numbersToUse.length; k++) {
if (numbersToUse[k] >= minDigits[i]) {
availableNumbers.push(numbersToUse[k]);
}
}
} else {
availableNumbers = numbersToUse;
}
} else if (randomDigit === maxDigits.length) {
if (!alreadyLow) {
for (let k = 0; k < numbersToUse.length; k++) {
if (numbersToUse[k] <= maxDigits[i]) {
availableNumbers.push(numbersToUse[k]);
}
}
} else {
availableNumbers = numbersToUse;
}
} else {
availableNumbers = numbersToUse;
}
availableNumbers = [...new Set(availableNumbers)];
const randomIndex = Math.floor(Math.random() * availableNumbers.length);
result += `${availableNumbers[randomIndex]}`;
alreadyHigh = !alreadyHigh ? availableNumbers[randomIndex] > minDigits[i] : true;
alreadyLow = !alreadyLow ? availableNumbers[randomIndex] < maxDigits[i] : true;
equal = equal ? availableNumbers[randomIndex] === maxDigits[i] : false;
}
return parseInt(result, 10);
};

Related

Randomising arrays to form an highly entropic grid

I am attempting to make a 5x5 grid using arrays with the following limitations
Should not exceed more than 4 check marks per grid
Should not have 2 consecutive check marks
This is what I have come up with so far, I would appreciate if someone could help me figure out how would I achieve the latter condition
let emoji = {
0: '✅',
1: '❓',
}
let grid = []
let checkmarks = 0
for (let i = 0; i < 5; i++) {
let row = []
for (let j = 0; j < 5; j++) {
let random = crypto.randomInt(0, 1000) % 2
if (random == 0) {
if(checkmarks < 4) {
row.push(emoji[0])
checkmarks++
}
else {
row.push(emoji[1])
}
} else {
row.push(emoji[1])
}
}
grid.push(row)
}
I am attempting to make it as random as possible.
I'm posting this answer because the accepted answer doesn't seem to produce a consistent result. I agree with most of the approach, but result just wasn't always returning 4 checkmarks (because it seems to reset after each iteration, which can increase the maximum number of loops needed).
But ultimately, the idea is to fill the 5x5 array with the ❓ character first, randomly select a location, verify the surrounding blocks are not ✅, and then place a ✅ if these conditions are met. If not, I instead just select a new position but keep the existing results until the needed number of ✅ have been set.
let grid = [],
rows = 5,
cols = 5,
maxChecks = 4,
totalChecks = 0,
emoji = {
0: '✅',
1: '❓',
};
const _RandomChecks = () => {
grid = [];
totalChecks = 0;
for(let i = 0; i < rows; i++) {
grid[i] = [];
for(let j = 0; j < cols; j++) {
grid[i] = [...grid[i], emoji[1]];
}
}
while(totalChecks < maxChecks) {
let rndRow = parseInt(crypto.randomUUID().replace(/[^0-9]/g, "").substr(-8)) % rows,
rndCol = parseInt(crypto.randomUUID().replace(/[^0-9]/g, "").substr(-8)) % cols,
valid = (grid[rndRow][rndCol] == emoji[1]) ? true : false;
if(grid[rndRow-1]?.[rndCol] && valid) valid = (grid[rndRow-1]?.[rndCol] == emoji[1]) ? true : false;
if(grid[rndRow+1]?.[rndCol] && valid) valid = (grid[rndRow+1]?.[rndCol] == emoji[1]) ? true : false;
if(grid[rndRow][rndCol-1] && valid) valid = (grid[rndRow][rndCol-1] == emoji[1]) ? true : false;
if(grid[rndRow][rndCol+1] && valid) valid = (grid[rndRow][rndCol+1] == emoji[1]) ? true : false;
if(valid) {
grid[rndRow][rndCol] = emoji[0];
totalChecks++;
}
}
console.log(grid.map(row => row.join('')).join('\n'));
}
_RandomChecks();
Instead of randomly determining if a cell should be a checkmark I would rather randomly find cells that should be a checkmark.
Your current solution decreases the chance of getting a checkmark with each cell.
Created some example code for you:
const emojis = ['✅', '❓']
const size = 5
const checkmarks = []
for (let i = 0; i < 4; i += 1) {
while (true) {
// get random x and y
const x = Math.random() * size | 0
const y = Math.random() * size | 0
// check if x and y are far enough from existing checkmarks
const areNeighbours = checkmarks.some(c => {
if (c.x === x) {
return Math.abs(c.y - y) <= 1
}
if (c.y === y) {
return Math.abs(c.x - x) <= 1
}
return false
})
if (!areNeighbours) {
checkmarks.push({
x,
y
})
break
}
}
}
const grid = []
for (let y = 0; y < size; y += 1) {
grid.push([])
for (let x = 0; x < size; x += 1) {
const checkmark = checkmarks.find(c => c.x === x && c.y === y)
grid[y][x] = checkmark ? emojis[0] : emojis[1]
}
}
console.log(grid.map(row => row.join('')).join('\n'))
Imagine a 5x5 board initially filled by ❓.
Next you toss 4 coins at once, each coin will landed in one cell, head or tail.
If head, place a ✅ in the cell.
Now check if non-consecutive ✅ condition is met. If not start over.
Solution:
const emojis = ['✅', '❓'];
function randomInt(min, max) {
return min + Math.floor(Math.random() * (max - min));
}
function tossCoins(checkmarkLimit, size) {
const positions = Array.from({ length: checkmarkLimit }, () => {
const pos = randomInt(0, size * size);
const tail = Math.random() > 0.5;
if (tail) return null;
const x = pos % 5;
const y = (pos - x) / 5;
return [x, y];
})
return positions.filter(Boolean);
}
function checkNonConsecutive(positions) {
for (let i = 0; i < positions.length; i++) {
const p = positions[i];
for (let j = 0; j < positions.length; j++) {
if (i == j) continue;
const o = positions[j];
const distance = Math.abs(p[0] - o[0]) + Math.abs(p[1] - o[1])
if (distance <= 1) {
return false;
}
}
}
return true;
}
function main() {
const checkmarkLimit = 4;
const size = 5;
const grid = Array.from({ length: size }, () => Array.from({ length: size }, () => emojis[1]));
let positions = tossCoins(checkmarkLimit, size);
while (!checkNonConsecutive(positions)) {
positions = tossCoins(checkmarkLimit, size);
}
positions.forEach(([x, y]) => {
grid[y][x] = emojis[0];
});
return grid;
}
for (let n=0; n < 10; n++) {
console.log('round: ' + n);
console.log(main().map(row => row.join('')).join('\n'));
}

Cheking if it's a prime number with JS

I'm first trying to push only prime numbers (without 2) to an array and then sum them all but getting undefined.
I've been working on this for long days, I'd appreciate if anyone could help me.
let letsCheck = () => {
let ourList = []
let sum = 0
for(let i = 2; i <= 50; i++) {
if(i % 2 !== Number.isInteger()) {
ourList.push(Number(i))
}
}
for(let prime in ourList) {
sum += ourList[prime]
}
}
First of all, You are not checking prime but checking odd numbers by % operator.
Second, you are checking Number.isNumber function which will return the boolean so, the comparison have some issues.
Here is one solution which may help.
let letsCheck = () => {
let ourList = []
let sum = 0
for(let i = 3; i <= 50; i++) {
if(isPrimeNumber(i)) {
ourList.push(Number(i))
}
}
for(let prime in ourList) {
sum += ourList[prime]
}
}
const isPrimeNumber = number => {
for(let i = 2; i <= Math.ceil(number/2); i++) {
if(number % 2 === 0) {
return false;
}
}
return true;
}
From, your code, it was more likely for obtaining odd/even numbers instead of prime numbers.
Prime numbers are whole numbers greater than 1, that have only two factors – 1 and the number itself
Odd numbers are the numbers that doesn't have 2 as its factor, and will have remainder = 1 if it gets divided by 2.
Then, as the basic programming math, the mod works like multiplication/add/subtraction that if both operators/numbers are Integer, the result would be Integer. The mod operation is basically for obtaining the remainders from the division, i.e. 5 / 2 = 2, with remainders = 1, thus 5 % 2 = 1.
And, in the looping, the i is already a number, so pushing the Number(i) is equivalent with pushing i alone. If you just want to get the sum, the array is not necessary there and should be just removed. You can get the sum by accumulate it into the sum variable.
Thus, if you wish to get the sum of odd numbers in the range [2,50], it should be:
let letsCheck = () => {
let sum = 0
for(let i = 2; i <= 50; i++) {
if(i % 2 !== 0) {
sum += i;
}
}
console.log(sum);
}
letsCheck();
And if you wish to get the prime numbers from 0 to 50 excluding 2, it should be:
function isPrimeExclude2(num) {
if(num <= 2) return false;
for(let i=2; i*i <= num; i++){
if (num % i == 0) return false;
}
return true;
}
let letsCheck = () => {
let sum = 0
for(let i = 2; i <= 50; i++) {
if(isPrimeExclude2(i)) {
sum = sum + i;
}
}
console.log(sum);
}
letsCheck();

Subset sum with number reuse allowed

I have a list of positive integers e.g. 15, 29, 110, and a target e.g. 44. I'm trying to find all possible combinations which sum to the target but importantly, the numbers in the set can be used multiple times e.g.
Target = 44
Result = 1x15, 1x29
Target = 307
Result = 2x110, 3x29
I found a dynamic programming solution which works when the combination is no more than one of each number. So Target 44 works but not my 307 example (returns Not Found).
How can the multiples or number reuse be done?
function subset(people, min, max)
{
var subsets = [];
subsets[0] = '';
for (var person in people)
{
for (var s = min-1; s >= 0; --s)
{
if (s in subsets)
{
var sum = s + people[person];
if (!(sum in subsets))
{
subsets[sum] = subsets[s] + ' ' + person;
if (sum >= min && sum <= max)
{
return subsets[sum];
}
}
}
}
}
return 'Not found';
}
var p = {
optionA:15,
optionB:29,
optionC:110
};
var qty = 307;
console.log(subset(p, qty, qty));
Try this recursive solution:
function subset(people, min, max) {
const pairs = Object.entries(people),
results = [],
getSum = multiplications => multiplications.reduce((sum, multiplicator, position) =>
sum + pairs[position][1] * multiplicator, 0),
formatResult = result => result.map(multiplications =>
multiplications.reduce((res, multiplicator, position) =>
(multiplicator > 0 ? res.push(`${multiplicator}x${pairs[position][1]}`) :
res, res), []));
function findSums(multiplications, position) {
let s;
while((s = getSum(multiplications)) <= max) {
if (s >= min) {
results.push([...multiplications]);
}
if (position < pairs.length - 1) {
const m = [...multiplications],
nextPosition = position + 1;
m[nextPosition]++;
findSums(m, nextPosition);
}
multiplications[position]++;
}
}
findSums(pairs.map(_ => 0), 0);
return results.length > 0 ? formatResult(results) : "Not found";
}
var p = {
optionA:15,
optionB:29,
optionC:110
};
var qty = 307;
console.log(subset(p, qty, qty));
Change the second loop in such way:
for (var s = 0; s <= wantedSum - people[person] ; s++)
Using this approach you fill all entries of subsets[] array\list where index is multiple of people[person] (instead of single entry). For example, with value 3 you fill 3,6,9,12... entries.

Rolling a die 60,000 times using if-else-if

I'm new to javascript and am facing trouble with the following problem.
Simulate rolling a die 60,000 times and display the frequency with which each face of the die finishes uppermost.
Use 6 variables to capture the frequencies and a 6-way if-else-if control structure need in the loop to increment them appropriately.
I know that I have to create an empty array which includes 6 variables and I have started the first iteration with 1.
What I don't understand is how to use the if-else-if statement to work through the 60000 iterations.
var array = [0, 0, 0, 0, 0, 0];
var i = 1;
You could introduce another variable for a random value between equal or greater than 0 and smaller than 6 and use it as index for the counting array.
Then you need a for loop, for counting the distribution of 60000 random values.
var array = [0, 0, 0, 0, 0, 0],
i,
r;
for (i = 0; i < 60000; i++) { // iterate 60000 times
r = Math.floor(Math.random() * 6); // generate random value
array[r]++; // increment counter
}
console.log(array);
for, Math.random:
var freqs = [0, 0, 0, 0, 0, 0];
var freqsLength = freqs.length; //* save array length into variable for more productivity
var rolls = 6000; //* how many time we want to roll dice
for(var i = 0; i < rolls; i++) { //* start rolling in loop
var j = Math.floor(Math.random() * freqsLength); //* get ramdom value
freqs[j]++; //* save freq result
}
alert(freqs);
Here's a working example with if-else:
var array = [0, 0, 0, 0, 0, 0];
var randomNumber;
for (var i = 0; i < 60000; i++) {
randomNumber = Math.floor(Math.random() * 6) + 1;
if(randomNumber === 1){
array[0]++;
}
else if(randomNumber === 2){
array[1]++;
}
else if(randomNumber === 3){
array[2]++;
}
else if(randomNumber === 4){
array[3]++;
}
else if(randomNumber === 5){
array[4]++;
}
else if(randomNumber === 6){
array[5]++;
}
}
console.log(array);
This question seems to be a homework, since you have to use if..else.
However, you don't need to use a if...else for this:
var arr = [0,0,0,0,0,0];
for(var i = 0; i < 60000; i++){
arr[~~(Math.random()*6)]++;
};
console.log(arr)
Explanation
The code has an for loop, which starts at 0 and ends at 60,000:
for(var i = 0; i < 60000; i++){
//...
};
For each iteration, a random value from 0 to 6 is generated...
Math.random()*6
... and converted to an integer using ~~.
Then, the element in the array at that random position is incremented:
arr[~~(Math.random()*6)]++;
Homework
Since this is in fact a homework and your requirements are:
Six variables
A six-way if..else
You can use this ugly, cumbersome and awkward code:
var one = two = three = four = five = six = 0;
for (var i = 0; i < 60000; i++) {
var random = ~~(Math.random() * 6) + 1;
if (random === 1) {
one++
} else if (random === 2) {
two++
} else if (random === 3) {
three++
} else if (random === 4) {
four++
} else if (random === 5) {
five++
} else if (random === 6) {
six++
}
};
var arr = [one, two, three, four, five, six];
console.log(arr)
Here's how I'd do it:
function randBetween(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
let counters = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0};
for (let i = 0; i < 60000; i++) {
counters[randBetween(1, 6)]++;
}
console.log(counters);
And here's what I'm guessing your teacher wants:
function randBetween(min, max) {
return Math.floor(Math.random() * max) + min;
}
let one = 0;
let two = 0;
let three = 0;
let four = 0;
let five = 0;
let six = 0;
for (let i = 0; i < 60000; i++) {
const n = randBetween(1, 6);
if (n === 1) { one++; }
else if (n === 2) { two++; }
else if (n === 3) { three++; }
else if (n === 4) { four++; }
else if (n === 5) { five++; }
else { six++; }
}
console.log(one, two, three, four, five, six);
You can decide for yourself which you think is the superior solution (Hint: How would you change each example to reflect rolling of a 100 sided die?)

frequency of random array integers

little stuck, please help! Trying to write code using the random number generator,initialize an array of size 50, with integer values in the
range 0..49 and compute the frequency of the numbers in the range 10..19. Here's what I have so far:
var array_nums = new Array (50);
var frequency = 0;
for (i=0; i<array_nums.length; i++){
array_nums [i] = Math.floor ((Math.random() * 50));
for (i=0; i<array_nums.length; i++){
if((i>=10) && (i<=19)){
frequency = frequency+ [i];
alert(frequency);
}
}
}
var array_nums = [];
var frequency = 0;
for (i=0; i < 50; i++) {
var randInt = Math.floor(Math.random()*50)
array_nums.push(randInt);
if(randInt >= 10 && randInt <= 19) {
frequency = frequency + 1;
}
}
document.getElementById('results').innerHTML = array_nums + '<br/><br/>frequency: ' + frequency;
<div id="results"></div>
We fill an array with 50 random numbers, then reduce it to an object that has the number of times each element between 10 and 19 occured, with a final "all" element that has the number of times all of the numbers between 10 and 19 occured.
var array_nums = Array.apply(null, Array(50)).map(function() {
return Math.floor(Math.random() * 50);
}).reduce(function (acc, curr) {
if (curr >= 10 && curr <= 19) {
acc[curr] = (acc[curr] || 0) + 1;
acc["all"]++;
}
return acc;
}, {all:0});
document.getElementById("results").innerHTML = JSON.stringify(array_nums);
<div id="results">

Categories

Resources