Le magnifique tiroir à motifs
Bonjour PPCG!
L'autre jour, lorsque j'essayais d'aider quelqu'un sur Stack Overflow, une partie de son problème m'a donné une idée de ce défi.
Tout d'abord, vérifiez la forme suivante:
Où tous les nombres noirs sont l'index des points dans la forme et tous les nombres bleu foncé sont l'index des liens entre les points.
Maintenant, étant donné un nombre hexadécimal pour 0x00000 à 0xFFFFF, vous devez dessiner une forme dans la console en utilisant uniquement un espace de caractères et "■" (l'utilisation du caractère "o" est également acceptable).
Voici quelques exemples où le nombre hexadécimal est entré et la forme est sortie:
0xE0C25 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
0xC1043 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■
■
■
■
■
■
■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE4F27 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xF1957 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xD0C67 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0x95E30 :
■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■
0x95622 :
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■
■
■
■ ■ ■ ■ ■
0xC5463 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE5975 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xB5E75 :
■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xF4C75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xF5D75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
Voici quelques explications sur son fonctionnement:
0xFFFFF(16) = 1111 1111 1111 1111 1111(2)
Vous avez ici 20 bits, chaque bit indique si un lien existe ou non.
L'index du bit le plus significatif (MSB) est 0 (référence d'image) ou le bit le moins significatif (LSB) est 19 (référence d'image à nouveau).
Voici comment cela fonctionne pour la première forme donnée à titre d'exemple:
0xE0C25(16) = 1110 0000 1100 0010 0101(2)
Cela signifie que vous aurez les liens existants suivants: 0,1,2,8,9,14,17,19.
Si vous mettez en surbrillance les lignes de l'image de référence avec ces chiffres, cela vous donnera cette forme:
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
Voici une implémentation Python simple et non gérée si vous avez besoin de plus d'aide:
patterns = [
0xE0C25, 0xC1043, 0xE4F27, 0xF1957,
0xD0C67, 0x95E30, 0x95622, 0xC5463,
0xE5975, 0xB5E75, 0xF4C75, 0xF5D75
]
def printIfTrue(condition, text = "■ "):
if condition:
print(text, end="")
else:
print(" "*len(text), end="")
def orOnList(cube, indexes):
return (sum([cube[i] for i in indexes]) > 0)
def printPattern(pattern):
cube = [True if n == "1" else False for n in str(bin(pattern))[2::]]
for y in range(9):
if y == 0: printIfTrue(orOnList(cube, [0, 2, 3]))
if y == 4: printIfTrue(orOnList(cube, [2, 4, 9, 11, 12]))
if y == 8: printIfTrue(orOnList(cube, [11, 13, 18]))
if y in [0, 4, 8]:
printIfTrue(cube[int((y / 4) + (y * 2))], "■ ■ ■ ")
if y == 0: printIfTrue(orOnList(cube, [0, 1, 4, 5, 6]))
if y == 4: printIfTrue(orOnList(cube, [3, 5, 7, 9, 10, 13, 14, 15]))
if y == 8: printIfTrue(orOnList(cube, [12, 14, 16, 18, 19]))
printIfTrue(cube[int((y / 4) + (y * 2)) + 1], "■ ■ ■ ")
elif y in [1, 5]:
for i in range(7):
if i in [2, 5]:
print(" ", end=" ")
printIfTrue(cube[y * 2 + (1 - (y % 5)) + i])
elif y in [2, 6]:
for i in range(5):
if i in [1, 2, 3, 4]:
print(" ", end=" ")
if i in [1, 3]:
if i == 1 and y == 2:
printIfTrue(orOnList(cube, [3, 4]))
elif i == 3 and y == 2:
printIfTrue(orOnList(cube, [6, 7]))
if i == 1 and y == 6:
printIfTrue(orOnList(cube, [12, 13]))
elif i == 3 and y == 6:
printIfTrue(orOnList(cube, [15, 16]))
else:
printIfTrue(cube[(y * 2 - (1 if y == 6 else 2)) + i + int(i / 4 * 2)])
elif y in [3, 7]:
for i in range(7):
if i in [2, 5]:
print(" ", end="")
ri, swap = (y * 2 - 2) + (1 - (y % 5)) + i, [[3, 6, 12, 15], [4, 7, 13, 16]]
if ri in swap[0]: ri = swap[1][swap[0].index(ri)]
elif ri in swap[1]: ri = swap[0][swap[1].index(ri)]
printIfTrue(cube[ri])
if y == 0: printIfTrue(orOnList(cube, [1, 7, 8]))
if y == 4: printIfTrue(orOnList(cube, [6, 8, 10, 16, 17]))
if y == 8: printIfTrue(orOnList(cube, [15, 17, 19]))
print()
for pattern in patterns:
printPattern(pattern)
Bien sûr, ce n'est pas parfait et c'est assez long pour ce qu'il devrait faire, et c'est la raison exacte pour laquelle vous êtes ici!
Rendre ce programme ridiculement court :)
C'est le golf de code, donc la réponse la plus courte l'emporte!
Réponses:
JavaScript (ES6),
202188187 octetsComment ça fonctionne
Nous travaillons sur une grille
g
de 9 lignes de 10 caractères. La grille est initialement remplie d'espaces, avec un saut de ligne tous les 10 caractères.Chaque segment est défini par une position de départ et une direction.
Les directions sont codées comme suit:
Chaque segment est codé sous forme d'entier:
Par exemple, le segment # 3 commence à la position 55 et utilise la 3ème direction. Par conséquent, il est codé en tant que
(55 << 2) | 3 == 223
.Voici la liste résultante des entiers, du segment # 19 au segment # 0:
Une fois codé en delta, à partir de 356, il devient:
Qui est finalement codé comme:
la source
Python 3, 289 octets
Rien d'intelligent, juste du codage en dur.
la source
"trq|t...a|eca".split("|")
devenir"tqr t...a eca".split()
?.split()
détruit||
.Rubis, 116 octets
Cela repose sur quelques schémas que j'ai observés. Tout d'abord, le motif se répète toutes les 9 lignes. Deuxièmement, si les points de départ des lignes horizontales sont choisis de manière appropriée, les directions x parcourent en continu la droite, la gauche, la droite.
Non testé dans le programme de test
Je crois qu'il existe une solution de 112 octets utilisant une chaîne de 20 caractères et un décodage pour définir les paramètres des 20 lignes. J'essaierai cela plus tard si j'ai le temps.
la source
PHP,
142150149 octetsimprime la forme autant que nécessaire; c'est-à-dire que si la partie inférieure est vide, elle sera coupée.
Courez avec
php -nr '<code>' <input>
. Ne pas préfixer l'entréeTestez-le en ligne
Ajoutez 11 octets pour ne pas couper: insérez
,$r[80]=" "
après$r=""
.explication du codage
Chaque ligne peut être décrite avec un point de départ et l'une des quatre directions.
Dessin sur une grille 9x9, la position de départ varie de
0,0
à8,4
; ou, combinés, de0
à8*9+4=76
. Heureusement, tous les points de départ[0,4,8,36,40,44,72,76]
sont divisibles par 4; de sorte que le code de direction[0..3]
peut être compressé en bits 0 et 1 -> aucun décalage nécessaire du tout.Pour un calcul facile du mouvement du curseur,
0
est pris pour l'est (seule direction sans mouvement vertical) et[1,2,3]
pour le sud-ouest, le sud, le sud-est, où le décalage est9
(pour le mouvement vertical) plus[-1,0,1]
->[8,9,10]
->delta=code?code+7:1
.La direction pour la première et la dernière ligne étant l'est, ce qui donne des codes allant de 0 à 76
[0+0,4+0,0+2,0+3,4+1,4+2,4+3,8+1,8+2,...,44+1,44+2,72+0,76+0]
; et xor 96 au niveau du bit sur chaque valeur entraîne des codes ascii imprimables et non problématiques[96,100,98,99,101,102,103,105,106,68, 72,70,71,73,74,75,77,78,40,44]
->`dbcefgijDHFGIJKMN(,
. Le code utilise le LSB pour le bit 0, tandis que la ligne 0 correspond au MSB, donc la chaîne doit être inversée. Finito.panne
un peu de golf expliqué
^96
n'a aucun effet sur les deux bits inférieurs, il peut être ignoré lors de l'extraction de la direction; il n'est donc pas nécessaire de stocker la valeur dans une variable, ce qui économise 5 octets sur le curseur init.~3
au lieu d'124
enregistrer un octet et permet le golf suivant:$k=3
à l'intérieur de l'$p
affectation permet d'économiser deux octetset cela ne nuit pas à la condition préalable (car la valeur supérieure a toujours un chiffre).
chunk_split
est le moyen le plus court d'insérer les sauts de ligne.Je ne veux même pas savoir combien il en faudrait d’autre.
7+($c&3?:-6)
est un octet plus court que$c&3?$c%4+7:1
.hexdec()
(8 octets) pour satisfaire la restriction d'entrée.la source
JavaScript,
184183178168167 octetsÉtait à l'origine de 206 octets, mais la réponse de @ Arnauld m'a inspiré à étudier une solution de tableau unidimensionnel. Edit: 1 octet enregistré grâce à @ edc65. Enregistré
515 octets grâce à @Arnauld. Sauvegardé un octet supplémentaire en modifiant le choix des caractères.la source
[0,1,2,3,4]
est plus court[67,65,52,36,51,50,34,49,48,35,33,20,4,19,18,2,17,16,3,1]
et[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o')
[..."ecVFUTDSREC6&54$32%#"]
et[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o',e=e.charCodeAt()-34)
pour enregistrer 10 octets supplémentaires.~
place de-34
(malheureusement, je tombe sous le coup de `\ ', c'est pourquoi je n'enregistre pas 2 octets).Lot, 491 octets
Remarque: la dernière ligne se termine par un espace. Mettre un
if
conditionnel avec une variable dans unefor
boucle est au-delà du lot, ce qui nécessite son propre sous-programme. Puisqu'il ne fait rien de visible, je tombe dedans pour sortir. Le ne~
cite pas les chaînes dans la boucle externe permettant à la boucle interne de boucler sur les nombres. Les nombres sont simplement les bitmasks pour tous les endroits oùo
s doit être dessiné.la source
C,
267262260256 caractèresCompter les échappées comme 1 caractère
k est une recherche faisant référence aux cases dans lesquelles mettre un «o».
Essayez-le en ligne!
la source
Befunge, 468 octets
Essayez-le en ligne!
La première ligne lit une chaîne depuis stdin, l'évaluant comme un nombre hexadécimal. Le reste du code est essentiellement une double boucle sur les coordonnées x / y de la grille, avec un calcul booléen massif déterminant si un
o
doit être sorti pour chaque emplacement.Il y a fondamentalement une condition distincte pour chacun des 20 points de grille, par exemple (les quatre premiers):
Et puis une fois que nous avons calculé les 20, nous OU le lot ensemble, et si ce résultat est vrai, nous produisons un
o
, sinon nous générons un espace.Befunge n'a rien à faire en termes d'opérations de manipulation de bits, donc pour extraire les bits de l'entrée, nous ne faisons qu'évaluer à plusieurs reprises
n%2
, puisn/=2
pendant que nous progressons dans les 20 calculs de condition.la source