Project Euler #1 - javascript

I only started programming about three days ago and I've been working with Javascript. I've been trying to tackle Project Euler Problem 1:
Find the sum of all the multiples of 3 or 5 below 1000.
And I feel like my program should work, but my answer is still slightly off. Could anyone tell me what's wrong with my code?
var threeSum = [];
var threeTotal = 0;
var fiveSum = [];
var fiveTotal = 0;
for (i = 0; i < 1000; i += 3) {
threeSum.push(i);
}
for (j = 0; j < threeSum.length; j++) {
threeTotal = threeTotal + threeSum[j];
}
for (a = 0; a < 1000; a += 5) {
fiveSum.push(a);
}
for (r = 0; r < fiveSum.length; r++) {
fiveTotal = fiveTotal + fiveSum[r];
}
console.log(threeTotal + fiveTotal);
I get an answer of 266333 when I run this program.

The task of Project Euler #1 is
Find the sum of all the multiples of 3 or 5 below 1000.
not
Find the sum of all the multiples of 3 below 1000 and all multiples of 5 below 1000.
Numbers like 45 that are multiples of both 3 and 5 should not be counted twice.

Side note - programming often also means searching for non-obvious solution. The wording of the question suggests looping of the numbers from 1 to 999 but with a bit of math no looping is required at all and you can solve the problem for n = 1.000.000.000 as fast as for n = 10 (if nothing overflows).
var n = 1000;
var multiplesOfThree = Math.floor((n - 1) / 3);
var multiplesOfFive = Math.floor((n - 1) / 5);
var multiplesOfThreeAndFive = Math.floor((n - 1) / 15);
var sum = 3 * multiplesOfThree * (multiplesOfThree + 1) / 2
+ 5 * multiplesOfFive * (multiplesOfFive + 1) / 2
- 15 * multiplesOfThreeAndFive * (multiplesOfThreeAndFive + 1) / 2;

Project Euler 1 is
If we list all the natural numbers below 10 that are multiples of 3 or
5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the
sum of all the multiples of 3 or 5 below 1000.
Since you're learning, I'm assuming you don't want an explicit answer to this.
Think about what you're summing. The first few terms of the 3 loop are
[3, 6, 9, 12, 15]
and the first few terms of the 5 loop are
[5, 10, 15]
Since you are counting the multiples of both 3 and 5 twice, your answer is larger than it should be

this is pretty much how I did it and I get the right answer.
`var threeSum=0;`
var fiveSum=0;
var dSum=0;
for (var b=3; b<1000; b++) {
if (b%3===0) {
threeSum=threeSum+b;
}
}
for (var c=5; c<1000; c++) {
if (c%5===0) {
fiveSum=fiveSum+c;
}
}
for (var d=15; d<1000; d++) {
if (d%15===0) {
dSum=dSum+d;
}
}
console.log((threeSum+threeSum)-dSum);

here's my solution to Project Euler 1st problem, simple and very easy to understand. It's in java, but it can be easily translated to any language
public class Multiples {
public static int multiplesSum(int n1, int n2, int limit) {
int sum = 0;
int n = Math.min(n1, n2);
for(int i=n; i<limit; i++) {
if(i%n1==0 || i%n2==0) {
sum+=i;
}
}
return sum;
}
public static void main(String[] args) {
int total = multiplesSum(3,5,1000);
System.out.println("Total sum is: " + total);
}
}
And here it is the best solution as suggested by Project Euler experts:
/**
* Remember that the sum of the first n natural numbers is: n(n+1)/2
*
* Let’s look at the details of our function and take as example n=3.
We would have to add:
3+6+9+12+......+999=3*(1+2+3+4+...+333)
For n=5 we would get:
5+10+15+...+995=5*(1+2+....+199)
Now note that 199=995/5 but also 999/5 rounded down to the nearest integer.
*
* #param n
* #param limit
* #return
*/
public static int multiplesSumOf(int n, int limit) {
int target = (limit-1)/n;
return n * target*(target+1)/2;
}
public static void main(String[] args) {
int total = multiplesSumOf(3,1000) + multiplesSumOf(5,1000) - multiplesSumOf(15,1000);
System.out.println("Total: " + total);
}

I posted my solution using Kotlin here:
https://github.com/moxi/project-euler-solutions/blob/master/code/src/main/kotlin/org/rcgonzalezf/onetoten/Problem1.kt
The nice thing about Kotlin and why I'm posting here is that they support JavaScript compilation(transpilation) as well, so you might find it interesting: https://kotlinlang.org/docs/tutorials/javascript/kotlin-to-javascript/kotlin-to-javascript.html
fun solve(baseNumber: Int): Int {
return (0..baseNumber - 1)
.filter { it % 3 == 0 || it % 5 == 0 }
.sum()
}
As you can see is very concise, I'm going to try to solve some of the Euler Project problems Streaming on LiveEdu I think it will be fun, I don't want to paste the link here since this is not an advertisement platform, if you want to discuss about it search for Project Euler over there.

var num = 1000
var numbers = []
for(var i = 0; i < num; i++){
if( i % 3 === 0|| i % 5 === 0){
numbers.push(i)
}
};
var sum = numbers.reduce((a, b) => a + b, 0);

Related

Sorting algorithm complexity [duplicate]

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
I have an array of numbers from 1 to 100 (both inclusive). The size of the array is 100. The numbers are randomly added to the array, but there is one random empty slot in the array.
What is the quickest way to find that slot as well as the number that should be put in the slot? A Java solution is preferable.
You can do this in O(n). Iterate through the array and compute the sum of all numbers. Now, sum of natural numbers from 1 to N, can be expressed as Nx(N+1)/2. In your case N=100.
Subtract the sum of the array from Nx(N+1)/2, where N=100.
That is the missing number. The empty slot can be detected during the iteration in which the sum is computed.
// will be the sum of the numbers in the array.
int sum = 0;
int idx = -1;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == 0)
{
idx = i;
}
else
{
sum += arr[i];
}
}
// the total sum of numbers between 1 and arr.length.
int total = (arr.length + 1) * arr.length / 2;
System.out.println("missing number is: " + (total - sum) + " at index " + idx);
We can use XOR operation which is safer than summation because in programming languages if the given input is large it may overflow and may give wrong answer.
Before going to the solution, know that A xor A = 0. So if we XOR two identical numbers the value is 0.
Now, XORing [1..n] with the elements present in the array cancels the identical numbers. So at the end we will get the missing number.
// Assuming that the array contains 99 distinct integers between 1..99
// and empty slot value is zero
int XOR = 0;
for(int i=0; i<100; i++) {
if (ARRAY[i] != 0) // remove this condition keeping the body if no zero slot
XOR ^= ARRAY[i];
XOR ^= (i + 1);
}
return XOR;
//return XOR ^ ARRAY.length + 1; if your array doesn't have empty zero slot.
Let the given array be A with length N. Lets assume in the given array, the single empty slot is filled with 0.
We can find the solution for this problem using many methods including algorithm used in Counting sort. But, in terms of efficient time and space usage, we have two algorithms. One uses mainly summation, subtraction and multiplication. Another uses XOR. Mathematically both methods work fine. But programatically, we need to assess all the algorithms with main measures like
Limitations(like input values are large(A[1...N]) and/or number of
input values is large(N))
Number of condition checks involved
Number and type of mathematical operations involved
etc. This is because of the limitations in time and/or hardware(Hardware resource limitation) and/or software(Operating System limitation, Programming language limitation, etc), etc. Lets list and assess the pros and cons of each one of them.
Algorithm 1 :
In algorithm 1, we have 3 implementations.
Calculate the total sum of all the numbers(this includes the unknown missing number) by using the mathematical formula(1+2+3+...+N=(N(N+1))/2). Here, N=100. Calculate the total sum of all the given numbers. Subtract the second result from the first result will give the missing number.
Missing Number = (N(N+1))/2) - (A[1]+A[2]+...+A[100])
Calculate the total sum of all the numbers(this includes the unknown missing number) by using the mathematical formula(1+2+3+...+N=(N(N+1))/2). Here, N=100. From that result, subtract each given number gives the missing number.
Missing Number = (N(N+1))/2)-A[1]-A[2]-...-A[100]
(Note:Even though the second implementation's formula is derived from first, from the mathematical point of view both are same. But from programming point of view both are different because the first formula is more prone to bit overflow than the second one(if the given numbers are large enough). Even though addition is faster than subtraction, the second implementation reduces the chance of bit overflow caused by addition of large values(Its not completely eliminated, because there is still very small chance since (N+1) is there in the formula). But both are equally prone to bit overflow by multiplication. The limitation is both implementations give correct result only if N(N+1)<=MAXIMUM_NUMBER_VALUE. For the first implementation, the additional limitation is it give correct result only if Sum of all given numbers<=MAXIMUM_NUMBER_VALUE.)
Calculate the total sum of all the numbers(this includes the unknown missing number) and subtract each given number in the same loop in parallel. This eliminates the risk of bit overflow by multiplication but prone to bit overflow by addition and subtraction.
//ALGORITHM
missingNumber = 0;
foreach(index from 1 to N)
{
missingNumber = missingNumber + index;
//Since, the empty slot is filled with 0,
//this extra condition which is executed for N times is not required.
//But for the sake of understanding of algorithm purpose lets put it.
if (inputArray[index] != 0)
missingNumber = missingNumber - inputArray[index];
}
In a programming language(like C, C++, Java, etc), if the number of bits representing a integer data type is limited, then all the above implementations are prone to bit overflow because of summation, subtraction and multiplication, resulting in wrong result in case of large input values(A[1...N]) and/or large number of input values(N).
Algorithm 2 :
We can use the property of XOR to get solution for this problem without worrying about the problem of bit overflow. And also XOR is both safer and faster than summation. We know the property of XOR that XOR of two same numbers is equal to 0(A XOR A = 0). If we calculate the XOR of all the numbers from 1 to N(this includes the unknown missing number) and then with that result, XOR all the given numbers, the common numbers get canceled out(since A XOR A=0) and in the end we get the missing number. If we don't have bit overflow problem, we can use both summation and XOR based algorithms to get the solution. But, the algorithm which uses XOR is both safer and faster than the algorithm which uses summation, subtraction and multiplication. And we can avoid the additional worries caused by summation, subtraction and multiplication.
In all the implementations of algorithm 1, we can use XOR instead of addition and subtraction.
Lets assume, XOR(1...N) = XOR of all numbers from 1 to N
Implementation 1 => Missing Number = XOR(1...N) XOR (A[1] XOR A[2] XOR...XOR A[100])
Implementation 2 => Missing Number = XOR(1...N) XOR A[1] XOR A[2] XOR...XOR A[100]
Implementation 3 =>
//ALGORITHM
missingNumber = 0;
foreach(index from 1 to N)
{
missingNumber = missingNumber XOR index;
//Since, the empty slot is filled with 0,
//this extra condition which is executed for N times is not required.
//But for the sake of understanding of algorithm purpose lets put it.
if (inputArray[index] != 0)
missingNumber = missingNumber XOR inputArray[index];
}
All three implementations of algorithm 2 will work fine(from programatical point of view also). One optimization is, similar to
1+2+....+N = (N(N+1))/2
We have,
1 XOR 2 XOR .... XOR N = {N if REMAINDER(N/4)=0, 1 if REMAINDER(N/4)=1, N+1 if REMAINDER(N/4)=2, 0 if REMAINDER(N/4)=3}
We can prove this by mathematical induction. So, instead of calculating the value of XOR(1...N) by XOR all the numbers from 1 to N, we can use this formula to reduce the number of XOR operations.
Also, calculating XOR(1...N) using above formula has two implementations. Implementation wise, calculating
// Thanks to https://a3nm.net/blog/xor.html for this implementation
xor = (n>>1)&1 ^ (((n&1)>0)?1:n)
is faster than calculating
xor = (n % 4 == 0) ? n : (n % 4 == 1) ? 1 : (n % 4 == 2) ? n + 1 : 0;
So, the optimized Java code is,
long n = 100;
long a[] = new long[n];
//XOR of all numbers from 1 to n
// n%4 == 0 ---> n
// n%4 == 1 ---> 1
// n%4 == 2 ---> n + 1
// n%4 == 3 ---> 0
//Slower way of implementing the formula
// long xor = (n % 4 == 0) ? n : (n % 4 == 1) ? 1 : (n % 4 == 2) ? n + 1 : 0;
//Faster way of implementing the formula
// long xor = (n>>1)&1 ^ (((n&1)>0)?1:n);
long xor = (n>>1)&1 ^ (((n&1)>0)?1:n);
for (long i = 0; i < n; i++)
{
xor = xor ^ a[i];
}
//Missing number
System.out.println(xor);
This was an Amazon interview question and was originally answered here: We have numbers from 1 to 52 that are put into a 51 number array, what's the best way to find out which number is missing?
It was answered, as below:
1) Calculate the sum of all numbers stored in the array of size 51.
2) Subtract the sum from (52 * 53)/2 ---- Formula : n * (n + 1) / 2.
It was also blogged here: Software Job - Interview Question
Here is a simple program to find the missing numbers in an integer array
ArrayList<Integer> arr = new ArrayList<Integer>();
int a[] = { 1,3,4,5,6,7,10 };
int j = a[0];
for (int i=0;i<a.length;i++)
{
if (j==a[i])
{
j++;
continue;
}
else
{
arr.add(j);
i--;
j++;
}
}
System.out.println("missing numbers are ");
for(int r : arr)
{
System.out.println(" " + r);
}
Recently I had a similar (not exactly the same) question in a job interview and also I heard from a friend that was asked the exactly same question in an interview.
So here is an answer to the OP question and a few more variations that can be potentially asked.
The answers example are given in Java because, it's stated that:
A Java solution is preferable.
Variation 1:
Array of numbers from 1 to 100 (both inclusive) ... The numbers are randomly added to the array, but there is one random empty slot in the array
public static int findMissing1(int [] arr){
int sum = 0;
for(int n : arr){
sum += n;
}
return (100*(100+1)/2) - sum;
}
Explanation:
This solution (as many other solutions posted here) is based on the formula of Triangular number, which gives us the sum of all natural numbers from 1 to n (in this case n is 100). Now that we know the sum that should be from 1 to 100 - we just need to subtract the actual sum of existing numbers in given array.
Variation 2:
Array of numbers from 1 to n (meaning that the max number is unknown)
public static int findMissing2(int [] arr){
int sum = 0, max = 0;
for(int n : arr){
sum += n;
if(n > max) max = n;
}
return (max*(max+1)/2) - sum;
}
Explanation:
In this solution, since the max number isn't given - we need to find it. After finding the max number - the logic is the same.
Variation 3:
Array of numbers from 1 to n (max number is unknown), there is two random empty slots in the array
public static int [] findMissing3(int [] arr){
int sum = 0, max = 0, misSum;
int [] misNums = {};//empty by default
for(int n : arr){
sum += n;
if(n > max) max = n;
}
misSum = (max*(max+1)/2) - sum;//Sum of two missing numbers
for(int n = Math.min(misSum, max-1); n > 1; n--){
if(!contains(n, arr)){
misNums = new int[]{n, misSum-n};
break;
}
}
return misNums;
}
private static boolean contains(int num, int [] arr){
for(int n : arr){
if(n == num)return true;
}
return false;
}
Explanation:
In this solution, the max number isn't given (as in the previous), but it can also be missing of two numbers and not one. So at first we find the sum of missing numbers - with the same logic as before. Second finding the smaller number between missing sum and the last (possibly) missing number - to reduce unnecessary search. Third since Javas Array (not a Collection) doesn't have methods as indexOf or contains, I added a small reusable method for that logic. Fourth when first missing number is found, the second is the subtract from missing sum.
If only one number is missing, then the second number in array will be zero.
Variation 4:
Array of numbers from 1 to n (max number is unknown), with X missing (amount of missing numbers are unknown)
public static ArrayList<Integer> findMissing4(ArrayList<Integer> arr){
int max = 0;
ArrayList<Integer> misNums = new ArrayList();
int [] neededNums;
for(int n : arr){
if(n > max) max = n;
}
neededNums = new int[max];//zero for any needed num
for(int n : arr){//iterate again
neededNums[n == max ? 0 : n]++;//add one - used as index in second array (convert max to zero)
}
for(int i=neededNums.length-1; i>0; i--){
if(neededNums[i] < 1)misNums.add(i);//if value is zero, than index is a missing number
}
return misNums;
}
Explanation:
In this solution, as in the previous, the max number is unknown and there can be missing more than one number, but in this variation, we don't know how many numbers are potentially missing (if any). The beginning of the logic is the same - find the max number. Then I initialise another array with zeros, in this array index indicates the potentially missing number and zero indicates that the number is missing. So every existing number from original array is used as an index and its value is incremented by one (max converted to zero).
Note
If you want examples in other languages or another interesting variations of this question, you are welcome to check my Github repository for Interview questions & answers.
(sum of 1 to n) - (sum of all values in the array) = missing number
int sum = 0;
int idx = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) idx = i; else sum += arr[i];
}
System.out.println("missing number is: " + (5050 - sum) + " at index " + idx);
On a similar scenario, where the array is already sorted, it does not include duplicates and only one number is missing, it is possible to find this missing number in log(n) time, using binary search.
public static int getMissingInt(int[] intArray, int left, int right) {
if (right == left + 1) return intArray[right] - 1;
int pivot = left + (right - left) / 2;
if (intArray[pivot] == intArray[left] + (intArray[right] - intArray[left]) / 2 - (right - left) % 2)
return getMissingInt(intArray, pivot, right);
else
return getMissingInt(intArray, left, pivot);
}
public static void main(String args[]) {
int[] array = new int[]{3, 4, 5, 6, 7, 8, 10};
int missingInt = getMissingInt(array, 0, array.length-1);
System.out.println(missingInt); //it prints 9
}
Well, use a bloom filter.
int findmissing(int arr[], int n)
{
long bloom=0;
int i;
for(i=0; i<;n; i++)bloom+=1>>arr[i];
for(i=1; i<=n, (bloom<<i & 1); i++);
return i;
}
This is c# but it should be pretty close to what you need:
int sumNumbers = 0;
int emptySlotIndex = -1;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == 0)
emptySlotIndex = i;
sumNumbers += arr[i];
}
int missingNumber = 5050 - sumNumbers;
The solution that doesn't involve repetitive additions or maybe the n(n+1)/2 formula doesn't get to you at an interview time for instance.
You have to use an array of 4 ints (32 bits) or 2 ints (64 bits). Initialize the last int with (-1 & ~(1 << 31)) >> 3. (the bits that are above 100 are set to 1) Or you may set the bits above 100 using a for loop.
Go through the array of numbers and set 1 for the bit position corresponding to the number (e.g. 71 would be set on the 3rd int on the 7th bit from left to right)
Go through the array of 4 ints (32 bit version) or 2 ints(64 bit version)
public int MissingNumber(int a[])
{
int bits = sizeof(int) * 8;
int i = 0;
int no = 0;
while(a[i] == -1)//this means a[i]'s bits are all set to 1, the numbers is not inside this 32 numbers section
{
no += bits;
i++;
}
return no + bits - Math.Log(~a[i], 2);//apply NOT (~) operator to a[i] to invert all bits, and get a number with only one bit set (2 at the power of something)
}
Example: (32 bit version) lets say that the missing number is 58. That means that the 26th bit (left to right) of the second integer is set to 0.
The first int is -1 (all bits are set) so, we go ahead for the second one and add to "no" the number 32. The second int is different from -1 (a bit is not set) so, by applying the NOT (~) operator to the number we get 64. The possible numbers are 2 at the power x and we may compute x by using log on base 2; in this case we get log2(64) = 6 => 32 + 32 - 6 = 58.
Hope this helps.
I think the easiest and possibly the most efficient solution would be to loop over all entries and use a bitset to remember which numbers are set, and then test for 0 bit. The entry with the 0 bit is the missing number.
This is not a search problem. The employer is wondering if you have a grasp of a checksum. You might need a binary or for loop or whatever if you were looking for multiple unique integers, but the question stipulates "one random empty slot." In this case we can use the stream sum. The condition: "The numbers are randomly added to the array" is meaningless without more detail. The question does not assume the array must start with the integer 1 and so tolerate with the offset start integer.
int[] test = {2,3,4,5,6,7,8,9,10, 12,13,14 };
/*get the missing integer*/
int max = test[test.length - 1];
int min = test[0];
int sum = Arrays.stream(test).sum();
int actual = (((max*(max+1))/2)-min+1);
//Find:
//the missing value
System.out.println(actual - sum);
//the slot
System.out.println(actual - sum - min);
Success time: 0.18 memory: 320576 signal:0
I found this beautiful solution here:
http://javaconceptoftheday.com/java-puzzle-interview-program-find-missing-number-in-an-array/
public class MissingNumberInArray
{
//Method to calculate sum of 'n' numbers
static int sumOfNnumbers(int n)
{
int sum = (n * (n+1))/ 2;
return sum;
}
//Method to calculate sum of all elements of array
static int sumOfElements(int[] array)
{
int sum = 0;
for (int i = 0; i < array.length; i++)
{
sum = sum + array[i];
}
return sum;
}
public static void main(String[] args)
{
int n = 8;
int[] a = {1, 4, 5, 3, 7, 8, 6};
//Step 1
int sumOfNnumbers = sumOfNnumbers(n);
//Step 2
int sumOfElements = sumOfElements(a);
//Step 3
int missingNumber = sumOfNnumbers - sumOfElements;
System.out.println("Missing Number is = "+missingNumber);
}
}
function solution($A) {
// code in PHP5.5
$n=count($A);
for($i=1;$i<=$n;$i++) {
if(!in_array($i,$A)) {
return (int)$i;
}
}
}
Finding the missing number from a series of numbers. IMP points to remember.
the array should be sorted..
the Function do not work on multiple missings.
the sequence must be an AP.
public int execute2(int[] array) {
int diff = Math.min(array[1]-array[0], array[2]-array[1]);
int min = 0, max = arr.length-1;
boolean missingNum = true;
while(min<max) {
int mid = (min + max) >>> 1;
int leftDiff = array[mid] - array[min];
if(leftDiff > diff * (mid - min)) {
if(mid-min == 1)
return (array[mid] + array[min])/2;
max = mid;
missingNum = false;
continue;
}
int rightDiff = array[max] - array[mid];
if(rightDiff > diff * (max - mid)) {
if(max-mid == 1)
return (array[max] + array[mid])/2;
min = mid;
missingNum = false;
continue;
}
if(missingNum)
break;
}
return -1;
}
One thing you could do is sort the numbers using quick sort for instance. Then use a for loop to iterate through the sorted array from 1 to 100. In each iteration, you compare the number in the array with your for loop increment, if you find that the index increment is not the same as the array value, you have found your missing number as well as the missing index.
Below is the solution for finding all the missing numbers from a given array:
public class FindMissingNumbers {
/**
* The function prints all the missing numbers from "n" consecutive numbers.
* The number of missing numbers is not given and all the numbers in the
* given array are assumed to be unique.
*
* A similar approach can be used to find all no-unique/ unique numbers from
* the given array
*
* #param n
* total count of numbers in the sequence
* #param numbers
* is an unsorted array of all the numbers from 1 - n with some
* numbers missing.
*
*/
public static void findMissingNumbers(int n, int[] numbers) {
if (n < 1) {
return;
}
byte[] bytes = new byte[n / 8];
int countOfMissingNumbers = n - numbers.length;
if (countOfMissingNumbers == 0) {
return;
}
for (int currentNumber : numbers) {
int byteIndex = (currentNumber - 1) / 8;
int bit = (currentNumber - byteIndex * 8) - 1;
// Update the "bit" in bytes[byteIndex]
int mask = 1 << bit;
bytes[byteIndex] |= mask;
}
for (int index = 0; index < bytes.length - 2; index++) {
if (bytes[index] != -128) {
for (int i = 0; i < 8; i++) {
if ((bytes[index] >> i & 1) == 0) {
System.out.println("Missing number: " + ((index * 8) + i + 1));
}
}
}
}
// Last byte
int loopTill = n % 8 == 0 ? 8 : n % 8;
for (int index = 0; index < loopTill; index++) {
if ((bytes[bytes.length - 1] >> index & 1) == 0) {
System.out.println("Missing number: " + (((bytes.length - 1) * 8) + index + 1));
}
}
}
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<Integer>();
int n = 128;
int m = 5;
for (int i = 1; i <= n; i++) {
arrayList.add(i);
}
Collections.shuffle(arrayList);
for (int i = 1; i <= 5; i++) {
System.out.println("Removing:" + arrayList.remove(i));
}
int[] array = new int[n - m];
for (int i = 0; i < (n - m); i++) {
array[i] = arrayList.get(i);
}
System.out.println("Array is: " + Arrays.toString(array));
findMissingNumbers(n, array);
}
}
Lets say you have n as 8, and our numbers range from 0-8 for this example
we can represent the binary representation of all 9 numbers as follows
0000
0001
0010
0011
0100
0101
0110
0111
1000
in the above sequence there is no missing numbers and in each column the number of zeros and ones match, however as soon as you remove 1 value lets say 3 we get a in balance in the number of 0's and 1's across the columns. If the number of 0's in a column is <= the number of 1's our missing number will have a 0 at this bit position, otherwise if the number of 0's > the number of 1's at this bit position then this bit position will be a 1. We test the bits left to right and at each iteration we throw away half of the array for the testing of the next bit, either the odd array values or the even array values are thrown away at each iteration depending on which bit we are deficient on.
The below solution is in C++
int getMissingNumber(vector<int>* input, int bitPos, const int startRange)
{
vector<int> zeros;
vector<int> ones;
int missingNumber=0;
//base case, assume empty array indicating start value of range is missing
if(input->size() == 0)
return startRange;
//if the bit position being tested is 0 add to the zero's vector
//otherwise to the ones vector
for(unsigned int i = 0; i<input->size(); i++)
{
int value = input->at(i);
if(getBit(value, bitPos) == 0)
zeros.push_back(value);
else
ones.push_back(value);
}
//throw away either the odd or even numbers and test
//the next bit position, build the missing number
//from right to left
if(zeros.size() <= ones.size())
{
//missing number is even
missingNumber = getMissingNumber(&zeros, bitPos+1, startRange);
missingNumber = (missingNumber << 1) | 0;
}
else
{
//missing number is odd
missingNumber = getMissingNumber(&ones, bitPos+1, startRange);
missingNumber = (missingNumber << 1) | 1;
}
return missingNumber;
}
At each iteration we reduce our input space by 2, i.e N, N/2,N/4 ... = O(log N), with space O(N)
//Test cases
[1] when missing number is range start
[2] when missing number is range end
[3] when missing number is odd
[4] when missing number is even
Solution With PHP $n = 100;
$n*($n+1)/2 - array_sum($array) = $missing_number
and array_search($missing_number) will give the index of missing number
Here program take time complexity is O(logn) and space complexity O(logn)
public class helper1 {
public static void main(String[] args) {
int a[] = {1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12};
int k = missing(a, 0, a.length);
System.out.println(k);
}
public static int missing(int[] a, int f, int l) {
int mid = (l + f) / 2;
//if first index reached last then no element found
if (a.length - 1 == f) {
System.out.println("missing not find ");
return 0;
}
//if mid with first found
if (mid == f) {
System.out.println(a[mid] + 1);
return a[mid] + 1;
}
if ((mid + 1) == a[mid])
return missing(a, mid, l);
else
return missing(a, f, mid);
}
}
public class MissingNumber {
public static void main(String[] args) {
int array[] = {1,2,3,4,6};
int x1 = getMissingNumber(array,6);
System.out.println("The Missing number is: "+x1);
}
private static int getMissingNumber(int[] array, int i) {
int acctualnumber =0;
int expectednumber = (i*(i+1)/2);
for (int j : array) {
acctualnumber = acctualnumber+j;
}
System.out.println(acctualnumber);
System.out.println(expectednumber);
return expectednumber-acctualnumber;
}
}
Use sum formula,
class Main {
// Function to ind missing number
static int getMissingNo (int a[], int n) {
int i, total;
total = (n+1)*(n+2)/2;
for ( i = 0; i< n; i++)
total -= a[i];
return total;
}
/* program to test above function */
public static void main(String args[]) {
int a[] = {1,2,4,5,6};
int miss = getMissingNo(a,5);
System.out.println(miss);
}
}
Reference http://www.geeksforgeeks.org/find-the-missing-number/
simple solution with test data :
class A{
public static void main(String[] args){
int[] array = new int[200];
for(int i=0;i<100;i++){
if(i != 51){
array[i] = i;
}
}
for(int i=100;i<200;i++){
array[i] = i;
}
int temp = 0;
for(int i=0;i<200;i++){
temp ^= array[i];
}
System.out.println(temp);
}
}
//Array is shorted and if writing in C/C++ think of XOR implementations in java as follows.
int num=-1;
for (int i=1; i<=100; i++){
num =2*i;
if(arr[num]==0){
System.out.println("index: "+i+" Array position: "+ num);
break;
}
else if(arr[num-1]==0){
System.out.println("index: "+i+ " Array position: "+ (num-1));
break;
}
}// use Rabbit and tortoise race, move the dangling index faster,
//learnt from Alogithimica, Ameerpet, hyderbad**
If the array is randomly filled, then at the best you can do a linear search in O(n) complexity. However, we could have improved the complexity to O(log n) by divide and conquer approach similar to quick sort as pointed by giri given that the numbers were in ascending/descending order.
This Program finds missing numbers
<?php
$arr_num=array("1","2","3","5","6");
$n=count($arr_num);
for($i=1;$i<=$n;$i++)
{
if(!in_array($i,$arr_num))
{
array_push($arr_num,$i);print_r($arr_num);exit;
}
}
?>
Now I'm now too sharp with the Big O notations but couldn't you also do something like (in Java)
for (int i = 0; i < numbers.length; i++) {
if(numbers[i] != i+1){
System.out.println(i+1);
}
}
where numbers is the array with your numbers from 1-100.
From my reading of the question it did not say when to write out the missing number.
Alternatively if you COULD throw the value of i+1 into another array and print that out after the iteration.
Of course it might not abide by the time and space rules. As I said. I have to strongly brush up on Big O.
========Simplest Solution for sorted Array===========
public int getMissingNumber(int[] sortedArray)
{
int missingNumber = 0;
int missingNumberIndex=0;
for (int i = 0; i < sortedArray.length; i++)
{
if (sortedArray[i] == 0)
{
missingNumber = (sortedArray[i + 1]) - 1;
missingNumberIndex=i;
System.out.println("missingNumberIndex: "+missingNumberIndex);
break;
}
}
return missingNumber;
}
Another homework question. A sequential search is the best that you can do. As for a Java solution, consider that an exercise for the reader. :P

Optimising Javascript

I was given a quiz and I had gotten the answer wrong and It's been bugging me ever since so I thought I'd ask for your thoughts
I needed to optimise the following function
function sumOfEvenNumbers(n) {
var sum = 0;
for(let i = 2; i < n;i++){
if(i % 2 == 0) sum += i;
}
return sum;
}
console.log(sumOfEvenNumbers(5));
I came up with
function sumOfEvenNumbers(n) {
var sum = 0;
while(--n >= 2) sum += n % 2 == 0? n : 0
return sum;
}
console.log(sumOfEvenNumbers(5));
What other ways were there?
It's a bit of a math question. The sum appears to be the sum of an arithmitic sequence with a common difference of 2. The sum is:
sum = N * (last + first) / 2;
where N is the number of the numbers in the sequence, last is the last number of those numbers, and first is the first.
Translated to javascript as:
function sumOfEvenNumbers(n) {
return Math.floor(n / 2) * (n - n % 2 + 2) / 2;
}
Because the number of even numbers between 2 and n is Math.floor(n / 2) and the last even number is n - n % 2 (7 would be 7 - 7 % 2 === 6 and 8 would be 8 - 8 % 2 === 8). and the first is 2.
Sum of n numbers:
var sum = (n * (n+1)) / 2;
Sum of n even numbers:
var m = Math.floor(n/2);
var sum = 2 * (m * (m+1) /2);
You can compute these sums using an arithmetic sum formula in constant time:
// Return sum of positive even numbers < n:
function sumOfEvenNumbers(n) {
n = (n - 1) >> 1;
return n * (n + 1);
}
// Example:
console.log(sumOfEvenNumbers(5));
Above computation avoids modulo and division operators which consume more CPU cycles than multiplication, addition and bit-shifting. Pay attention to the limited range of the bit-shifting operator >> though.
See e.g. http://oeis.org/A002378 for this and other formulas leading to the same result.
First thing is to eliminate the test in the loop:
function sumOfEvenNumbers(n) {
var sum = 0;
var halfN= Math.floor(n/2);
for(let i = 1; i < n/2;i++) {
sum += i;
}
return sum * 2;
}
Then we can observe that is just calculating the sum of all the integers less than a limit - and there is a formula for that (but actually formula is for less-equal a limit).
function sumOfEvenNumbers(n) {
var halfNm1= Math.floor(n/2)-1;
var sum = halfNm1 * (halfNm1+1) / 2;
return sum * 2;
}
And then eliminate the division and multiplication and the unnecessary addition and subtraction:
function sumOfEvenNumbers(n) {
var halfN= Math.floor(n/2);
return (halfN-1) * halfN;
}
Your solution computes in linear (O(N)) time.
If you use a mathematical solution, you can compute it in O(1) time:
function sum(n) {
let half = Math.ceil(n/2)
return half * (half + 1)
}
Because the question is tagged ecmascript-6 :)
const sumEven = x => [...Array(x + 1).keys()].reduce((a, b) => b % 2 === 0 ? a + b : a, 0);
// set max number
console.log(sumEven(10));

Looping through array elements in javascript generated by random nr generator [duplicate]

How can I generate some unique random numbers between 1 and 100 using JavaScript?
For example: To generate 8 unique random numbers and store them to an array, you can simply do this:
var arr = [];
while(arr.length < 8){
var r = Math.floor(Math.random() * 100) + 1;
if(arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);
Populate an array with the numbers 1 through 100.
Shuffle it.
Take the first 8 elements of the resulting array.
Modern JS Solution using Set (and average case O(n))
const nums = new Set();
while(nums.size !== 8) {
nums.add(Math.floor(Math.random() * 100) + 1);
}
console.log([...nums]);
Another approach is to generate an 100 items array with ascending numbers and sort it randomly. This leads actually to a really short and (in my opinion) simple snippet.
const numbers = Array(100).fill().map((_, index) => index + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));
Generate permutation of 100 numbers and then choose serially.
Use Knuth Shuffle(aka the Fisher-Yates shuffle) Algorithm.
JavaScript:
function fisherYates ( myArray,stop_count ) {
var i = myArray.length;
if ( i == 0 ) return false;
int c = 0;
while ( --i ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var tempi = myArray[i];
var tempj = myArray[j];
myArray[i] = tempj;
myArray[j] = tempi;
// Edited thanks to Frerich Raabe
c++;
if(c == stop_count)return;
}
}
CODE COPIED FROM LINK.
EDIT:
Improved code:
function fisherYates(myArray,nb_picks)
{
for (i = myArray.length-1; i > 1 ; i--)
{
var r = Math.floor(Math.random()*i);
var t = myArray[i];
myArray[i] = myArray[r];
myArray[r] = t;
}
return myArray.slice(0,nb_picks);
}
Potential problem:
Suppose we have array of 100 numbers {e.g. [1,2,3...100]} and we stop swapping after 8 swaps;
then most of the times array will look like {1,2,3,76,5,6,7,8,...numbers here will be shuffled ...10}.
Because every number will be swapped with probability 1/100 so
prob. of swapping first 8 numbers is 8/100 whereas prob. of swapping other 92 is 92/100.
But if we run algorithm for full array then we are sure (almost)every entry is swapped.
Otherwise we face a question : which 8 numbers to choose?
The above techniques are good if you want to avoid a library, but depending if you would be alright with a library, I would suggest checking out Chance for generating random stuff in JavaScript.
Specifically to solve your question, using Chance it's as easy as:
// One line!
var uniques = chance.unique(chance.natural, 8, {min: 1, max: 100});
// Print it out to the document for this snippet so we can see it in action
document.write(JSON.stringify(uniques));
<script src="http://chancejs.com/chance.min.js"></script>
Disclaimer, as the author of Chance, I am a bit biased ;)
To avoid any long and unreliable shuffles, I'd do the following...
Generate an array that contains the number between 1 and 100, in order.
Generate a random number between 1 and 100
Look up the number at this index in the array and store in your results
Remove the elemnt from the array, making it one shorter
Repeat from step 2, but use 99 as the upper limit of the random number
Repeat from step 2, but use 98 as the upper limit of the random number
Repeat from step 2, but use 97 as the upper limit of the random number
Repeat from step 2, but use 96 as the upper limit of the random number
Repeat from step 2, but use 95 as the upper limit of the random number
Repeat from step 2, but use 94 as the upper limit of the random number
Repeat from step 2, but use 93 as the upper limit of the random number
Voila - no repeated numbers.
I may post some actual code later, if anybody is interested.
Edit: It's probably the competitive streak in me but, having seen the post by #Alsciende, I couldn't resist posting the code that I promised.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>8 unique random number between 1 and 100</title>
<script type="text/javascript" language="Javascript">
function pick(n, min, max){
var values = [], i = max;
while(i >= min) values.push(i--);
var results = [];
var maxIndex = max;
for(i=1; i <= n; i++){
maxIndex--;
var index = Math.floor(maxIndex * Math.random());
results.push(values[index]);
values[index] = values[maxIndex];
}
return results;
}
function go(){
var running = true;
do{
if(!confirm(pick(8, 1, 100).sort(function(a,b){return a - b;}))){
running = false;
}
}while(running)
}
</script>
</head>
<body>
<h1>8 unique random number between 1 and 100</h1>
<p><button onclick="go()">Click me</button> to start generating numbers.</p>
<p>When the numbers appear, click OK to generate another set, or Cancel to stop.</p>
</body>
I would do this:
function randomInt(min, max) {
return Math.round(min + Math.random()*(max-min));
}
var index = {}, numbers = [];
for (var i=0; i<8; ++i) {
var number;
do {
number = randomInt(1, 100);
} while (index.hasOwnProperty("_"+number));
index["_"+number] = true;
numbers.push(number);
}
delete index;
This is a very generic function I have written to generate random unique/non-unique integers for an array. Assume the last parameter to be true in this scenario for this answer.
/* Creates an array of random integers between the range specified
len = length of the array you want to generate
min = min value you require
max = max value you require
unique = whether you want unique or not (assume 'true' for this answer)
*/
function _arrayRandom(len, min, max, unique) {
var len = (len) ? len : 10,
min = (min !== undefined) ? min : 1,
max = (max !== undefined) ? max : 100,
unique = (unique) ? unique : false,
toReturn = [], tempObj = {}, i = 0;
if(unique === true) {
for(; i < len; i++) {
var randomInt = Math.floor(Math.random() * ((max - min) + min));
if(tempObj['key_'+ randomInt] === undefined) {
tempObj['key_'+ randomInt] = randomInt;
toReturn.push(randomInt);
} else {
i--;
}
}
} else {
for(; i < len; i++) {
toReturn.push(Math.floor(Math.random() * ((max - min) + min)));
}
}
return toReturn;
}
Here the 'tempObj' is a very useful obj since every random number generated will directly check in this tempObj if that key already exists, if not, then we reduce the i by one since we need 1 extra run since the current random number already exists.
In your case, run the following
_arrayRandom(8, 1, 100, true);
That's all.
Shuffling the numbers from 1 to 100 is the right basic strategy, but if you need only 8 shuffled numbers, there's no need to shuffle all 100 numbers.
I don't know Javascript very well, but I believe it's easy to create an array of 100 nulls quickly. Then, for 8 rounds, you swap the n'th element of the array (n starting at 0) with a randomly selected element from n+1 through 99. Of course, any elements not populated yet mean that the element would really have been the original index plus 1, so that's trivial to factor in. When you're done with the 8 rounds, the first 8 elements of your array will have your 8 shuffled numbers.
var arr = []
while(arr.length < 8){
var randomnumber=Math.ceil(Math.random()*100)
if(arr.indexOf(randomnumber) === -1){arr.push(randomnumber)}
}
document.write(arr);
shorter than other answers I've seen
Implementing this as a generator makes it pretty nice to work with. Note, this implementation differs from ones that require the entire input array to be shuffled first.
This sample function works lazily, giving you 1 random item per iteration up to N items you ask for. This is nice because if you just want 3 items from a list of 1000, you don't have to touch all 1000 items first.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let ys = xs.slice(0);
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield ys.splice(i,1)[0];
n--; len--;
}
}
// example inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// get 3 random items
for (let i of sample(3) (items))
console.log(i); // f g c
// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
console.log(i); // 3 8 7
// shuffle an array
const shuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]
I chose to implement sample in a way that does not mutate the input array, but you could easily argue that a mutating implementation is favourable.
For example, the shuffle function might wish to mutate the original input array. Or you might wish to sample from the same input at various times, updating the input each time.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield xs.splice(i,1)[0];
n--; len--;
}
}
// deal :: [Card] -> [Card]
const deal = xs => Array.from(sample (2) (xs));
// setup a deck of cards (13 in this case)
// cards :: [Card]
let cards = 'A234567890JQK'.split('');
// deal 6 players 2 cards each
// players :: [[Card]]
let players = Array.from(Array(6), $=> deal(cards))
console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]
// `cards` has been mutated. only 1 card remains in the deck
console.log(cards);
// [3]
sample is no longer a pure function because of the array input mutation, but in certain circumstances (demonstrated above) it might make more sense.
Another reason I chose a generator instead of a function that just returns an array is because you may want to continue sampling until some specific condition.
Perhaps I want the first prime number from a list of 1,000,000 random numbers.
"How many should I sample?" – you don't have to specify
"Do I have to find all the primes first and then select a random prime?" – Nope.
Because we're working with a generator, this task is trivial
const randomPrimeNumber = listOfNumbers => {
for (let x of sample(Infinity) (listOfNumbers)) {
if (isPrime(x))
return x;
}
return NaN;
}
This will continuously sample 1 random number at a time, x, check if it's prime, then return x if it is. If the list of numbers is exhausted before a prime is found, NaN is returned.
Note:
This answer was originally shared on another question that was closed as a duplicate of this one. Because it's very different from the other solutions provided here, I've decided to share it here as well
var numbers = [];
for (let i = 0; i < 8; i++) {
let a = true,
n;
while(a) {
n = Math.floor(Math.random() * 100) + 1;
a = numbers.includes(n);
}
numbers.push(n);
}
console.log(numbers);
Same permutation algorithm as The Machine Charmer, but with a prototyped implementation. Better suited to large number of picks. Uses js 1.7 destructuring assignment if available.
// swaps elements at index i and j in array this
// swapping is easy on js 1.7 (feature detection)
Array.prototype.swap = (function () {
var i=0, j=1;
try { [i,j]=[j,i]; }
catch (e) {}
if(i) {
return function(i,j) {
[this[i],this[j]] = [this[j],this[i]];
return this;
}
} else {
return function(i,j) {
var temp = this[i];
this[i] = this[j];
this[j] = temp;
return this;
}
}
})();
// shuffles array this
Array.prototype.shuffle = function() {
for(var i=this.length; i>1; i--) {
this.swap(i-1, Math.floor(i*Math.random()));
}
return this;
}
// returns n unique random numbers between min and max
function pick(n, min, max) {
var a = [], i = max;
while(i >= min) a.push(i--);
return a.shuffle().slice(0,n);
}
pick(8,1,100);
Edit:
An other proposition, better suited to small number of picks, based on belugabob's answer. To guarantee uniqueness, we remove the picked numbers from the array.
// removes n random elements from array this
// and returns them
Array.prototype.pick = function(n) {
if(!n || !this.length) return [];
var i = Math.floor(this.length*Math.random());
return this.splice(i,1).concat(this.pick(n-1));
}
// returns n unique random numbers between min and max
function pick(n, min, max) {
var a = [], i = max;
while(i >= min) a.push(i--);
return a.pick(n);
}
pick(8,1,100);
for arrays with holes like this [,2,,4,,6,7,,]
because my problem was to fill these holes. So I modified it as per my need :)
the following modified solution worked for me :)
var arr = [,2,,4,,6,7,,]; //example
while(arr.length < 9){
var randomnumber=Math.floor(Math.random()*9+1);
var found=false;
for(var i=0;i<arr.length;i++){
if(arr[i]==randomnumber){found=true;break;}
}
if(!found)
for(k=0;k<9;k++)
{if(!arr[k]) //if it's empty !!MODIFICATION
{arr[k]=randomnumber; break;}}
}
alert(arr); //outputs on the screen
The best earlier answer is the answer by sje397. You will get as good random numbers as you can get, as quick as possible.
My solution is very similar to his solution. However, sometimes you want the random numbers in random order, and that is why I decided to post an answer. In addition, I provide a general function.
function selectKOutOfN(k, n) {
if (k>n) throw "k>n";
var selection = [];
var sorted = [];
for (var i = 0; i < k; i++) {
var rand = Math.floor(Math.random()*(n - i));
for (var j = 0; j < i; j++) {
if (sorted[j]<=rand)
rand++;
else
break;
}
selection.push(rand);
sorted.splice(j, 0, rand);
}
return selection;
}
alert(selectKOutOfN(8, 100));
Here is my ES6 version I cobbled together. I'm sure it can be a little more consolidated.
function randomArray(i, min, max) {
min = Math.ceil(min);
max = Math.floor(max);
let arr = Array.from({length: i}, () => Math.floor(Math.random()* (max - min)) + min);
return arr.sort();
}
let uniqueItems = [...new Set(randomArray(8, 0, 100))]
console.log(uniqueItems);
How about using object properties as a hash table? This way your best scenario is to only randomize 8 times. It would only be effective if you want a small part of the range of numbers. It's also much less memory intensive than Fisher-Yates because you don't have to allocate space for an array.
var ht={}, i=rands=8;
while ( i>0 || keys(ht).length<rands) ht[Math.ceil(Math.random()*100)]=i--;
alert(keys(ht));
I then found out that Object.keys(obj) is an ECMAScript 5 feature so the above is pretty much useless on the internets right now. Fear not, because I made it ECMAScript 3 compatible by adding a keys function like this.
if (typeof keys == "undefined")
{
var keys = function(obj)
{
props=[];
for (k in ht) if (ht.hasOwnProperty(k)) props.push(k);
return props;
}
}
var bombout=0;
var checkArr=[];
var arr=[];
while(arr.length < 8 && bombout<100){
bombout++;
var randomNumber=Math.ceil(Math.random()*100);
if(typeof checkArr[randomNumber] == "undefined"){
checkArr[randomNumber]=1;
arr.push(randomNumber);
}
}​
// untested - hence bombout
if you need more unique you must generate a array(1..100).
var arr=[];
function generateRandoms(){
for(var i=1;i<=100;i++) arr.push(i);
}
function extractUniqueRandom()
{
if (arr.length==0) generateRandoms();
var randIndex=Math.floor(arr.length*Math.random());
var result=arr[randIndex];
arr.splice(randIndex,1);
return result;
}
function extractUniqueRandomArray(n)
{
var resultArr=[];
for(var i=0;i<n;i++) resultArr.push(extractUniqueRandom());
return resultArr;
}
above code is faster:
extractUniqueRandomArray(50)=>
[2, 79, 38, 59, 63, 42, 52, 22, 78, 50, 39, 77, 1, 88, 40, 23, 48, 84, 91, 49, 4, 54, 93, 36, 100, 82, 62, 41, 89, 12, 24, 31, 86, 92, 64, 75, 70, 61, 67, 98, 76, 80, 56, 90, 83, 44, 43, 47, 7, 53]
Adding another better version of same code (accepted answer) with JavaScript 1.6 indexOf function. Do not need to loop thru whole array every time you are checking the duplicate.
var arr = []
while(arr.length < 8){
var randomnumber=Math.ceil(Math.random()*100)
var found=false;
if(arr.indexOf(randomnumber) > -1){found=true;}
if(!found)arr[arr.length]=randomnumber;
}
Older version of Javascript can still use the version at top
PS: Tried suggesting an update to the wiki but it was rejected. I still think it may be useful for others.
This is my personal solution :
<script>
var i, k;
var numbers = new Array();
k = Math.floor((Math.random()*8));
numbers[0]=k;
for (var j=1;j<8;j++){
k = Math.floor((Math.random()*8));
i=0;
while (i < numbers.length){
if (numbers[i] == k){
k = Math.floor((Math.random()*8));
i=0;
}else {i++;}
}
numbers[j]=k;
}
for (var j=0;j<8;j++){
alert (numbers[j]);
}
</script>
It randomly generates 8 unique array values (between 0 and 7), then displays them using an alert box.
function getUniqueRandomNos() {
var indexedArrayOfRandomNo = [];
for (var i = 0; i < 100; i++) {
var randNo = Math.random();
indexedArrayOfRandomNo.push([i, randNo]);
}
indexedArrayOfRandomNo.sort(function (arr1, arr2) {
return arr1[1] - arr2[1]
});
var uniqueRandNoArray = [];
for (i = 0; i < 8; i++) {
uniqueRandNoArray.push(indexedArrayOfRandomNo[i][0]);
}
return uniqueRandNoArray;
}
I think this method is different from methods given in most of the answers, so I thought I might add an answer here (though the question was asked 4 years ago).
We generate 100 random numbers, and tag each of them with numbers from 1 to 100. Then we sort these tagged random numbers, and the tags get shuffled randomly. Alternatively, as needed in this question, one could do away with just finding top 8 of the tagged random numbers. Finding top 8 items is cheaper than sorting the whole array.
One must note here, that the sorting algorithm influences this algorithm. If the sorting algorithm used is stable, there is slight bias in favor of smaller numbers. Ideally, we would want the sorting algorithm to be unstable and not even biased towards stability (or instability) to produce an answer with perfectly uniform probability distribution.
This can handle generating upto 20 digit UNIQUE random number
JS
var generatedNumbers = [];
function generateRandomNumber(precision) { // input --> number precision in integer
if (precision <= 20) {
var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
if (generatedNumbers.indexOf(randomNum) > -1) {
if (generatedNumbers.length == Math.pow(10, precision))
return "Generated all values with this precision";
return generateRandomNumber(precision);
} else {
generatedNumbers.push(randomNum);
return randomNum;
}
} else
return "Number Precision shoould not exceed 20";
}
generateRandomNumber(1);
jsFiddle
This solution uses the hash which is much more performant O(1) than checking if the resides in the array. It has extra safe checks too. Hope it helps.
function uniqueArray(minRange, maxRange, arrayLength) {
var arrayLength = (arrayLength) ? arrayLength : 10
var minRange = (minRange !== undefined) ? minRange : 1
var maxRange = (maxRange !== undefined) ? maxRange : 100
var numberOfItemsInArray = 0
var hash = {}
var array = []
if ( arrayLength > (maxRange - minRange) ) throw new Error('Cannot generate unique array: Array length too high')
while(numberOfItemsInArray < arrayLength){
// var randomNumber = Math.floor(Math.random() * (maxRange - minRange + 1) + minRange)
// following line used for performance benefits
var randomNumber = (Math.random() * (maxRange - minRange + 1) + minRange) << 0
if (!hash[randomNumber]) {
hash[randomNumber] = true
array.push(randomNumber)
numberOfItemsInArray++
}
}
return array
}
document.write(uniqueArray(1, 100, 8))
You can also do it with a one liner like this:
[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]
getRandom (min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
getNRandom (min, max, n) {
const numbers = []
if (min > max) {
return new Error('Max is gt min')
}
if (min === max) {
return [min]
}
if ((max - min) >= n) {
while (numbers.length < n) {
let rand = this.getRandom(min, max + 1)
if (numbers.indexOf(rand) === -1) {
numbers.push(rand)
}
}
}
if ((max - min) < n) {
for (let i = min; i <= max; i++) {
numbers.push(i)
}
}
return numbers
}
Using a Set is your fastest option. Here is a generic function for getting a unique random that uses a callback generator. Now it's fast and reusable.
// Get a unique 'anything'
let unique = new Set()
function getUnique(generator) {
let number = generator()
while (!unique.add(number)) {
number = generator()
}
return number;
}
// The generator. Return anything, not just numbers.
const between_1_100 = () => 1 + Math.floor(Math.random() * 100)
// Test it
for (var i = 0; i < 8; i++) {
const aNumber = getUnique(between_1_100)
}
// Dump the 'stored numbers'
console.log(Array.from(unique))
This is a implementation of Fisher Yates/Durstenfeld Shuffle, but without actual creation of a array thus reducing space complexity or memory needed, when the pick size is small compared to the number of elements available.
To pick 8 numbers from 100, it is not necessary to create a array of 100 elements.
Assuming a array is created,
From the end of array(100), get random number(rnd) from 1 to 100
Swap 100 and the random number rnd
Repeat step 1 with array(99)
If a array is not created, A hashMap may be used to remember the actual swapped positions. When the second random number generated is equal to the one of the previously generated numbers, the map provides the current value in that position rather than the actual value.
const getRandom_ = (start, end) => {
return Math.floor(Math.random() * (end - start + 1)) + start;
};
const getRealValue_ = (map, rnd) => {
if (map.has(rnd)) {
return getRealValue_(map, map.get(rnd));
} else {
return rnd;
}
};
const getRandomNumbers = (n, start, end) => {
const out = new Map();
while (n--) {
const rnd = getRandom_(start, end--);
out.set(getRealValue_(out, rnd), end + 1);
}
return [...out.keys()];
};
console.info(getRandomNumbers(8, 1, 100));
console.info(getRandomNumbers(8, 1, Math.pow(10, 12)));
console.info(getRandomNumbers(800000, 1, Math.pow(10, 15)));
Here is an example of random 5 numbers taken from a range of 0 to 100 (both 0 and 100 included) with no duplication.
let finals = [];
const count = 5; // Considering 5 numbers
const max = 100;
for(let i = 0; i < max; i++){
const rand = Math.round(Math.random() * max);
!finals.includes(rand) && finals.push(rand)
}
finals = finals.slice(0, count)

Why isn't my attempted solution working?

When I run the code in the console, the browser just stops working (am assuming stack overflow).
I've come up with several different algorithms for solving this problem, but I thought this one would not cause any SOs.
The problem:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1 3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
Failing solution:
function divisors(n){
var counter = 0;
var triangle = 3;
var triangle_add = 2;
while (counter < n){
for (var i = 1; i = triangle; i++){
if (triangle % i === 0){
counter++;
}
};
if (counter < n){
triangle_add++;
triangle = triangle + triangle_add;
counter = 0;
};
};
return triangle;
};
console.log(divisors(501));
Your solution is not working because, most probably, it is very slow. This problem can be solved much faster by the following method:
Find all the prime numbers smaller than some N (put, for example, N=100'000) using Sieve of Eratosthenes. It is quite fast.
As we know from elementary math each number can be written in the form X=p1^i1*p2^i2*...*pn^in where pj is prime number and ij is the power of corresponding prime number. The number of divisors of X is equal to (i1+1)*(i2+1)*...*(in+1) since that many different ways we can form a number which will be divisor of X. Having an array of prime numbers the number of divisors for X can be calculated quite fast (the code still has place to be optimized):
int divisorCount(long long X)
{
int c = 1;
for (int i = 0; PRIMES[i] <= X; ++i)
{
int pr = PRIMES[i];
if (X % pr == 0)
{
int p = 1;
long long r = X;
while (r % pr == 0)
{
r = r / pr;
++p;
}
c *= p;
}
}
return c;
}
Iterate through all triangle numbers and count divisor numbers for them using the above function. The i-th triangle number is i * (i + 1) / 2, so no need to keep a variable, increment it and add it each time.

Generate unique random numbers between 1 and 100

How can I generate some unique random numbers between 1 and 100 using JavaScript?
For example: To generate 8 unique random numbers and store them to an array, you can simply do this:
var arr = [];
while(arr.length < 8){
var r = Math.floor(Math.random() * 100) + 1;
if(arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);
Populate an array with the numbers 1 through 100.
Shuffle it.
Take the first 8 elements of the resulting array.
Modern JS Solution using Set (and average case O(n))
const nums = new Set();
while(nums.size !== 8) {
nums.add(Math.floor(Math.random() * 100) + 1);
}
console.log([...nums]);
Another approach is to generate an 100 items array with ascending numbers and sort it randomly. This leads actually to a really short and (in my opinion) simple snippet.
const numbers = Array(100).fill().map((_, index) => index + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));
Generate permutation of 100 numbers and then choose serially.
Use Knuth Shuffle(aka the Fisher-Yates shuffle) Algorithm.
JavaScript:
function fisherYates ( myArray,stop_count ) {
var i = myArray.length;
if ( i == 0 ) return false;
int c = 0;
while ( --i ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var tempi = myArray[i];
var tempj = myArray[j];
myArray[i] = tempj;
myArray[j] = tempi;
// Edited thanks to Frerich Raabe
c++;
if(c == stop_count)return;
}
}
CODE COPIED FROM LINK.
EDIT:
Improved code:
function fisherYates(myArray,nb_picks)
{
for (i = myArray.length-1; i > 1 ; i--)
{
var r = Math.floor(Math.random()*i);
var t = myArray[i];
myArray[i] = myArray[r];
myArray[r] = t;
}
return myArray.slice(0,nb_picks);
}
Potential problem:
Suppose we have array of 100 numbers {e.g. [1,2,3...100]} and we stop swapping after 8 swaps;
then most of the times array will look like {1,2,3,76,5,6,7,8,...numbers here will be shuffled ...10}.
Because every number will be swapped with probability 1/100 so
prob. of swapping first 8 numbers is 8/100 whereas prob. of swapping other 92 is 92/100.
But if we run algorithm for full array then we are sure (almost)every entry is swapped.
Otherwise we face a question : which 8 numbers to choose?
The above techniques are good if you want to avoid a library, but depending if you would be alright with a library, I would suggest checking out Chance for generating random stuff in JavaScript.
Specifically to solve your question, using Chance it's as easy as:
// One line!
var uniques = chance.unique(chance.natural, 8, {min: 1, max: 100});
// Print it out to the document for this snippet so we can see it in action
document.write(JSON.stringify(uniques));
<script src="http://chancejs.com/chance.min.js"></script>
Disclaimer, as the author of Chance, I am a bit biased ;)
To avoid any long and unreliable shuffles, I'd do the following...
Generate an array that contains the number between 1 and 100, in order.
Generate a random number between 1 and 100
Look up the number at this index in the array and store in your results
Remove the elemnt from the array, making it one shorter
Repeat from step 2, but use 99 as the upper limit of the random number
Repeat from step 2, but use 98 as the upper limit of the random number
Repeat from step 2, but use 97 as the upper limit of the random number
Repeat from step 2, but use 96 as the upper limit of the random number
Repeat from step 2, but use 95 as the upper limit of the random number
Repeat from step 2, but use 94 as the upper limit of the random number
Repeat from step 2, but use 93 as the upper limit of the random number
Voila - no repeated numbers.
I may post some actual code later, if anybody is interested.
Edit: It's probably the competitive streak in me but, having seen the post by #Alsciende, I couldn't resist posting the code that I promised.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>8 unique random number between 1 and 100</title>
<script type="text/javascript" language="Javascript">
function pick(n, min, max){
var values = [], i = max;
while(i >= min) values.push(i--);
var results = [];
var maxIndex = max;
for(i=1; i <= n; i++){
maxIndex--;
var index = Math.floor(maxIndex * Math.random());
results.push(values[index]);
values[index] = values[maxIndex];
}
return results;
}
function go(){
var running = true;
do{
if(!confirm(pick(8, 1, 100).sort(function(a,b){return a - b;}))){
running = false;
}
}while(running)
}
</script>
</head>
<body>
<h1>8 unique random number between 1 and 100</h1>
<p><button onclick="go()">Click me</button> to start generating numbers.</p>
<p>When the numbers appear, click OK to generate another set, or Cancel to stop.</p>
</body>
I would do this:
function randomInt(min, max) {
return Math.round(min + Math.random()*(max-min));
}
var index = {}, numbers = [];
for (var i=0; i<8; ++i) {
var number;
do {
number = randomInt(1, 100);
} while (index.hasOwnProperty("_"+number));
index["_"+number] = true;
numbers.push(number);
}
delete index;
This is a very generic function I have written to generate random unique/non-unique integers for an array. Assume the last parameter to be true in this scenario for this answer.
/* Creates an array of random integers between the range specified
len = length of the array you want to generate
min = min value you require
max = max value you require
unique = whether you want unique or not (assume 'true' for this answer)
*/
function _arrayRandom(len, min, max, unique) {
var len = (len) ? len : 10,
min = (min !== undefined) ? min : 1,
max = (max !== undefined) ? max : 100,
unique = (unique) ? unique : false,
toReturn = [], tempObj = {}, i = 0;
if(unique === true) {
for(; i < len; i++) {
var randomInt = Math.floor(Math.random() * ((max - min) + min));
if(tempObj['key_'+ randomInt] === undefined) {
tempObj['key_'+ randomInt] = randomInt;
toReturn.push(randomInt);
} else {
i--;
}
}
} else {
for(; i < len; i++) {
toReturn.push(Math.floor(Math.random() * ((max - min) + min)));
}
}
return toReturn;
}
Here the 'tempObj' is a very useful obj since every random number generated will directly check in this tempObj if that key already exists, if not, then we reduce the i by one since we need 1 extra run since the current random number already exists.
In your case, run the following
_arrayRandom(8, 1, 100, true);
That's all.
Shuffling the numbers from 1 to 100 is the right basic strategy, but if you need only 8 shuffled numbers, there's no need to shuffle all 100 numbers.
I don't know Javascript very well, but I believe it's easy to create an array of 100 nulls quickly. Then, for 8 rounds, you swap the n'th element of the array (n starting at 0) with a randomly selected element from n+1 through 99. Of course, any elements not populated yet mean that the element would really have been the original index plus 1, so that's trivial to factor in. When you're done with the 8 rounds, the first 8 elements of your array will have your 8 shuffled numbers.
var arr = []
while(arr.length < 8){
var randomnumber=Math.ceil(Math.random()*100)
if(arr.indexOf(randomnumber) === -1){arr.push(randomnumber)}
}
document.write(arr);
shorter than other answers I've seen
Implementing this as a generator makes it pretty nice to work with. Note, this implementation differs from ones that require the entire input array to be shuffled first.
This sample function works lazily, giving you 1 random item per iteration up to N items you ask for. This is nice because if you just want 3 items from a list of 1000, you don't have to touch all 1000 items first.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let ys = xs.slice(0);
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield ys.splice(i,1)[0];
n--; len--;
}
}
// example inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// get 3 random items
for (let i of sample(3) (items))
console.log(i); // f g c
// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
console.log(i); // 3 8 7
// shuffle an array
const shuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]
I chose to implement sample in a way that does not mutate the input array, but you could easily argue that a mutating implementation is favourable.
For example, the shuffle function might wish to mutate the original input array. Or you might wish to sample from the same input at various times, updating the input each time.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield xs.splice(i,1)[0];
n--; len--;
}
}
// deal :: [Card] -> [Card]
const deal = xs => Array.from(sample (2) (xs));
// setup a deck of cards (13 in this case)
// cards :: [Card]
let cards = 'A234567890JQK'.split('');
// deal 6 players 2 cards each
// players :: [[Card]]
let players = Array.from(Array(6), $=> deal(cards))
console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]
// `cards` has been mutated. only 1 card remains in the deck
console.log(cards);
// [3]
sample is no longer a pure function because of the array input mutation, but in certain circumstances (demonstrated above) it might make more sense.
Another reason I chose a generator instead of a function that just returns an array is because you may want to continue sampling until some specific condition.
Perhaps I want the first prime number from a list of 1,000,000 random numbers.
"How many should I sample?" – you don't have to specify
"Do I have to find all the primes first and then select a random prime?" – Nope.
Because we're working with a generator, this task is trivial
const randomPrimeNumber = listOfNumbers => {
for (let x of sample(Infinity) (listOfNumbers)) {
if (isPrime(x))
return x;
}
return NaN;
}
This will continuously sample 1 random number at a time, x, check if it's prime, then return x if it is. If the list of numbers is exhausted before a prime is found, NaN is returned.
Note:
This answer was originally shared on another question that was closed as a duplicate of this one. Because it's very different from the other solutions provided here, I've decided to share it here as well
var numbers = [];
for (let i = 0; i < 8; i++) {
let a = true,
n;
while(a) {
n = Math.floor(Math.random() * 100) + 1;
a = numbers.includes(n);
}
numbers.push(n);
}
console.log(numbers);
Same permutation algorithm as The Machine Charmer, but with a prototyped implementation. Better suited to large number of picks. Uses js 1.7 destructuring assignment if available.
// swaps elements at index i and j in array this
// swapping is easy on js 1.7 (feature detection)
Array.prototype.swap = (function () {
var i=0, j=1;
try { [i,j]=[j,i]; }
catch (e) {}
if(i) {
return function(i,j) {
[this[i],this[j]] = [this[j],this[i]];
return this;
}
} else {
return function(i,j) {
var temp = this[i];
this[i] = this[j];
this[j] = temp;
return this;
}
}
})();
// shuffles array this
Array.prototype.shuffle = function() {
for(var i=this.length; i>1; i--) {
this.swap(i-1, Math.floor(i*Math.random()));
}
return this;
}
// returns n unique random numbers between min and max
function pick(n, min, max) {
var a = [], i = max;
while(i >= min) a.push(i--);
return a.shuffle().slice(0,n);
}
pick(8,1,100);
Edit:
An other proposition, better suited to small number of picks, based on belugabob's answer. To guarantee uniqueness, we remove the picked numbers from the array.
// removes n random elements from array this
// and returns them
Array.prototype.pick = function(n) {
if(!n || !this.length) return [];
var i = Math.floor(this.length*Math.random());
return this.splice(i,1).concat(this.pick(n-1));
}
// returns n unique random numbers between min and max
function pick(n, min, max) {
var a = [], i = max;
while(i >= min) a.push(i--);
return a.pick(n);
}
pick(8,1,100);
for arrays with holes like this [,2,,4,,6,7,,]
because my problem was to fill these holes. So I modified it as per my need :)
the following modified solution worked for me :)
var arr = [,2,,4,,6,7,,]; //example
while(arr.length < 9){
var randomnumber=Math.floor(Math.random()*9+1);
var found=false;
for(var i=0;i<arr.length;i++){
if(arr[i]==randomnumber){found=true;break;}
}
if(!found)
for(k=0;k<9;k++)
{if(!arr[k]) //if it's empty !!MODIFICATION
{arr[k]=randomnumber; break;}}
}
alert(arr); //outputs on the screen
The best earlier answer is the answer by sje397. You will get as good random numbers as you can get, as quick as possible.
My solution is very similar to his solution. However, sometimes you want the random numbers in random order, and that is why I decided to post an answer. In addition, I provide a general function.
function selectKOutOfN(k, n) {
if (k>n) throw "k>n";
var selection = [];
var sorted = [];
for (var i = 0; i < k; i++) {
var rand = Math.floor(Math.random()*(n - i));
for (var j = 0; j < i; j++) {
if (sorted[j]<=rand)
rand++;
else
break;
}
selection.push(rand);
sorted.splice(j, 0, rand);
}
return selection;
}
alert(selectKOutOfN(8, 100));
Here is my ES6 version I cobbled together. I'm sure it can be a little more consolidated.
function randomArray(i, min, max) {
min = Math.ceil(min);
max = Math.floor(max);
let arr = Array.from({length: i}, () => Math.floor(Math.random()* (max - min)) + min);
return arr.sort();
}
let uniqueItems = [...new Set(randomArray(8, 0, 100))]
console.log(uniqueItems);
How about using object properties as a hash table? This way your best scenario is to only randomize 8 times. It would only be effective if you want a small part of the range of numbers. It's also much less memory intensive than Fisher-Yates because you don't have to allocate space for an array.
var ht={}, i=rands=8;
while ( i>0 || keys(ht).length<rands) ht[Math.ceil(Math.random()*100)]=i--;
alert(keys(ht));
I then found out that Object.keys(obj) is an ECMAScript 5 feature so the above is pretty much useless on the internets right now. Fear not, because I made it ECMAScript 3 compatible by adding a keys function like this.
if (typeof keys == "undefined")
{
var keys = function(obj)
{
props=[];
for (k in ht) if (ht.hasOwnProperty(k)) props.push(k);
return props;
}
}
var bombout=0;
var checkArr=[];
var arr=[];
while(arr.length < 8 && bombout<100){
bombout++;
var randomNumber=Math.ceil(Math.random()*100);
if(typeof checkArr[randomNumber] == "undefined"){
checkArr[randomNumber]=1;
arr.push(randomNumber);
}
}​
// untested - hence bombout
if you need more unique you must generate a array(1..100).
var arr=[];
function generateRandoms(){
for(var i=1;i<=100;i++) arr.push(i);
}
function extractUniqueRandom()
{
if (arr.length==0) generateRandoms();
var randIndex=Math.floor(arr.length*Math.random());
var result=arr[randIndex];
arr.splice(randIndex,1);
return result;
}
function extractUniqueRandomArray(n)
{
var resultArr=[];
for(var i=0;i<n;i++) resultArr.push(extractUniqueRandom());
return resultArr;
}
above code is faster:
extractUniqueRandomArray(50)=>
[2, 79, 38, 59, 63, 42, 52, 22, 78, 50, 39, 77, 1, 88, 40, 23, 48, 84, 91, 49, 4, 54, 93, 36, 100, 82, 62, 41, 89, 12, 24, 31, 86, 92, 64, 75, 70, 61, 67, 98, 76, 80, 56, 90, 83, 44, 43, 47, 7, 53]
Adding another better version of same code (accepted answer) with JavaScript 1.6 indexOf function. Do not need to loop thru whole array every time you are checking the duplicate.
var arr = []
while(arr.length < 8){
var randomnumber=Math.ceil(Math.random()*100)
var found=false;
if(arr.indexOf(randomnumber) > -1){found=true;}
if(!found)arr[arr.length]=randomnumber;
}
Older version of Javascript can still use the version at top
PS: Tried suggesting an update to the wiki but it was rejected. I still think it may be useful for others.
This is my personal solution :
<script>
var i, k;
var numbers = new Array();
k = Math.floor((Math.random()*8));
numbers[0]=k;
for (var j=1;j<8;j++){
k = Math.floor((Math.random()*8));
i=0;
while (i < numbers.length){
if (numbers[i] == k){
k = Math.floor((Math.random()*8));
i=0;
}else {i++;}
}
numbers[j]=k;
}
for (var j=0;j<8;j++){
alert (numbers[j]);
}
</script>
It randomly generates 8 unique array values (between 0 and 7), then displays them using an alert box.
function getUniqueRandomNos() {
var indexedArrayOfRandomNo = [];
for (var i = 0; i < 100; i++) {
var randNo = Math.random();
indexedArrayOfRandomNo.push([i, randNo]);
}
indexedArrayOfRandomNo.sort(function (arr1, arr2) {
return arr1[1] - arr2[1]
});
var uniqueRandNoArray = [];
for (i = 0; i < 8; i++) {
uniqueRandNoArray.push(indexedArrayOfRandomNo[i][0]);
}
return uniqueRandNoArray;
}
I think this method is different from methods given in most of the answers, so I thought I might add an answer here (though the question was asked 4 years ago).
We generate 100 random numbers, and tag each of them with numbers from 1 to 100. Then we sort these tagged random numbers, and the tags get shuffled randomly. Alternatively, as needed in this question, one could do away with just finding top 8 of the tagged random numbers. Finding top 8 items is cheaper than sorting the whole array.
One must note here, that the sorting algorithm influences this algorithm. If the sorting algorithm used is stable, there is slight bias in favor of smaller numbers. Ideally, we would want the sorting algorithm to be unstable and not even biased towards stability (or instability) to produce an answer with perfectly uniform probability distribution.
This can handle generating upto 20 digit UNIQUE random number
JS
var generatedNumbers = [];
function generateRandomNumber(precision) { // input --> number precision in integer
if (precision <= 20) {
var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
if (generatedNumbers.indexOf(randomNum) > -1) {
if (generatedNumbers.length == Math.pow(10, precision))
return "Generated all values with this precision";
return generateRandomNumber(precision);
} else {
generatedNumbers.push(randomNum);
return randomNum;
}
} else
return "Number Precision shoould not exceed 20";
}
generateRandomNumber(1);
jsFiddle
This solution uses the hash which is much more performant O(1) than checking if the resides in the array. It has extra safe checks too. Hope it helps.
function uniqueArray(minRange, maxRange, arrayLength) {
var arrayLength = (arrayLength) ? arrayLength : 10
var minRange = (minRange !== undefined) ? minRange : 1
var maxRange = (maxRange !== undefined) ? maxRange : 100
var numberOfItemsInArray = 0
var hash = {}
var array = []
if ( arrayLength > (maxRange - minRange) ) throw new Error('Cannot generate unique array: Array length too high')
while(numberOfItemsInArray < arrayLength){
// var randomNumber = Math.floor(Math.random() * (maxRange - minRange + 1) + minRange)
// following line used for performance benefits
var randomNumber = (Math.random() * (maxRange - minRange + 1) + minRange) << 0
if (!hash[randomNumber]) {
hash[randomNumber] = true
array.push(randomNumber)
numberOfItemsInArray++
}
}
return array
}
document.write(uniqueArray(1, 100, 8))
You can also do it with a one liner like this:
[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]
getRandom (min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
getNRandom (min, max, n) {
const numbers = []
if (min > max) {
return new Error('Max is gt min')
}
if (min === max) {
return [min]
}
if ((max - min) >= n) {
while (numbers.length < n) {
let rand = this.getRandom(min, max + 1)
if (numbers.indexOf(rand) === -1) {
numbers.push(rand)
}
}
}
if ((max - min) < n) {
for (let i = min; i <= max; i++) {
numbers.push(i)
}
}
return numbers
}
Using a Set is your fastest option. Here is a generic function for getting a unique random that uses a callback generator. Now it's fast and reusable.
// Get a unique 'anything'
let unique = new Set()
function getUnique(generator) {
let number = generator()
while (!unique.add(number)) {
number = generator()
}
return number;
}
// The generator. Return anything, not just numbers.
const between_1_100 = () => 1 + Math.floor(Math.random() * 100)
// Test it
for (var i = 0; i < 8; i++) {
const aNumber = getUnique(between_1_100)
}
// Dump the 'stored numbers'
console.log(Array.from(unique))
This is a implementation of Fisher Yates/Durstenfeld Shuffle, but without actual creation of a array thus reducing space complexity or memory needed, when the pick size is small compared to the number of elements available.
To pick 8 numbers from 100, it is not necessary to create a array of 100 elements.
Assuming a array is created,
From the end of array(100), get random number(rnd) from 1 to 100
Swap 100 and the random number rnd
Repeat step 1 with array(99)
If a array is not created, A hashMap may be used to remember the actual swapped positions. When the second random number generated is equal to the one of the previously generated numbers, the map provides the current value in that position rather than the actual value.
const getRandom_ = (start, end) => {
return Math.floor(Math.random() * (end - start + 1)) + start;
};
const getRealValue_ = (map, rnd) => {
if (map.has(rnd)) {
return getRealValue_(map, map.get(rnd));
} else {
return rnd;
}
};
const getRandomNumbers = (n, start, end) => {
const out = new Map();
while (n--) {
const rnd = getRandom_(start, end--);
out.set(getRealValue_(out, rnd), end + 1);
}
return [...out.keys()];
};
console.info(getRandomNumbers(8, 1, 100));
console.info(getRandomNumbers(8, 1, Math.pow(10, 12)));
console.info(getRandomNumbers(800000, 1, Math.pow(10, 15)));
Here is an example of random 5 numbers taken from a range of 0 to 100 (both 0 and 100 included) with no duplication.
let finals = [];
const count = 5; // Considering 5 numbers
const max = 100;
for(let i = 0; i < max; i++){
const rand = Math.round(Math.random() * max);
!finals.includes(rand) && finals.push(rand)
}
finals = finals.slice(0, count)

Categories