How to generate 4 random non-repeating numbers from 0-9? - javascript

I want to get a random digit from 0-9 and have it popped so it doesn't get repeated but I find that after the the second number is pushed it doesn't have it's number popped. Instead, some other number not yet selected is popped giving room for a repeat.
var yourNum = [],
oppNum = [],
choose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function chooseRandomNumber() {
return choose[Math.floor(Math.random() * choose.length)];
}
for (var i = 0; i < 4; i++) {
if (i === 0) {
yourNum.push(chooseRandomNumber());
if (yourNum[yourNum.length - 1] === 9) {
choose.pop();
} else {
choose.splice(yourNum[0], 1);
}
} else if (i === 1) {
yourNum.push(chooseRandomNumber());
if (yourNum[yourNum.length - 1] === 9) {
choose.pop();
} else {
choose.splice(yourNum[1], 1);
}
} else if (i === 2) {
yourNum.push(chooseRandomNumber());
if (yourNum[yourNum.length - 1] === 9) {
choose.pop();
} else {
choose.splice(yourNum[2], 1);
}
} else if (i === 3) {
yourNum.push(chooseRandomNumber());
if (yourNum[yourNum.length - 1] === 9) {
choose.pop();
} else {
choose.splice(yourNum[3], 1);
}
}
}
console.log(choose);
console.log(yourNum);

function getRand(min, max, result) {
result = result || [];
if(result.length == 4) {
return result;
}
var rand = Math.floor(Math.random()*max) + min;
if(result.indexOf(rand) === -1) {
result.push(rand);
}
return getRand(min, max, result);
}
var result = getRand(1,9);
console.log(result);

Your whole approach is way to complicated and unperformant.
A better approach:
//first we need a shuffle function
function shuffle(array){
for(var i = array.length, j, tmp; i--; ){
j = 0|(Math.random() * i);
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
return array;
}
//now let's define a sequence of possible values
var numset = [0,1,2,3,4,5,6,7,8,9];
//shuffle the sequence and take the first 4 values
var fourRandomValues = shuffle(numset).slice(0,4);
console.log("four random values: " + fourRandomValues);
//doing this multiple times:
for(var values = []; values.length < 10;){
//shuffle again, and take the values that are now at the beginning of this sequence
values.push( shuffle(numset).slice(0,4) );
}
console.log("more random values: \n" + values.join("\n"));
Edit:
to address holi-java's approach by implementing sort of an Iterator, I'll add a way to do this with ES6 Iterators/Generators
Since Generators can be unlimited sequences we need to account for that. We do that by buffering a limited amount of values and returning them randomly; basically a shifiting frame of shuffled values.
function *shuffled(iterable, bufferSize = 256){
var buffer, numValues = 0, randomIndex;
if(Array.isArray(iterable) && iterable.length <= bufferSize){
//an optimization for (small) Arrays:
buffer = iterable.slice();
numValues = iterable.length;
}else{
buffer = Array( bufferSize )
for(var value of iterable){
//push value from the iterable to the buffer
buffer[numValues++] = value;
//buffer is full, yield a random value
if(numValues === bufferSize){
//choose a random value from the buffer
randomIndex = 0|(Math.random() * (numValues-1));
//yield it
yield buffer[randomIndex];
//overwrite the value with the last index
//that's cheaper than pop() and splice()
buffer[randomIndex] = buffer[--numValues];
}
}
}
//iterable doesn't provide any more values
//flush the buffer in a random order
while(numValues){
randomIndex = 0|(Math.random() * (numValues-1));
yield buffer[randomIndex];
buffer[randomIndex] = buffer[--numValues];
}
}
//every Array is a valid iterator
for(var v of shuffled([0,1,2,3,4,5,6,7,8,9]))
console.log(v);
That way we can shuffle a stream of values without first caching all the values in an array.
pro: memory efficient
possible problem: if the buffer's to small the result doesn't feel random anymore since values that are generated late in the sequence simply can not be shifted entirely to the start. You see some noise but it doesn't feel random anymore.
now let's take a jump into potentially infinite sequences:
// *shuffled again, for this snippet
function *shuffled(iterable, bufferSize = 256){
var buffer, numValues = 0, randomIndex;
if(Array.isArray(iterable) && iterable.length <= bufferSize){
buffer = iterable.slice();
numValues = iterable.length;
}else{
buffer = Array( bufferSize )
for(var value of iterable){
buffer[numValues++] = value;
if(numValues === bufferSize){
randomIndex = 0|(Math.random() * (numValues-1));
yield buffer[randomIndex];
buffer[randomIndex] = buffer[--numValues];
}
}
}
while(numValues){
randomIndex = 0|(Math.random() * (numValues-1));
yield buffer[randomIndex];
buffer[randomIndex] = buffer[--numValues];
}
}
//creates an infinite sequence of numbers
function *count(){
for(var index = 0; true;)
yield index++;
}
//like limits a iterator but for iterators
function *take(n, iterator){
for(var value of iterator){
if(n-- > 0) yield value;
else break;
}
}
//create an (infinite) counter and convert it into a generator of shuffled values
//with a bufferSize of 256 entries (play a bit with that value)
var shuffledSequence = shuffled(count(), 256);
//to convert that into an Array we take the first 1000 values generated from that generator
var array = [...take(1000, shuffledSequence)];
//and log it
console.log(array.toString());

what do you mean like this below:
function next() {
function all() {
return [].concat(Array(10).fill(null).map(function (_, index) {
return index;
}));
}
function random(start, end) {
return parseInt(Math.random() * (end + 1 - start)) + start;
}
var self = this;
self.all = self.all && self.all.length && self.all || all().sort(function(){
return random(-1, 1);
});
return self.all.shift();}
var results=Array(4).fill(null).map(next);
console.log(results);

my be this is better for browser to run.
var it = {
next: function () {
var self = this;
self._all = self._all && self._all.length && self._all || self.shuffle(self.all());
return self._all.shift();
},
all: function () {
return [0,1,2,3,4,5,6,7,8,9];
},
random: function (start, end) {
if (!end && end != 0) {
end = start;
start = 0;
}
return parseInt(Math.random() * (end + 1 - start)) + start;
},
shuffle: function (array) {
var self = this;
for (var i = array.length - 1; i > 0; --i) {
self.swap(array, i, self.random(i));
}
return array;
},
swap: function (array, i, j) {
var tmp = array[i];
array[i] = array[j];
array[j] = tmp;
},
reset: function () {
this._all = null;
}
};
for (var i = 0; i < 10; i++) {
var results=[];
for(var n=0;n<4;n++) results.push(it.next());
console.log("retain:"+it._all + '>>generated:' + results);
it.reset();
}

Edit
Takes four unique numbers out of the choose array. Is that what you're after?
var yourNum = [],
oppNum = [],
choose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function chooseRandomNumber() {
return choose[Math.floor(Math.random() * choose.length)];
}
var rand;
for (var i = 0; i < 4; i++) {
rand = chooseRandomNumber();
yourNum.push(rand);
choose.splice(choose.indexOf(rand), 1);
}
console.log(choose);
console.log(yourNum);
Old approach:
var start = 0, end = 9;
function generate(count) {
var nums = [],
random;
for (var i = 0; i < count; i++) {
while (!random || nums.indexOf(random) !== -1) {
random = Math.floor(Math.random() * (end + 1)) + start;
}
nums.push(random);
}
return nums;
}
console.log(
generate(4)
);

Demo:
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
var yourNums = [];
var choose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < 4; i++) {
yourNums = yourNums.concat(choose.splice(getRandomInt(0, choose.length), 1))
}
console.log("yourNums is:")
console.log(yourNums);
console.log("===")
console.log("choose is:")
console.log(choose);

Related

Javascript/ variable place/ what is wrong with the code

I want to write a Generator for Fibonacci numbers in Javascript;
0,1,1,2,5,7,12..... (to make the sequence you have to add the last two numbers)
But I have this problem when I assign the the output.length to a variable the code is not working, if I write it down straight instead of "newNumber" the code down is however working, but I don't understand what is wrong with the first one. Is it something wrong with the place of the variables?
function fibonacciGenerator(n) {
var output = [];
var lastNumber = output[output.length - 1];
var nPrev = output[output.length - 2];
var newNumber = lastNumber + nPrev;
if (n === 1) {
output = [0];
} else if (n === 2) {
output = [0, 1];
} else {
output = [0, 1];
for (var i = 2; i < n; i++) {
output.push(newNumber);
}
}
return output
}
console.log(fibonacciGenerator(5));
function fibonacciGen(n) {
const output = [0, 1];
// Return an empty array if n is less than 1
if (n < 1) {
return [];
}
// If n is 1 or 2, we can return the array now
if (n <2) {
return output;
}
// Loop through the remaining numbers in the sequence
for (let i = 2; i < n; i++) {
// Calculate the next number in the sequence
let lastNumber = output[output.length - 1];
let nPrev = output[output.length - 2];
let newNumber = lastNumber + nPrev;
// Add the new number to the output array
output.push(newNumber);
}
// Return the output array
return output;
}
console.log(fibonacciGen(5));
you have to declare your logic of next term in loop because first time length of output is zero
function fibonacciGenerator (n) {
var output =[];
if (n < 1) {
return [];
}
if (n===1){
output=[0];
}
else if (n===2){
output=[0,1];
}
else{
output=[0,1];
for( var i = 2; i < n; i++){
var lastNumber=output[output.length-1];
var nPrev=output[output.length-2];
var newNumber=lastNumber+nPrev;
output.push(newNumber);
}
}
return output
}

JavaScript find longest Uniform Substring

Trying to find longest Uniform Substring.
Suppose I have abbbccda then it should return [1, 3]. Because it starts from index 1 and is 3 characters long.
Other Example:
"10000111" => [ 1, 4 ]
"aabbbbbCdAA" => [ 2, 5 ]
I tried:
function longestUniformSubstring(input){
if(input){
let arr = input.split("");
let obj = {};
arr.map((ele, index) => {
return obj[ele] ? obj[ele][1]++ : obj[ele] = [index,1];
});
console.log(obj);
return obj;
}
else {
return [ -1, 0 ];
}
}
longestUniformSubstring("abbbccda");
It gives me object of all character But, no idea how can i get with highest length.
You could iterate the string and check the previous character and continue if the caracters are equal.
If not, check the length and assign a new logest array, if necessary and check if a longer string is not possible, then break the loop.
Assign the new found character and set a new start value to the actual index.
function longestUniformSubstring(input) {
var longest = [-1, 0],
start = 0,
character = input[0];
for (let i = 1; i <= input.length; i++) {
if (input[i] === character) continue;
if (longest[1] < i - start) {
longest = [start, i - start];
if (i + i - start >= input.length) break;
}
character = input[i];
start = i;
}
return longest;
}
console.log(...longestUniformSubstring("aabbbbbCdAA"));
console.log(...longestUniformSubstring("ab"));
console.log(...longestUniformSubstring("aa"));
console.log(...longestUniformSubstring(""));
You can keep track of the character being evaluated. When it changes, check to see if its repetition is larger than previous repetitions. If so, store the new version and move on.
function longestUniformSubstring(input){
const result = [-1, 0];
let currentCharacter = '';
let currentIndex = -1;
let currentCount = 0;
(input || '').split('').forEach((character, index) => {
if (character == currentCharacter) {
currentCount++;
} else {
if (currentCount > result[1]) {
result[0] = currentIndex;
result[1] = currentCount;
}
currentCharacter = character;
currentIndex = index;
currentCount = 1;
}
});
if (currentCount > result[1]) {
result[0] = currentIndex;
result[1] = currentCount;
}
return result;
}
console.log(longestUniformSubstring("abbbccdddda"));
You can write the logic like this, this works at my end.
function longestUniformSubstring(input) {
let length = input.length;
let firstLetter = input[0];
let sIndex = 0;
let eIndex = 0;
let resultIndex = 0;
let resultLength = 0;
while(sIndex < length && eIndex < length) {
if (input[eIndex] === firstLetter) {
eIndex++;
if (eIndex - sIndex > resultLength) {
resultLength = eIndex - sIndex;
resultIndex = sIndex;
}
}
else {
sIndex++;
if (input[sIndex] !== firstLetter)
{
firstLetter = input[sIndex];
}
}
}
return [resultIndex, resultLength];
}
console.log(longestUniformSubstring('AABBBBBCC'));
You can create a queue, to keep track of elements. and pop once all the iteration has been done.
function longestUniformSubstring(input) {
if (!input) return [-1, 0];
let queue = [];
const map = {};
for (let index = 0; index < input.length; index++) {
const char = input[index];
if (!map[char]) map[char] = [index, 1];
else {
map[char][1] += 1;
}
const max = queue[0];
if (max && max[1] < map[char][1]) {
queue.unshift(map[char]);
} else {
queue.push(map[char]);
}
}
return queue.shift();
}
console.log(longestUniformSubstring("abbbccda"));
console.log(longestUniformSubstring("10000111"));
console.log(longestUniformSubstring("aabbbbbCdAA"));
The dirty one, keep track of longest
function longestUniformSubstring(input) {
if (!input) return [-1, 0];
let max = ["", -1, 0];
let map = {}
for (let index = 0; index < input.length; index++) {
const char = input[index];
if (!map[char]) map[char] = [index, 1];
else {
map[char][1] += 1;
}
if (max[2] < map[char][1]) {
max = [char, map[char][0], map[char][1]];
}
}
return [max[1], max[2]];
}
console.log(longestUniformSubstring("abbbccda"));
console.log(longestUniformSubstring("10000111"));
console.log(longestUniformSubstring("aabbbbbCdAA"));
You can use .reduce to count. .sort method to get the min or max.
function longestUniformSubstring(input) {
if (!input) return [-1, 0];
const map = input.split("").reduce((m, item, index) => {
if (!m[item]) m[item] = [index, 1];
else {
m[item][1] += 1;
}
return m;
}, {});
return Object.values(map).sort(([_, i], [__, j]) => j - i)[0];
}
console.log(longestUniformSubstring("abbbccda"));
console.log(longestUniformSubstring("10000111"));
console.log(longestUniformSubstring("aabbbbbCdAA"));
You can just iterate over
function longestUniformSubstring(input){
if(!input) {
return [-1, 0];
}
let lastIndex=0;
let lastLength=1;
let currIndex=0;
let currLength=0;
for (let i = 1; i < input.length; i++) {
if(input.charAt(i)===input.charAt(i-1)) {
currLength++;
} else {
if (currLength > lastLength) {
lastIndex = currIndex;
lastLength = currLength;
}
currIndex = i;
currLength = 1;
}
}
return [lastIndex, lastLength];
}

Fibonacci series in JavaScript

function fib(n) {
const result = [0, 1];
for (var i = 2; i <= n; i++) {
const a = (i - 1);
const b = (i - 2);
result.push(a + b);
}
return result[n];
}
console.log(fib(8));
The output of the code above is 13. I don't understand the for loop part. In very first iteration i = 2, but after second iteration i = 3 so a = 2 and b = 1 and third iteration i = 4 so a = 3, b = 2, and so on... If it's going on final sequence will be :
[0, 1, 1, 3, 5, 7, 9, 11], which is incorrect. The correct sequence will be [0, 1, 1, 2, 3, 5, 8, 13]
You were not using the previous two numbers that are already in the array to > generate the new fibonacci number to be inserted into the array.
https://www.mathsisfun.com/numbers/fibonacci-sequence.html
Here I have used the sum of result[i-2] and result[i-1] to generate the new fibonacci number and pushed it into the array.
Also to generate n number of terms you need the condition to be i < n and not i <= n.
function fib(n) {
const result = [0, 1];
for (var i = 2; i < n; i++) {
result.push(result[i-2] + result[i-1]);
}
return result; // or result[n-1] if you want to get the nth term
}
console.log(fib(8));
Return result[n-1] if you want to get the nth term.
My solution for Fibonacci series:
const fibonacci = n =>
[...Array(n)].reduce(
(acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
[]
)
This function is incorrect. It cat be checked by just adding the console.log call just before the function return:
function fib(n) {
const result = [0, 1];
for (var i = 2; i <= n; i++) {
const a = (i - 1);
const b = (i - 2);
result.push(a + b);
}
console.log(result);
return result[n];
}
console.log(fib(7));
As you can see, the sequence is wrong and (for n = 7) the return value is too.
The possible change would be as following:
function fib(n) {
const result = [0, 1];
for (var i = 2; i <= n; i++) {
const a = result[i - 1];
const b = result[i - 2];
result.push(a + b);
}
console.log(result);
return result[n];
}
console.log(fib(8));
This is the "classical" Fibonacci numbers; if you really want to use the first number of 0, not 1, then you should return result[n-1], since array indexes start from zero.
One approach you could take for fibonacci sequence is recursion:
var fibonacci = {
getSequenceNumber: function(n) {
//base case to end recursive calls
if (n === 0 || n === 1) {
return this.cache[n];
}
//if we already have it in the cache, use it
if (this.cache[n]) {
return this.cache[n];
}
//calculate and store in the cache for future use
else {
//since the function calls itself it's called 'recursive'
this.cache[n] = this.getSequenceNumber(n - 2) + this.getSequenceNumber(n - 1);
}
return this.cache[n];
},
cache: {
0: 0,
1: 1
}
}
//find the 7th number in the fibbonacci function
console.log(fibonacci.getSequenceNumber(7));
//see all the values we cached (preventing extra work)
console.log(fibonacci.cache);
//if you want to output the entire sequence as an array:
console.log(Object.values(fibonacci.cache));
The code above is also an example of a dynamic programming approach. You can see that I am storing each result in a cache object the first time it is calculated by the getSequenceNumber method. This way, the second time that getSequenceNumber is asked to find a given input, it doesn't have to do any actual work - just grab the value from cache and return it! This is an optimization technique that can be applied to functions like this where you may have to find the value of a particular input multiple times.
const fib = n => {
const array = Array(n);
for (i = 0; i < array.length; i++) {
if (i > 1) {
array[i] = array[i - 1] + array[i - 2];
} else {
array[i] = 1;
}
}
return array;
}
console.log(fib(5))
What you are doing wrong is adding the iterator index (i), whereas what you need to do is add the element in the result at that index.
function fib(n) {
const result = [0, 1];
for (let i = 2; i <= n; i++) {
const a = result[(i - 1)];
const b = result[(i - 2)];
result.push(a + b);
}
console.log("Result Array: " + result);
return result[n];
}
console.log("Fibonacci Series element at 8: " + fib(8));
There are two issues with the logic:
Variables a and b currently refer to i - 1 and i - 2. Instead they should refer to the elements of result array, i.e. result[i - 1] and result[i - 2].
If you need 8th element of the array, you need to call result[7]. So the returned value should be result[n - 1] instead of result[n].
function fib(n) {
const result = [0, 1];
for (var i = 2; i < n; i++) {
const a = result[i - 1];
const b = result[i - 2];
result.push(a + b);
}
console.log(result);
return result[n - 1];
}
console.log(fib(8));
simple solution for Fibonacci series:
function fib(n){
var arr = [];
for(var i = 0; i <n; i++ ){
if(i == 0 || i == 1){
arr.push(i);
} else {
var a = arr[i - 1];
var b = arr[i - 2];
arr.push(a + b);
}
}
return arr
}
console.log(fib(8))
This is certainly one of those "more than one way to clean chicken" type situations, this JavaScript method below works for me.
function fibCalc(n) {
var myArr = [];
for (var i = 0; i < n; i++) {
if(i < 2) {
myArr.push(i);
} else {
myArr.push(myArr[i-2] + myArr[i-1]);
}
}
return myArr;
}
fibCalc(8);
When called as above, this produces [0,1,1,2,3,5,8,13]
It allows me to have a sequence of fib numbers based on n.
function fib(n) {
const result = [0];
if (n > 1) {
result.push(1);
for (var i = 2; i < n; i++) {
const a = result[result.length - 1]
const b = result[result.length - 2];
result.push(a + b);
}
}
console.log(result);
}
i came up with this solution to get the n index fibonacci value.
function findFac(n){
if (n===1)
{
return [0, 1];
}
else
{
var s = findFac(n - 1);
s.push(s[s.length - 1] + s[s.length - 2]);
return s;
}
}
function findFac0(n){
var vv1 = findFac(n);
return vv1[n-1];
}
console.log(findFac0(10));
Here, you have it, with few argument check, without using exception handling
function fibonacci(limit){
if(typeof limit != "number"){return "Please enter a natural number";}
if(limit <=0){
return "limit should be at least 1";
}
else if(limit == 1){
return [0];
}
else{
var series = [0, 1];
for(var num=1; num<=limit-2; num++){
series.push(series[series.length-1]+series[series.length-2]);
}
return series;
}
}
I came up with this solution.
function fibonacci(n) {
if (n == 0) {
return [0];
}
if ( n == 1) {
return [0, 1];
} else {
let fibo = fibonacci(n-1);
let nextElement = fibo [n-1] + fibo [n-2];
fibo.push(nextElement);
return fibo;
}
}
console.log(fibonacci(10));
function fibonacciGenerator (n) {
var output = [];
if(n===1){
output=[0];
}else if(n===2){
output=[0,1];
}else{
output=[0,1];
for(var i=2; i<n; i++){
output.push(output[output.length-2] + output[output.length-1]);
}
}
return output;
}
output = fibonacciGenerator();
console.log(output);
function fibonacci(end) {
if (isNaN(end) === false && typeof (end) === "number") {
var one = 0, res, two = 1;
for (var i = 0; i < end; ++i) {
res = one + two;
one = two;
two = res;
console.log(res);
}
} else {
console.error("One of the parameters is not correct!")
}
}
fibonacci(5);
var input = parseInt(prompt(""));
var a =0;
var b=1;
var x;
for(i=0;i<=input;i++){
document.write(a+"<br>")
x = a+b;
a =b;
b= x;
}

Javascript least common multiple algorithm

I'm trying to script a function that takes two numbers and returns the smallest common multiple that is also divisible by all the numbers between those numbers, what I've got only works for 1,1 through 1,12, but for some reason stops working at 1,13. Other set like 12,14 work but I can't figure out why or what the pattern is.
function smallestCommons(arr) {
arr.sort(function(a, b) {
return a-b;
});
var arr1 = [];
var arr2 = [];
for (var k = arr[0]; k<=arr[1]; k++) {
arr1.push(k);
}
function remainder(val1, val2) {
return val1%val2;
}
var b = arr1.reduce(function(a, b) {
return a*b;
});
var i = arr1[arr1.length-1]*arr1[arr1.length-2];
while (i<=b) {
for (var m = 0; m<arr1.length; m++) {
var a = remainder(i, arr1[m]);
arr2.push(a);
}
var answer = arr2.reduce(function(c, d) {
return c+d;
});
if (answer === 0) {
return i;
} else {
arr2 = [];
i++;
}
}
}
I guess you can do as follows in JavaScript; It can calculate the common LCM up to an 216 item array, such as [1,2,3,...,216] in less than 0.25 ms.
function gcd(a,b){
var t = 0;
a < b && (t = b, b = a, a = t); // swap them if a < b
t = a%b;
return t ? gcd(b,t) : b;
}
function lcm(a,b){
return a/gcd(a,b)*b;
}
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13],
brr = Array(216).fill().map((_,i) => i+1), // limit before Infinity
result = arr.reduce(lcm);
console.log(result);
console.time("limit");
result = brr.reduce(lcm);
console.timeEnd("limit");
console.log(result);
A way is to keep multiplying the largest number in your range with an increasing number and check if all the others are divisible by that. If yes, return that or continue the loop.
Here is my solution in typescript...
function findLowestCommonMultipleBetween(start: number, end: number): number {
let numbers: number[] = [];
for (let i = start; i <= end; i++) {
numbers.push(i);
}
for (let i = 1; true; i++) {
let divisor = end * i;
if (numbers.every((number) => divisor % number == 0)) {
return divisor;
}
}
}
...but for larger ranges, this is a more efficient answer :)
As far as I can tell your algorithm is giving you a correct answer.
I am far from being a professional programmer so anyone who wants please give options to improve my code or its style :)
If you want to be able to check for the answer yourself you can check this fiddle:
https://jsfiddle.net/cowCrazy/Ld8khrx7/
function multiplyDict(arr) {
arr.sort(function (a, b) {
return a - b;
});
if (arr[0] === 1) {
arr[0] = 2;
}
var currentArr = [];
for (var i = arr[0]; i <= arr[1]; i++) {
currentArr.push(i);
}
var primeDivs = allPrimes(arr[1]);
var divsDict = {};
for (var j = currentArr[0]; j <= currentArr[currentArr.length -1]; j++){
divsDict[j] = [];
if (primeDivs.indexOf(j) > -1) {
divsDict[j].push(j);
} else {
var x = j;
for (var n = 2; n <= Math.floor(j / 2); n++) {
if (x % n === 0) {
divsDict[j].push(n);
x = x / n;
n--;
continue;
}
}
}
}
return divsDict;
}
function allPrimes(num) {
var primeArr = [];
var smallestDiv = 2;
loopi:
for (var i = 2; i <= num; i++) {
loopj:
for (var j = smallestDiv; j <= largestDiv(i); j++) {
if (i % j === 0) {
continue loopi;
}
}
primeArr.push(i);
}
return primeArr;
}
function largestDiv (a) {
return Math.floor(Math.sqrt(a));
}
multiplyDict([1,13]);
it gives a dictionary of the requested array and the divisors of each element.
from there you can go on your own to check that your algorithm is doing the right job or you can check it here:
https://jsfiddle.net/cowCrazy/kr04mas7/
I hope it helps
It is true! The result of [1, 13] is 360360. and after this we have [1, 14].
14 = 2 * 7 and we now 360360 is dividable to 2 and 7 so the answer is 360360 again.
[1, 15]: 15 = 3 * 5 and result is same.
[1, 16]: result is 720720.
[1, 17]: result is: 12252240
[1, 18]: 18 = 2 * 9 and result is 12252240 same as 17
[1, 19]: for my computer this process is so heavy and can not do this. But in a strong machine it will work. I promise. But your code is not good in performance.
To find the LCM in N numbers.
It is Compatible with ES6, and consider that is there is no control for boundaries in case that we need to find for large numbers.
var a = [10, 40, 50, 7];
console.log(GetMinMultiple(a));
function GetMinMultiple(data) {
var maxOf = data.reduce((max, p) => p > max ? p : max, 0);
var incremental = maxOf;
var found = false;
do {
for (var j = 0; j < data.length; j++) {
if (maxOf % data[j] !== 0) {
maxOf += incremental;
break;
}
else {
if (j === data.length - 1) {
found = true;
break;
}
}
}
} while (!found);
return maxOf;
}
https://jsfiddle.net/djp30gfz/
Here is my solution in Typescript
function greatestCommonDivider(x: number, y: number): number {
if (y === 0) {
return x;
}
return greatestCommonDivider(y, x % y);
}
function singleLowestCommonMultiply(x: number, y: number): number {
return (x * y) / greatestCommonDivider(x, y);
}
function lowestCommonMultiply(...numbers: number[]): number {
/**
* For each number, get it's lowest common multiply with next number.
*
* Then using new number, compute new lowest common multiply
*/
return numbers.reduce((a, b) => {
return singleLowestCommonMultiply(a, b);
});
}
lowestCommonMultiply(2, 3); // Outputs 6
lowestCommonMultiply(2, 3, 5); // Outputs 30
Playground - click here

Decrease the probability of getting random item from array same as previous one

Say, I've got an array like
var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
and I wanna get random array item, but later I would like to re-randomize my current item. What is the efficient way to exclude or reduce the chance of getting the same item once again?
Does stuff like this really help:
current != arr[Math.floor(Math.random() * 12)] ? current = arr[Math.floor(Math.random() * 12)] : arr[Math.floor(Math.random() * 12)];
I mean, would it recalculate random array index each time or just link to the same value?
What is a better way?
If you can keep array unsorted: (if not, you can use array which only contains indices of elements in first array)
var array = [ ... ];
var len = array.length;
function getRandomItem(){
if (len <= 0) len = array.length;
var item = Math.floor(Math.random()*len--);
var x = array[item];
array[item] = array[len];
array[len] = x;
return array[len];
}
Idea behind is to exclude already dispatched items by placing them outside of item fetching range. Function getRandomItem() will not return same item twice until all other elements also will be returned.
Following modification will only prevent function to return same element which was returned during previous call, as requested.
var array = [ 3, 1, 4, 5, 9, 2, 6, 8, 7 ];
var len = array.length-1;
function getRandomItem(){
if (len == 0) return array[0];
var item = Math.floor(Math.random()*len);
var x = array[item];
array[item] = array[len];
array[len] = x;
return array[len];
}
document.write("Starting array: " + array + "<br/>");
document.write("Selected value: " + getRandomItem() + "<br/>");
document.write("Resulting array: " + array);
Also see Fisher–Yates shuffle
I think the best solution is to put a while loop to check if the value is similar to the previous one or not.
var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
Then you write:
var last_generated_value = null;
var val = Math.random();
val = Math.floor(val * 12);
while(last_generated_val == val)
{
val = Math.random();
val = Math.floor(val * 12);
}
last_generated_value = val;
Though you may put the above code block in a parent loop or a function to generate a concatenated set of values(in your case, number).
There are so many ways to achieve this. Maybe add a weight to each value and consider it in your random number selection? Then when you get it, reduce its weight. For example:
var weights = {};
var max = 12;
function initializeWeights() {
var i;
for (i = 1; i <= max; ++i) {
weights[i] = 100;
}
}
function getPseudoRandom() {
var possible_values = [], i, j;
for (i = 1; i <= max; ++i) {
for (j = 0; j < weights[i]; ++j) {
possible_values.push(i);
}
}
random_index = Math.floor(Math.random() * possible_values.length) + 1;
random = possible_values[random_index];
weights[random] = weights[random] - 10;
return random;
}
initializeWeights()
alert(getPseudoRandom());
Then you just have to figure out what to do when you reach 0. Maybe you can increment all the weights by 100.
Try
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var clone = arr.slice();
var res = [];
do {
res.push(clone.splice(Math.random() * clone.length, 1)[0])
} while (clone.length !== 0);
// do stuff with res
document.write(JSON.stringify(res));
document.write(res[Math.floor(Math.random() * res.length)]);
console.log(arr);
perhaps this is ok? It seems to work, but maybe I'm missing some details?
var current = arr[Math.floor(Math.random() * 12)];
var prev = current;
do { current = arr[Math.floor(Math.random() * 12)]; }
while (current == prev);
You could randomly shuffle the array using a version of the Fisher-Yates algorithm and then just iterate through it:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12],
shuffle = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
},
randomisedArray = shuffle(arr),
nextItem = function(){
return randomisedArray.pop();
};
while(randomisedArray.length>0){
console.log(nextItem());
}
You can do this with a single calculation:
// Just like before...
var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
// Initialize first random index
var currentIndex = Math.floor(Math.random() * arr.length);
// And now...
function Next() {
currentIndex = (Math.floor(Math.random() * (arr.length - 1)) +
1 + currentIndex) % arr.length;
return currentIndex;
}
// Or if you want the next value...
function NextValue() {
return arr[Next()];
}
The idea is that you always randomize how many items to advance, with a maximum of (length - 1), and use modulo to truncate the index into the valid range.

Categories