多角形の辺の数を数える


18

多角形の辺の数を数える

ポリゴンサイドカウントロボットは、誰にも言わずに世界を旅することにしましたが、ポリゴンカウントのプロセスを長時間停止しないことが重要です。したがって、次のタスクがあります。ポリゴンの白黒画像を指定すると、プログラム/関数は辺の数を返す必要があります。

プログラムは古いパンチカードコンピューターに送られ、パンチカードは最近非常に高価なので、プログラムをできるだけ短くすることをお勧めします。

エッジの長さは少なくとも10ピクセルであり、2つの隣接するエッジによって形成される角度は少なくとも10°ですが、170°以下(または190°以上)です。ポリゴンは画像内に完全に含まれており、ポリゴンとその補数が接続されているため(孤立した島はありません)、この入力は無効になります。

ここに画像の説明を入力してください

得点

これはcodegolfです。つまり、バイト単位の最短のサブミッションが勝ち、サブミッションはすべてのテストケースのエッジの正しい数を見つける必要があります。(また、提出は他のケースでも機能するはずです。それらのテストケースだけの最適化は許可されていません。)

毎回正しい番号を見つけられないソリューションを提出したい場合、それも提出できますが、それはより良いパフォーマンスのすべての提出の後ろにランク付けされます。

提出タイトルに合計数を含めてください。(総誤差は、辺の実際の数と各出力の間の絶対差の合計です)。

テストケース

n = 10

ここに画像の説明を入力してくださいここに画像の説明を入力してください

n = 36

ここに画像の説明を入力してくださいここに画像の説明を入力してください

n = 7

ここに画像の説明を入力してくださいここに画像の説明を入力してください

n = 5

ここに画像の説明を入力してくださいここに画像の説明を入力してください

これはテストケースではなく、単なる好奇心からです:この入力に対していくつのエッジを取得しますか?

ここに画像の説明を入力してください


テストケースには、170°を超える多くの角度があります。たとえば、星のすべての「非ポイント」角度(中心に近い角度)。
ドアノブ

@Doorknob 170°未満の小さな角度です。
リトシアスト

はい。ただし、再び190°を超えています。この制限のポイントは、隣接する2つの側面を区別することが難しい例を排除することです。
-flawr

2
ポリゴンの内部はどの色ですか?
feersum

1
プログラムは、古いパンチカード、コンピュータに供給され、パンチカードは、最近非常に高価なものとして、あなたはより良いできるだけ短くしてプログラムを作ってみる :-)
ルイスMendo

回答:


12

Python 2 + PIL、エラーなし、 313 307バイト

from Image import*
I=open(sys.argv[1])
w,h=I.size;D=I.getdata()
B={i%w+i/w*1j for i in range(w*h)if D[i]!=D[0]}
n=d=1;o=v=q=p=max(B,key=abs)
while p-w:
 p+=d*1j;e=2*({p}<B)+({p+d}<B)
 if e!=2:e%=2;d*=1j-e*2j;p-=d/1j**e
 if abs(p-q)>5:
    t=(q-v)*(p-q).conjugate();q=p;w=o
    if.98*abs(t)>t.real:n+=1;v=p
print n

コマンドラインでイメージファイル名を取得し、結果をSTDOUTに出力します。

すべてのテストで正しい結果が得られ、円ではn = 28です。

説明

このアルゴリズムは、多角形の周囲を歩いて、検出された頂点の数をカウントすることで機能します(方向の変化として検出されます)。原点から最も離れたピクセルから開始しますo。これは、頂点であることが保証されているため、エッジ(つまり、前景ピクセルと背景ピクセルの境界)に隣接することが保証されています。位置p、、最新の頂点v、および最新の「チェックポイント」を追跡qoます。これらはすべて最初はに等しくなっています。またd、現在のピクセルに対するエッジの方向を追跡します。d最初は東を指しますが、これは安全な方向です。oまたは、原点から最も遠くはないでしょう。エッジに沿って、に垂直な方向、つまり左dd指すように、つまり時計回りに移動します。「エッジから落ちる」、つまり、pポリゴンの外側にある状況、または左のピクセル(つまりの方向d)がポリゴンの内側にある状況では、調整をp行い、dそれに応じて再開します。

たびの間の距離pと最後のチェックポイントは、q5よりも大きくなり、我々は間の頂点を引き渡すかどうかを判断しようとするqp:私たちはとの間の角度を比較するvq(すなわち、からベクトルvq)の一般的な方向であり、最後のチェックポイントに到達したときに歩いていたポリゴンの側面、およびqp最後のチェックポイントと現在の位置の間の変位。角度が約10°より大きい場合、ポリゴンの別の辺に沿って歩いていると判断し、頂点の数を増やしv、現在の頂点をに設定しpます。各チェックポイントで、頂点を検出したかどうかに関係なくq、最後のチェックポイントであるを更新して、po開始点であるに戻るまでこの方法を続け、見つかった頂点の数を返します(開始点o自体が頂点であるため、頂点カウントは最初は1であることに注意してください)。

以下の画像は、検出された頂点を示しています。p新しい頂点の位置は最適ではないため、各チェックポイントでの現在位置を取得することに注意してください。実際の頂点は、おそらく周囲に沿って最後のチェックポイント、、qおよびの間にあるためpです。ご覧のとおり、最初の頂点(通常、右下の頂点)以外のすべての頂点が少しずれています。これを修正すると、より多くのバイトがかかりますが、これはそのままで十分に機能しているようです。そうは言っても、4つのテストケースだけでオーバーフィットするのは少し難しいです。

n = 10 n = 36 n = 7 n = 5 サークル


この詳細な説明をありがとう!あなたのイラストが大好きです!
flawr

の東にエッジがある場合o、もう一方の端は原点からさらに遠くにありませんか?
aditsu

1
@aditsuここでは、用語が少しわかりにくいかもしれません。我々は、の話幾何学的な意味で、多角形の、およびエッジのラスタグラフィックスとして、ポリゴン(含む画素の集合します)。oは原点から最も遠い前景ピクセルであるため、その東のピクセルは背景ピクセルでなければなりません。したがって、の東にエッジがあると言いoます。
エル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.