パスセグメントのように。初めて触れた


14

2つ以上の2Dデカルトポイントの順序付きリストが与えられた場合、パスがそれ自体に触れるか自己交差する場合、真の値を出力します。それ以外の場合、それ自体に触れたり自己交差したりしない場合、偽の値を出力します。

リスト内の連続したポイントは別個のものであると想定することができます。

例:

(0,0), (1,0) -> falsey
(0,0), (1,0), (0,0) -> truthy
(0,0), (1,0), (1,1), (0,0) -> truthy
(0,0), (2,0), (1,1), (1,-1) -> truthy
(0,0), (10,0), (0,1), (10,1), (0,2), (10,2) -> falsey

ここで指定したすべての座標は整数です。{整数、小数、有理数、浮動小数点、...}のうち、好きなものの座標入力をサポートできます。ただし、実装の計算では、与えられた入力に対して正しい答えを与える必要があります。


4
なんて良いタイトルA +
地下

初期シーンレザボア・ドッグス、誰?
ルイスメンドー

誤解している場合はご容赦ください。ただし、最後のテストケースはどのように交差していませんか。i.imgur.com/wiNMByd.png
完全に人間の

2
@icrieverytim閉ざされた散歩ではありません。最後のポイントは最初のポイントに接続しません。
ハイパーニュートリノ

回答:


5

Pythonの2315の 309 298 382 380 372バイト

s=sorted
w=lambda(x,y),(X,Y),(z,w):(X-x)*(w-y)-(z-x)*(Y-y)
def I(a,b):p,q=s(a);P,Q=s(b);n,N,m,M=w(p,q,P),w(p,q,Q),w(P,Q,p),w(P,Q,q);return(q>=P)*(Q>=p)if{n,N,m,M}=={0}else(b[1]!=a[0])*(n*N<=0>=m*M)
def f(l):
 i=0
 while i<len(l)-2:
	x=l[i:i+3];i+=1
	if w(*x)==0and s(x)==x:l.pop(i);i-=1
 L=zip(l,l[1:]);return any(I(*l)for l in[(k,x)for i,k in enumerate(L)for x in L[:i]])

オンラインでお試しください!

ここからのアルゴリズムを使用し、共線セグメントのこのSO回答と組み合わせます。

編集:(0,0),(1,0),(2,0)中間点を削除することで同じ方向(例:)に続く線分を修正(結果として(0,0),(2,0))。


2つのスペースの2つの出現箇所すべてを1つのタブに置き換えることにより、2バイトを節約できます。
ジョナサンフレッチ

*((n*N>0)+(m*M>0)<1)-> *(n*N<=0>=m*M)
ジョナサンフレッチ

3

Eukleides154 148バイト

number i (set p)
g=card(p);h=g;n=0;e=p[0];q=e.e
for d in p
if h<g-1 
q=q.e
n=card(intersection(d.e,q))>1or d on q?1|n
end
e=d;h=h-1
end;return n;end

i一連のポイントを渡して、0または1を返すという名前の関数とにかくここの周りのコード。

Eukleidesは、主にグラフィック出力用の平面ジオメトリ言語ですが、適切なプログラム機能も備えています。この作業には素晴らしいと思いましたが、いくつかのことがイライラしました。まず、Eukleidesのセットは本質的にポイントの配列であり、該当する場合は接続されたラインセグメントで構成されるパスとしてレンダリングされることに注意してください。Eukleidesは、プロセス内でセットを作成するforループに似た、軌跡を介したセットの反復生成をサポートします。軌跡を使用できれば、バイトを削り取ることができましたが、Eukleidesは部分的に形成された軌跡を内部から参照することを好まないようです。

もう1つの大きな不満は、2つの同一の線分が互いに重なり合っているように見える場合、intersection問題のあるポイントを1つしか返さないことです(これは理にかなっていますが、無限の交差点があると思います)。私の方法は、基本的に1つ後ろのパスを構築し、次のラインセグメントでパスとの交差をテストすることです。前述の交差動作のため、ポイントがパス上にあるかどうかを個別にチェックします。

編集or前にスペースを削除できるようにステートメントを並べ替えて、1バイトをカットしorます。そのifブロックを3項演算に変更することにより、さらに5バイト。

テストケース:

ta=point(0,0).point(1,0)
tb=point(0,0).point(1,0).point(0,0)
tc=point(0,0).point(1,0).point(1,1).point(0,0)
td=point(0,0).point(2,0).point(1,1).point(1,-1)
te=point(0,0).point(10,0).point(0,1).point(10,1).point(0,2).point(10,2)
print i(ta);print i(tb);print i(tc);print i(td);print i(te)

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