查找具有不同数字的10位整数,以便前n个数字可从1到n整除。
一个较小的例子是123。
1可被1整除 12可被1和2整除 123可以被1,2和3整除
我写了一些代码来尝试自动执行此操作:
import sympy
import itertools
x = itertools.permutations('1234567890',10)
for s in x:
string_number = ''.join(s)
for j in range(1, len(string_number)):
a = set(range(1,j+1))
divisors = set( sympy.divisors( int(string_number[:j] ) ) )
if not (a.issubset(divisors) and a!=divisors):
break
print('FOUND IT %s'%string_number)
这似乎不起作用,我认为这是因为最后一点的逻辑。我怎样才能确保如果一个数字违反条件,我继续下一个数字,如何确保如果数字服从条件,我选择正确的数字打印?
答案 0 :(得分:5)
不是枚举所有可能的排列,而是一次创建一个数字的数字,并且当数字到目前为止有效时继续。这是一个基本的深度优先搜索。
你也可以使它成为一个生成器函数来找到第一个或所有这样的数字。这是一个相当直接的实现,没有任何优化:
def find_number(stop, number=""):
if len(number) == stop:
yield number
for d in "1234567890":
if d not in number:
new_num = number + d
if int(new_num) % len(new_num) == 0:
for n in find_number(stop, new_num):
yield n
示例:
>>> next(find_number(10))
3816547290
>>> list(find_number(9))
['381654729', '381654720', '783204165', '801654723', '081654327']
但 10!可能的数字也不是所有那么多,所以如果你可以等几秒钟,你的详尽方法也应该有效。将它全部置于一个可怕的单行列表理解/生成器表达式中怎么样?
next(s for s in map(''.join, itertools.permutations('1234567890', 10))
if all(int(s[:i]) % i == 0 for i in range(1, len(s)+1)))
如评论中所述,问题似乎是break
,它只是从内部循环中断,但不会跳过print
语句。我没有尝试这个,因为我现在没有安装sympy
,但您应该能够使用for/else
循环修复此问题:
for j in range(1, len(string_number)):
a = set(range(1,j+1))
divisors = set( sympy.divisors( int(string_number[:j] ) ) )
if not (a.issubset(divisors) and a!=divisors):
break
else:
print('FOUND IT %s'%string_number)