ターゲット製品がサブセットで見つかったら、Pythonを停止させる方法は?


8

私は、サブセット製品などのNP完全な問題の趣味と実証的研究のためにpythonを学んでいます。私が持っているアルゴリズムは機能しますが、意図したとおりには実行されません。

私がやろうとしていることはcombinations、入力変数のサブセット積に到達したらitertoolsを停止することですtarget。これにより、コードが少し速くなります。コードは洗練段階にあるため、不要なリストがありますres_2

これがループです。

res_2 = [];
for i in range(1, len(s)+1):

   var = (findsubsets(s, i))   
   kk = list(map(numpy.prod, var))
   res_2.append(kk)
   if target in kk:
     print('yes')
     print(var)
     break

これは私が望まない出力です。スクリプトが(4、4)で停止しないことに注意してください。ターゲットが「ヒット」した後ですべての組み合わせをチェックし続けるのは、リソースの無駄です。

Enter numbers WITH SPACES: 4 4 3 12
enter target integer:
16
yes
[(4, 4), (4, 3), (4, 12), (4, 3), (4, 12), (3, 12)]
 kk
[16, 12, 48, 12, 48, 36]

私の意図する出力は、最初の「ヒット」の場合は(4、4)で停止することです。(1,2,3)や(1,2,3 --- any-length)のような他のサブセットについても同じです。ヒットが見つかるまでスクリプトを続行することをお勧めします。ヒットが見つかると、アルゴリズムの速度が向上するため、停止します。

以下の完全なスクリプト

# Naive Subset-Product solver
# with python's itertools

import itertools 
import numpy

s = list(map(int, input('Enter numbers WITH SPACES: ').split(' ')))
print('enter target integer: ')
target = int(input())


if s.count(target) > 0:
   print('yes')
   quit()

if target > numpy.prod(s):
  print('sorry cant be bigger than total product of s')
  quit()


def findsubsets(s, n): 
    return list(itertools.combinations(s, n)) 

# Driver Code 
n = len(s)

# This code snippet is a for loop. It also is intended to cut down execution
# time once it finds the target integer. (instead of creating all combinations)

res_2 = [];
for i in range(1, len(s)+1):

   var = (findsubsets(s, i))   
   kk = list(map(numpy.prod, var))
   res_2.append(kk)
   if target in kk:
     print('yes')
     print(var)
     break

質問

これを機能させてアルゴリズムの速度を上げるにはどうすればよいですか?どんなpythonicトリックが私の問題を解決しますか?これを行うより短い方法はありますか?

回答:


3

itertoolsのcombinations戻り値をに変換するのは時期尚早listです。特に、早く終了してオーバーヘッドが多すぎないようにしようとしている場合はなおさらです。通常、ライブラリ関数が完全に実現されたリストではなくイテレータを返すのには十分な理由があります。

ここに提案があります:

def findsubsets(s, n): 
    return itertools.combinations(s, n)

def find_subset(target,nums):
    for i in range(1,len(nums)+1):
        for ss in findsubsets(nums, i):
            if np.prod(ss) == target:
                prodstr = '*'.join(str(num) for num in ss)
                print(f"{target} = {prodstr}")
                return ss
    return None

find_subset(96,[1,6,2,8])

それfindsubsetsが単一の行であることを考えると、それをスタンドアロン関数として持つことは一種の疑わしいものです(基本的にcombinationsimport X as Yステートメントで実行できるエイリアスにすぎません)。いずれにせよ、これは、より大きな入力でRAMを過剰に消費することなく、早期に停止するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.