2016-08-28 12 views
2

私はPythonの初心者ですから、いくつかのWebサイトからいくつかのコードを勉強しようとしています。 GitHubで演算式のためにBruteforce searchを実行するアルゴリズムが見つかりました。コードは次のとおりです。算術演算のブルートフォース検索アルゴリズム

#!python 
import operator 
import itertools 
from fractions import Fraction 

operations = dict() 
operations['+'] = operator.add 
operations['-'] = operator.sub 
operations['/'] = operator.truediv 
operations['*'] = operator.mul 

def solve(target, numbers): 
    """List ways to make target from numbers.""" 
    numbers = [Fraction(x) for x in numbers] 
    return solve_inner(target, numbers) 

def solve_inner(target, numbers): 
    if len(numbers) == 1: 
     if numbers[0] == target: 
      yield str(target) 
     return 

    # combine a pair of numbers with an operation, then recurse 
    for a,b in itertools.permutations(numbers, 2): 
     for symbol, operation in operations.items(): 
      try: 
       product = operation(a,b) 
      except ZeroDivisionError: 
       continue 

      subnumbers = list(numbers) 
      subnumbers.remove(a) 
      subnumbers.remove(b) 
      subnumbers.append(product) 

      for solution in solve_inner(target, subnumbers): 
       # expand product (but only once) 
       yield solution.replace(str(product), "({0}{1}{2})".format(a, symbol, b), 1) 

if __name__ == "__main__": 
    numbers = [1, 5, 6, 7] 
    target = 5 
    solutions = solve(target, numbers) 
    for solution in solutions: 
     print("{0}={1}".format(target, solution)) 

それは単に私のnumbersを使用して、任意の算術式をしようとして終了し、その結果(私が持っている結果)としてtargetを取得したものを印刷します。

私は、式が結果として得られなかったときにスクリプトが試した解決策を印刷するにはどうすればいいですか?target私が設定しましたか?

編集:

これは私が試したコードです:

#!python 
import operator 
import itertools 
from fractions import Fraction 

operations = dict() 
operations['+'] = operator.add 
operations['-'] = operator.sub 
operations['/'] = operator.truediv 
operations['*'] = operator.mul 

def solve(target, numbers): 
    """List ways to make target from numbers.""" 
    numbers = [Fraction(x) for x in numbers] 
    return solve_inner(target, numbers) 

def solve_inner(target, numbers): 
    if len(numbers) == 1: 
     num = numbers[0] 
     yield str(num), num == target 
     return 

    # combine a pair of numbers with an operation, then recurse 
    for a,b in itertools.permutations(numbers, 2): 
     for symbol, operation in operations.items(): 
      try: 
       product = operation(a,b) 
      except ZeroDivisionError: 
       continue 

      subnumbers = list(numbers) 
      subnumbers.remove(a) 
      subnumbers.remove(b) 
      subnumbers.append(product) 

      for solution, truth in solve_inner(target, subnumbers): 
       yield solution.replace(str(product), 
        "{0}=({1}{2}{3})".format(product, a, symbol, b), 1), truth 


if __name__ == "__main__": 
    numbers = [1, 5, 6, 7] 
    target = 5 
    solutions = solve(target, numbers) 
    for solution, truth in solutions: 
     print("{0}? {1}".format(solution, 
       'True' if truth else '')) 

私は、結果として、実際の製品を得るが、私は式の中で、小さな操作の結果を得る:

42=(7*6)/5=(42/5)=(1*42/5) 

ながら私は実際に文字列の始めにわずか42を取得しようとしています。

答えて

2

num [0]がtargetと等しい場合はstr(num [0])を返し、それ以外の場合は再帰を終了します。何かが得られた場合、文字列式は連続した歩留まりで構築されます。すべての表現を得るためには、何かを常に出さなければなりません。目標に達したかどうかを確認することも選択します。代わりに、式は印刷前に評価される可能性があります。

#!python 
import operator 
import itertools 
from fractions import Fraction 

operations = dict() 
operations['+'] = operator.add 
operations['-'] = operator.sub 
operations['/'] = operator.truediv 
operations['*'] = operator.mul 

def solve(target, numbers): 
    """List ways to make target from numbers.""" 
    numbers = [Fraction(x) for x in numbers] 
    return solve_inner(target, numbers) 

def solve_inner(target, numbers): 
    if len(numbers) == 1: 
     num = numbers[0] 
     yield str(num), num == target 
     return 

    # combine a pair of numbers with an operation, then recurse 
    for a,b in itertools.permutations(numbers, 2): 
     for symbol, operation in operations.items(): 
      try: 
       product = operation(a,b) 
      except ZeroDivisionError: 
       continue 

      subnumbers = list(numbers) 
      subnumbers.remove(a) 
      subnumbers.remove(b) 
      subnumbers.append(product) 

      for solution, truth in solve_inner(target, subnumbers): 
       # expand product (but only once) 
       yield solution.replace(str(product), 
        "({0}{1}{2})".format(a, symbol, b), 1), truth 

if __name__ == "__main__": 
    numbers = [1, 5, 6, 7] 
    target = 5 
    solutions = solve(target, numbers) 
    for solution, truth in solutions: 
     print("{0}={1}? {2}".format(target, solution, 
       'True' if truth else '')) 

オリジナルにグリッチがあります。製品が最後に追加されますが、正面から製品と一致する最初の番号が置き換えられます。私はその結果が表現の省略であると信じています。その場合、アルゴリズムは完全ではありません。交換は最後からはできないので、交換する製品になるように、製品を正面(subnumbers.insert(0, product))に配置する必要があります。私はあなたに何が違うのかを実験させます。しかし、コードが正しく書かれていれば、コードが少し分かりやすくなっていると思います。

+0

質問を編集しました。 – Rhanny

+0

テリー、任意の提案? 'product'が算術式全体の正しいものであることをどうやって確認できますか? 'subnumbers.insert(0、product))'は最後の再帰に置かなければなりません。 – Rhanny

+0

インサートは、現在の 'subnumbers.append(product)'を置き換えるべきです。 –