找到所有三个“两位数字”,没有重复的数字

时间:2017-05-30 13:22:44

标签: python for-loop

编写一个程序,查找所有正整数的三元组(i, j, k),使ijk为两位数字,{中不会出现多次数字{1}},ij

我写道:

k

为什么它仍然不正确?它仍包含for i in range(10,100): for j in range(10,100): for k in range(10,100): if i%10 !=i//10 !=j%10 !=j//10 != k%10 != k//10: print(i,j,k) ij中的相同数字。怎么了?

4 个答案:

答案 0 :(得分:3)

正如Arya McCarthy所说,你的代码只会检查它们是不是完全一样。以下代码检查ijk中是否存在重复数字。

for i in range(10,100):
    for j in range(10,100):
        for k in range(10,100):
            digits = {i%10, i//10, j%10, j//10, k%10, k//10}
            if len(digits) == 6:
                print(i,j,k)

答案 1 :(得分:1)

你可以直接从两位数字建立一个集合,检查长度是6;保存所有数学:

for i in range(10,100):
    for j in range(10,100):
        for k in range(10,100):
            if len(set('{}{}{}'.format(i,j,k))) == 6:
                    print(i,j,k)

如果您选择坚持数学,可以将%//替换为divmod,然后检查:

len(set(divmod(i,10)+divmod(j,10)+divmod(k,10))) == 6

答案 2 :(得分:1)

另一种方法是使用itertools.combinations

from itertools import combinations

possible_values = combinations(range(10, 100), 3)

satisfies_condition = {(x, y, z) for x, y, z in possible_values if 
                        len({x%10, x//10, y%10, y//10, z%10, z//10}) == 6}

print('\n'.join(map(str, satisfies_condition)))

打印:

(17, 40, 82)
(74, 90, 28)
(29, 37, 40)
(73, 96, 10)
(31, 97, 85)
(83, 70, 91)
(15, 23, 69)
(23, 49, 15)
(56, 18, 37)

从技术上讲,要匹配您正在做的事情,您需要使用itertools.permutations(因为订单在您的方法中很重要)。但我认为,在这个问题的核心,长度为3的组合是最合适的。

答案 3 :(得分:1)

有一种更快的方法来解决这个问题;使用combinationspermutations

from itertools import combinations, permutations

l = range(10)

for c in combinations(l, 6):  # all 6-combinations of the numbers 0-9
    for c1, c2, c3, c4, c5, c6 in permutations(c):  # all permutations of these numbers
        if c1 == 0 or c3 == 0 or c5 == 0:
            continue  # exclude those where the first digit of any number is 0
        else:
            print('{}{} {}{} {}{}'.format(c1, c2, c3, c4, c5, c6))

这从数字0到9中取6个数字(没有替换!)然后迭代这些数字的所有排列。唯一的检查是每个数字的第一个数字不是0(否则根据问题它不会是两位数字)。要获得您可以使用的数字:

i = 10*c1 + c2
j = 10*c3 + c4
k = 10*c5 + c6

如果你需要它们。

使用这种方法,与原始方法相比,您不需要丢弃那么多数字。

您甚至可以更进一步,使用set从中绘制数字:

l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}  # set of allowed numbers

for n1 in l - {0}:  # all numbers except 0
    for n2 in l - {n1}:  # all numbers except the first number
        for n3 in l - {0, n1, n2}:  # all numbers except 0 and the first and second number
            for n4 in l - {n1, n2, n3}:  # ...
                for n5 in l - {0, n1, n2, n3, n4}:
                    for n6 in l - {n1, n2, n3, n4, n5}:
                        print('{}{} {}{} {}{}'.format(n1, n2, n3, n4, n5, n6))

if差异替换set条件,不会产生“不必要”的对。

时序

要了解这种方法有何不同,我可以为不同的答案计时:

%%timeit

l = set(range(10))

for n1 in l - {0}:
    for n2 in l - {n1}:
        for n3 in l - {0, n1, n2}:
            for n4 in l - {n1, n2, n3}:
                for n5 in l - {0, n1, n2, n3, n4}:
                    for n6 in l - {0, n1, n2, n3, n4, n5}:
                        pass
  

每循环57.3 ms±295μs(平均值±标准偏差,7次运行,每次循环10次)

%%timeit

from itertools import combinations, permutations

l = range(10)

for c in combinations(l, 6):
    for c1, c2, c3, c4, c5, c6 in permutations(c):
        if c1 == 0 or c3 == 0 or c5 == 0:
            continue
        else:
            pass
  

每循环61.2 ms±101μs(7次运行的平均值±标准差,每次10次循环)

%%timeit

for i in range(10,100):
    for j in range(10,100):
        for k in range(10,100):
            digits = {i%10, i//10, j%10, j//10, k%10, k//10}
            if len(digits) == 6:
                pass
  

每循环1.7 s±2.36 ms(平均值±标准偏差,7次运行,每次循环1次)

%%timeit

for i in range(10,100):
    for j in range(10,100):
        for k in range(10,100):
            if len(set('{}{}{}'.format(i,j,k))) == 6:
                pass
  

每循环3.29 s±40.1 ms(平均值±标准偏差,7次运行,每次循环1次)

%%timeit

from itertools import combinations

possible_values = combinations(range(10, 100), 3)

satisfies_condition = {(x, y, z) for x, y, z in possible_values if 
                        len({x%10, x//10, y%10, y//10, z%10, z//10}) == 6}

for i in satisfies_condition:
    pass
  

每循环300 ms±7.73 ms(平均值±标准偏差,7次运行,每次循环1次)

因此,生成较少被排除对(前两个)的方法比使用C循环的方法(@not_a_robot给出的combinations方法)快〜5倍 - 但是这种方法不会不提供所有解决方案,所以在实践中它会慢很多,比range(10, 100)上的三个循环快〜30倍(@Will Da Silva的答案 - @Moses Koledoye的回答甚至更慢,因为字符串格式化或元组连接比使用set literal慢很多。