任意の長方形を配置してスペースを埋める


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または似たようなもの)
説明:サイズの異なる2つの正方形を並べて、それらの端を揃えることができないことが明らかになります。

テストケース3

入力:

1 1
1 2
1 2
2 1
2 1

出力:( trueまたは同様のもの)配置方法:

AAB
DEB
DCC

@ETHProductionsが指摘したように、他のすべてのテストケースでは、長方形が1つだけになるまで、長方形を共通の辺の長さで結合し続けることができます。

テストケース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

PSこの問題にどのタグを適用するべきかを知っているなら、それを追加してください。code-golf以外のタグとして何を置くべきか全く分かりません。

編集:あなたのプログラムは、まともなコンピューターで最大10秒で最大25の長方形を処理できるはずです(この規則についてはかなり柔軟になります)。

編集:提出の受付期限を年末まで延長しましたが、それまでに回答が得られるとは思わない...

編集:提出の受付期限を2週間延長しました。それまでに回答が届かない場合は、現在のCの回答が受け付けられます。:)


各入力長方形は一度だけ使用されると考えていますか?
xnor

7
期限があるのはなぜですか?あなたはその時点で答えを受け入れると言うことができますが、挑戦は無期限に開かれるべきです:)
ネイサンメリル

4
長方形を回転できますか?
-xnor

3
さて、あなたの問題は決定可能性の問題です:「これらの方向付けられた長方形は無駄がゼロの別の長方形を形成するように配置できます」、これはNP完全問題です(Korf、2003:pdfs.semanticscholar.org/90a5/…)。Korfのアルゴリズムは、ソリューションを使用せずに構成をより効率的に削除するための最適化を備えたブルートフォースです。私はこれのゴルフがほとんどの言語で250文字以下になるとは思わない。
ガブリエルベナミー

1
簡単な方法は、同じ幅または高さの2つの長方形を1つの長方形が残るまで繰り返し結合できるかどうかを判断することです。このアルゴリズムは、現在のすべてのテストケースで機能します。ただし、[[1, 2], [2, 1], [1, 1], [1, 2], [2, 1]](アレンジ可能ABB ACD EED)に失敗します。この簡単なテストケースを追加できます。
ETHproductions

回答:


5

C、1135 1158 1231 1598バイト

さて、それは定められた期限を過ぎていますが、まだ答えがないので、Cに1つ(少し長い)があります。

戻り値:

  • 失敗時には0(ゼロ)(適合しない)
  • 成功時の完全なフィッティングマトリックス

更新:

元のコードは、許可された10秒よりもはるかに長い時間を要して、一部のマトリックスでスタックする可能性があります。現在の改訂では、すべての行列が1秒未満で完了する必要があります。これは、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);}

UnGolfed:

#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つの機能を持っている:mainOQFLTT tが与えられた場所での長方形のためのスペースがあるかどうかを確認するためのEST。 Lfil lは長方形を出力バッファーに入れるか、または上書きすることによって長方形を削除します。OそしてQ、それぞれ、左と上壁を構築し、F fは、反復検索によって長方形の残りを悪。

基本的な検索は繰り返し実行されますが、マスター長方形の幅と高さの許容される組み合わせを構築し、次に不可能な構成を削除することにより、可能な検索ベクトルの大部分を削除します。中央を埋める前に下と右の壁を決定することにより、より大きな長方形で追加の速度を得ることができますが、25個の内部長方形に制限する場合、まともな速度には必要ありません。


良くやった!動作しているように見えます...しかし、出力形式を指定できますか?動作している場合は印刷物で、動作していない場合はクラッシュしているように見えますが、これが唯一の答えであるため許可します。また、「Everybody fit!」の代わりに「1」を印刷することで、かなりのバイトを節約できます。(許可されているため)、また、それらがどのように配置されているかを出力しないことにより、かなりのバイト数を占めています。それを印刷するのは良いことですが、不要なバイトを使用し、目的はそれを保存することです。そうでなければ、良い仕事です!期限を半月延長しますが、今のところは賛成票を投じます。:)
HyperNeutrino

ありがとう。フォーマットを指定するように更新し、クラッシュを修正しました(意図しない)。マトリックス出力(+30バイト)を残したのは、気の利いたものであり、他の誰かがゴルフ言語のソリューションを投稿した場合、彼らは単に30までに私をbeるわけではありません:)
セス

-367バイト...おそらく史上最大のゴルフですか?:
ハイパーニュートリノ

:-)まあ、それはハックのような出発点を持つのに役立ちます。
セス

確かに!私の最大のゴルフは、いくつかの編集でJavaの337キャラクターでしたが、かなりひどいアイデアから始めました(ああ、5000万の変数を作成し、2つだけを必要とする古き良き時代...)。とにかく、私は答えを待っていますが、これが唯一の有効なものであるように見えます!
ハイパーニュートリノ

6

Haskell、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ダイアグラムであるすべての部分タイルを再帰的に検索し、一度に1つの長方形を追加し、最終結果のいずれかが長方形であるかどうかを確認します。

長方形のタイルをこの方法で構築できることを確認するには、空でないYoungダイアグラムのタイルで、南西隅が他の長方形に触れないタイルの長方形のセットをRとします。Youngダイアグラムの各凹頂点は、Rの最大1つの長方形にエッジ隣接(単なるコーナー隣接ではなく)し、これらの凹頂点の数はRの長方形の数より1少ないため、少なくともこれらの凹型頂点のいずれにも隣接しないRの1つの長方形。それを削除すると、もう1つのYoungダイアグラムが生成されるため、帰納法で進めます。


良いですね!これは素晴らしいです。よくやった!:)
HyperNeutrino
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.