Given a range of numbers (1-25) how can I create a loop so that at each iteration I get a unique set of variables.
It sounds like you are talking about the permutations of a set. You can find a bunch of different algorithms to do this. Here is a nice one from this StackOverflow answer:
function getArrayMutations(arr, perms = [], len = arr.length) {
if (len === 1) perms.push(arr.slice(0))
for (let i = 0; i < len; i++) {
getArrayMutations(arr, perms, len - 1)
len % 2 // parity dependent adjacent elements swap
? [arr[0], arr[len - 1]] = [arr[len - 1], arr[0]]
: [arr[i], arr[len - 1]] = [arr[len - 1], arr[i]]
}
return perms
}
getArrayMutations([1, 2, 3])
> [ [ 1, 2, 3 ],
[ 2, 1, 3 ],
[ 3, 1, 2 ],
[ 1, 3, 2 ],
[ 2, 3, 1 ],
[ 3, 2, 1 ] ]
Be careful though! Permutations are factorial which means they grow really fast.
P(n, k) =
This means that if you want to permute 25 numbers, you are looking at 1.551121e+25
possible combinations which is getting into the not-computable-in-your-lifetime territory.
What I am trying to do is iterate over every possible number for each position (think sudoku) so in a 3x3 grid: a = top left position, b = top middle, etc...
Two dimensional arrays (really just lists of lists) are a great way to store matrix data like this. It doesn't fundamentally change the math to change the representation from a single array, but it might be easier to think about. I'm not 100% sure if you want a 3x3 grid or a 5x5 grid but I'll assume 5x5 since you have 25 numbers in your example. You can easily reshape them like this:
function reshapeArray(array, n=5) {
let result = []
let row = 0
let col = 0
for (let i = 0; i < array.length; i++) {
if (col == 0) {
result[row] = []
}
result[row][col] = array[i]
col++
if (col == n) {
col = 0
row++
}
}
return result
}
reshapeArray([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25])
> [ [ 1, 2, 3, 4, 5 ],
[ 6, 7, 8, 9, 10 ],
[ 11, 12, 13, 14, 15 ],
[ 16, 17, 18, 19, 20 ],
[ 21, 22, 23, 24, 25 ] ]
so similar to sudoku I would have a condition (each row = 65: a + b + c + d + e= 65)
Now that you have your data in an iteratable array, you can very easily check this or any other constraint. For example:
/**
* Checks if a matrix (a 2-d array like the output from reshapeArray())
* meets our criteria.
*/
function checkMatrix(matrix) {
for (let row = 0; row < matrix.length; row++) {
let rowSum = 0
for (let col = 0; col < matrix[row].length; col++) {
rowSum += matrix[row][col]
}
// The row sum does not equal 65, so this isn't the one!
if (rowSum != 65) {
return false
}
}
// All the row sums equal 65
return true
}
If you want add extra rules (like having the columns sum to 65 as well) just modify the code to check for that. You can get the value at any point in the matrix by indexing it matrix[row][col]
so matrix[0][0]
is the upper-left, etc.
However the obvious problem with this is that it's just randomly selecting values. So it will take an incredible amount of time. I can't work out how to iterate over every possible combination (without having 25 for loops) so I can check which values will pass the condition.
Yes, it will. Sudoku is an NP-Hard problem. If you haven't seen complexity classes before, that's just a very mathematically formal way of saying that there's no clever solution that's going to be significantly faster than just checking every possible solution. This hypothetical problem is not exactly the same, so it might be possible, but it has a very np-ish feel to it.
Currently, your pseudocode solution would look like this:
let permutations = getPermutations() // You're going to need to change this part
// because getting all the permutations
// ahead of time will take too long.
// Just picking random numbers each time is
// not actually a terrible idea. Or, look at
// generator functions (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)
for (let permutation of permutations) {
let matrix = reshapeArray(permutation)
if (checkMatrix(matrix)) {
console.log("Found it")
console.log(matrix)
break
}
}
If there is only one possible solution that matches your criteria, you will never find it this way. If there is a relatively high density of solutions, you will probably find some. If you really want to solve this problem I would recommend first looking at it from a mathematical perspective -- can you prove that it is or isn't NP? can you make some prediction about the density of solutions?