Dans le jeu Tetris , il existe 7 types de briques ou Tetr i minoes , qui sont mathématiquement connus comme tetr o minoes car ils sont tous constitués de 4 segments carrés:
Ils ont les noms I, J, L, O, S, T et Z, qui correspondent à leurs formes approximatives. En comptant les rotations à 90 °, il existe 19 formes uniques au total:
I
I
I
I
IIII
J
J
JJ
JJJ
J
JJ
J
J
J
JJJ
L
L
LL
L
LLL
LL
L
L
LLL
L
OO
OO
SS
SS
S
SS
S
TTT
T
T
TT
T
T
TTT
T
TT
T
ZZ
ZZ
Z
ZZ
Z
Défi
Ecrivez un bloc de code rectangulaire qui sert de segment de base à partir duquel ces 19 formes sont créées. Lorsque ce code est organisé dans l'une des formes, un programme doit être formé pour générer la seule lettre majuscule associée à cette forme. Cela doit fonctionner pour les 19 formes.
Les principales zones vides présentes dans certaines des 19 formes sont entièrement remplies d’espaces ( ). Les dernières zones vides ne sont remplies de rien (les programmes ne sont donc pas toujours exactement rectangulaires).
Exemple
Supposons que ceci soit votre bloc de code:
ABC
123
Ensuite, l’un ou l’autre arrangement du bloc dans la pièce S Tetris serait un programme qui imprime S
:
ABCABC
123123
ABCABC
123123
ABC
123
ABCABC
123123
ABC
123
(Notez que tous les espaces vides en tête sont remplis par des espaces et qu'aucune ligne ne comporte d'espaces de fin.)
La même idée s'applique aux 6 autres pièces et à leurs rotations respectives.
Remarques
- Les 19 programmes finaux doivent être exécutés dans le même langage de programmation.
- Si vous le souhaitez, vous pouvez ajouter une nouvelle ligne de fin à tous les programmes (pas seulement certains, tous ou aucun).
- Votre bloc de code peut contenir des caractères (espaces compris) qui ne sont pas des fins de ligne .
- Générez la lettre sur stdout (ou l'alternative la plus proche de votre langue) avec un retour à la ligne facultatif.
Notation
La soumission dont le bloc de code a la plus petite surface (largeur fois la hauteur) gagne. Cela signifie essentiellement que le code le plus court gagne, c'est pourquoi il s'agit du code-golf tagged . Tiebreaker va à la réponse la plus votée .
L' ABC\n123
exemple a l'aire 3 × 2 = 6.
Fragment
Étant donné un bloc de code, cet extrait générera les 19 programmes:
<script>function drawShape(X,n,v){for(var t="",e=0;e<v.length;e++)for(var l=0;l<n.length;l++){for(var r=0;r<v[e].length;r++)t+="X"===v[e][r]?n[l]:X[l];t+="\n"}return t}function go(){var X=document.getElementById("input").value;if(0!=X.length){var n=X.replace(/./g," ").split("\n");X=X.split("\n");for(var v="I (v1):|I (v2):|J (v1):|J (v2):|J (v3):|J (v4):|L (v1):|L (v2):|L (v3):|L (v4):|O:|S (v1):|S (v2):|T (v1):|T (v2):|T (v3):|T (v4):|Z (v1):|Z (v2):".split("|"),t="X\nX\nX\nX|XXXX| X\n X\nXX|XXX\n X|XX\nX\nX|X\nXXX|X\nX\nXX| X\nXXX|XX\n X\n X|XXX\nX|XX\nXX| XX\nXX|X\nXX\n X|XXX\n X|X\nXX\nX| X\nXXX| X\nXX\n X|XX\n XX| X\nXX\nX".split("|"),e="",l=0;l<v.length;l++)e+=v[l]+"\n\n"+drawShape(n,X,t[l].split("\n"))+"\n";e=e.substring(0,e.length-2),document.getElementById("output").value=e}}</script><style>html *{font-family: monospace;}</style>Code Block:<br><textarea id='input' rows='8' cols='64'>ABC
123</textarea><br><button type='button' onclick='go()'>Go</button><br><br>All 19 Programs:<br><textarea id='output' rows='24' cols='64'></textarea>
la source
Réponses:
<> <(Poisson) - 12 * 32 = 384
Je prévoyais une solution plus élégante, mais je me suis retrouvé avec ceci, ce qui est plutôt brutal:
C'est assez simple, il vérifie le code dans un carré 3x3 et utilise les résultats pour voir quel tétrimino correspond à la forme du code. Je n'ai pas encore pris beaucoup d'efforts pour jouer au golf.
Essayez le code ici (après avoir utilisé l'extrait pour le façonner comme un tétrimino)
Exemple de code en forme Z (v1) ici
la source
C (gcc) ,
26x20 = 52025x19 = 47523x17 = 391J'ai récemment été informé des attributs de fonction de GNU et, plus intéressant encore, du
constructor
attribut, ce qui permet une mise en œuvre plus concise de ce que je faisais de manière plus détournée dans mon approche précédente de ce problème.L’idée de base est la même que précédemment: créez une chaîne et recherchez-la dans une liste pour identifier le bloc de tétris dans lequel le code est présenté. Ceci est fait en appelant des fonctions, chacune ajoutant un caractère à la chaîne. La complication était et reste que le nombre de fonctions varie.
Définir une fonction avec
attribute((constructor(x)))
permet d’exécuter la fonction avant de lamain()
saisir, avec le paramètre optionnelx
étant la priorité (plus faible signifie qu'elle est exécutée plus tôt). Cela supprime le besoin de pointeurs de fonction, ce qui nous permet de supprimer une macro, certaines déclarations et la chaîne d'appel.En utilisant
__LINE__
de la priorité est incertaine, car les niveaux de priorité 0 à 100 sont réservés. Cependant, cela n'entraîne pas d'erreurs, mais uniquement des avertissements, et ceux-ci sont nombreux lorsque vous jouez au golf.Il aurait été utile de ne pas utiliser de priorités du tout dans une autre colonne, mais l'ordre d'exécution ne semble pas être défini. (Ils sont inversés dans ce cas, mais les autres tests ne sont pas concluants.)
Exemple de L v2 ici
Une approche plus ancienne et plus portable
Un de mes problèmes préférés que j'ai résolus sur ce site.
J'ai commencé par imaginer que chaque bloc devinerait ses propres coordonnées. Les rangées sont faciles avec
__LINE__
, et le nombre de blocs adjacents horizontalement pourrait être trouvé en utilisant la longueur d'un littéral de chaîne, comme ceci:Prenez la longueur de la chaîne résultante et divisez-la par un nombre approprié et vous aurez la largeur. Malheureusement, tout espace vide avant le bloc est invisible grâce à cette méthode. Je cordes encore suspectées serait la solution, puisque les espaces n'a de sens en dehors des cordes très rarement, dans des choses comme
a+++b
contrea+ ++b
. J'ai brièvement envisagé quelque chose comme ça, mais je n'ai rien trouvé d'utile. Une autre possibilité aurait été de laisser les identifiants être "collés" lorsque les blocs se rencontreraient:Je ne serais pas surpris si cela pouvait encore constituer une solution intéressante.
Malgré sa simplicité, il m'a fallu un certain temps pour trouver la solution de chaîne basée sur ce fragment de bloc:
Si le fragment n'a pas de voisins horizontaux, le retour à la ligne de la deuxième ligne est échappé par la barre oblique inverse, créant ainsi une chaîne de longueur 2. Si, toutefois, il a un voisin, la barre oblique inverse échappera à la marque de mouvement au début de la ligne. 2 du bloc suivant:
Cela créera la chaîne "\" "de longueur 5.
Plus important encore, cela permet également de détecter l’espace vide avant le bloc:
Encore une fois, la nouvelle ligne est échappée et les espaces du bloc vide à gauche sont inclus dans la chaîne résultante "" de longueur 6.
Au total, il y a sept configurations différentes de blocs sur une ligne dont nous devons nous préoccuper, et toutes créent des chaînes de longueurs uniques:
Les derniers blocs n'auront bien sûr pas une longueur aussi courte, mais le principe est le même quelle que soit la taille du bloc. Cela a également l'avantage qu'un mécanisme séparé pour détecter la largeur n'est pas nécessaire. En ajoutant un caractère correspondant à la longueur de cette chaîne à une chaîne de résultats, chacune des 19 configurations génère une chaîne unique, qu'il suffit de comparer à une liste appropriée une fois que tous les blocs ont été exécutés.
Une fois cela réglé, le problème suivant était de savoir comment "visiter" chaque rangée de blocs. En C, nous sommes très limités à ce qui peut être fait en dehors des fonctions. Nous devons également
main()
comparaître, mais une seule fois. Ce dernier est facilement réalisé par certains#define
s, mais si nous voulons que le code des blocs suivants soit à l’intérieur demain()
, le problème est de savoir quand mettre l’accolade de fermeture finale. Après tout, nous ne savons pas combien de rangées de blocs seront réellement utilisées. Nous avons donc besoin d'avoirmain()
statique et le reste pour être dynamique.Si les autres lignes de bloc doivent être autonomes, elles doivent être des fonctions, mais nous devons nous assurer que chaque fonction a un nom unique, tout en étant suffisamment prévisible pour pouvoir être appelé
main()
. Nous avons également besoin d'un mécanisme pour savoir quelles fonctions sont réellement appelées. La génération de noms uniques est résolue par les macros helper:L'appel
F
créera un identifiant dont le nom commence par un f et se termine par le numéro de ligne.A
fait de même, mais avec un préfixe as, utilisé pour la deuxième partie de la solution, à savoir les pointeurs de fonction. Nous déclarons quatre de ces pointeurs:Comme elles sont déclarées en tant que variables globales, elles ont la valeur NULL. Plus tard, chaque bloc-ligne aura le code suivant:
Cela va d'abord déclarer une fonction, définir le pointeur de fonction approprié pour pointer sur cette fonction (nous ne pouvons définir qu'une seule fois les globales, mais la déclaration précédente ne comptait pas comme une définition, même si elle était initialisée à NULL), puis définissait la valeur réelle. une fonction. Cela permet
main()
d’appeler n’importe quel pointeur de fonction non NULL (a17 ne sera jamais NULL):Cela va construire la chaîne
r
, qui sera ensuite recherchée dans la table des chaînes et, si elle est trouvée, la lettre appropriée est générée.La seule astuce restante consiste à raccourcir la liste des chaînes à comparer, chaque fois que l’ambiguïté peut être évitée, ou à fusionner les chaînes qui se chevauchent.
Exemple de L v2 ici
la source
Opcode x86 (.com),
8682 octetsTesteur:
La source:
Exécuter dans win7dos où init AX = 0, SI = 100, BX = 0 Références
la source
mov bx, 100h
le début.