공백을 채우기 위해 임의의 사각형 배열


26

이 직사각형이 직사각형 공간을 채울 수 있습니까?

직사각형이 많이 있으면 직사각형 공간을 채우도록 배열 할 수 있는지 묻습니다.

명세서

임의의 m x n사각형이 주어진다. 0 <= m, n <= 1000구멍이나 겹치지 않고 정확히 직사각형 영역을 덮도록 배열 할 수 있는지 여부를 결정하십시오. 사각형은 회전 할 수 없으며 각 사각형은 한 번만 배치 할 수 있습니다.

입력

입력이 2 차원 차원 목록을 제공하는 한이 입력은 매우 유연합니다. 예를 들어 다음 두 가지 모두 유효합니다.

공백으로 분리, 리턴

1 2
1 5
4 5
3 6

치수 목록

[[1, 2], [1, 5], [4, 5], [3, 6]]

산출

true / false, 0/1, T / F, True / False 등과 같은 모든 종류의 true / false 값입니다. 명확하지 않은 출력 방법을 사용하려는 경우 답을 지정하십시오.

테스트 사례 1

입력:

1 1
1 5
2 6

출력 : true(또는 비슷한 것)
정렬 방법 :

XYYYYY
ZZZZZZ
ZZZZZZ

테스트 사례 2

입력:

1 1
2 2

출력 : false(또는 이와 유사한 것)
설명 : 크기가 다른 두 정사각형을 정렬 할 수없고 가장자리를 정렬 할 수 없습니다.

테스트 사례 3

입력:

1 1
1 2
1 2
2 1
2 1

출력 : true(또는 비슷한 것) 정렬 방법 :

AAB
DEB
DCC

@ETHProductions가 지적했듯이 다른 모든 테스트 사례의 경우 직사각형이 하나만 될 때까지 공통 가장자리 길이로 직사각형을 계속 결합 할 수 있으므로이 테스트 사례는이 아이디어를 사용하는 코드를 중단하는 것입니다.

테스트 사례 4

입력:

3 2
4 1
2 1
4 1
2 1
5 2
3 2
1 4
3 2
2 1
2 1
1 1
5 1

출력 : true(또는 비슷한 것)
정렬 방법 :

AAABBBBEE
AAACCDDDD
FFFFFGGGH
FFFFFGGGH
IIIJJKKLH
IIIMMMMMH

참고 : 배열 방법을 명시 할 필요가 없으며 배열 할 수 있는지 여부 만 결정하면됩니다.

이것은 코드 골프이므로 바이트 단위의 최단 답변이 이깁니다! 1 월 14 일부터 가장 짧은 답변을 수락 할 것입니다. 그러나 여전히 찬성 투표를 할 수 있으므로 답변보다 늦게 답변을 제출해주세요. :)

행복한 골프!

~ AL

추신 :이 문제에 어떤 태그를 적용 해야하는지 알고 있다면 추가하십시오. 코드 골프 이외의 태그로 무엇을 넣을 지 전혀 모릅니다.

편집 : 귀하의 프로그램은 괜찮은 컴퓨터에서 최대 10 초 안에 최대 25 개의 직사각형을 처리 할 수 ​​있어야합니다 (이 규칙에 상당히 유연합니다).

편집 : 제출 접수 마감일을 연말로 연장했지만 그때까지 답변을받을 수는 없습니다 ...

편집 : 제출 접수 마감일을 2 주 연장 했으므로 그때까지 더 이상 답변이 없으면 현재 C 답변이 수락됩니다! :)


각 입력 사각형을 한 번만 사용한다고 생각합니까?
xnor

7
마감일이 왜 있습니까? 당신은 그때 대답을 받아 들일 것이라고 말할 수 있지만, 도전은 무기한 열려야합니다. :)
Nathan Merrill

4
사각형을 회전시킬 수 있습니까?
xnor

3
문제는 결정적인 문제입니다. "이러한 방향의 사각형을 낭비가 0 인 다른 사각형을 형성하도록 배열 할 수 있습니까? "는 NP- 완전 문제입니다 (Korf, 2003 : pdfs.semanticscholar.org/90a5/… ). Korf의 알고리즘은 본질적으로 솔루션없이 구성을보다 효율적으로 제거하기위한 최적화 기능을 갖춘 무차별 대입입니다. 나는 이것의 골프가 대부분의 언어에서 250 자 미만일 것이라고 의심한다.
Gabriel Benamy

1
쉬운 방법은 하나의 직사각형이 남을 때까지 동일한 너비 또는 높이의 두 직사각형을 반복적으로 결합 할 수 있는지 여부를 결정하는 것입니다. 이 알고리즘은 모든 현재 테스트 케이스에서 작동합니다. 그러나 [[1, 2], [2, 1], [1, 1], [1, 2], [2, 1]](정렬 할 수 있음)에 실패합니다 ABB ACD EED. 이 간단한 테스트 사례를 추가 할 수 있습니다.
ETHproductions

답변:


5

C, 1135 1158 1231 1598 바이트

글쎄, 그것은 정해진 마감일이 지났지 만 아직 답변이없는 방법으로 보아 C에 하나 있습니다.

보고:

  • 실패시 0 (제로) (적합하지 않음)
  • 성공에 대한 완벽한 피팅 매트릭스

최신 정보:

원래 코드가 일부 행렬에 붙어서 허용되는 10 초보다 훨씬 오래 걸릴 수 있습니다. 현재 수정 버전은 1s 미만의 모든 행렬을 완성해야합니다. 이것은 1) 입력 사각형을 정렬하고 2) 피팅 할 때 반복되는 크기를 건너 뛰어 수행합니다.

골프 :

#define R r[i]
#define Z return
#define _(B,D,E) for(int B=E;B<D;B++)
struct{int x,y,u,p;}r[25],*S;int A,M,N,U,V,X,Y;char *P;T(x,y,w,h){_(I,x+w,x)_(J,y+h,y)if(I/U|J/V|P[J*U+I])Z 0;Z 1;}L(x,y,w,h,c){_(I,x+w,x)_(J,y+h,y)P[J*U+I]=c;}F(){int x=0,y;while(++x<A)if(!P[x])break;if(x/A){_(i,V,0)printf("%*.*s\n",U,U,P+i*U);exit(0);}y=x/U;x-=y*U;_(i,N,0)if(!R.u&T(x,y,R.x,R.y))R.u=1,L(x,y,R.x,R.y,'A'+i),F(),R.u=0,L(x,y,R.x,R.y,0);}O(i,y){if(!R.u){if(!T(0,y,R.x,R.y))Z;R.u=1;R.p=0;L(0,y,R.x,R.y,'A'+i);y+=R.y;}if(y-V||F())_(j,N,0)if(j-i&!r[j].u){O(j,y);while(r[j].x-r[j+1].x|r[j].y-r[j+1].y)j++;}R.u=0;L(R.p,(y-=R.y),R.x,R.y,0);}Q(i,x){if(!R.u){if(R.x>U-x)Z;R.u=1;R.p=x;L(x,0,R.x,R.y,'A'+i);x+=R.x;}if(x-U||O(i,1))_(j,N,0)if(j-i&!r[j].u)Q(j,x);L(x-=R.x,0,R.x,R.y,0);R.u=0;}C(int*a,int*b){Z*a-*b?*a-*b:a[1]-b[1];}main(){_(i,25,0)if(++N&scanf("%d%d\n",&R.x,&R.y)-2)break;_(i,N,0){A+=R.x*R.y;if(R.x>X)X=R.x;if(R.y>Y)Y=R.y;}_(i,A+1,1)if(!(A%i)){if(i<Y|A/i<X)continue;M++;S=realloc(S,M*16);S[M-1].y=i;S[M-1].x=A/i;}qsort(S,M,16,C);P=calloc(A+1,1);_(j,M,0){U=S[j].x;V=S[j].y;_(i,N,0)R.u=1,L(0,0,R.x,R.y,'A'+i),Q(i,R.x),R.u=0;}printf("0\n");exit(1);}

언 골프 드 :

#define R r[i]
#define Z return
#define _(B,D,E) for(int B=E;B<D;B++)
struct {
    int x,y,u,p;
} r[25],*S;
int A,M,N,U,V,X,Y;
char *P;

test_space(x,y,w,h) {
    _(I,x+w,x)
        _(J,y+h,y)
            if (    I >= U |
                    J >= V |
                    P[J*U+I]) Z 0;
    Z 1;
}
place_rect(x,y,w,h,c){
    _(I,x+w,x)
        _(J,y+h,y)P[J*U+I] = c;
}

fill_rest() {
    int x=0,y;
    while(++x<A) if (!P[x])break;
    if (x>=A) {
        _(i,V,0) printf("%*.*s\n", U,U, P+i*U);
        exit(0);
    }
    y = x / U; x -= y*U;

    _(i,N,0)
        if (!R.u & test_space(x, y, R.x, R.y))
                R.u = 1,
                place_rect(x, y, R.x, R.y, 'A'+i),
                fill_rest(),
                R.u = 0,
                place_rect(x, y, R.x, R.y, 0);

}

fill_y(i,y) {
    if (!R.u) {
        if (!test_space(0, y, R.x, R.y)) Z;
        R.u = 1;
        R.p = 0;
        place_rect(0, y, R.x, R.y, 'A'+i);
        y += R.y;
    }
    if (y == V) fill_rest();
    else _(j,N,0)
        if (j!=i && !r[j].u){ fill_y(j, y);
        while (r[j].x^r[j+1].x||r[j].y^r[j+1].y)j++;
        }
    R.u = 0;
    place_rect(R.p, (y -= R.y), R.x, R.y, 0);
}

fill_x(i,x) {
    if (!R.u) {
        if (R.x > U - x) Z;
        R.u = 1;
        R.p = x;
        place_rect(x, 0, R.x, R.y, 'A'+i);
        x += R.x;
    }
    if (x == U) fill_y(i, 1);
    else
        _(j,N,0)
            if (j!=i && !r[j].u) fill_x(j, x);
    place_rect((x -= R.x), 0, R.x, R.y, 0);
    R.u = 0;
}
C(int*a,int*b) {
    Z *a^*b?*a-*b:a[1]-b[1];
}


main() {
    _(i,25,0)
        if (++N&&scanf("%d %d\n", &R.x, &R.y)!=2) break;
    _(i,N,0){
        A+=R.x*R.y;
        if(R.x>X)X=R.x;
        if(R.y>Y)Y=R.y;
    }
    _(i,A+1,1)
        if (!(A%i)) {
            if (i < Y | A/i < X) continue;
            M++;
            S = realloc(S,M*16);
            S[M-1].y=i;
            S[M-1].x=A/i;
        }
    qsort(S, M, 16,C);
    P = calloc(A + 1,1);
    _(j,M,0){
        U = S[j].x; V = S[j].y;
        _(i,N,0)
            R.u = 1,
            place_rect(0, 0, R.x, R.y, 'A'+i),
            fill_x(i, R.x),
            R.u = 0;
    }
    printf("0\n");
    exit(1);
}

설명 : 우리는 6 개 기능을 가지고 : main, O, Q, F, LT. T t는 주어진 자리에서 사각형 공간이 있는지 ESTS. LFIL에서 L은 출력 버퍼에 구형 S 또는 교대로 덮어 쓰기함으로써 하나를 제거한다. O그리고 Q각각 왼쪽 상단 벽을 구축하고 F f를 반복 검색하여 사각형의 나머지 부분을 악.

기본 검색은 반복적이지만 먼저 마스터 사각형에 허용되는 너비와 높이의 조합을 구성한 다음 불가능한 구성을 제거하여 가능한 많은 검색 벡터를 제거합니다. 중심을 채우기 전에 바닥과 오른쪽 벽을 결정하면 큰 직사각형에서 추가 속도를 얻을 수 있지만 내부 사각형을 25 개로 제한 할 때 적절한 속도는 필요하지 않습니다.


좋은 작업! 작동하는 것 같습니다 ... 그러나 출력 형식을 지정할 수 있습니까? 그것이 작동하면 물건을 인쇄하고 있고 그렇지 않으면 충돌하는 것 같습니다. 어쨌든 유일한 대답이므로 허용 할 것입니다. 또한 "Everybody fits!"대신 "1"을 인쇄하여 몇 바이트를 절약 할 수 있습니다. (허용 되었기 때문에) 그리고 배열 방식을 인쇄하지 않음으로써 꽤 많은 바이트입니다. 그것을 인쇄하는 것이 좋지만 불필요한 바이트를 사용하며 그 목적은 저축합니다. 그렇지 않으면 잘 했어! 마감일을 반 달로 연장하고 있지만 지금은 공감대가 있습니다. :)
HyperNeutrino

감사. 형식을 지정하고 충돌을 수정했습니다 (의도적이지 않음). 나는 매끄 럽기 때문에 매트릭스 출력 (+30 바이트)을 떠났고 다른 누군가가 골프 언어 솔루션을 게시하면 30 일까지 나를 때리지 않을 것입니다.)
Seth

-367 바이트 ... 아마도 가장 큰 골프? :-)
HyperNeutrino

:-) 글쎄, 그것은 해킹 시작점을 갖는 데 도움이됩니다.
Seth

물론 이죠! 내 가장 큰 골프는 여러 번의 편집을 통해 Java에서 337 자였으며 꽤 끔찍한 아이디어로 시작했습니다 (오, 5 천만 개의 변수를 만들고 2 만 필요합니다.) 어쨌든, 나는 대답을 계속 기다릴 것이지만 이것이 유일하게 작동하는 것처럼 보입니다!
HyperNeutrino

6

하스켈, 226 바이트

((y,z):l)&(w,x)|x*y<1=(w+y,x+z):l
(q:l)&p=p:q:l
(p@(u,v):r@(y,z):l)%q@(w,x)=[((y-w,z):l)&q&(u,v-x)|w<=y,x<=v]++[p:m|m<-(r:l)%q]
_%_=[]
g m(p:n)l=any(g[]$m++n)(l%p)||g(p:m)n l
g[]_[_,_,_]=0<1
g _[]_=0<0
($[(0,9^9),(9^9,0)]).g[]

Ideone에서 사용해보십시오

작동 원리

이렇게하면 모양이 Young 다이어그램 인 모든 부분 타일링을 재귀 적으로 검색합니다. 한 번에 하나의 사각형을 추가하여 하고 최종 결과가 사각형인지 확인합니다.

비어 있지 않은 Young 다이어그램의 타일링에서 R을 남서쪽 모서리가 다른 사각형에 닿지 않는 타일 세트로 지정하면 사각형의 타일이 이런 식으로 빌드 될 수 있습니다. 영 다이어그램의 각 오목 정점은 R에서 최대 하나의 사각형에 대해 모서리 인접 (단지 모서리가 아닌)이고,이 오목 정점의 수는 R의 사각형 수보다 하나가 작으므로, 최소한 있어야합니다. 이 오목한 정점들 중 어느 것에도 인접하지 않는 R의 하나의 직사각형. 그것을 제거하면 또 다른 젊은 다이어그램이 생성되므로 유도를 통해 진행할 수 있습니다.


좋은 것! 환상적이다. 잘 했어! :)
HyperNeutrino 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.