找到满足特定条件的数量的优化方法

时间:2015-04-22 23:13:38

标签: python python-2.7 math

我在某个地方看到了这个问题。 有一个8位数字。从左到右的第一个数字表示数字中有多少个零。第二个数字告诉你数字中有多少个,第三个数字告诉你数字中有多少2个,直到第8个数字告诉你数字中有多少个7。找到号码。 所以我在python中写了一段代码来找出数字。除了上面提到的条件之外,我还有一些额外的检查,例如“数字总和应该是8”,“数字中应该不存在8或9”。我已粘贴下面的代码。这只是蛮力,因为我拿走每个号码并检查条件。我很想知道是否有更好的方法来解决问题

def returnStat(number, digit, count):
    number = str(number)    
    digit = str(digit)
    print "Analysing for ",digit," to see if it appears ",count, " times in ",number,"."        
    actCnt = number.count(digit)
    count = str(count)
    actCnt = str(actCnt)
    if (actCnt == count):
        return 1
    else:
        return 0

def validateNum(number):
    numList = str(number)
    if '8' in numList:
        print "Skipping ",number, " since it has 8 in it"
        return (-1)
    elif '9' in numList:
        print "Skipping ",number, " since it has 9 in it"
        return (-1)
    elif (sum(int(digit) for digit in numList) != 8):
        print "Skipping ",number, " since its sum is not equal to 8"
        return (-1)
    index = 0
    flag = 0
    for num in numList:
        if (returnStat(number,index,num)) :
            index = index+1
            continue
        else:
            flag = 1
            break 
if (flag == 1):
    return (-1)
else:
    return number

for num in range(0,80000000):
number = '{number:0{width}d}'.format(width=8,number=num)

desiredNum = "-1"
desiredNum = validateNum(number)
if (desiredNum == -1):
    print number," does not satisfy all "
    continue
else:
    print "The number that satisfies all contition is ",number
    break

2 个答案:

答案 0 :(得分:3)

你可以更进一步,只是说数字8或9是不可能的。

最后一位数字是否可以大于0?答案是不。如果最后一个数字是1,这意味着在其他地方有一个7。但是,如果有7,则表示发生了7次相同的数字。这显然是不可能的。因此,最后一位必须为0。

所以我们有xxxxxxx0。

倒数第二位怎么样?

如果xxxxxx10,则必须至少有一个6,这意味着相同的数字出现了6次。我们可以尝试60000010,但这是不正确的,因为有一个1,应该反映在第二个数字。倒数第二个数字不能高于1,因为2表示有2个6,这意味着一个数字出现6次,而另一个数字也出现6次,这是不可能的。

所以我们有xxxxxx00。

如果xxxxx100,则必须至少有一个5,这意味着相同的数字出现了5次。让我们从51000100开始。差不多,但现在有2个1。所以它应该是52000100.但是等等,现在有一个1.和一个2.所以我们尝试52100100.但现在我们只有4 0。我们不能拥有xxxxx200,因为这意味着有2 5个,这是不可能的,如上所述。

所以我们有xxxxx000。

如果xxxx1000,我们可以尝试40001000,nope,41001000,nope,42101000。

啊,就是这样。 42101000

答案 1 :(得分:1)

即使你在其中没有8s或9s的所有8位数字上进行迭代,也没有多少可能性(实际上,8 ^ 8 = 1 <&lt; 24~1700万)。

这是一个尝试所有人的天真程序:

import itertools

for digs in itertools.product(range(8), repeat=8):
    counts = [0] * 8
    for d in digs:
        counts[d] += 1
    if counts == list(digs):
        print digs

它在我的机器上在15秒内完成(只有一个解决方案)。

为了加快速度,您只能考虑8位数字,其数字加起来为8.这里的代码与以前相同,但现在它使用sum_k来产生可能性。 (sum_k(n, k)生成所有n个数字元组,其中所有数字都小于8,总和为k。)

def sum_k(n, k):
    if k < 0 or n * 7 < k: return
    if n == 1:
        yield k,
        return
    for d in xrange(8):
        for s in sum_k(n-1, k-d):
            yield (d,) + s

for digs in sum_k(8, 8):
    counts = [0] * 8
    for d in digs:
        counts[d] += 1
    if counts == list(digs):
        print digs

此代码在我的机器上以0.022秒完成。

调整代码以解决一般情况会产生以下解决方案:

1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000