秘密の「>」スタッキングチャレンジ:グレーディング

Aug 18 2020

バックグラウンド

テトリスグランドマスター3には、ゲーム終了時のスタックの形状に基づいた隠しグレーディングシステムがあります。これはシークレット ">"スタッキングチャレンジと呼ばれます。これは、左下のセルから始まり、幅全体に広がるジグザグパターンを除いて、最下位の行を完全に埋めることで構成されます。

#
.#########
#.########
##.#######
###.######
####.#####
#####.####
######.###
#######.##
########.#
#########.
########.#
#######.##
######.###
#####.####
####.#####
###.######
##.#######
#.########
.#########

ボードは、ボトムラインからこの正確なパターンに従うラインの数によって評価されます。パターンの一番上の穴は、余分なブロックでブロックする必要があることに注意してください。#sと.sを必須パターン(空白は何でもかまいません)と見なすと、上記のパターンが一番下の行から一致する場合にのみ、19のスコアを取得できます。同様に、ボードがこのパターンに一致する場合

   #
###.######
##.#######
#.########
.#########

だがしかし

    #
####.#####
###.######
##.#######
#.########
.#########

その場合、スコアは4です。

この課題では、任意のサイズのボード(高さ20セル、幅10セル以外)を検討してください。同じパターンでボードを評価できます。たとえば、ボードの幅が4の場合、これはスコア3のパターンです。

  #
##.#
#.##
.###

これがスコア10のパターンです。

   #
###.
##.#
#.##
.###
#.##
##.#
###.
##.#
#.##
.###

チャレンジ

任意のサイズのテトリスボードの最終状態を考慮して、上記のシステムを使用してボードを等級分けします。

すべてのセルに2つの異なる値(それぞれ空と塗りつぶし)のいずれかが含まれている長方形の行列に対して、適切な形式を使用してボードを取得できます。グリッドは有効なテトリスボードであると想定できます(行が完全に埋められることはありません)。また、グリッドの幅は少なくとも2です。

標準のコードゴルフルールが適用されます。バイト単位の最短コードが優先されます。

テストケース

混乱を防ぐために、ここでのテストケースOはブロックと.空きスペースに使用します。

Input:
..O.O
OOOO.
OOO..
OO.OO
O.OOO
.OOOO
Output: 3

Input:
..
O.
.O
.O
O.
.O
O.
.O
Output: 4

Input:
.OOO
O.OO
OO.O
OO.O
OO.O
O.OO
.OOO
Output: 2 (any lines above the first non-conforming line are ignored;
           doesn't get 3 because 3rd line's hole is not capped)

Input:
OOO.
.OOO
O.OO
OO.O
OOO.
OO.O
O.OO
Output: 0 (Wrong starting hole)

Input:
.OOO
O.OO
OO.O
OOO.
Output: 0 (Wrong starting hole)

Input:
.OOO
.OOO
Output: 0 (Hole is not covered)

Input:
OOO...O..O
.OOOOOOOOO
O.OOOOOOOO
OO.OOOOOOO
OOO.OOOOOO
OOOO.OOOOO
OOOOO.OOOO
OOOOOO.OOO
OOOOOOO.OO
OOOOOOOO.O
OOOOOOOOO.
OOOOOOOO.O
OOOOOOO.OO
OOOOOO.OOO
OOOOO.OOOO
OOOO.OOOOO
OOO.OOOOOO
OO.OOOOOOO
O.OOOOOOOO
.OOOOOOOOO
Output: 19

回答

3 Arnauld Aug 18 2020 at 12:47

JavaScript(ES6)、84バイト

1空のスペースと0ブロックの文字列のリストが必要です。

f=(a,i=j=1<<a[k=0].length)=>(v='0b'+a.pop()+0)^i?v&i/k&&-1:1+f(a,i*=k=i&j?.5:i&2||k)

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

どうやって?

入力配列の各文字列には余分な文字が埋め込ま0れ、2進数として解釈されます。変数jはに初期化されます2**W。ここWで、はボードの幅です。パターン内の穴の予想される位置を追跡するためにi初期化さjれたビットマスクを使用します。

各反復の後、はでi乗算されkます。kwhen (i & j) != 0(左端で(i & 2) != 0バウンス)または(右端でバウンス)の値を更新します。

W = 5

j = 0b100000

i = 0b100000 // -> set k to 1/2
i = 0b010000 // \
i = 0b001000 //  }-> leave k unchanged
i = 0b000100 // /
i = 0b000010 // -> set k to 2
i = 0b000100 // \
i = 0b001000 //  }-> leave k unchanged
i = 0b010000 // /
i = 0b100000 // -> set k to 1/2
...

コメント

f = (                // f is a recursive function taking:
  a,                 //   a[] = input array
  i = j =            //   i = hole bit mask, initialized to ...
    1 << a[k = 0]    //   ... j = 2 ** W, where W is the width of the board
         .length     //   k = bit mask multiplier, initialized to 0
) =>                 //
( v =                // pop the last value from a[], append a '0' and interpret
  '0b' + a.pop() + 0 // it as a binary number saved in v
) ^ i ?              // if v is not equal to i:
  v & i / k          //   use the previous bit mask i / k to test whether there's
  && -1              //   a hole in v above the last hole of the pattern, in
                     //   which case we subtract 1 from the final result
:                    // else:
  1 +                //   add 1 to the final result
  f(                 //   do a recursive call:
    a,               //     pass a[] unchanged
    i *=             //     multiply i by:
      k =            //       the new value of k:
        i & j ?      //         if we've reached the leftmost side:
          .5         //           set k to 1/2
        :            //         else:
          i & 2      //           set k to 2 if we've reached the rightmost side,
          || k       //           or leave k unchanged otherwise
  )                  //   end of recursive call
3 Zgarb Aug 20 2020 at 04:54

ハスク、18バイト

Lδ↑€…¢ŀT¹↑εΨ↑-↔m¥0

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

0-1行列を取ります。

説明

このプログラムには3つのオカレンスがあり、修飾子関数δとのおかげで、それらはすべて異なる動作をしΨます。デフォルトで↑αα、単項関数であることが期待され、リストを受け取りα、真の値を返す要素の最長のプレフィックスを返します。Ψ↑ααバイナリでxあるα x yと想定し、trueである要素の最長のプレフィックスを返しますy。ここで、は次の要素です。バイナリであることがδ↑α期待さαれ、1つではなく2つのリストを取ります。要素がをy満たす2番目のリストの最長のプレフィックスを返しますα x y。ここxで、は最初のリストの対応する要素です。

Input is a list of lists of integers.
Example: [[0,1,1],[1,0,1],[1,1,0],[1,0,1],[1,1,0],[0,0,1],[0,1,1]]

m     Map
 ¥0   indices where 0 occurs:
        [[1],[1,2],[3],[2],[3],[2],[1]]
↔     Reverse:
        [[1],[2],[3],[2],[3],[1,2],[1]]

 ↑    Take while
Ψ     this element and the next
  -   have nonempty set difference:
        [[1],[2],[3],[2],[3],[1,2]]

↑     Take while
 ε    this element is a singleton:
        [[1],[2],[3],[2],[3]]
      Call this list X.

ŀT¹   Indices of input transposed:
        [1,2,3]
¢     Cycle infinitely:
        [1,2,3,1,2,3,..]
…     Rangify:
        [1,2,3,2,1,2,3,2,1,..]
 ↑    Take from X while
δ     the corresponding integer in this list
  €   is an element of it:
        [[1],[2],[3],[2]]
L     Length: 4
2 Neil Aug 18 2020 at 19:06

木炭、52バイト

WS⊞υι≔⮌υυP⪫υ¶W∧⁼.O⪫KD²↓ω⁼¹№§υⅉ.M✳⁻⁷⊗÷﹪ⅉ⊗⊖Lθ⊖Lθ≔ⅉθ⎚Iθ

オンラインでお試しください!リンクは、コードの詳細バージョンへのリンクです。.O文字の文字列の改行で終了するリストとして入力を受け取ります。説明:

WS⊞υι

リストを入力します。

≔⮌υυ

リストを逆にします。

P⪫υ¶

カーソルを動かさずにリストを印刷します。

W∧

両方の間に繰り返します...

⁼.O⪫KD²↓ω

...カーソルの下の文字はa.で、下の文字(リストが逆になっているため)は、、O...

⁼¹№§υⅉ.

...現在のリスト行には1つだけ含まれています.

M✳⁻⁷⊗÷﹪ⅉ⊗⊖Lθ⊖Lθ

カーソルを斜め下に移動し、行に応じて右または左に移動します。

≔ⅉθ⎚Iθ

最初の無効な行インデックス(0インデックス、つまり有効な行の数に等しい)をキャプチャし、キャンバスをクリアして、文字列として出力します。

2 xash Aug 18 2020 at 12:33

J、5742バイト

ブロックされている場合は0、空の場合は1を取り込みます。

[:#.~(|.@$2^|@}:@i:@<:)/@$=2#.[*[+_1|.!.2]

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

使い方

[*[+_1|.!.2]

ボードを1つ下にシフトします(トップスポットがカウントされないように、2が上部に押し込まれます)。次に、元のボードに追加され、それ自体で乗算されます。これは基本的に次のように要約されます。有効なオープンスポットは1のままですが、無効なオープンスポットは2になります。

 (|.@$2^|@}:@i:@<:)/@$

寸法-x … x - 1を指定して、幅の排他範囲(たとえば、4 _3 _2 _1 0 1 2:)を取得し、それらの絶対値を取得します3 2 1 0 1 2。そのリストのサイズをボードの高さに変更し、最初の3が最後の行に揃うように回転させ2^x、リストを次のようにします。8 4 2 1 2 4 8 4 2…

 =2#.

行を基数2の数値として解釈し、ジグザグリストと比較します。

 [:#.~

また、再帰基数変換により、先頭の1を数えることができるため、有効な先頭の行がカウントされます。

1 JonathanAllan Aug 19 2020 at 17:47

ゼリー、25バイト

ZJŒḄṖṁLW€⁻"ⱮṚT€,Ḋ$ƊZḄCTḢ’

行のリストを受け入れるモナドリンク。各行は1s(空)と0s(塗りつぶし)のリストであり、負でない整数(スコア)を生成します。

オンラインでお試しください!または、テストスイートを参照してください。

どうやって?

下から各行の予想される空のインデックスのリストを作成し、それを2つのリスト((a)実際の空のインデックスと(b)デキューされた実際の空のインデックス)のそれぞれと比較します。次に、この比較の結果を処理してスコアを見つけます。

ZJŒḄṖṁLW€⁻"ⱮṚT€,Ḋ$ƊZḄCTḢ’ - Link: list of lines, A
Z                         - transpose
 J                        - range of length     -> [1,2,...,w=#Columns]
  ŒḄ                      - bounce              -> [1,2,...,w-1,w,w-1,...,2,1]
    Ṗ                     - pop                 -> [1,2,...,w-1,w,w-1,...,2]
      L                   - length (A)          -> h=#Lines
     ṁ                    - mould like (repeat Ṗ result such that it is length h)
       W€                 - wrap each of these integers in a list (call this x)
                  Ɗ       - last three links as a monad - i.e. f(A):
            Ṛ             -   reverse (A)
             T€           -   for each (line) get the list of truthy ("empty") indices
                 $        -   last two links as a monad - i.e. f(z=that):
                Ḋ         -     dequeue (drop the leftmost)
               ,          -     (z) pair (that)
           Ɱ              - map across (the two results of f(A)) applying:
          "               -   (x) zip with (result) applying:
         ⁻                -     not equal?
                   Z      - transpose - now we have leading [0,1]'s for valid rows
                                        from the bottom up
                    Ḅ     - convert from binary - now leading 1s for valid rows
                     C    - complement (subtract (each) from one)
                      T   - truthy indices
                       Ḣ  - head
                        ’ - decrement
1 KevinCruijssen Aug 21 2020 at 10:39

05AB1E、32バイト

R©εDgݨû¨NèDU._ƶO®N>èX.__н*Θ}γнO

1と0の行列として入力します。ここで、1は空のスペースで、0は塗りつぶされたセルです。

オンラインでお試しください。または、すべてのテストケースを確認します。

説明:

R             # Reverse the rows of the (implicit) input-matrix
 ©            # Store it in variable `®` (without popping)
  ε           # Map over each row:
   Dg         #  Get the width of the matrix
     Ý        #  Push a list in the range [0,width]
      ¨       #  Remove the last element to change the range to [0,width-1]
       û      #  Palindromize it: [0,1,2,...,w-2,w-1,w-2,...,2,1,0]
        ¨     #  Remove the last value: [0,1,2,...,w-2,w-1,w-2,...,2,1]
         Nè   #  Index the map-index into this list
           DU #  Store a copy in variable `X`
    ._        #  Rotate the current row that many times to the left
      ƶ       #  Multiply each value by its 1-based index
       O      #  And sum this list
   ®          #  Push the reversed input-matrix again from variable `®`
    N>è       #  Index the map-index + 1 into this to get the next row
       X._    #  Also rotate it `X` amount of times towards the left
          _   #  Invert all booleans (1s becomes 0s, and vice-versa)
           н  #  And only leave the first value
   *          #  Multiply both together
    Θ         #  And check that it's equal to 1 (1 if 1; 0 otherwise)
  }γ          # After the map: split the list into groups of adjacent equivalent values
    н         # Only leave the first group
     O        # And take the sum of that
              # (after which it is output implicitly as result)