Notifications
Clear all

[Closed] Getting all combinations of a set of arrays

Hi…
I have a number of arrays and I want to return an array with every combination of the values in the arrays.
So I might have:
x=#(“1”, “2”, “3”)
y=#(“a”, “b”, “c”, “d”)
z=#(“y”, “z”)
arr = #(x, y, z)

and I want to return
#(#(“1”, “a”, “y”), #(“1”, “a”, “z”), #(“1”, “b”, “y”), #(“1”, “b”, “z”), #(“1”, “c”, “y”)…#(“3”, “d”, “z”))

The amount of arrays in arr is variable as is the number of elements in all arrays
Its doing my head in! :banghead:
Any Ideas?

6 Replies

something like this?

 x=#("1", "2", "3")
y=#("a", "b", "c", "d")
z=#("y", "z") 
combArr = #()
for i = 1 to x.count do
(
for j = 1 to y.count do
(
for k = 1 to z.count do
(
local tmparr = #(x[i],y[j],z[k])
append combArr tmparr
)
)
)

This can be simplified to

x=#("1", "2", "3")
y=#("a", "b", "c", "d")
z=#("y", "z") 
combArr = #()
for i in x do for j in y do for k in z do append combArr #(i,j,k)
combArr

Yep something like that… but it wont dynamically work for
w=#(“9”, “8”)
x=#(“1”, “2”, “3”)
y=#(“a”, “b”, “c”, “d”)
z=#(“y”, “z”)

or just

y=#(“a”, “b”, “c”, “d”)
z=#(“y”, “z”)

The amount of arrays is no set unfortunatley, and this is my problem!

This is what I have at the moment… doesnt quite work


 x=#("1", "2", "3")
 y=#("a", "b", "c", "d")
 z=#("y", "z")
 arr = #(x, y, z)
 count = 1
 manArr = #(arr.count) --management array - adding arrayIndexTracker
 finalArr=#()
 clearlistener()
 for i = 1 to arr.count do
 	(
 	count = count*arr[1].count
 	append manArr #(1, i, arr[i].count) --add #(arrayItemTracker, arrayIndex, arrayCount) to management array per array
 	)
 
 print count
 print (manArr as string)
 
 
 for i = 1 to count do
 	(
 	MyVal=#()
 	for x = 1 to arr.count do
 		(
 		append MyVal arr[manarr[x+1][2]][manarr[x+1][1]]
 		)
 	append finalArr MyVal
 	
 	if manarr[manArr[1]+1][1]==manarr[manArr[1]+1][3] then --if at the end of arrayCount reset arrayItemTracker
 		(
 		manarr[manArr[1]+1][1] = 1
 		manArr[1] -=1 
 		)
 	else manarr[manArr[1]+1][1] += 1
 	)
 print finalArr
 /*
 

Here is my take on it.
In short, I create a management array that contains counters that start at 1 and reach the max. number of iterations each, just like a digital clock, with the right most element incrementing fastest and the one to the left incrementing once each time the right one warps around to 1. We also know how many elements we expect, so we do not have to loop forever, only until we have the expected number of combinations.
The rest works just like a bunch of nested for loops, but since we store the variables of the “loops” in an array, we can nest ANY number of them without actually creating for loops. We just let the “digital clock” tick and we collect the elements the “clock” is pointing at…

(
  --this is a recursive function to increase the counter(s) in the indexArr array
  fn increaseCounter indexArr theArray theIndex =
  (
  	indexArr[theIndex] += 1 --increase the indexed element by 1
  	if indexArr[theIndex] > theArray[theIndex].count do --if it is higher than the number of sub-array elements
  	(
  		indexArr[theIndex]=1 --warp back to one
  		if theIndex > 1 do --and if not the left most element, 
  			increaseCounter indexArr theArray (theIndex-1) --increase the counter to the left
  	)--end if
  )--end fn 
  
  fn getArrayCombinations theArray =
  (
  	local indexArr = for i in theArray collect 1 --collect 1 for each entry in arr
  	local combArr = #() --here we will collect the results
  
  	maxNumber = 1 --this will store the number of elements we expect
  	for i in theArray do maxNumber *= i.count --we multiply the counts of all sub-arrays
  	while combArr.count < maxNumber do --as long as we are below that expected number,
  	(
  		--collect all elements based on the counter array	
  		append combArr (for i = 1 to theArray.count collect theArray[i][indexArr[i]]) 
  		increaseCounter indexArr theArray theArray.count	 --then increase the right-most counter
  	)--end while
  	print combArr --print the result
  	OK
  )
  
  --define some arrays
  x=#("1", "2", "3") 
  y=#("a", "b", "c", "d")
  z=#("y", "z") 
  
  getArrayCombinations #(x, y, z) --can be ANY number of sub-arrays
  )

Thats it! Thanks Bobo! I had the right idea but not the 1337 scripting skillz to do it!
Thanks mate!