How do I find the min value from randomised set of numbers? - javascript

see http://jsfiddle.net/JPxXp/
I understand as to why I keep getting 1 as the minimum ball number; do I create another variable / array that holds the 6 randomised numbers (if so, how - I don't fully understand how to do this).

First, define an array that holds the randomised numbers:
var random_balls = [];
Each time you generate a random number, add it to that array:
// generate, the + is to convert a string like '12' to the number 12, otherwise
// comparing them gives wrong results: '12' < '9' but 12 > 9
var random_ball = +balls[Math.floor(Math.random()*balls.length)];
// if indexOf returns -1, the ball is not present in the array
// (otherwise it returns the index at which the ball is)
while(random_balls.indexOf(random_ball) !== -1) {
// generate again if you already took this ball
random_ball = +balls[Math.floor(Math.random()*balls.length)];
}
// add to array
random_balls.push(random_ball);
// display
document.write(random_ball);
The min checker would iterate the new array with random numbers like this:
for (i=0; i<random_balls.length; i++)
{ if (random_balls[i] < min)
min = random_balls[i];
}
In case you didn't know, you can also use:
var min = Math.min.apply(null, random_balls); // use built in min function, passing array as arguments
http://jsfiddle.net/pimvdb/JPxXp/7/

Define global min variable and change it after selecting random ball:
var min = Number.POSITIVE_INFINITY;
...
for(i=0; i<NUMBER_OF_BALLS; i++) {
var ball = balls[Math.floor(Math.random()*balls.length)];
min = Math.min(ball, min);
document.write(ball);
document.write(" ");
}
fiddle: http://jsfiddle.net/Daess/JPxXp/4/
After the loop min variable will hold min number.

Indeed you need to push the values that you randomly choose into an array, and find the min WRT to that array.
document.write("your balls are ");
NUMBER_OF_BALLS = 6
var i = 0;
var balls = ['1','2','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','31','32','33','34','35','36','37','39','40'];
var chosen = [];
for(i=0; i<NUMBER_OF_BALLS; i++) {
chosen.push(balls[Math.floor(Math.random()*balls.length)]);
document.write(chosen[chosen.length-1]);
document.write(" ");
}
document.write("<br>");
document.write("<br>");
min = Number.POSITIVE_INFINITY;
for (i=0; i<chosen.length; i++) {
if (chosen[i] < min)
min = chosen[i];
}
document.write("The lowest ball was: " + min);
document.write("<br>");

You're taking the minimum from the balls array. All you're doing is printing out six random elements from the array. You'll need to create a new array with 6 elements, copy 6 random ones from the original array into that, then get the minimum. Also mind that you could get the same element twice.

I'm going to go for a different way here:
var arr = [], // acceptable values
randomArray = []; // random array
// Create an array of numbers 0 to 45;
for(var i=1; i <=45 ; i++){
arr.push(i);
}
// From http://stackoverflow.com/q/962802#962890
function shuffle(array) {
var tmp, current, top = array.length;
if(top) while(--top) {
current = Math.floor(Math.random() * (top + 1));
tmp = array[current];
array[current] = array[top];
array[top] = tmp;
}
return array;
}
// Randomly sort the array and take 6
randomArray = shuffle(arr).slice(0,6);
document.write("Random array: " + randomArray + "<br>");
document.write("Minimum value: " + Math.min.apply(Math, randomArray));
Example: http://jsfiddle.net/jonathon/85vEA/
At the start, I'm generating my set of numbers from 1-45 (instead of the string array you have). I'm then sorting it randomly using the Fisher-Yates shuffle (see the link to the other question) and, to get my subset of 6 random numbers, I do a slice on the array.
The minimum value can then be found by doing Math.min.apply(Math, randomArray)

Related

Having Issue On Generating Random Numbers More Than Random Rage Number

I need to generate 30 Random Numbers between 1 to 20. I am using this code but this is making conflict since the loop number is bigger than the Random range (I guess!)
var arr1 = [];
for (var i = 0; i < 30;) {
var ran = Math.floor(Math.random() * 20) + 1;
if ( arr1.indexOf(ran) == -1)
arr1[i++] = ran;
}
can you please let me know why this is happening and how I can prevent this to create 30 random numbers?
Thanks
I created a fiddle here , have a look
https://jsbin.com/kagixi/edit?html,js,output
In first case, we are updating values by iterating over all the indices.
var list = new Array(30).fill(0);
list.forEach(function(d, index){
list[index] = Math.floor(Math.random() * 20) + 1;
});
console.log(list);
Another way of doing this is to initialize array just to loop and then simply create a new array with same length or replace the existing one as I did in this example.
var list2 = new Array(30).fill(0);
list2 = list2.map(function(){
return Math.floor(Math.random() * 20) + 1;
});
You miss the third argument on your for statement.
Try this:
var arr1 = [];
for (var i = 0; i < 30; i++) {
arr1[i] = Math.floor(Math.random() * 20) + 1;
}
Your code creates an infinite loop.
Your random numbers are between 1 and 20 but you want 30 of them in your array. The check for duplicates in the line if ( arr1.indexOf(ran) == -1) is guaranteed to return false after 20 iterations, creating an infinite loop.

How do I count the number of items in an array that start with the highest number?

I've got an array that is filled with dates. They each start with the number of the year.
How do I cound the number of items present in the array that start with the highest number?
My array in question:
["12-A*januari", "12-B*februari", "12-C*maart", "12-D*april", "12-E*mei", "12-F*juni", "12-G*juli", "12-H*augustus", "12-I*september", "12-J*oktober", "12-K*november", "12-L*december", "13-A*januari", "13-B*februari", "13-C*maart", "13-D*april", "13-E*mei", "13-F*juni", "13-G*juli", "13-H*augustus", "13-I*september", "13-J*oktober", "13-K*november", "13-L*december", "14-A*januari", "14-B*februari", "14-C*maart", "14-D*april", "14-E*mei", "14-F*juni", "14-G*juli"]
So in this example I want to count the number of items in the array that start with 14, which in this example case would be 7. The numbers are dynamic so in the future the highest number will be different.
How do i return the count for the items that start with the highest number?
If your data is stored in arr:
var numbers = arr.map(function(x){ return parseInt(x); })
var max = Math.max.apply(Math,numbers)
var n = numbers.filter(function(x){ return x==max; }).length
Then your count will be in n.
P.S. in your example array there are 7 elements starting with 14.
you can sort the array, reverse it, then just filter to get the count
var count = ar.sort().reverse().filter(function(v){
return v.split('-')[0] == ar[0].split('-')[0];
}).length;
FIDDLE
First loop through your array, splitting your string and finding the largest element, by looking at the first element of the new array, like this:
var splitString = iteratingString.split("-");
if(Number(splitString[0]) > max){
max = Number(splitString[0]);
}
Then you iterate again, split each string again into a temporary array and increase the counter if the first element of the temp array is equal to max.
Combinations of map/max/filter is elegant, but unless these functions were lazy, it's quite inefficient in theory since you have to loop multiple times over the input for each functionnal operation.
It really doesn't matter in practice, unless your input is very large, but why not something standard like the following?
highestNumberOccurenceFrom(['13a', '12b', '13c']); //2
function highestNumberOccurenceFrom(arr) {
var count = 0, max = 0, i = arr.length, num;
while (i) {
num = parseInt(arr[--i]);
if (num > max) max = num, count = 1;
else if (num === max) ++count;
}
return count;
}
You could try something like this:
var maxCount = 0;
var maxVal = null;
var curVal = null;
for (var ctr=0; ctr< array.length; ctr++){
//TODO: parse the number from the beginning of the string
// You will need to write the function 'parseValFromString'
curVal = parseValFromString(array[ctr]);
if (curVal > maxVal || maxVal === null){
maxVal = curVal;
maxCount = 1;
}
else if (curVal === maxVal){
maxCount++;
}
}
console.log("count=" + maxCount;
Sort the Array first. Let the name of array be list
list.sort();
If you are sure that the array is already sorted, you can omit this step.
Get the max number
var max = list[list.length-1].substr(0,2);
Now filter the Array like this.
var list2 = list.filter(function(a){
return max == a.substr(0,2);
})
Now get number of elements in list2.
var answer = list2.length;

Generate 7 unique random numbers in javascript

I have a project i'm working on.
I am to basically recreate lotto on the client side using javascript to generate 6 random numbers plus a bonus ball. as we all know, lotto numbers cannot be the same. this is where my question comes in.
Is it possible to remove a number that has been generated from being available in the next time round in the loop? This would make the function completely random. or do I need to still compare the number with the others in the array using indexOf?
for example, is the following possible?,
the first number that generates is 25,
the function then removes that number from being able to come up again.
so on...
Here is my js code,
function play(){
numbersArray = [];
for (i=0; i<=6;){
n = Math.floor(Math.random()*40)+1;
a = numbersArray.indexOf(n);
if ( a == "-1"){
numbersArray[i] = n;
i++;
var ballId = "ball"+i;
if( i != "7"){
document.getElementById(ballId).innerHTML = '<p>'+ n +'</p>';
} else {
document.getElementById("bonus").innerHTML = '<p>'+ n +'</p>';
}
} //end of if
}//end of for loop
}//end of play function
You need to create an object, in this case you could use an array, that holds all the possible numbers that can appear on the ball, we'll cal it n. Then you can use a while loop to keep picking numbers from that array, and splice/remove that specific number from the array on every iteration.
function play(n) {
var picks = [];
// Store possibilities in the numbersArr array
var numbersArr = [];
// n is the max number you can choose to appear on a ball
for ( var i = 0; i < n; i++ ) {
numbersArr.push(i);
}
while (picks.length < 7){
var randomIndex = Math.floor(Math.random() * numbersArr.length);
picks.push(numbersArr[randomIndex]);
numbersArr.splice(randomIndex, 1);
}
return picks;
}

Javascript generate random unique number every time

Ok so i need to create four randomly generated numbers between 1-10 and they cannot be the same. so my thought is to add each number to an array but how can I check to see if the number is in the array, and if it is, re-generate the number and if it isnt add the new number to the array?
so basically it will go,
1.create new number and add to array
2.create second new number, check to see if it exist already, if it doesn't exist, add to array. If it does exist, re-create new number, check again etc...
3.same as above and so on.
You want what is called a 'random grab bag'. Consider you have a 'bag' of numbers, each number is only represented once in this bag. You take the numbers out, at random, for as many as you need.
The problem with some of the other solutions presented here is that they randomly generate the number, and check to see if it was already used. This will take longer and longer to complete (theoretically up to an infinite amount of time) because you are waiting for the random() function to return a value you don't already have (and it doesn't have to do that, it could give you 1-9 forever, but never return 10).
There are a lot of ways to implement a grab-bag type solution, each with varying degrees of cost (though, if done correctly, won't ever be infinite).
The most basic solution to your problem would be the following:
var grabBag = [1,2,3,4,5,6,7,8,9,10];
// randomize order of elements with a sort function that randomly returns -1/0/1
grabBag.sort(function(xx,yy){ return Math.floor(Math.random() * 3) - 1; })
function getNextRandom(){
return grabBag.shift();
};
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
This is of course destructive to the original grabBag array. And I'm not sure how 'truly random' that sort is, but for many applications it could be 'good enough'.
An slightly different approach would be to store all the unused elements in an array, randomly select an index, and then remove the element at that index. The cost here is how frequently you are creating/destroying arrays each time you remove an element.
Here are a couple versions using Matt's grabBag technique:
function getRandoms(numPicks) {
var nums = [1,2,3,4,5,6,7,8,9,10];
var selections = [];
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
You can see it work here: http://jsfiddle.net/jfriend00/b3MF3/.
And, here's a version that lets you pass in the range you want to cover:
function getRandoms(numPicks, low, high) {
var len = high - low + 1;
var nums = new Array(len);
var selections = [], i;
// initialize the array
for (i = 0; i < len; i++) {
nums[i] = i + low;
}
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
And a fiddle for that one: http://jsfiddle.net/jfriend00/UXnGB/
Use an array to see if the number has already been generated.
var randomArr = [], trackingArr = [],
targetCount = 4, currentCount = 0,
min = 1, max = 10,
rnd;
while (currentCount < targetCount) {
rnd = Math.floor(Math.random() * (max - min + 1)) + min;
if (!trackingArr[rnd]) {
trackingArr[rnd] = rnd;
randomArr[currentCount] = rnd;
currentCount += 1;
}
}
alert(randomArr); // Will contain four unique, random numbers between 1 and 10.
Working example: http://jsfiddle.net/FishBasketGordo/J4Ly7/
var a = [];
for (var i = 0; i < 5; i++) {
var r = Math.floor(Math.random()*10) + 1;
if(!(r in a))
a.push(r);
else
i--;
}
That'll do it for you. But be careful. If you make the number of random numbers generated greater than the may number (10) you'll hit an infinite loop.
I'm using a recursive function. The test function pick 6 unique value between 1 and 9.
//test(1, 9, 6);
function test(min, max, nbValue){
var result = recursValue(min, max, nbValue, []);
alert(result);
}
function recursValue(min, max, nbValue, result){
var randomNum = Math.random() * (max-min);
randomNum = Math.round(randomNum) + min;
if(!in_array(randomNum, result)){
result.push(randomNum);
nbValue--;
}
if(nbValue>0){
recursValue(min, max, nbValue, result);
}
return result;
}
function in_array(value, my_array){
for(var i=0;i< my_array.length; i++){
if(my_array[i] == value){
console.log(my_array+" val "+value);
return true;
}
}
return false;
}
Here is a recursive function what are you looking for.
"howMany" parameter is count of how many unique numbers you want to generate.
"randomize" parameter is biggest number that function can generate.
for example : rand(4,8) function returns an array that has 4 number in it, and the numbers are between 0 and 7 ( because as you know, Math.random() function generates numbers starting from zero to [given number - 1])
var array = [];
var isMatch= false;
function rand(howMany, randomize){
if( array.length < howMany){
var r = Math.floor( Math.random() * randomize );
for( var i = 0; i < howMany; i++ ){
if( array[i] !== r ){
isMatch= false;
continue;
} else {
isMatch= true;
break;
}
}
if( isMatch == false ){
array.push(r);
ran(howMany, randomize);
}
ran(howMany, randomize);
return array;
}
}
In your answer earlier, you do have a small bug. Instead of
var originalLength = grabBag.length;
for(var i = 0; i < originalLength .length; i++){
console.log(getNextRandom());
}
I believe you meant:
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
Thanks.

Sorting function?

I need to organize an array of strings of random length into the least number of new strings with a max size. Is there a function or something in javascript, or something that can be translated to javascript, that will do this?
For example, the new strings might have max lengths of 1000 characters. The array might have strings of lengths 100, 48, 29, etc. I would want to combine those strings into as few new strings as possible.
edit: Sorry if this doesn't make sense, I tried my best.
No standard method in Javascript, but plenty of theoretical work has been done on this (i.e. the bin packing problem).
http://en.wikipedia.org/wiki/Bin_packing_problem
Some sample pseudo code in the link - should be trivial to translate to javascript.
The algorithm shown isn't going to be optimal in every case. To find the optimal solution to your example you'll just need to iterate over every possibility which might not be that bad depending on how many strings you have.
For my own entertainment, I wrote a simple bin packing algorithm. I picked a simple algorithm which is to sort the input strings by length. Create a new bin. Put the first (longest remaining) string into the bin and then keep filling it up with the longest strings that will fit until no more strings will fit. Create a new bin, repeat. To test it, I allocate an array of strings of random lengths and use that as input. You can see the output visually here: http://jsfiddle.net/jfriend00/FqPKe/.
Running it a bunch of times, it gets a fill percentage of between 91-98%, usually around 96%. Obviously the fill percentage is higher if there are more short strings to fill with.
Here's the code:
function generateRandomLengthStringArrays(num, maxLen) {
var sourceChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY1234567890";
var sourceIndex = 0;
var result = [];
var len, temp, fill;
function getNextSourceChar() {
var ch = sourceChars.charAt(sourceIndex++);
if (sourceIndex >= sourceChars.length) {
sourceIndex = 0;
}
return(ch);
}
for (var i = 0; i < num; i++) {
len = Math.floor(Math.random() * maxLen);
temp = new String();
fill = getNextSourceChar();
// create string
for (var j = 0; j < len; j++) {
temp += fill;
}
result.push(temp);
}
return(result);
}
function packIntoFewestBins(input, maxLen) {
// we assume that none of the strings in input are longer than maxLen (they wouldn't fit in any bin)
var result = [];
// algorithm here is to put the longest string into a bin and
// then find the next longest one that will fit into that bin with it
// repeat until nothing more fits in the bin, put next longest into a new bin
// rinse, lather, repeat
var bin, i, tryAgain, binLen;
// sort the input strings by length (longest first)
input.sort(function(a, b) {return(b.length - a.length)});
while (input.length > 0) {
bin = new String(); // create new bin
bin += input.shift(); // put first one in (longest we have left) and remove it
tryAgain = true;
while (bin.length < maxLen && tryAgain) {
tryAgain = false; // if we don't find any more that fit, we'll stop after this iteration
binLen = bin.length; // save locally for speed/convenience
// find longest string left that will fit in the bin
for (i = 0; i < input.length; i++) {
if (input[i].length + binLen <= maxLen) {
bin += input[i];
input.splice(i, 1); // remove this item from the array
tryAgain = true; // try one more time
break; // break out of for loop
}
}
}
result.push(bin);
}
return(result);
}
var binLength = 60;
var numStrings = 100;
var list = generateRandomLengthStringArrays(numStrings, binLength);
var result = packIntoFewestBins(list, binLength);
var capacity = result.length * binLength;
var fillage = 0;
for (var i = 0; i < result.length; i++) {
fillage += result[i].length;
$("#result").append(result[i] + "<br>")
}
$("#summary").html(
"Fill percentage: " + ((fillage/capacity) * 100).toFixed(1) + "%<br>" +
"Number of Input Strings: " + numStrings + "<br>" +
"Number of Output Bins: " + result.length + "<br>" +
"Bin Legnth: " + binLength + "<br>"
);

Categories

Resources