私はいくつかのサイトでいくつかの議論を見て、それらのどれも私に解決策を与えませんでした。このコードは、実行に5秒以上かかります。
for i in xrange(100000000):
pass
私は整数の最適化問題に取り組んでおり、O(n log n)アルゴリズムedit:an O(n²/4)アルゴリズム。ここで、nはすべての行列の項目を表します。つまり、次のコードではn * m = 10000です。したがって、10000の要素を持つ行列100 * 100の場合、結果はほぼ25000000の反復になります...。そのコードは次のように要約できます:
m = 100
n = 100
for i in xrange(m):
for j in xrange(n):
for i2 in xrange(i + 1, m):
for j2 in xrange(j + 1, n):
if myarray[i][j] == myarray[i2][j2] and myarray[i2][j] == myarray[i][j2]:
return [i, j], [i2, j2]
Pythonをあきらめて、JavaまたはCに戻りますか?
Python 2.7で作業していますが、Psycoは利用できません。PyPyはそのままではTkinterをサポートしていません。Tkinterを使用しています。
では、ループ速度を向上させるでしょうか?他の解決策はありますか?
かわいらしいコーディングスタイルではありませんが、絶望的な時代には必死のコーディングが必要です。ネストされたネストされたループを1つの大きなジェネレータ式に変えてみてください。
try:
i,j,i2,j2 = ((i,j,i2,j2)
for i in xrange(m)
for j in xrange(n)
for i2 in xrange(i + 1, m)
for j2 in xrange(j + 1, n)
if myarray[i][j] == myarray[i2][j2] and
myarray[i2][j] == myarray[i][j2]).next()
return [i,j],[i2,j2]
except StopIteration:
return None
ビルトインnext
とproduct
、およびrange
の代わりにPy3 xrange
を使用するように更新:
from itertools import product
match = next(((i,j,i2,j2)
for i, j in product(range(m), range(n))
for i2, j2 in product(range(i+1, m), range(j+1, n))
if myarray[i][j] == myarray[i2][j2] and
myarray[i2][j] == myarray[i][j2]), None)
if match is not None:
i,j,i2,j2 = match
return [i,j],[i2,j2]
else:
return None
引き続きpython表記を使用し、 Cython プロジェクトを使用してCの速度を持つことができます。最初のステップは、Cループでループを変換することです。それはループで使用されるすべての変数を入力することによって自動的に行われます:
cdef int m = 100
cdef int n = 100
cdef int i, j, i2, j2
for i in xrange(m):
for j in xrange(n):
for i2 in xrange(i + 1, m):
for j2 in xrange(j + 1, n):
次の部分では、myarrayが純粋なC配列であり、リッチpython比較も配列アクセスもない場合はさらに優れています。python配列、ネイティブ比較を行うことで豊富な比較を削除できます(配列にdoubleがある場合)。
cdef double a, b, c, d
a = myarray[i][j]
b = myarray[i2][j2]
c = myarray[i2][j]
d = myarray[i][j2]
if a == b and c == d:
return [i, j], [i2, j2]
cython -a yourfile.pyx
を実行して最適化がどのように行われているかを確認し、yourfile.html
生成を開きます。 Cythonがどのようにコードを最適化し、Pythonオーバーヘッドを削除したか)がわかります。
申し訳ありませんが、最適化の問題ではありません。選択する言語や実装に関係なく、このアルゴリズムは最悪の場合や平均的な場合ではO(n*log n)
ではありません。 Big-O表記の仕組み を読んで、より優れたアルゴリズムを開発することをお勧めします。
ジェネレータexprが機能しませんでした。これは、最初にすべての同様の値を集計し、次に長方形グループを探す別のスキームです。
from collections import defaultdict
from itertools import permutations
def f3(myarray):
tally = defaultdict(list)
for i,row in enumerate(myarray):
for j,n in enumerate(row):
tally[n].append((i,j))
# look for rectangular quads in each list
for k,v in tally.items():
for quad in permutations(v,4):
# sort quad so that we can get rectangle corners
quad = sorted(quad)
(i1,j1),(i2,j2) = quad[0], quad[-1]
# slice out opposite corners to see if we have a rectangle
others = quad[1:3]
if [(i1,j2),(i2,j1)] == others:
return [i1,j1],[i2,j2]
私はあなたのコード全体を何度か調べましたが、正しければ、2つの異なるコーナーマーカーで長方形をマークしています。私の答えがあなたの立場を明確にするためのコメントである場合は本当に申し訳ありません。
Answer-Part::適切なアルゴリズムを探している場合は、スキャンラインアルゴリズムを検討してください。 「最大の長方形の解」の例 ここでは@SO を見つけました。
あなたへの私の質問は、あなたは本当に何を探しているのですか?
ポールとあなたの解決策は異なる結果を生み出すことも指摘しなければなりません。ポールはコーナーが同じ値でマークされていると想定し、コーナーは2つの異なる値でマークされていると想定しているためです。
醜いc&pスクリプトでそれを説明するのに時間と自由を費やしました。2Dフィールドを作成して両方のアルゴリズムを比較し、string.lowercase文字を入力して、角を大文字にします。
from random import choice
from string import lowercase
from collections import defaultdict
from itertools import permutations
from copy import deepcopy
m,n = 20, 20
myarray = [[choice(lowercase) for x in xrange(m)] for y in xrange(n)]
def markcorners(i,j,i2,j2):
myarray[i][j] = myarray[i][j].upper()
myarray[i2][j] = myarray[i2][j].upper()
myarray[i2][j2] = myarray[i2][j2].upper()
myarray[i][j2] = myarray[i][j2].upper()
def printrect():
for row in myarray:
print ''.join(row)
print '*'*m
def paul_algo():
tally = defaultdict(list)
for i,row in enumerate(myarray):
for j,n in enumerate(row):
tally[n].append((i,j))
# look for rectangular quads in each list
for k,v in tally.items():
for quad in permutations(v,4):
# sort quad so that we can get rectangle corners
quad = sorted(quad)
(i1,j1),(i2,j2) = quad[0], quad[-1]
# slice out opposite corners to see if we have a rectangle
others = quad[1:3]
if [(i1,j2),(i2,j1)] == others:
markcorners(i1,j1,i2,j2)
def xavier_algo():
for i in xrange(m):
for j in xrange(n):
for i2 in xrange(i + 1, m):
for j2 in xrange(j + 1, n):
if myarray[i][j] == myarray[i2][j2] and myarray[i2][j] == myarray[i][j2]:
markcorners(i,j,i2,j2)
savearray = deepcopy(myarray)
printrect()
xavier_algo()
printrect()
myarray = deepcopy(savearray)
paul_algo()
printrect()