Défi secret d'empilement «>»: classement

Aug 18 2020

Contexte

Tetris Grand Master 3 dispose d'un système de notation caché basé sur la forme de la pile à la fin du jeu, qui s'appelle Secret ">" Stacking Challenge . Il consiste à remplir entièrement les lignes les plus basses à l'exception du motif en zigzag qui commence à la cellule inférieure gauche et s'étend sur toute la largeur:

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

Le tableau est noté en fonction du nombre de lignes qui suivent ce modèle exact à partir de la ligne du bas. Notez que le trou le plus haut du motif doit être bloqué par un morceau de bloc supplémentaire. Si vous considérez le #s et le .s comme le modèle obligatoire (les blancs peuvent être n'importe quoi), vous ne pouvez obtenir le score de 19 que si le modèle exact ci-dessus correspond à la ligne du bas. De même, si la carte correspond à ce modèle

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

mais non

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

alors le score est de 4.

Pour ce défi, considérez une carte de taille arbitraire (autre que 20 cellules de haut et 10 cellules de large). Nous pouvons noter la planche pour le même motif: par exemple, si la planche a une largeur de 4, voici le motif pour le score 3:

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

et voici le modèle du score 10:

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

Défi

Étant donné l'état final de la carte Tetris de taille arbitraire, notez la carte en utilisant le système ci-dessus.

Vous pouvez prendre le tableau en utilisant n'importe quel format raisonnable pour une matrice rectangulaire, où chaque cellule contient l'une des deux valeurs distinctes (pour vide et rempli respectivement). Vous pouvez supposer que la grille est un tableau Tetris valide (aucune ligne n'est entièrement remplie). De plus, la largeur de la grille est d'au moins 2.

Les règles standard du code-golf s'appliquent. Le code le plus court en octets l'emporte.

Cas de test

Afin d'éviter toute confusion possible, les cas de test utilisent ici Opour les blocs et .pour les espaces vides.

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

Réponses

3 Arnauld Aug 18 2020 at 12:47

JavaScript (ES6), 84 octets

Attend une liste de chaînes, avec 1pour les espaces vides et 0pour les blocs.

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)

Essayez-le en ligne!

Comment?

Chaque chaîne du tableau d'entrée est complétée par un supplément 0et interprétée comme un nombre binaire. La variable jest initialisée à 2**W, où West la largeur de la carte. Nous utilisons un masque de bits iinitialisé à jpour garder une trace de la position attendue du trou dans le motif.

Après chaque itération, iest multiplié par k. Nous mettons à jour la valeur de kchaque fois (i & j) != 0(rebondissant sur le côté le plus à gauche) ou (i & 2) != 0(rebondissant sur le côté le plus à droite).

Exemple pour 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
...

Commenté

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 octets

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

Essayez-le en ligne!

Prend une matrice 0-1.

Explication

Il y a trois occurrences de dans ce programme, et elles fonctionnent toutes différemment grâce aux fonctions de modification δet Ψ. Par défaut, ↑αs'attend αà être une fonction unaire, prend une liste et renvoie le préfixe le plus long des éléments pour lesquels αrenvoie une valeur de vérité. Ψ↑αs'attend αà être binaire et renvoie le préfixe le plus long des éléments xpour lesquels α x yest la vérité, où yest l'élément suivant. δ↑αs'attend αà être binaire et prend deux listes au lieu d'une. Il renvoie le préfixe le plus long de la deuxième liste dont les éléments ysatisfont α x y, où xest l'élément correspondant de la première liste.

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

Charbon , 52 octets

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

Essayez-le en ligne! Le lien est vers la version verbeuse du code. Prend l'entrée sous la forme d'une liste de chaînes de caractères .et se terminant par une nouvelle ligne O. Explication:

WS⊞υι

Saisissez la liste.

≔⮌υυ

Inversez la liste.

P⪫υ¶

Imprimez la liste sans déplacer le curseur.

W∧

Répétez pendant que les deux ...

⁼.O⪫KD²↓ω

... le caractère sous le curseur est un .et le caractère ci-dessous (car la liste a été inversée) est un O, et ...

⁼¹№§υⅉ.

... la ligne de liste actuelle en contient exactement une .:

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

Déplacez le curseur en diagonale vers le bas et vers la droite ou vers la gauche selon la ligne.

≔ⅉθ⎚Iθ

Capturez le premier index de ligne non valide (indexé à 0, donc égal au nombre de lignes valides), effacez le canevas et imprimez-le sous forme de chaîne.

2 xash Aug 18 2020 at 12:33

J , 57 42 octets

Prend 0 pour bloqué, 1 pour vide.

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

Essayez-le en ligne!

Comment ça fonctionne

[*[+_1|.!.2]

Décalez le tableau de un vers le bas (2 est poussé en haut pour s'assurer que les premières places ne comptent pas.) Ensuite, il s'ajoute au tableau d'origine et se multiplie avec lui-même. Cela se résume essentiellement à: un spot ouvert valide reste 1, tandis que les non valides deviennent 2.

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

Étant donné les dimensions, obtenez la plage exclusive -x … x - 1pour la largeur, par exemple 4:, _3 _2 _1 0 1 2et obtenez leurs valeurs absolues 3 2 1 0 1 2. Redimensionnez cette liste à la hauteur du tableau, faites-la pivoter pour que les 3 de départ s'alignent sur la dernière ligne et 2^xla liste:8 4 2 1 2 4 8 4 2…

 =2#.

Interprétez les lignes comme un nombre de base 2 et comparez-le à la liste en zig-zag.

 [:#.~

Et par conversion de base réflexive, nous pouvons compter les premiers 1, donc les premières lignes qui sont valides.

1 JonathanAllan Aug 19 2020 at 17:47

Gelée , 25 octets

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

Un lien monadique acceptant une liste de lignes où chaque ligne est une liste de 1s (vide) et 0s (rempli) qui donne un entier non négatif (le score).

Essayez-le en ligne! Ou consultez la suite de tests .

Comment?

Construit une liste des indices vides attendus pour chaque ligne à partir du bas et la compare à chacune des deux listes, (a) les indices vides réels et (b) les indices vides réels retirés de la file d'attente. Les résultats de cette comparaison sont ensuite traités pour trouver le score.

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 octets

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

Entrée sous forme de matrice de 1 et de 0, où les 1 sont des espaces vides et les 0 sont des cellules remplies.

Essayez-le en ligne. ou vérifiez tous les cas de test .

Explication:

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)