3

given a list of non-zero integers like, [2, 3, 4, 2]

generate a list of all the permutations possible where each element above reflects its maximum variance (I am sure there is a better way to express this, but I don't have the math background); each element in the above array can be considered a dimension; the above 2 would allow for values 0 and 1; the 3 would allow for values 0, 1 and 2, etc

the result would be a list of zero-based tuples:

[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 0, 2, 0)... 

and so on till (1, 2, 3, 1)]

the length of the array could vary, from 1 element to x

yatu
  • 86,083
  • 12
  • 84
  • 139
NAs
  • 89
  • 6
  • This is definitely not a duplicate, this is a completely different question that's not really related to permutations at all. – Calvin Godfrey Jul 03 '19 at 12:23
  • Perhaps it may help to clarify the expected input and output with a smaller tuple? To me, it looks like counting, but with extra steps. – norok2 Jul 03 '19 at 12:25
  • 3
    Those are not permutations, but a [product](https://docs.python.org/3/library/itertools.html#itertools.product). – tobias_k Jul 03 '19 at 12:32
  • Thanks for correcting my description. It really is counting, but in different base systems. I was thinking "permutations" because the problem I am trying to solve relates to product configurations, e.g. 6 different colors, 4 different thicknesses, 2 different substrates, etc. – NAs Jul 03 '19 at 13:35
  • I disagree with the duplicate marking. Much more importantly, the referenced page doesn't even come remotely close to the elegance of Adam.Er8's answer. – NAs Jul 04 '19 at 19:48

3 Answers3

3

you can use itertools.product:

try this:

from itertools import product

limits = [2, 3, 4, 2]
result = list(product(*[range(x) for x in limits]))
print(result)

Adam.Er8
  • 12,675
  • 3
  • 26
  • 38
0

What you're basically doing is trying to represent integers in a changing base. In your example, some of the digits are base 2, some base 3, and some base 4. So you can use an algorithm that chance base 10 to any base, and have the base you convert to depend on the current digit. Here's what I threw together, not sure if it's completely clear how it works.

n = [2, 3, 4, 2]
max_val = 1
for i in n:
  max_val *= i

ans = [] # will hold the generated lists

for i in range(max_val):
  current_value = i
  current_perm = []
  for j in n[::-1]: # For you, the 'least significant bit' is on the right
    current_perm.append(current_value % j)
    current_value //= j # integer division in python 3
  ans.append(current_perm[::-1]) # flip it back around!
print(ans)
Calvin Godfrey
  • 2,171
  • 1
  • 11
  • 27
0

So you basically just want to count, but you have a different limit for each position?

limits = [2,3,4,2]
counter = [0] * len(limits)

def check_limits():
    for i in range(len(limits)-1, 0, -1):
        if counter[i] >= limits[i]:
            counter[i] = 0
            counter[i-1] += 1
    return not counter[0] >= limits[0]

while True:
    counter[len(counter)-1] += 1

    check = check_limits()
    if check:
        print(counter)
    else:
        break

Not a list of tuples, but you get the idea...

Maracana
  • 211
  • 2
  • 6