2011-09-21 34 views
3

昨天我遇到了一個有趣的數學問題,並解決了它,但是用我寫的代碼,我不得不做一個鍵盤中斷,否則它將永遠運行,哈哈。所以我改變它有一個結束條件,,但現在它只打印1個解決方案並停止。在Python中檢查唯一輸出

問題是這樣的:「你的數字是123456789,按順序在每個數字之間,你必須插入無符號,加號或乘號,以便得到的表達式等於2002.寫(有兩個)「

import random 


def try1(param): 
    global solved 
    opers = ['+', '*', ''] 
    hotpotato = ('%s'.join(param) % (random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            ) 
      ) 
    if eval(hotpotato) == 2002: 
     solved += 1 
     print "Solution:", hotpotato, "= 2002  :-)" 

    else: 
     pass 


solved = 0 
while solved == 0: 
    try1('123456789') 

此代碼打印遇到和停止的第一個解決方案。任何人都可以告訴我如何在停止之前打印兩種解決方案?

+0

這是來自歐拉項目嗎? – Blender

+1

@Blender如果是這樣,我還沒有看到它。 –

回答

3

存儲您的解決方案中的一組:

solutions = set([]) 

每次找到解決方法,更新設置:

solutions.append(solution) 

集是很好的,因爲不存儲重複:

>>> len(set([1, 1, 1, 1, 1, 1, 1])) 
1 

因此,只是循環,直到設置的大小大於一個:

while len(solved) < 2: 
    try1('123456789') 

此外,您還可以縮短這個代碼:

hotpotato = ('%s'.join(param) % (random.choice(opers), 
           random.choice(opers), 
           random.choice(opers), 
           random.choice(opers), 
           random.choice(opers), 
           random.choice(opers), 
           random.choice(opers), 
           random.choice(opers), 
           ) 
     ) 

要這樣:

hotpotato = ('%s'.join(param) % (random.choice(opers) for i in range(8)))) 
+0

我還沒有學過套。現在看起來很美好。我會馬上回復你的回答。 –

+2

就像一個建議,我會嘗試做這個蠻力而不是隨機的。它會運行得更快,並且可以擴展(你的程序會找到一個'1/3^8 = 0的解決方案。00015'每運行一次,這意味着在找到所有解決方案之前,您的預計運行次數爲3^8 = 6,561'。 – Blender

+0

你測試了縮短的代碼嗎?在擴展它之前,我嘗試了類似的方法,但它沒有將適當數量的參數傳遞給字符串格式器。不幸的是,你的代碼對我來說也一樣。 –

2

爲了記錄,我會鼓勵採用不同的方法來搜索解決方案,例如Andy T's answeryi_H's answer中建議的方法。也就是說,這個答案解決了問題中提出的問題。

你目前將運行至一個答案是發現和制止,因爲找到的第一個答案的代碼將使solved不等於0。因爲你知道有2個解決方案,你可以改變你的while循環的條件:

while solved < 2: 
    try1('123456789') 

迴應馬克評論說,這可能會導致重複的答案,這裏是代碼,這將確保你得到不同的解決方案:

import random 
def try1(param): 
    global solved 
    try1.prev_soln = [] 
    opers = ['+', '*', ''] 
    hotpotato = ('%s'.join(param) % (random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            random.choice(opers), 
            ) 
      ) 
    if eval(hotpotato) == 2002: 
     if hotpotato not in try1.prev_soln: 
      solved += 1 
      try1.prev_soln.append(hotpotato) 
      print "Solution:", hotpotato, "= 2002  :-)"  
    else: 
     pass 

solved = 0 
while solved < 2: 
    try1('123456789') 

當然,這種方法假設2級的解決方案。如果您的解決方案數量未知,您將無法知道什麼時候停止,因此我建議您尋找其他解決方案。

+3

但是請注意,當你在測試隨機排列時,你的兩個解決方案可能是一樣的。 – Mark

+0

而這正是我碰到的。我運行代碼20次,它總是返回相同的解決方案。 –

+0

@Shon Freelen:更新的答案應該解決獲得相同解決方案的問題。 – GreenMatt

8

不要使用隨機,枚舉所有可能的操作符組合(好吧,您可以稍微剪切一下搜索空間,如果第一對數字的結果大於2002,那麼結果沒有辦法小)。 itertools是你的朋友。

如果你這樣做,你的程序將很快完成。

如果你知道有正好兩種解決方案可以從try1返回解決方案,直到你收集到兩種不同的解決方案做的環,但不是真正的優雅,是嗎?

+0

3 ** 8 == 6561(八(「」,「+」,「*」)的笛卡爾乘積),因此沒有切實需要切斷搜索空間。 – tzot

3

要接收你需要完全不同的方法都(全部)的解決方案來解決這個問題。檢查插入操作的所有排列。排列在這裏展示瞭如何計算:http://www.bearcave.com/random_hacks/permute.html

編輯:

例子:

ops = ['+', '*'] 

def gen(ver, i): 
    if i == len(ver): 
     return 
    for op in ops: 
     ver = ver[:i] + op + ver[i:] 
     if eval(ver) == 2002: 
      yield ver 
     for j in range(i + 2, len(ver)): 
      for sol in gen(ver, j): 
       yield sol 
     ver = ver[:i] + ver[i+1:] 

for sol in gen("123456789", 1): 
    print "solution:", sol 

輸出:

solution: 1*2+34*56+7+89 
solution: 1*23+45*6*7+89 
+0

增加了一個例子 –

5

解決你的問題,解決了當斷= = 2.

但是你的代碼的真正問題是使用隨機的。在算法中使用隨機數通常是一個壞主意。您的代碼有可能持續一個多世紀。

有很多simplier和更快的方式使用itertools:

import itertools 

for s in itertools.product(("+", "*", ""), repeat=8): 
    z = itertools.izip_longest("123456789", s, fillvalue="") 
    e = "".join(itertools.chain.from_iterable(z)) 

    if eval(e) == 2002: 
     print(e) 

沒有必要打破當兩個解決方案中,因爲代碼已經在0.2秒內完成:)。

+0

我打算糾正你,然後我重新考慮了在數字之間插入符號的另一種方法。非常好 :) –