Desafio de empilhamento secreto “>”: classificação

Aug 18 2020

fundo

Tetris Grand Master 3 tem um sistema de classificação oculto baseado na forma da pilha no final do jogo, que é chamado de Desafio de Empilhamento Secreto ">" . Consiste em preencher inteiramente as linhas mais baixas, exceto para o padrão de ziguezague que começa na célula inferior esquerda e se estende por toda a largura:

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

O quadro é classificado de acordo com o número de linhas que seguem esse padrão exato a partir do resultado final. Observe que o orifício superior do padrão deve ser bloqueado por um pedaço extra de bloco. Se você considerar #s e .s como o padrão obrigatório (espaços em branco podem ser qualquer coisa), você poderá obter a pontuação 19 somente se o padrão exato acima corresponder ao resultado final. Analogamente, se o tabuleiro corresponder a este padrão

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

mas não

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

então, a pontuação é 4.

Para este desafio, considere um tabuleiro de tamanho arbitrário (diferente de 20 células de altura e 10 células de largura). Podemos classificar o tabuleiro para o mesmo padrão: por exemplo, se o tabuleiro tem largura 4, este é o padrão para pontuação 3:

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

e este é o padrão para pontuação 10:

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

Desafio

Dado o estado final do tabuleiro de Tetris de tamanho arbitrário, classifique o tabuleiro usando o sistema acima.

Você pode pegar o tabuleiro usando qualquer formato adequado para uma matriz retangular, onde cada célula contém um de dois valores distintos (para vazio e preenchido respectivamente). Você pode assumir que a grade é um tabuleiro de Tetris válido (nenhuma linha está totalmente preenchida). Além disso, a largura da grade é de pelo menos 2.

Aplicam-se as regras padrão de golfe de código . O código mais curto em bytes vence.

Casos de teste

Para evitar possíveis confusões, os casos de teste aqui usam Opara os blocos e .para os espaços vazios.

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

Respostas

3 Arnauld Aug 18 2020 at 12:47

JavaScript (ES6), 84 bytes

Espera uma lista de strings, com 1para espaços vazios e 0para blocos.

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)

Experimente online!

Quão?

Cada string na matriz de entrada é preenchida com um extra 0e interpretada como um número binário. A variável jé inicializada para 2**W, onde Wé a largura da placa. Usamos uma máscara de bits iinicializada para jmanter o controle da posição esperada do furo no padrão.

Após cada iteração, ié multiplicado por k. Atualizamos o valor de ksempre (i & j) != 0(saltando no lado esquerdo) ou (i & 2) != 0(saltando no lado direito).

Exemplo para 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
...

Comentou

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

Husk , 18 bytes

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

Experimente online!

Pega uma matriz 0-1.

Explicação

Existem três ocorrências de neste programa, e todas funcionam de forma diferente graças às funções modificadoras δe Ψ. Por padrão, ↑αespera αser uma função unária, pega uma lista e retorna o maior prefixo de elementos para o qual αretorna um valor verdadeiro. Ψ↑αespera αser binário e retorna o prefixo de elementos mais longo xpara o qual α x yé verdadeiro, onde yé o próximo elemento. δ↑αespera αser binário e aceita duas listas em vez de uma. Ele retorna o prefixo mais longo da segunda lista cujos elementos ysatisfazem α x y, onde xé o elemento correspondente da primeira lista.

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

Carvão , 52 bytes

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

Experimente online! O link é para a versão detalhada do código. Aceita a entrada como uma lista terminada por nova linha de strings de .e Ocaracteres. Explicação:

WS⊞υι

Insira a lista.

≔⮌υυ

Inverta a lista.

P⪫υ¶

Imprima a lista sem mover o cursor.

W∧

Repita enquanto ambos ...

⁼.O⪫KD²↓ω

... o caractere sob o cursor é um .e o caractere abaixo (porque a lista foi invertida) é um O, e ...

⁼¹№§υⅉ.

... a linha da lista atual contém exatamente um .:

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

Mova o cursor diagonalmente para baixo e para a direita ou esquerda dependendo da linha.

≔ⅉθ⎚Iθ

Capture o primeiro índice de linha inválido (indexado em 0, portanto igual ao número de linhas válidas), limpe a tela e imprima-o como uma string.

2 xash Aug 18 2020 at 12:33

J , 57 42 bytes

Leva em 0 para bloqueado, 1 para vazio.

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

Experimente online!

Como funciona

[*[+_1|.!.2]

Mova o tabuleiro para baixo em um (2 são empurrados no topo para garantir que as primeiras posições não contam). Em seguida, ele adiciona ao tabuleiro original e multiplica-se. Isso basicamente se resume a: um ponto aberto válido permanece 1, enquanto os inválidos tornam-se 2.

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

Dadas as dimensões, obtenha o intervalo exclusivo -x … x - 1para a largura, por exemplo, 4:, _3 _2 _1 0 1 2e obtenha seus valores absolutos 3 2 1 0 1 2. Redimensione essa lista para a altura do quadro, gire-a para que os 3 iniciais se alinhem à última linha e 2^xa lista:8 4 2 1 2 4 8 4 2…

 =2#.

Interprete as linhas como um número de base 2 e compare-as com a lista em zigue-zague.

 [:#.~

E por conversão de base reflexiva , podemos contar os 1's iniciais, portanto, as linhas iniciais que são válidas.

1 JonathanAllan Aug 19 2020 at 17:47

Jelly , 25 bytes

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

Um Link monádico que aceita uma lista de linhas onde cada linha é uma lista de 1s (vazio) e 0s (preenchido) que resulta em um número inteiro não negativo (a pontuação).

Experimente online! Ou veja o conjunto de testes .

Quão?

Constrói uma lista dos índices vazios esperados para cada linha a partir da parte inferior e a compara com cada uma das duas listas, (a) os índices vazios reais e (b) os índices vazios reais retirados da fila. Os resultados dessa comparação são então processados ​​para encontrar a pontuação.

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 bytes

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

Insira como uma matriz de 1s e 0s, onde os 1s são espaços vazios e os 0s são células preenchidas.

Experimente online. ou verifique todos os casos de teste .

Explicação:

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)