사각형 파인더 – 정사각형 찾기


27

평면에 그려진 여러 개의 사각형을 상상해보십시오. 각 사각형에는 정점과 정수 좌표가 있고 측면은 축과 평행합니다.

여기에 이미지 설명을 입력하십시오

사각형은 평면을 아래의 빨간색과 파란색으로 여러 개의 분리 된 영역으로 분할합니다.

여기에 이미지 설명을 입력하십시오

당신의 목표는 완벽한 사각형 인 그러한 지역의 수를 찾는 것입니다. 위의 예에는 세 가지가 있습니다.

여기에 이미지 설명을 입력하십시오

가운데의 큰 정사각형은 단일 영역이 아니라 여러 개의 작은 분리 된 영역으로 구성되므로 계산되지 않습니다.

입력

이 도전에 대한 기능이나 전체 프로그램을 작성할 수 있습니다.

입력은 평면에서 사각형을 4n정의하는 음 이 아닌 정수 n입니다. 각 사각형은 예를 들면, 두 개의 대향하는 정점에 의해 표현된다 4 9 7 8대향하는 꼭지점을 가진 사각형 나타내고 (4, 9)(7, 8). 이 사각형은 7 8 4 9또는 로 표시 될 수도 있습니다 4 8 7 9.

정확한 입력 형식은 유연하지만 (예 : 공백으로 구분 된 문자열, 쉼표로 구분 된 문자열, 단일 정수 배열, 좌표 튜플 목록 등) 합리적 이며 게시물에서 코드를 실행하는 방법에 대한 예를 제공하십시오. 입력 순서를 바꿀 수 없습니다.

간단하게하기 위해 두 개의 모서리가 겹치지 않을 것이라고 가정 할 수 있습니다. 여기에는 꼭지점에서의 겹치기가 포함됩니다. 특히 이것은 두 개의 사각형이 모서리에서 모서리로 또는 모서리에서 모서리로 닿지 않으며 사각형이 0이 아닌 영역을 갖음을 의미합니다.

산출

프로그램은 제곱 영역의 수인 단일 정수를 인쇄하거나 반환해야합니다.

채점

이것은 코드 골프이므로 가장 적은 바이트의 코드가 이깁니다.


테스트 사례

입력:

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

산출:

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

이것은 하나의 큰 사각형입니다.


입력:

0 99999 100000 0
2 1 142857 285714

산출:

1

겹치는 두 개의 큰 직사각형.

답변:


9

SQL (PostGIS와) 286 269 261 240 226 218 216

PostgreS에 대한 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

설명

쿼리는 각 좌표 쌍에 대한 형상을 작성합니다. 외부 링을 결합하여 선을 올바르게 연결합니다. 결과를 다각형으로 바꾸고 너비와 높이를 비교 하고 면적을 각 변의 제곱에 대해 두 배로 테스트 합니다 .

PostGIS Extension이있는 PostgreSQL 데이터베이스에서 독립 실행 형 쿼리로 실행됩니다.

편집 몇 가지를 더 발견했습니다.


1
... 그리고 Haskell
Optimizer

@optimizer 나는 그것이 지속 될지 의심한다 :)
MickyT

@MickyT 이것은 건강한 경쟁으로 바뀌 었습니다. :)
Zgarb

@ zgarb 그것은 조금 있습니다 :-) 그러나 나는 갈 다른 것이 없다고 생각합니다.
MickyT

13

파이썬 2, 480436386 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)

설명

이 프로그램은 복잡한 다각형을 다루는 대신 간단한 선분을 처리합니다. 각 입력 사각형에 대해 네 개의 모서리 각각을 개별 세그먼트 목록에 개별적으로 추가합니다. 목록에 세그먼트를 추가하는 방법은 다음과 같습니다. 기존 세그먼트 각각을 테스트하여 새 세그먼트와 교차하는지 확인합니다. 교차점을 찾으면 교차점에서 두 세그먼트를 나누고 계속합니다. 일을 더 쉽게하기 위해 실제로 수평선과 수직으로 구분 된 두 개의 세그먼트 목록을 유지합니다. 세그먼트는 겹치지 않기 때문에 가로 세그먼트는 세로 세그먼트와 교차 할 수 있으며 그 반대도 마찬가지입니다. 더 나은 방법은 모든 교차점 (동일한 사각형의 모서리를 고려하지 않음)이 "적절"하다는 것을 의미합니다. 즉, T 자형 교차점이 없으므로 각 세그먼트의 "양쪽"이 실제로 분할됩니다.

세그먼트리스트를 구성한 후에는 제곱 계산을 시작합니다. 4 개의 세그먼트 (특히, 2 개의 수평 세그먼트와 2 개의 수직 세그먼트)의 각 조합에 대해 사각형을 형성하는지 테스트합니다. 또한이 정사각형 내에 정점이 없는지 확인합니다 (예 : 더 큰 정사각형 안에 작은 정사각형이있는 경우 발생할 수 있음). 이는 원하는 수량을 제공합니다. 프로그램이 각 조합을 다른 순서로 네 번 테스트하더라도 세그먼트 좌표의 특정 순서는 각 정사각형을 한 번만 계산합니다.


1
이 문제를 얼마나 빨리 해결했으며 문제에 접근 한 방식에 깊은 인상을 받았습니다! for 루프를 사용하면 "확실히 무언가를 수행 할 수 있습니다 ..."
Sp3000

@ Sp3000 예. itertools루프에 사용하려고했지만 더 길어졌습니다. exec+ 문자열 대체로 몇 바이트를 면도 할 수는 있지만 너무 흥미로운 것은 없습니다.
Ell

4

하스켈, 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 은 입력의 모든 사각형의 전체 둘레입니다) 마지막 두 테스트 사례에서 평가할 수 없습니다. 최적화를 켠 상태에서 컴파일 [(0,249,250,0),(2,1,357,714)]하여 마지막 테스트 의 400 배 축소 버전에서 실행하면 12 초가 조금 넘게 완료되었습니다. 이를 바탕으로 실제 테스트 케이스는 약 25 년 안에 완료됩니다.

설명 (부분적으로 시간이 있으면 이것을 확장 할 것입니다)

우리는 처음 두 목록을 작성 h하고 v같은 다음과 같습니다. 입력의 각 직사각형에 대해 경계를 길이 1의 세그먼트로 분할합니다. 가로 세그먼트의 서쪽 끝점은에 저장되고 h세로 세그먼트의 남쪽 끝점은 에 길이 2의 v목록 [x,y]으로 v저장됩니다 . 좌표 는 반대로 저장됩니다. [y,x]골프의 이유로 양식 . 그런 다음 두 목록을 통해 우리가 루프와 수평 에지를 검색 [x,j]및 수직 에지 [i,y]그러한 x < ii-x == j-y(그들은 북서쪽 사각형의 남동쪽 모서리 그래서), 그리고 광장의 경계가 올바른 목록에 있는지 확인 h하고 v내부 동안, 좌표가 아닙니다. 검색의 긍정적 인 인스턴스 수는 출력입니다.


잘 했어요, 이제 인정해야 할 것 같아요 :)
MickyT

@MickyT 일주일이 지났으므로 지금은 Zgarb의 답변을 수락했지만 나중에 이길 경우 체크 표시가 움직일 수 있습니다! 솔직히 저는 두
분이

@ Zgarb 잘 자격이 승리 :-)
MickyT

멋진 작은 도전에 감사합니다.
MickyT

@ Sp3000 감사합니다! 나는 이것을 골프 재미있었습니다.
Zgarb
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.