I want to push arrays containing random numbers (0 to 10) into a bigger array once the total of its contents is about to exceed 30. But the output is messed up.
var bigarray = new Array();
var smallarray = new Array();
var randNum = 0;
var total = 0;
for (var i = 0; i<10; i++){
randNum = (10*Math.random()).toFixed(0);
total = total + randNum;
if(total>30) {
bigarray.push(smallarray)
smallarray.length=0;
smallarray.push(randNum);
total = randNum;
} else {
smallarray.push(randNum);
}
}
alert(" BIG ARRAY IS "+bigarray);
two wrong things are visible on the first sight in the code
(1) instead of
randNum = (10*Math.random()).toFixed(0);
you probably want
randNum = Math.floor(11*Math.random());
Math.floor instead of toFixed() - see #kennebec comment
11 instead of 10 to return numbers 0 to 10, as 0 <= Math.random() < 1
(2) the following line pushes (many times) the reference to the same smallarray object.
bigarray.push(smallarray);
In the next step you clear the array with smallarray.length = 0. Because the array is not copied to the bigarray, but only referenced, the generated items are lost.
EDIT: I read your question wrong - the rest of the answer is fixed
You probably want to push the duplicate of the smallarray into bigarray, so replace the line above with the following:
bigarray.push(smallarray.slice(0));
You need another loop inside the main one to populate the smallarray, something like:
var bigarray = new Array();
for (var i = 0; i<10; i++){
// moving the variable declarations inside this loop means they are re-set for each small array
var smallarray = new Array();
// create the first entry for the small array
var randNum = Math.floor(11*Math.random());
var total = randNum;
// loop to populate the small array
while(total <= 30){
smallarray.push(randNum);
randNum = Math.floor(11*Math.random());
total += randNum;
}
bigarray.push(smallarray)
}
I made changes to you code and came up with this.
var bigarray = [];
var smallarray = [];
var randNum = 0;
var total = 0;
for (var i = 0; i < 10; i += 1) {
randNum = Math.floor(10 * Math.random()); // you will never have a value of 10?
total = total + randNum;
if (total > 30) {
bigarray.push(smallarray.slice())
smallarray.length = 0;
smallarray.push(randNum);
total = randNum;
} else {
smallarray.push(randNum);
}
}
alert(" BIG ARRAY IS " + bigarray);
On jsfiddle
Things I changed were:
Ran the code through a beautifier
Changed your use of new Array to []
{} and []
Use {} instead of new Object(). Use [] instead of new Array().
Because Object and Array can be overwritten by the user
Changed ++ to += 1
This pattern can be confusing.
Check out Code Conventions for the JavaScript Programming Language and jslint
Added array.slice when you push smallarray to bigarray, this makes a copy in this case. It is important to understand how javascript works, read Is JavaScript a pass-by-reference or pass-by-value language? Without using slice, which makes a copy as the array only contains primitives, when you set the length of the array to 0, then the data was lost.
Changed your use of number.toFixed to Math.floor so that randNum remains a number
Note: Math.random returns a floating-point, pseudo-random number in the range [0, 1] that is, from 0 (inclusive) up to but not including 1 (exclusive)
Whether your code now produces your expected out, I can not be sure from your description but this should be a good starting point.
var bigarray = new Array();
var smallarray = new Array();
var randNum = 0;
var total = 0;
for (var i = 0; i < 10; i++) {
for (var j = 0; j < smallarray.length; j++) {
total = total + smallarray[j];
}
if (total <= 30)
{
randNum = Math.floor((Math.random() * 10) + 1);
smallarray.push(randNum);
}
else {
bigarray.push(smallarray.slice(0));
smallarray.length = 0;
}
total = 0;
}
alert(" BIG ARRAY IS " + bigarray);
Related
I'm implementing the Fisher-yates shuffle in a Photoshop script. I want to create an array of n unique random elements from a maximum of about 99999. Where n is a small value but could be up to to maximum.
With maximum of under a thousand this is fine (runs in milliseconds), but considerably much slower for 10,000 (about 20 seconds).
Is there a better/faster way to do this? Bear in mind that'll it'll need to be in ECMAScript.
var maxNumber = 99;
var numToGenerate = 5;
var bigShuffle = shuffle(maxNumber);
var randomNumbers = bigShuffle.slice(0, numToGenerate);
alert(randomNumbers);
function shuffle(m)
{
var temp;
var rnd;
// create an empy array
var arr = new Array();
for(var i = 0 ; i < m; i++)
{
arr.push(i);
}
while (m)
{
rnd = Math.floor(Math.random() * m-=1);
// And swap it
temp = arr[m];
arr[m] = arr[rnd];
arr[rnd] = temp;
}
return arr;
}
I'm trying to solve this problem where I initialize an array of 5 elements and print the sum of the elements. I can't wrap my head around the logic behind the solution. Please review my code.
Another problem with reading an array of 5 integers and printing the smallest element. I keep getting the wrong answer...
This's a script embedded inside an HTML file.
Problem 1
var num= [1,1,1,1];
var total=num[0];
for( var i=0 ; i < num.length ; i++)
{
total =+num[i];
}
window.alert("The total is "+ total);
I expected the answer to be 4, but all I get is 1.
Problem 2
var r = new Array(5);
var len = r.length;
for(var i=0 ; i <len ; i++)
{
r[i] = window.prompt("Enter the elements of the array");
}
var small= [0];
for(var j=0; j< len ; j++)
{
if(r[i] < small )
small = r[i];
}
window.alert("The smallest element is the array is "+small);
I get the last element in my array as the smallest element which's obviously isn't right.
In problem 1) you just need to change =+ to +=
In problem 2) you need to start in the first element of r and in the for loop you need index the r array by the variable j instead of i variable
var r = new Array(5);
var len = r.length;
for(var i=0 ; i <len ; i++)
{
r[i] = window.prompt("Enter the elements of the array");
}
var small = r[0];
for( var j=0; j< len ; j++)
{
if(r[j] < small )
small = r[j];
}
window.alert("The smallest element is the array is "+small);
But you could just do:
const min = Math.min(...r)
window.alert("The smallest element is the array is "+ min);
There are a couple things here.
For problem 1:
Since you initialize the total to the first item I think you end up counting it 2 times. Likely you'd want to initialize to 0. var total = 0.
You will also want to use += instead of =+ the latter sets the value instead of adding it.
For Problem 2:
new Array(5) creates a new sparse array. It's kinda weird. It's like it's full of undefined values. So when you assign small you'll want to access the first element of r, var small = r[0] but that will be undefined due to r being a sparse array. So you'll want var r = new Array(5).fill().map((x,i) => i) to set values in that array. You will also want to use j instead of i in the body of the second loop.
That should do it ;).
Hi The problem 1 could be tackled with reduce method check the Docs here:
The problem 2 could be solved with Math.min method:
var num= [1,1,1,1];
var numMin= [100,1121,1212,122, 12];
//Problem1
let totalSum = num.reduce( ( accumulator, currentItem ) => {
return accumulator = accumulator += currentItem;
} , 0 );
console.log(totalSum)
//Problem 2
console.log( 'Min',Math.min( ...numMin ) );
Here is a replit so you can play with the code
// Find array elements sum
let total = 0;
let arr = [1,2,3,4];
arr.map(el => total+=el);
console.log(total); // 10
// Find array smallest element
let arr = [1,-2,13,-4,7];
let smlEl = arr[0]
arr.map(el => {
if(el < smlEl) {
smlEl = el;
}
})
console.log(smlEl); // -4
Hello guys I am trying to create an LCM function that takes in two numbers. The findCommonMultiple() function in this piece of code basically returns an array for the prime factors for that number. What I'm trying to do in this function is to check if there are duplicates in both arrays and if there are any that number will be pushed inside a new array. After a number has been pushed the inner loop should break and continue to the next iteration. If both numbers are not equal to each other they both will be pushed. This also goes on even if one of the arrays goes over their index. After all the duplicate factors and unique ones have been pushed I will begin to multiply them and return the LCM of both numbers. I have yet to create a helper function for that but I need to fix this problem first.
function leastCommonMultiple(num1, num2){
var prime1 = findPrimeFactors(num1);
var prime2 = findPrimeFactors(num2);
var primes = [];
var lcm = 1;
for(var i = 0; i < prime1.length; i++){
var factor1 = prime1[i];
for(var j = i; j < prime2.length; j++){
var factor2 = prime2[j];
if(factor1 === factor2){
primes.push(factor1);
break;
} else if(factor1 === undefined && factor2 > 0){
primes.push(factor2);
} else if(factor2 === undefined && factor2 > 0){
primes.push(factor1)
} else {
primes.push(factor1);
primes.push(factor2);
break;
}
}
}
return primes;
}
EDIT:
So I'm adding a test case. So if I have values 26 and 24 passed I would get two arrays. One would be [2, 2, 2, 3] and the other would be [2, 13]. This function will take my duplicates in side the new array and add in all the others that aren't duplicates so: [2] is in first because both arrays have 2 and then [2, 2, 2, 3, 13] the rest of the numbers without duplicates gets added into the array.
If all you need is unique items from both the arrays, I suggest doing it this way,
First concatenate the two arrays and store it in a new array, in this case,
var tempPrimes= prime1.concat(prime2);
Then just write a simple filter to filter out unique values,
var primes = tempPrimes.filter(function(item, pos){
return tempPrimes.indexOf(item)== pos;
});
If you also want to remove 0 values, then just modify it a bit,
var primes = tempPrimes.filter(function(item, pos){
return tempPrimes.indexOf(item)== pos && tempPrimes[pos]!=0;
});
Hope I helped :)
Edit (after further clarification of the question):
var tempPrimes= prime2.filter(function(item) {
return prime1.indexOf(item) < 0;
});
var primes= prime1.concat(tempPrimes);
When your arrays of prime factors are sorted, which I think they are, you can just traverse them simultaneously. If one of the array heads is smaller than the other, advance that head and push it to the result array. If both array heads are equal, push the head value and advance both heads. That way, you don't have nested loops.
The following code does this and creates arrays or the least common multiple and the greatest common divisor at the same time:
var prime1 = findPrimeFactors(num1);
var prime2 = findPrimeFactors(num2);
var lcm = [];
var gcd = [];
let i = 0;
let j = 0;
while (i < prime1.length && j < prime2.length) {
if (prime1[i] < prime2[j]) {
lcm.push(prime1[i++]);
} else if (prime1[i] > prime2[j]) {
lcm.push(prime2[j++]);
} else {
gcd.push(prime1[i]);
lcm.push(prime1[i]);
i++;
j++;
}
}
while (i < prime1.length) lcm.push(prime1[i++]);
while (j < prime2.length) lcm.push(prime2[j++]);
Another way to solve this is to ceate a count dictionary for both numbers. Merge the two dicts by adding the maximum count for each key to the result dict. This method doesn't require sorted prime factor arrays:
var pmax = {}; // result count dict
var pmax2 = {}; // auiliary count dict of primes2
for (let i = 0; i < prime1.length; i++) {
let p = prime1[i];
pmax[p] = (pmax[p] || 0) + 1;
}
for (let i = 0; i < prime2.length; i++) {
let p = prime2[i];
pmax2[p] = (pmax2[p] || 0) + 1;
}
for (let k in pmax2) {
pmax[k] = Math.max((pmax[k] || 0), pmax2[k]);
}
for (let k in pmax) {
let n = pmax[k];
while (n--) lcm.push(k);
}
Finally, the easiest way to calculate the least common multiple might be to calculate the greatest common divisor with Euclid's algorithm and to apply the relation
lcm(a, b) = a * b / gcd(a, b)
(But be careful, because that method might cause overflow for large numbers.)
There was a simpler way to get the lcm of two numbers. My solution was good but it needed more work.
function lcm(num1, num2){
for(var i = 1; i <= num1 * num2; i++){
if(i % num1 === 0 && i % num2 === 0){
return i;
}
}
}
I came across the challenge of building a random numbers generator for the lottery.
6 numbers, which are between 1 and 49, none of which appears to be twice, in ascending order. One 7th number, the super-seven, not sorted, can't be one of the previous numbers.
<script type="text/javascript">
const numb = new Array();
for (var i = 0; i < 6; i++) {
numb[i] = Math.floor(49 * Math.random()) + 1;
//compare to existing numbs
for (var k = 0; k < numb.length - 1; k++) {
if (numb[i] == numb[k]) {
i--;
break;
}
}
}
let supNumb = new Array();
supNumb = Math.floor(49 * Math.random()) + 1;
for (var s = 0; s <= 1; s++) {
// compare supNumb to numb
for (var t = 0; t < numb.length - 1; t++) {
if (supNumb == numb[t]) {
s--;
break;
}
}
}
// SORT & DISPLAY NUMBERS
function sort(a, b) {
return a - b;
}
numb.sort(sort);
document.write("<p> " + numb);
document.write("<h4>" + "SuperSeven: " + supNumb);
</script>
I know by trying the super-seven supNumb is still giving out same numbers as in numb.
I can't get it to work and can't find anywhere this being mentioned.
Somebody here can look over it and let me know how I can compare supNumb to numb?
Is this even the right structure?
Thanks in advance!
You can make an infinit loop and break it if you find a valid number like so:
while(true){
supNumb = Math.floor(49 * Math.random()) + 1;
if(numb.indexOf(supNumb) < 0){
break;
}
}
Also better use indexOf so search in the array. It is much faster than plain JS.
https://www.w3schools.com/jsref/jsref_indexof_array.asp
You could even use the Set mechanics to achieve this. Sets can only store unique values. All duplicates will thereby be ignored:
var numbers = new Set(),
supNumb = 0;
while(numbers.size < 6){
numbers.add(Math.floor(49 * Math.random()) + 1);
}
while(true){
supNumb = Math.floor(49 * Math.random()) + 1;
if(!numbers.has(supNumb)) break;
}
var sortedNumbers = [...numbers].sort((a,b)=>{return a-b})
console.log(sortedNumbers, supNumb);
https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Set
You have supNumb as an Array, I think it should be a scalar (single integer) as you are doing a compare against array member of your array numb
As well you'd have to regenerate via Random if the supNumb fails to pass he criteria 'it must be unique'
To sample non-repeating numbers there is a method called Fisher-Yates-Knuth shuffle. It is guaranteed to select 7 non-repeating numbers from 1...49 range, without any secondary checks.
In some pseudocode (sorry, don't know Javascript)
a = _.range(1, 50);
for i from nā1 downto 1 do
j ā random integer such that 0 ā¤ j ā¤ i
exchange a[j] and a[i]
sort(a, 6); // sort first 6 elements
super = a[6];
function Deal()
{
var suffledDeck:Array;
var playerOneCards: Array;
var playerTwoCards: Array;
var first:int =0;
var second:int = 1;
suffledDeck = new Array();
playerOneCards = new Array();
playerTwoCards = new Array();
//var CardLeft:int = Deck.length;
for(var i = 0; i < Deck.length; i++)
{
Debug.Log(Deck.length);
var ranNum = Random.Range(1,Deck.length);
suffledDeck.Add(Deck[ranNum]);
Debug.Log("suffled deck: " + suffledDeck.length);
}
//var halfDeck: int = (suffledDeck.length / 2);
for(var j = 0; j <=26 ; j++)
{
Debug.Log(first);
Debug.Log(second);
playerOneCards.Add(suffledDeck[first]);
playerTwoCards.Add(suffledDeck[second]);
Debug.Log(playerOneCards[first].img);
Debug.Log(playerTwoCards[second].img);
first += 2;
second += 2;
}
}
when i begin to split the array into 2 separate arrays it begins to ignore every element except the first element. the suffleDeck[] has 52 Card objects loaded in and im trying to split the array so that each player can have there own deck.
Console window for debug purpose: http://puu.sh/2dqZm
I believe the problem is var ranNum = Random.Range(1,Deck.length).
ranNum should be generating a random index between 0 to Deck.length - 1 because array indices start at 0 (not 1).
The problem is with these logging statements:
Debug.Log(playerOneCards[first].img);
Debug.Log(playerTwoCards[second].img);
first and second are valid indexes into suffledDeck, but each player's deck only has half as many cards. Try using j as the subscript in both logging statements instead of first or second.
You should also limit your loop to j < 26, not j <= 26. As it is, you are trying to put 27 cards in each player's deck.
because:
Debug.Log(playerTwoCards[second].img);
here second value us 1 while your array contains only one item that is at zero. causing ArgumentoutofRangeException.
so try:
for(var j = 0; j <=26 ; j++)
{
Debug.Log(first);
Debug.Log(second);
playerOneCards.Add(suffledDeck[first]);
playerTwoCards.Add(suffledDeck[second]);
Debug.Log(playerOneCards[j].img);
Debug.Log(playerTwoCards[j].img);
first += 2;
second += 2;
}