I am trying to get every single combination of elements into an array. Now I can use the method below, and remove the duplicates, but this way is far to slow for my use.
The code below would find every possible combination for 2 digits below 4. Now in the code I actually want to use this for, the least possible code would be 6 for loops (within each other) with the amount being 18 (rememeber this is the minimum).
The code below would execute amount^[amount of for loops], or amount^2 which in this case is 16. That means that in the code I want to use this for, it executes 18^6 times, or 34 million times. And this is the minimum, which would get much higher.
After trying to run my code (with 6 foor loops in which amount = 18), it crashed my browser... My question is: Is there any faster and more efficient (not elegant. I don't care how elegant it is) in which my browser won't crash?
Note: This question is not a duplicate question. All the other questions simply ask for a way to do this, however I already have a way. I am just trying to make it more efficient and faster so that it actually works correctly.
let combinations = [];
let amount = 4;
for (let a = 0; a < amount; a++) {
for (let b = 0; b < amount; b++) {
combinations.push(`${a}${b}`);
}
}
console.log(combinations);
Below is a snippet providing a possible example for how my code would work.
let possibilities = [];
let amount = 6; //Amount is set by me, so don't worry about it being incorrect
for (let a = 0; a < amount; a++) {
for (let b = 0; b < amount; b++) {
possibilities.push(a + b);
}
}
possibilities = [...new Set(possibilities)]; //Removes duplicates
possibilities.sort((a, b) => b - a); //Sorts in descending order
possibilities = possibilities.slice(0, 3); //Gets top 3 values
console.log(possibilities);
Ok, as discussed in the comments, if you need top 3 values for a particular amount, you could just do something simple like below:
let amount = 6;
let highest = amount - 1,second_highest = amount - 2,third_highest = amount - 3;
let possibilities = [
highest + highest,
highest + second_highest,
highest + third_highest
];
console.log(possibilities);
I don't know the any better solution for this, but yes there are some conditions you need to check first.
If(amount <= 0) return 'Invalid amount, Please enter a valid amount"
So if somebody enters a negative or zero value your loop will goes into infinite loop, and make the situation more worst.
if(amount === 1) return '1 possible combination'
As amount less than 1 is 0 only and combinations for 0 is 1 only, you need not to parse whole loop for 6 digits or n digits for 0 so it will get solve in complexity of 1 instead of N(no. of digits).
And for amount greater then 1 you can create manual loops, like here you created 2 loops for 2 digits, you create 6 loops for 6 digits, better create dynamic logic for this to create number of loops automatically.
You need to consider 1111, 1112 this type of combinations as well right?
Or if only 1234, 2134, 2314 this kind of scenarios are required? This can be done in very less complexity.
For duplication you can store combinations as a key value pair. and then Object.Keys will be your combinations.
Related
What is an off-by-one error? If I have one, how do I fix it?
An off-by-one error is for example when you intend to perform a loop n times and write something like:
for (int i = 1; i < n; ++i) { ... }
or:
for (int i = 0; i <= n; ++i) { ... }
In the first case the loop will be executed (n - 1) times and in the second case (n + 1) times, giving the name off-by-one. Other variations are possible but in general the loop is executed one too many or one too few times due to an error in the initial value of the loop variable or in the end condition of the loop.
The loop can be written correctly as:
for (int i = 0; i < n; ++i) { ... }
A for loop is just a special case of a while loop. The same kind of error can be made in while loops.
An off-by-one error is when you expect something to be of value N, but in reality it ends up being N-1 or N+1. For example, you were expecting the program to perform an operation 10 times, but it ends up performing 9 or 11 times (one too few or one too many times). In programming this is most commonly seen happening when dealing with "for" loops.
This error happens due to a misjudgement where you do not realize that the number you are using to keep track of your counting may not be the same as the number of things you are counting. In other words, the number you are using to count may not be the same as the total of things you are counting. There is nothing that obligates both things to be the same. Try to count out loud from 0 to 10 and you end up saying 11 numbers in total, but the final number that you say is 10.
One way to prevent the problem is to realize that our brain has a tendency (maybe a cognitive bias) to make that error. Keeping that in mind may help you identify and prevent future situations. But I guess that the best thing you can do to prevent this error is to write unit tests. The tests will help you make sure that your code is running as it should.
Say you have the following code featuring an array and a for loop:
char exampleArray[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
for(int i = 0; i <= 11; i++)
{
print(exampleArray[i])
}
See the issue here? Because I counted my array to have eleven characters in it, I have set my loop to iterate eleven times. However, arrays start at zero in most languages, meaning that when my code goes to print
exampleArray[11]
I will get an index out of bounds error because the array in the example has no value at index eleven.
In this case, I can fix this easily by simply telling my loop to iterate one fewer times.
The easiest way to debug this issue is to print out your upper and lower bounds and see which value generates an index out of bounds error, then set your value to be one greater or one fewer than it is throughout your entire iteration.
Of course, this assumes the error is generated by a loop going one over or one less than the bounds of an array, there are other situations where an index out of bounds error can occur, however, this is the most common case. An index out of bounds will always refer to trying to access data where data does not exist due to the boundaries past not being within the boundaries of data.
A common off-by-one confusion arises because some languages enumerate vectors from zero (C, for example) and other languages from one (R, for example). Thus, a vector x of size n has members running from x[0] to x[n-1] in C but from x[1] to x[n] in R.
You are also confronted with the off-by-one challenge when coding the common idiom for cyclic incrementation:
In C:
i = (i+1)%n
In R:
i <- (i-1)%%n + 1
Off by one error (sometimes called OBOE) crop up when you're trying to target a specific index of a string or array (to slice or access a segment), or when looping over the indices of them.
If we consider Javascript as an example language, indexing starts at zero, not one, which means the last index is always one less than the length of the item. If you try to access an index equal to the length, the program may throw an
"index out of range" reference error
or
print undefined.
When you use string or array methods that take index ranges as arguments, it helps to read the documentation of that language and understand if they are inclusive (the item at the given index is part of what's returned) or not. Here are some examples of off by one errors:
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let len = alphabet.length;
for (let i = 0; i <= len; i++) {
// loops one too many times at the end
console.log(alphabet[i]);
}
for (let j = 1; j < len; j++) {
// loops one too few times and misses the first character at index 0
console.log(alphabet[j]);
}
for (let k = 0; k < len; k++) {
// Goldilocks approves - this is just right
console.log(alphabet[k]);
}
A simple rule of thumb:
int i = 0; // if i is initiated as 0, always use a < or > in the condition
while (i < 10)
System.out.printf("%d ", i++);
int i = 1; // if i is initiated as 1, always use a <= or >= in the condition
while (i <= 10)
System.out.printf("%d ". i++);
I would like to sort a news feed according to created date, which is trivial, but I don't want 2 consecutive posts with the same userId field.
This might not be theoritically possible because what if I have only 2 posts with the same userId field?
I am looking for an algorithm that sorts according to fieldA but doesn't have 2 consecutive elements with the same fieldB.
It would also nice to have a parametrized algorithm about the required number of different posts between same user's different posts. (In the first scenario this parameter is 1)
I'm not looking for performance (O(n^2) would be okay) but a clever & simple way, maybe with 5 lines of code.
Language doesn't matter but Javascript is preferred.
To solve this problem in 5 lines is somewhat difficult,I'm trying to give a short pseudocode and you may translate it to js.
First we group the input to A[1],A[2],...,A[k].A[i] is a container contains all posts of i-th user,this can be easily done via O(n) scanning.
code:
for i = 1 to k
lastOccurPosition[i] = -intervalLength; //that is the interval length specified by parameter
for i = 1 to k
sort(A[i]);
for i = 1 to n
minElement = INF; //find the minimum
minUserId = -1; //record whose post is minimun
for j = 1 to k
if(i - lastOccurPosition[i] <= intervalLength) //if the user has occured within interval length,the user's post shouldn't be choosen
continue;
if(A[j][1] < minElement)
minElement = A[j][1];
minUserId = j;
answer[i] = minElement; //put min element into answer array
lastOccurPosition[minUserId] = i; //update choosen user's last occur position
A[minUserId].pop_front(); //delele first element
It is easy to analyse this algorithm's complexity is O(n^2) and I haven't thought out a more concise solution.
Hope to be helpful.
Put the atributes in an array, and sort that array:
arr.sort();
Put the second atribute in another array and sort that array according to the first one.
var newarr = [arr[0]];
for (var i=1; i<arr.length; i++) {
if (arr[i]!=arr[i-1]) newarr.push(arr[i]);
}
Now this just remove duplicates.
This all feels kind of trivial, am I missing something?
Hope this helps.
Cheers,
Gijs
I want to fill the 9 x 9 grid from the array by taking care of following condition
A particular number should not be repeated across the same column.
A particular number should not be repeated across the same row.
When i execute the below mentioned code it fills all the 9 X 9 grid with random values without the above mentioned condition.How can I add those two condition before inserting values into my 9 X 9 Grid.
var sudoku_array = ['1','2','3','4','6','5','7','8','9'];
$('.smallbox input').each(function(index) {
$(this).val(sudoku_array[Math.floor(Math.random()*sudoku_array.length)]);
});
My JSFIDDLE LINK
Generating and solving Sudokus is actually not as simple as other (wrong) answers might suggest, but it is not rocket science either. Instead of copying and pasting from Wikipedia I'd like to point you to this question.
However, since it is bad practice to just point to external links, I want to justify it by providing you at least with the intuition why naive approaches fail.
If you start generating a Sudoku board by filling some fields with random numbers (thereby taking into account your constraints), you obtain a partially filled board. Completing it is then equivalent to solving a Sudoku which is nothing else than completing a partially filled board by adhering to the Sudoku rules. If you ever tried it, you will know that this is not possible if you decide on the next number by chosing a valid number only with respect to the 3x3 box, the column and the row. For all but the simplest Sudokus there is some trial and error, so you need a form of backtracking.
I hope this helps.
To ensure that no number is repeated on a row, you might need a shuffling function. For columns, you'll just have to do it the hard way (checking previous solutions to see if a number exists on that column). I hope i am not confusing rows for columns, i tend to do it a lot.
It's similar to the eight queens problem in evolutionary computing. Backtracking, a pure random walk or an evolved solution would solve the problem.
This code will take a while, but it'll do the job.
You can the iterate through the returned two dimensional array, and fill the sudoku box. Holla if you need any help with that
Array.prototype.shuffle = function() {
var arr = this.valueOf();
var ret = [];
while (ret.length < arr.length) {
var x = arr[Math.floor(Number(Math.random() * arr.length))];
if (!(ret.indexOf(x) >= 0)) ret.push(x);
}
return ret;
}
function getSudoku() {
var sudoku = [];
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
sudoku.push(arr);
for (var i = 1; i < 9; i++) {
while (sudoku.length <= i) {
var newarr = arr.shuffle();
var b = false;
for (var j = 0; j < arr.length; j++) {
for (var k = 0; k < i; k++) {
if (sudoku[k].indexOf(newarr[j]) == j) b = true;
}
}
if (!b) {
sudoku.push(newarr);
document.body.innerHTML += `${newarr}<br/>`;
}
}
}
return sudoku;
}
getSudoku()
You need to keep track of what you have inserted before, for the following line:
$(this).val(sudoku_array[Math.floor(Math.random()*sudoku_array.length)]);
For example you can have a jagged array (arrays of arrays, its like a 2-D array) instead of 'sudoku_array' you have created to keep track of available numbers. In fact, you can create two jagged arrays, one for column and one for rows. Since you don't keep track of what you have inserted before, numbers are generated randomly.
After you create an array that keeps available numbers, you do the following:
After you generate number, remove it from the jagged array's respective row and column to mark it unavailable for those row and columns.
Before creating any number, check if it is available in the jagged array(check for both column and row). If not available, make it try another number.
Note: You can reduce the limits of random number you generate to available numbers. If you do that the random number x you generate would mean xth available number for that cell. That way you would not get a number that is not available and thus it works significantly faster.
Edit: As Lex82 pointed out in the comments and in his answer, you will also need a backtracking to avoid dead ends or you need to go deeper in mathematics. I'm just going to keep my answer in case it gives you an idea.
I am working on an implementation of the 15-pieces-sliding puzzle, and I am stuck at the point were I must make sure I only shuffle into "solvable permutations" - in my case with the empty tile in the down right corner: even permutations.
I have read many similar threads such as How can I ensure that when I shuffle my puzzle I still end up with an even permutation? and understand that I need to "count the parity of the number of inversions in the permutation".
I am writing in Javascript, and using Fischer-Yates-algorithm to randomize my numbers:
var allNrs = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14];
for (var i = allNrs.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp1 = allNrs[i];
var temp2 = allNrs[j];
allNrs[i] = temp2;
allNrs[j] = temp1;
}
How do I actually caculate this permutation or parity value that I have read about in so many posts?
Just count the number of swaps you're making. If the number of swaps is even then the permutation has an even parity.
For example, these are the even permutations for 3 numbers. Note that you need 0 or 2 swaps to get to them from [1,2,3]:
1,2,3
2,3,1
3,1,2
Each swap of two numbers you do flips the parity. If you have an even number of them, you are good. If you have an odd number, you are not.
This is essentially what parity means and it is a (simple) theorem of group theory that any two ways to get to the same shuffle have the same parity.
We are trying to create a random number generator to create serial numbers for products on a virtual assembly line.
We got the random numbers to generate, however since they are serial numbers we don't want it to create duplicates.
Is there a way that it can go back and check to see if the number generated has already been generated, and then to tell it that if it is a duplicate to generate a new number, and to repeat this process until it has a "unique" number.
The point of a serial number is that they're NOT random. Serial, by definition, means that something is arranged in a series. Why not just use an incrementing number?
The easiest way to fix this problem is to avoid it. Use something that is monotonically increasing (like time) to form part of your serial number. To that you can prepend some fixed value that identifies the line or something.
So your serial number format could be NNNNYYYYMMDDHHMMSS, where NNNN is a 4-digit line number and YYYY is the 4 digit year, MM is a 2 digit month, ...
If you can produce multiple things per second per line, then add date components until you get to the point where only one per unit time is possible -- or simply add the count of items produced this day to the YYYYMMDD component (e.g., NNNNYYYYMMDDCCCCCC).
With a truly random number you would have to store the entire collection and review it for each number. Obviously this would mean that your generation would become slower and slower the larger the number of keys you generate (since it would have to retry more and more often and compare to a larger dataset).
This is entirely why truly random numbers just are never used for this purpose. For serial numbers the standard is always to just do a sequential number - is there any real real for them to be random?
Unique IDs are NEVER random - GUIDs and the like are based on the system time and (most often) MAC address. They're globally unique because of the algorithm used and the machine specifics - not because of the size of the value or any level of randomness.
Personally I would do everything I could to either use a sequential value (perhaps with a unique prefix if you have multiple channels) or, better, use a real GUID for your purpose.
is this what you are looking for?
var rArray;
function fillArray (range)
{
rArray = new Array ();
for(var x = 0; x < range; x++)
rArray [x] = x;
}
function randomND (range)
{
if (rArray == null || rArray.length < 1)
fillArray (range);
var pos = Math.floor(Math.random()*rArray.length);
var ran = rArray [pos];
for(var x = pos; x < rArray.length; x++)
rArray [x] = rArray [x+1];
var tempArray = new Array (rArray.length-1)
for(var x = 0; x < tempArray.length; x++)
tempArray [x] = rArray [x];
rArray = tempArray;
return ran;
}