キューブネットの釣り


30

キューブは、側面として6つの正方形で作成できます。しかし、3つの2x1長方形を半分に折り、それらを接着して立方体を形成することもできます。この課題では、それぞれが正方形から作られたピースのセットを取得し、ユニットキューブを形成するためにピースを選択できるかどうかを判断する必要があります。すべてのピースを使用する必要はありませんが、いくつか残っている可能性があります。

詳細

ピースは、2つの異なる文字の文字列、白黒画像、または便利な2Dラスター形式として提供されます。以下では、ピースを形成するピクセルは黒で、背景は白であると仮定します。

辺を共有する2つのピクセルは、同じ部分に属すると見なされます。ピースは、ピクセルを分離するグリッド線に沿ってのみ折りたたむことができ、カットすることはできません。立方体の各辺のサイズは1ピクセルであり、立方体の各辺は1つのレイヤーでのみ作成できます。

出力がなければなりませんtruthyまたはfalsey値。

テストケース

以下では、スペースは背景であり、ハッシュ記号#はピースを表します。

(追加予定)

有効な

##  
 ## 
  ##

 #  
####
 #  

# # # # # # #

# ##
## #

無効

###
###

#  #
####

### ## ####

より多くのテストケースについては、次のスニペットを実行します。

PS:これはこの課題の一般化です


JSコードスニペットが追加のハードコードされたテストケースを印刷するのはなぜですか?なぜそれらをポストハハに入れないのですか?
魔法のタコUr

1
@carusocomputingこれは、投稿が乱雑になるのを防ぐための手段に過ぎませんでした。
-flawr

常に6ピクセルがオンになりますか?
小麦ウィザード

いいえ、多かれ少なかれあります。
flawr 16

1
@Blueあぁ、ピースの入力を分析することは挑戦の一部です。この入力はそれをかなり単純化するので、許可しません。尋ねていただきありがとうございます!
-flawr

回答:


7

C、824の 803バイト

#define Z return
#define Y char*b
#define N --n
i,j,n,w,h,A,B,C,D,E,F,G,H;char c[9999],*r,*d;x(b)Y;{if(b<c||*b<35)Z;++n;*b^=1;x(b-1);x(b+1);x(b-w);x(b+w);}m(b,p,y)Y,*p;{d=b;if(!y)for(y=-1,--p;1[++p]&31;)d+=w;for(i=0;*p&31?!(*p&16>>i)||b[i]&1:0;++i>4?p+=y,b+=w,i=0:0);Z!(*p&31)?x(d),n:0;}a(b)Y;{for(j=n=0;j<w*h;++j)if(m(c+j,b,1)||m(c+j,b,0))Z n;Z 0;}f(Y){bzero(c,9999);for(h=0,b=strcpy(c,b);r=b,b=strchr(b+1,10);h++,w=b-r);for(A=2,r=1+"@_`^C@|T@^R@XO@XX`|FB@|PP@|DD@PXN@XHX@XPX`PPXL@XHHX@XLDD@XPPX`PPPXH@PXHHH@PPPPP@";*r;r+=A+=r[-1]/96)while(a(r));A=B=C=D=E=F=G=H=0;while(a("PX")||a("XH")) (n-=3)?N?N?N?0:++H:++G:++F:++C;while(a("^")||a("PPPP"))(n-=4)?N?N?0:++H:++G:++E;while(a("P"))N?N?N?N?N?N?0:++H:++G:++F:++D:++B:++A;Z H||(G&&A)||(F&&B+B+A>1)||(E&&A>1)||D>1||C>1||((D||C)*3+B*2+A>5)*(A>1||B>2||A*B);}

注:バグ修正が含まれています(前のエントリは、キューブを形成していると、トロミノと2つのドミノを誤って識別しました)。 TIOドライバーコードには、より多くのテストケースがあり、現在は合格/不合格トラッカーがあります。hexominoテストケースは、ラベルの予想される合否値で更新されました。

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

...そしてこれを詳細に説明する前に、概要を説明する価値があります。

基本的な概要

このアルゴリズムは、パターンマッチャーを適用して、特定のパターンをサブセットとして検出した各ポリオミノを分類します。ポリオミノは一致するため、「マークされていない」ため、再びパターンマッチングから除外されます。マッチャーによって与えられる最初の分類は、単にポリオミノのタイルの数のカウントです。

最初にマッチャーを適用して、キューブに折り畳むことができないすべてのポリオミノを選別します。これらのポリオミノの分類は破棄されます。これらのポリオミノがより高いレベルのポリオミノ内に表示される場合、一致は成功します。したがって、各クラスの「展開可能」の最小サブセットのみを考慮します。ここに、パディングされたエンコーディングとともに、すべてのそのようなポリオミノが示されています(垂直反射を除く)。エンコードでは、各文字のビット4〜0を使用して、各行の正方形を表します。

[^C```] [XHX``] [PPPXH] [XHHX`] [PXN``] [|PP``]
 ####.   ##...   #....   ##...   #....   ###..
 ...##   .#...   #....   .#...   ##...   #....
 .....   ##...   #....   .#...   .###.   #....
 .....   .....   ##...   ##...   .....   .....
 .....   .....   .#...   .....   .....   .....
[|FB``] [XPX``] [PPXL`] [XLDD`] [XPPX`] [|DD``]
 ###..   ##...   #....   ##...   ##...   ###..
 ..##.   #....   #....   .##..   #....   ..#..
 ...#.   ##...   ##...   ..#..   #....   ..#..
 .....   .....   .##..   ..#..   ##...   .....
 .....   .....   .....   .....   .....   .....
[|T```] [^R```] [PXHHH] [XO```] [_````] [PPPPP]
 ###..   ####.   #....   ##...   #####   #....
 #.#..   #..#.   ##...   .####   .....   #....
 .....   .....   .#...   .....   .....   #....
 .....   .....   .#...   .....   .....   #....
 .....   .....   .#...   .....   .....   #....

[XX```]
 ##...
 ##...
 .....
 .....
 .....

これらのポリオミノが選別されると、残りのポリオミノを関連するカテゴリに分類します。ほとんどすべての場合、残っている(キューブに折り畳むことができる)ポリオミノを見つけて、単純に合計6個を検索できることに注意してください。2つの例外があります。

  • コーナートロミノとライントロミノはキューブを形成できません
  • ラインテトロミノとドミノはキューブを形成できません

この制限に対応するために、AHから8つのカテゴリを形成します:Aからモノミノ(単タイル)、Bをドミノ、Cをコーナートロミノ、Dをライントロミノ、Eをラインテトラミノ、Fを他のテトロミノ、Gペントミノ、Hはヘキソミノ。これらのカテゴリのいずれにも該当しないものはすべて無視されます。各カテゴリに分類されるポリオミノを数えるだけで十分です。

最後に、巨大な方程式とこれらの集計に基づいて、真実性または虚偽を返します。

コメントなしでゴルフ

i,j,n,w,h,A,B,C,D,E,F,G,H;char c[9999],*r,*d;
x(b)char*b;{      // recursively unmarks polyomino pointed to by b.
   if(b<c||*b<35)return;
   ++n; *b^=1;    // Tabulates tiles in n as it goes.
   x(b-1);x(b+1);x(b-w);x(b+w); // left/up/down/right
}
m(b,p,y)char*b,*p;{ // pattern match area b with pattern p, direction y.
                    //   y=1 scans down; y=0 scans up.
   d=b; // d tracks a tile in the currently matched pattern for unmarking.
        // Note that all patterns are oriented to where "top-left" is a tile.
   if(!y) // ...when scanning up, move p to the end, set y to -1 to count backward,
          //    and advance d to guarantee it points to a tile (now "bottom-left")
      for(y=-1,--p;1[++p]&31;)d+=w;
   // Match the pattern
   for(i=0;*p&31?!(*p&16>>i)||b[i]&1:0;++i>4?p+=y,b+=w,i=0:0);
   return !(*p&31)   // If it matches...
          ? x(d),n   // ...unmark/count total polyomino tiles and return the count
          : 0;
}
a(b)char*b;{ // Scan for an occurrence of the pattern b.
   for(j=n=0;j<w*h;++j)
      if(m(c+j,b,1)||m(c+j,b,0)) // (short circuit) try down then up
         return n;
   return 0;
}
// This is our function.  The parameter is a string containing the entire area,
// delimited by new lines.  The algorithm assumes that this is a rectangular area.
// '#' is used for tiles; ' ' spaces.
f(char*b) {
   bzero(c,9999); // Init categories, c buffer
   for(h=0,b=strcpy(c,b);r=b,b=strchr(b+1,10);h++,w=b-r); // Find width/height
   // Unmark all polyominoes that contain unfoldable subsets.  This was
   // compacted since the last version as follows.  A tracks
   // the current pattern's length; r[-1], usually terminator for the
   // previous pattern, encodes whether the length increases; and o/c
   // the patterns were sorted by length.
   for(A=2,r=1+"@_`^C@|T@^R@XO@XX`|FB@|PP@|DD@PXN@XHX@XPX`PPXL@XHHX@XLDD@XPPX`PPPXH@PXHHH@PPPPP@";*r;r+=A+=r[-1]/96)
      while(a(r));
   A=B=C=D=E=F=G=H=0;
   // Match corner trominoes now to ensure they go into C.
   while(a("PX")||a("XH"))
      (n-=3)
         ?   --n
             ?   --n
                 ?   --n
                    ?   0 // More than 6 tiles?  Ignore it.
                    : ++H // 6 tiles?  It's an H.
                 : ++G // 5 tiles?  It's a G.
             : ++F // 4 tiles?  It's an F.
        : ++C; // only 3 tiles?  It's a C.
   // Now match line tetrominoes to ensure they go into E.
   while(a("^")||a("PPPP"))
      (n-=4)
         ?   --n
             ?   --n
                 ?   0 // More than 6 tiles?  Ignore it.
                 : ++H // 6 tiles?  It's an H.
             : ++G // 5 tiles?  It's a G.
         : ++E; // only 4 tiles?  It's an E.
   // Find all remaining tetrominoes ("P" is a monomino pattern)
   while(a("P"))
      --n
         ?   --n
             ?   --n
                 ?   --n
                     ?   --n
                         ?   --n
                             ?   0 // More than 6 tiles?  Ignore it.
                             : ++H // 6 tiles?  It's an H.
                         : ++G // 5 tiles? It's a G.
                     : ++F // 4 tiles?  It's an F.
                : ++D // 3 tiles?  It's a D.
            : ++B // 2 tiles?  It's a B.
         : ++A; // only 1 tile? It's an A.
   // Figure out if we can form a cube:
   return H               // Yes if we have a foldable hexomino
      ||(G&&A)            // Yes if we have a foldable pentomino
                          // and a monomino
      ||(F&&B+B+A>1)      // Yes if we have a foldable non-line tetromino
                          // and 2 other tiles (dominoes count twice).
                          // Either one domino or two monominoes will do.
      ||(E&&A>1)          // Yes if we have a foldable line tetromino (E)
                          // and two monominoes (A).  Note we can't make a
                          // cube with a line tetromino and a domino (B).
      ||D>1               // Yes if we have two line trominoes
      ||C>1               // Yes if we have two corner trominoes
      ||((D||C)*3+B*2+A>5)
                          // Any combination of trominoes, dominoes, monominoes>6,
                          // where trominoes are used at most once
                          // (via logical or)...
         * (A>1||B>2||A*B)
                          // ...times this includer/excluder fudge factor
                          // that culls out the one non-working case;
                          // see table:
                          //
                          // Trominos Dominos Monomos Cube  A>1 B>2 A*B
                          //    1        0       3+    yes   Y   N   0
                          //    1        1       1+    yes   Y   N   1
                          //    1        2       0     no    N   N   0
                          //    0+       3       0+    yes   Y   Y   1
      ;
}

これは機能しません。質問では、一部の部品が未使用の場合があると述べています
ジョンドヴォルザーク

@JanDvorakそれを指摘してくれてありがとう!
H・ウォルターズ

私には、triominoの代わりにtrominoをスペルするのは奇妙に思えますが、どちらも有効なスペルです。
mbomb007
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.