Squarefinder –正四角形の配置


27

平面に描かれた長方形の束を想像してください。各長方形の頂点は整数座標にあり、辺は軸に平行です。

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

長方形は、平面をいくつかのばらばらの領域に分割します。これらの領域は、下の赤と青の色です。

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

あなたの目標は、そのような完全な正方形の領域の数を見つけることです。上記の例では、次の3つがあります。

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

中央の大きな正方形は、単一の領域ではないため数えられず、代わりにいくつかの小さなばらばらの領域で構成されていることに注意してください。

入力

このチャレンジのために関数または完全なプログラムを書くことができます。

入力は、平面内の長方形を4n定義する非負の整数になりますn。各長方形は、2つの対向する頂点で表されます。たとえば4 9 7 8、対向する頂点(4, 9)とで長方形を表し(7, 8)ます。この長方形は7 8 4 9またはとしても表されることに注意してください4 8 7 9

正確な入力形式は、(例えば、スペースで区切られた文字列、カンマ区切りの文字列、整数の単一のアレイ、座標タプルのリストなど)柔軟ですが、してください合理的であるとあなたのポストにあなたのコードを実行する方法の例を与えます。入力を並べ替えることはできません。

簡単にするために、2つのエッジがオーバーラップしないことを想定できます。これには、頂点でのオーバーラップが含まれます。特に、これは、2つの長方形が端から端または角から角に触れず、長方形の面積がゼロでないことを意味します。

出力

プログラムは、単一の整数(正方形の領域の数)を出力または返す必要があります。

得点

これはコードゴルフであるため、最も少ないバイト数のコードが優先されます。


テストケース

入力:

0 0 5 5
6 8 10 4
14 16 11 13
19 1 18 2

出力:

4

これは、単純に4つの独立した正方形です。

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


入力:

2 1 3 11
1 10 5 19
6 10 11 3
8 8 15 15
13 13 9 5
15 1 19 7
17 19 19 17

出力:

3

これは、投稿の開始時のサンプルテストケースです。


入力:

0 9 15 12
6 3 18 15
9 6 12 20
13 4 17 8

出力:

7

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


入力:

5 9 11 10
5 12 11 13
6 8 7 14
9 8 10 14
13 8 14 9
13 10 14 14

出力:

14

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


入力:

0 99999 100000 0

出力:

0

これは1つの大きな長方形です。


入力:

0 99999 100000 0
2 1 142857 285714

出力:

1

重なり合う2つの大きな長方形。

回答:


9

SQL(PostGISの)、286 269 261 240 226 218 216

これは、PostgreSQLへのPostGIS拡張機能のクエリです。合計で入力値をカウントしていません。

SELECT SUM(1)FROM(SELECT(ST_Dump(ST_Polygonize(g))).geom d FROM(SELECT ST_Union(ST_Boundary(ST_MakeEnvelope(a,b,c,d)))g FROM(VALUES
-- Coordinate input
(2, 1, 3, 11)
,(1, 10, 5, 19)
,(6, 10, 11, 3)
,(8, 8, 15, 15)
,(13, 13, 9, 5)
,(15, 1, 19, 7)
,(17, 19, 19, 17)
)i(a,b,c,d))i)a WHERE(ST_XMax(d)-ST_XMin(d))^2+(ST_YMax(d)-ST_YMin(d))^2=ST_Area(d)*2

説明

クエリは、各座標ペアのジオメトリを構築します。外部リングを結合して、ラインを適切にノード化します。結果をポリゴンに変換し、幅と高さをテスト、面積を各辺の2乗の合計に対して2倍にします。

PostGIS拡張機能を備えたPostgreSQLデータベースでスタンドアロンクエリとして実行されます。

編集さらに2つ見つかりました。


1
...とハスケル
オプティマイザ

@optimizer私はそれが続くことを疑います:)
MickyT 14

@MickyTこれは健全な競争に変わりました。:)
ズガルブ14

@zgarbには少しあります:-)しかし、私は他に何かを持っていないと思う
MickyT 14

13

Python 2、 480 436 386 352バイト

exec u"""s=sorted;H=[];V=[]
FRIinput():
 S=2*map(s,zip(*R))
 FiI0,1,2,3:
    c=S[i][i/2];a,b=S[~i]
    FeIs(H):
     C,(A,B)=e
     if a<C<b&A<c<B:e[:]=C,(A,c);H+=[C,(c,B)],;V+=[c,(a,C)],;a=C
    V+=[c,(a,b)],;H,V=V,H
print sum(a==A==(d,D)&c==C==(b,B)&B-b==D-d&1-any(d<X[0]<D&b<y<B Fy,XIH)Fb,aIH FB,AIH Fd,cIV FD,CIV)""".translate({70:u"for ",73:u" in ",38:u" and "})

次の形式で、STDINを介して座標ペアのリストを取得します。

[  [(x, y), (x, y)],  [(x, y), (x, y)],  ...  ]

結果をSTDOUTに出力します。


文字列置換後の実際のプログラムは次のとおりです。

s=sorted;H=[];V=[]
for R in input():
 S=2*map(s,zip(*R))
 for i in 0,1,2,3:
    c=S[i][i/2];a,b=S[~i]
    for e in s(H):
     C,(A,B)=e
     if a<C<b and A<c<B:e[:]=C,(A,c);H+=[C,(c,B)],;V+=[c,(a,C)],;a=C
    V+=[c,(a,b)],;H,V=V,H
print sum(a==A==(d,D) and c==C==(b,B) and B-b==D-d and 1-any(d<X[0]<D and b<y<B for y,X in H)for b,a in H for B,A in H for d,c in V for D,C in V)

説明

このプログラムは、複雑なポリゴンをいじる代わりに、単純な線分を扱います。入力四角形ごとに、4つのエッジをそれぞれ個別に集合セグメントリストに追加します。リストにセグメントを追加すると、次のようになります。新しいセグメントとの交差について、既存の各セグメントをテストします。交差点が見つかった場合、交差点で両方のセグメントを分割して続行します。物事を簡単にするために、実際には水平と垂直の2つのセグメントリストを保持しています。セグメントはオーバーラップしないため、水平セグメントは垂直セグメントとしか交差できません。さらに良いことに、すべての交点(同じ長方形のエッジを考慮しない)は「適切」です。つまり、T字型の交点がないため、各セグメントの「両側」は本当に分割されます。

セグメントリストを作成したら、正方形のカウントを開始します。4つのセグメント(特に、2つの水平セグメントと2つの垂直セグメント)の組み合わせごとに、それらが正方形を形成するかどうかをテストします。さらに、この正方形内に頂点がないことを確認します(たとえば、大きな正方形の内側に小さな正方形がある場合に発生する可能性があります)。これにより、必要な量が得られます。プログラムは各組み合わせを異なる順序で4回テストしますが、セグメント座標の特定の順序により、各正方形が1回だけカウントされることが保証されます。


1
これをどれほど迅速に解決し、問題に取り組んだかには非常に感銘を受けました!forループにより、「確実に何かを行うことができます...」
Sp3000 14

@ Sp3000うん。itertoolsforループを使用してみましたが、結果的に長くなりました。exec+文字列の置換で数バイトを削ることができますが、エキサイティングなことは何もありません。
エル14

4

Haskell、276266250237225222217バイト

それは短くなり続けています...そしてより難読化されています。

(x#i)l=mapM id[[min x i..max x i-1],l]
(y!j)l f=and[p l==p(f[y,j])|p<-map elem$f[y..j]]
s[h,v]=sum[1|[x,j]<-h,[y,i]<-v,x<i,i-x==j-y,(y!j)h$x#i,(x!i)v$y#j]
n=s.foldr(\(x,y,i,j)->zipWith(++)[x#i$[y,j],y#j$[x,i]])[[],[]]

n [(0,0,5,5),(6,8,10,4),(14,16,11,13),(19,1,18,2)]最初のテストケースを評価します。Haskellでこのアルゴリズムをゴルフする限界に近づいていると思います。

この関数は非常に遅い(少なくともO(n 3ここで nは入力内のすべての矩形の全周長である)私は、最後の2つのテストケースでそれを評価することができません。最適化を有効にしてコンパイルし[(0,249,250,0),(2,1,357,714)]、最後のテストの400倍に縮小したバージョンで実行すると、12秒強で終了しました。これに基づいて、実際のテストケースは約25年で終了します。

説明(一部、時間があればこれを拡張します)

最初に、次の2つのリストhを作成vします。入力の各長方形について、その境界を長さ1のセグメントに分割します。水平セグメントの西の端点はに格納されh、垂直セグメントの南の端点v[x,y]、長さ2のリストとしてv格納されます。[y,x]ゴルフの理由として。次に、両方のリストをループし、水平エッジ[x,j]と垂直エッジを検索[i,y]x < ii-x == j-y(およびそれらが正方形の北西と南東の角になるように)、正方形の境界が正しいリストにhありv、内部が座標はありません。検索の肯定的なインスタンスの数が出力です。


よくやった、私はすぐに認めなければならないだろうと思う:)
MickyT 14

@MickyT 1週間が経過したので、私は今のところZgarbの答えを受け入れましたが、後でそれを破ることに成功した場合、チェックマークが動くかもしれません!正直なところ、私は非常に2に行くために管理どこまであなたに感銘を受けています
SP3000

@Zgarbが勝利に値する:-)
MickyT 14

@ Sp3000は、ちょっとしたチャレンジに感謝します。
MickyT 14

@ Sp3000ありがとう!私はこれをゴルフするのがとても楽しかったです。
ズガルブ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.