I will explain: it is necessary to make a step from the minimum number, ie from the minimum number in this case 11986913 + range in this case + 353584,3 and until we reach the maximum number , determined how many numbers are in the range, for example 11986913 + 353584,3 = 12 340 497.3 and determine how many numbers from this array are in this range
I made it to find min and max and range
let array = [
11986913,
12128796,
12284564,
12452765,
12630047,
12810118,
12982023,
13147666,
13330769,
13527845,
13731794,
13935560,
14133509,
14313965,
14480596,
14659880,
14840502,
15020573,
15199720,
15370419,
15522756,
];
let max = getMaxValue(array);
let min = getMinValue(array);
function getMaxValue(array){
var max = array[0];
for (let i = 0; i < array.length; i++) {
if (max < array[i]) max = array[i];
}
console.log("Max number =", max);
}
function getMinValue(array){
let min = array[0];
for (let i = 0; i < array.length; i++) {
if (min > array[i]) min = array[i];
}
console.log("Min number =", min);
}
k = 10
let stepLength = (15522756 - 11986913) / k;
console.log("Range = ", stepLength);
Suppose there is an array of 10 numbers you need to find its minimum and maximum, then find the range (max - min) / 10. And then from the minimum number (11986913) to go with this range until we reach the maximum number (15522756) and after each step you need to determine how many numbers are in this interval.
This is what I came up with, I'm not exactely sure if I got your question correctly but I thought I'd give it a try.
const array=[11986913,12128796,12284564,12452765,12630047,12810118,12982023,13147666,13330769,13527845,13731794,13935560,14133509,14313965,14480596,14659880,14840502,15020573,15199720,15370419,15522756];
const max = Math.max(...array); // get max
const min = Math.min(...array); // get min
const stepLength = ((max - min) / array.length) | 0; // calc step length
console.log("Range = ", stepLength);
for (let i = min; i < max; i += stepLength) { // loop over all seperate ranges
const e = i + stepLength; // get end of range
const numbers = array.filter(a => a >= i && a < e);
console.log(`${numbers.length || "No"} numbers are in range [${i}, ${e}] >>`, numbers.join(', ')); // filter count of numbers that are between start and end range
}
Related
I have a bit weird requirement where I need to generate Random numbers of the length that is given by user. User can give Minimum Length and the Maximum Length and I need to generate the random numbers which consist of the character length between this range.
For example if the Minimum Length is 6 and Maximum Length is 10 then I need to generate the random numbers whose number of characters has to be between the range 6 and 10. For this example following can be the random generators:
123456,
7654321,
12345678,
987654321,
5432109876, etc.
Like this the Random generators has to contain the length which is between the provided inputs.
I know how to create random numbers between a range and based on fixed character length but I don't know how to created based on variable length. I tried finding the answers but most of them are based on the fixed length and fixed range, could not find the exact match that I am looking for.
It would be really great if someone can help me with this.
You may produce an array (Array.from() of randomly chosen length in the range of minLen and maxLen) and populate that with random digits in the range 1 through 9, then Array.prototype.join() the array into string and convert to number:
const randomNum = (minLen, maxLen) =>
+Array
.from(
{length: 0|Math.random()*(maxLen-minLen+1)+minLen},
() => 0|Math.random()*9+1
)
.join('')
console.log(randomNum(3,7))
You could generate the range and get the random values from that range.
For example
min = 2
max = 4
rangeMin = 10
rangeMax = 10000
const
getRandom = (min, max) => Math.floor(Math.random() * (max - min)) + min,
getRandomX = (min, max) => getRandom(10 ** (min - 1), 10 ** max);
let min = Infinity,
max = -Infinity;
for (let i = 0; i < 1e6; i++) {
let r = getRandomX(6, 10);
if (min > r) min = r;
if (max < r) max = r;
}
console.log(min, max);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Other solutions generate randoms for each digit and join them together to form a number. This is unnecessary. We know that a number with at least m-th digits is at least 10m - 1. Similarly, having at most n digits means that the number is smaller than 10n.
const randomWithinRange = (min, max) => Math.floor(Math.random() * (max - min) + min);
const randomWithMagnitude = (min, max) => randomWithinRange(Math.pow(10, min - 1), Math.pow(10, max));
const arr = Array(100000).fill().map(() => randomWithMagnitude(6, 10)).sort((a, b) => a - b);
console.log(arr.slice(0, 100).join(", "));
console.log(arr.slice(99900, 100000).join(", "));
Note: I've sorted the 100.000-sized array just to show you the smallest and largest numbers generated.
Try this:
var minLength = 6;
var maxLength = 10;
var generatedNumbers = [];
for(var i=minLength ; i<=maxLength; i++){
var num = "";
for(var j=1;j<=i;j++){
num = num + Math.floor(Math.random(10) * 10);
}
generatedNumbers.push(num);
}
console.log(generatedNumbers);
Edit
var minLength = 1;
var maxLength = randomNumber;
var generatedNumbers = [];
for(var i=minLength ; i<=maxLength; i++){
var num = "";
for(var j=1;j<=i;j++){
num = num + Math.floor(Math.random(10) * 10);
}
generatedNumbers.push(num);
}
console.log(generatedNumbers);
this will help.
Thanks a lot, everyone for the answer. Here is the approach that I have used.
If the random numbers with just Numeric is required:
var charset = "0123456789";
var max_Length = 5;
var min_Length = 10;
var charPicker = Math.floor(Math.random() * (max_Length - min_Length + 1) + min_Length);
var randomId;
for (var i = 0; i < charPicker; i++)
{
randomId += charset.charAt(Math.floor(Math.random() * charset.length));
}
console.log(randomId);
Change the character set for Alphanumeric and Alphanumeric with URL specific characters like this:
var charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~()'!*:#,;";
I would like to generate x random number between a and b. Each of this x random number should not be closer that y to the others ones:
If y = 100 then I shouldn't have 500 and 555 generated but 500 and 601 would be okay.
More context:
I would like to generate x circles with d3.js, that don't touch each other (so y would be the radius of the the bigger circle). I could use something like this but I would prefer something without using force().
The easiest thing to do would be to loop on Math.random() until you get an answer that isn't in the no-fly zone. The downside is some unnecessary calls to Math.random, but if the no-fly space is small compared to the range it wouldn't be significant.
UPDATE: avoid history of results. fun.
let history = [];
function myRand(range, margin) {
while(true) {
let result = Math.trunc(Math.random() * range);
if (history.every(last => {
return Math.abs(result - last) > margin;
})) {
history.push(result);
return result;
}
}
}
for (let i = 0; i < 5; i++)
console.log(myRand(100, 10));
I would make a simple b-tree and keep track of the nodes as I go along. This should be very fast and dependable.
let MAX = 100
let MIN = 0
let BUFFER = 10
let MAXCOUNT = 6
function randomBetween(min, max) {
return {
val: Math.floor(Math.random() * (max - min + 1) + min)
}
}
function addLeaves(f, min = MIN - BUFFER, max = MAX + BUFFER, arr = []) {
if (arr.length >= MAXCOUNT) return arr
arr.push(f.val)
f.left = (min + BUFFER < f.val - BUFFER) && addLeaves(randomBetween(min + BUFFER, f.val - BUFFER), min, f.val, arr)
f.right = (f.val + BUFFER < max - BUFFER) && addLeaves(randomBetween(f.val + BUFFER, max - BUFFER), f.val, max, arr)
return arr
}
let res = addLeaves(randomBetween(MIN, MAX))
console.log(res)
This will give at most MAXCOUNT values separated by BUFFER. It's possible it will return fewer than MAXCOUNT if there is no room in the range given a large buffer. Because of the nature of the b-tree, it will fill out gaps as necessary.
EDIT:
Since we don't actually use the tree structure(it might be useful in other circumstances thought), this can be rewritten to use the raw numbers. This changes it to a single function call to make reuse easier:
function getRandom(min, max, buffer, maxcount) {
let randomBetween = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)
function addLeaves(f, min, max, arr = []) {
if (arr.length < maxcount) {
arr.push(f);
if(min + buffer < f - buffer) addLeaves(randomBetween(min + buffer, f - buffer), min, f, arr);
if(f + buffer < max - buffer) addLeaves(randomBetween(f + buffer, max - buffer), f, max, arr);
}
return arr
}
return addLeaves(randomBetween(min, max), min - buffer, max + buffer)
}
// now you can call with just: min, max, buffer, maxcount
let res = getRandom(0, 100, 10, 6)
console.log(res)
Here's another approach, though it feels a little less random to me. It doesn't run the risk of infinite loops in the case of a narrow space.
function randomWithMargin(start, stop, count, margin) {
let spacing = Math.trunc((stop - start) / count);
let left = start;
let right = start + spacing;
let results = [];
while (count--) {
let r = left + Math.trunc(Math.random() * (right - left));
results.push(r);
left = r + margin; // ensure next number is at least margin from last
right += spacing;
}
return results;
}
console.log(randomWithMargin(10, 110, 10, 7));
Using JavaScript, how would I go about generating 30 random integers and have the sum of those 30 integers be 60000? I need the script to produce a different set of numbers each time it is run, making sure that the total is always 60000
var n = 30;
var total = 60000;
var min = 10;
var max = 5000;
for (i = 0; i < n; i++) {
// Math.floor(Math.random()*(max-min+1)+min); ??
}
In order to avoid excessively large and small numbers, the min and max values will likely be needed
You can try something like this:
Logic
Accept Max total and total number of resulting Numbers.
Now loop based on this number - 1 for n-1 random numbers and last value should be max - currentSum. Since rest of numbers are random, this difference will also be random and this will also ensure total being equal.
Now all you need to do is return a random number based on a given range.
I have also added a flag to check for unique values. Currently I have just added 1 to it but this will not ensure its uniqueness, but as its out of scope, not rectifying it.
Code
function getRandomInRange(max) {
var raiseVal = Math.pow(10, (max.toString().length - 1) || 1);
return Math.floor(Math.random() * raiseVal) % max;
}
function getRandomNumbers(max, n, uniqueNum) {
var nums = [];
var sum = 0;
for (var i = 0; i < n - 1; i++) {
let r = getRandomInRange(max - sum);
if(uniqueNum && nums.indexOf(r) > -1){
r += 1;
}
nums.push(r)
sum += r;
}
nums.push(max - sum);
console.log(nums)
return nums
}
getRandomNumbers(3, 3, true)
getRandomNumbers(3, 3)
getRandomNumbers(1000, 10)
getRandomNumbers(600000, 30)
I'm trying to create an array of numbers of a set length, defining the minimum and a maximum number in the set, and letting a function determine the rest of the numbers between. The kicker is that the sum of this array of numbers must be equal to a predetermined value. The trick is figuring out how that function works.
I found this on stack overflow, which got me the following function:
export const distributeValues = (amount, weights=[]) => {
const distributedAmounts = []
let totalWeights = weights.reduce( (a,b) => a + b)
weights.forEach( weight => {
const weightValue = parseFloat(weight)
const percentage = weightValue / totalWeights
const distributedAmount = Math.round(percentage * amount)
distributedAmounts.push(distributedAmount)
totalWeights -= weightValue
amount -= distributedAmount
})
return distributedAmounts
}
This seems like a good start, but I actually need to work backwards; I'm trying to figure out a function that will give me the weights that would be passed into the above function.
Right now, I have this, a function broken into two parts (apologies for the redundancy):
export const getDistributions = (amount, distributions, modifier) => {
const values = []
let amountLeft = amount;
for (let i = 0; i < distributions; i++ ) {
const value = Math.max(Math.round((amountLeft / (modifier || 4))),1)
amountLeft -= value
values.push(value)
}
// -------------------------------------------- //
// --- correct for cases where total values --- //
// --- end up greater/less than amount --- //
// -------------------------------------------- //
let iterator = 0
let totalAssignedValue = values.reduce((a,b) => a+b);
const lastIndex = (values.length - 1);
const getIndex = (iterator, values) => {
return iterator > lastIndex ? iterator % lastIndex : iterator
}
while (totalAssignedValue > amount) {
iterator = getIndex(iterator)
if (iterator !== lastIndex && iterator !== 0 && values[iterator] > 1) {
values[iterator]--
}
iterator ++
totalAssignedValue = values.reduce((a,b) => a+b);
}
while (totalAssignedValue < amount) {
iterator = getIndex(iterator)
if (iterator !== lastIndex && iterator !== 0) {
values[iterator]++
}
iterator ++
totalAssignedValue = values.reduce((a,b) => a+b);
}
// -------------------------------------------- //
// -------------- end correction -------------- //
// -------------------------------------------- //
return values;
}
The first part tries and distributes the values, but invariably I end up with values that are greater or lesser than the input amount, so there's a second part of the equation that fixes that. Seems a little unclean though, and it's a little arbitrary how the remainders get distributed, so a pure mathematical solution would be great.
I'm starting to wonder if I'm going to need calculus for this, because I basically have the integral (the sum of the array's values), the range of the integral (min and max values), and now have to figure out the formula for the curve. This may be overkill at this point, though.
Thanks for the input!
How about this? First create the set in such way that the first member is the minimum, the second member is minimum + 1, the third minimum + 2, etc. Then sum up the numbers in the set and subtract the sum from the predetermined value. Then distribute the result of the subtraction among all the numbers in the set as outlined betlow.
Set makeSet(int preDet, int min, int max, int setLength)
{
if((max + max - setLength + 1) * setLength / 2 < preDet) return null;
if((min + min + setLength - 1) * setLength / 2 > preDet) return null;
Set set = Set(setLength);
int val = min;
for (int i = 0; i < setLength; i++)
{
set[i] = val++;
}
int sum = (min + val - 1) * setLength / 2;
int dev = preDet - sum;
if(dev)
{
int adj = dev / setLength;
if(dev % setLength) adj++;
for(int i = setLength -1; dev; i--)
{
if(adj > dev) adj = dev;
set[i] += adj;
dev -= adj;
}
}
return set;
}
I am trying to make this thing where it generates 7 random numbers. I am using
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateNum(max, thecount) {
var r = [];
var currsum = 0;
for (var i = 0; i < thecount - 1; i++) {
r[i] = getRandomInt(15, max - (thecount - i - 1) - currsum);
currsum += r[i];
}
r[thecount - 1] = max - currsum;
return r;
}
This will sometimes return numbers that are NaN or are greater than 40 (which needs to be the max)
or less than 15 (which needs to be the min) and even less than 0.
It generates numbers that add up to another random number which is somewhere between 110 or 150.
How can I make it add up to the total random number and still be in a certain range?
We must ensure that it is possible to have numbers such that we can reach the minimum total, and numbers such that we can not exceed the maximum total.
For each number, recalculate the its minimum and maximum value such that the intended sum is still reachable.
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomInts(n, min, max, minSum, maxSum) {
if (min * n > maxSum || max * n < minSum) {
throw 'Impossible';
}
var ints = [];
while (n--) {
// calculate a lower bound for this number
// n * max is the max of the next n numbers
var thisMin = Math.max(min, minSum - n * max);
// calculate an upper bound for this number
// n * min is the min of the next n numbers
var thisMax = Math.min(max, maxSum - n * min);
var int = getRandomInt(thisMin, thisMax);
minSum -= int;
maxSum -= int;
ints.push(int);
}
return ints;
}
For completeness, I should point out there are several possible ways you could chose the probability distribution. This method at least ensures that every possible combination of integers has non-zero probability.