嵌套循环的数学公式是什么?



想象一下这个循环:

for i in range(3):
for j in range(3):
for k in range(3):
print("{}{}{}".format(letter, number, symbol))

我想通过操作I, j和k值,以数字方式生成这个序列,而不需要嵌套的for循环。包含这3个值的所有排列的公式是什么?

给定3个数字I, j, k,我如何计算下一个不重复的位置?我应该加上I j k可能有不同的大小

我已经尝试使用python itertools置换,我已经使用了计数算法。

我尝试用计数算法生成它。但我认为我的计数算法中有一些明显的东西我遗漏了,但我不确定是什么。

想象一个名为.tick的函数,它产生序列中的下一项而不重复。

我的计数算法是这样的。你可以在Repl上找到它。这里。

class Tick:
def __init__(self, collections, func):
self.collections = collections
self.indexes = []
self.loops = 0
self.reset = -1
self.func = func
self.started = False
for collection in collections:
self.indexes.append(0)
def size(self):
total = len(self.collections[0])
for collection in self.collections[1:]:
total = total * len(collection)
return total

def tick(self):
if self.started:
if self.reset != -1:
self.indexes[self.reset + 1] = 0
for index in range(self.reset + 1, len(self.indexes)):

self.indexes[index] = 0
self.reset = -1

else:
self.loop = len(self.indexes) - 1
while self.loop != -1 and self.indexes[self.loop] == len(self.collections[self.loop]) - 1:
self.loop = self.loop - 1
if self.loop == -1:
return

self.indexes[self.loop] = self.indexes[self.loop] + 1
if self.loop < len(self.indexes) - 1:
self.reset = self.loop
else:
self.started = True
items = []
for loop in range(len(self.indexes)):
items.append(self.collections[loop][self.indexes[loop]])
return self.func(items)

a = ["0", "1", "2"]      
b  = ["0", "1", "2"]
c = ["0", "1", "2"]
def printer(items):
output = ""
for item in items:
output += item
return output
ticker = Tick([a, b, c], printer)
print(ticker.size())
for index in range(ticker.size()):
print(ticker.tick())

不幸的是,它产生如下

27
000
001
002
012
010
011
012
022
020
021
022
122
100
101
102
112
110
111
112
122
120
121
122
222
200
201
202

注意以下内容是重复的。我使用了这个重复的行查找器。

COUNT    | LINE
-----------------------------------------------------
3 |     122
2 |     012
2 |     022
2 |     112
1 |     000
1 |     001
1 |     002
1 |     010
1 |     011
1 |     020
1 |     021
1 |     100
1 |     101
1 |     102
1 |     110
1 |     111
1 |     120
1 |     121
1 |     200
1 |     201
1 |     202
1 |     222
-----------------------------------------------------
27 | TOTAL LINES
22 | DISTINCT LINES

如果我正确理解你的问题,你正在寻找一种方法:给定一个数字n,在不同列表的product中找到n-第一个元素,而不生成之前的所有元素。这类似于将数字转换为不同的进制,不同之处在于每个数字可能有不同的进制,并且不是返回数字本身,而是从相应的列表中获取这些元素。

def nth_product(list_of_lists, n):
res = []
# reversed to match order of itertools.product
for lst in reversed(list_of_lists): 
n, r = divmod(n, len(lst))
res.append(lst[r])
return tuple(reversed(res))

同样,你可以计算给定产品在产品列表中的位置,例如,将该产品直接放在其他产品之后:

def position(list_of_lists, tup):
t = 1
res = 0
for lst, x in zip(reversed(list_of_lists), reversed(tup)):
res += t * lst.index(x)
t *= len(lst)
return res

itertools.product产量比较:

import itertools
list_of_lists = [[1,2], [3,4,5,6], [7,8,9]]
for n, prod in enumerate(itertools.product(*list_of_lists)):
print(n, prod, nth_product(list_of_lists, n), prod_position(list_of_lists, prod))

结果:

0 (1, 3, 7) (1, 3, 7) 0
1 (1, 3, 8) (1, 3, 8) 1
...
23 (2, 6, 9) (2, 6, 9) 23

这是我最后使用的代码。我还有一个额外的要求,我希望笛卡尔积均匀地展开!它使用tobias_k answer生成嵌套循环的第n个乘积。我还想均匀地分布嵌套循环的求值:所以我想要111 222 333,而不是001 002 003 010 011 100 100 101 111。请参阅这个stackoverflow答案,枚举笛卡尔积,同时尽量减少公式的重复,以均匀地展开笛卡尔积。秘诀,多用模!

class Tick:
def __init__(self, collections, func):
self.collections = collections
self.n = 0
self.func = func

self.current = []
for item in range(len(self.collections)):

self.current.append(0)

def size(self):
total = len(self.collections[0])
for collection in self.collections[1:]:
total = total * len(collection)
return total
def tick(self):

items = []
n = self.n
self.indexes = []


# reversed to match order of itertools.product
for collection in reversed(self.collections): 
n, r = divmod(n, len(collection))
self.indexes.append(r)

for loop in range(len(self.collections)):
previous = 0
for mod in range(0, len(self.collections)):
previous = previous + self.indexes[mod]

self.indexes[loop] = previous % len(self.collections[loop])

for loop, item in enumerate(self.indexes):
items.append(self.collections[loop][item])

self.n = self.n + 1
return self.func(items)

a = ["a", "b", "c"]      
b  = ["1", "2", "3"]
c = ["÷", "×", "("]
def printer(items):
output = ""
for item in items:
output += item
return output
ticker = Tick([a, b, c], printer)
print(ticker.size())
for index in range(ticker.size()):
print(ticker.tick())
print("CORRECT")
for letter in a:
for number in b:
for symbol in c:
print("{}{}{}".format(letter, number, symbol))

对于好奇的人来说,这是它产生的结果:

a1÷
b2(
c3×
b3÷
c1(
a2×
c2÷
a3(
b1×
b3×
c1÷
a2(
c2×
a3÷
b1(
a1×
b2÷
c3(
c2(
a3×
b1÷
a1(
b2×
c3÷
b3(
c1×
a2÷

我们

b3÷ which is 2 3 1
c1( which is 3 1 3
a2× which is 1 2 2

等等,均匀地展开!

最新更新