En el juego Tetris , hay 7 tipos de ladrillos o Tetr i minoes , que matemáticamente se conocen como tetr o minoes porque todos están hechos con 4 segmentos cuadrados:
Tienen los nombres I, J, L, O, S, T y Z, que corresponden a sus formas aproximadas. Contando rotaciones de 90 °, hay 19 formas únicas en 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
Reto
Escriba un bloque rectangular de código que actúe como el segmento base del que están hechas estas 19 formas. Cuando este código se organiza en una de las formas, se debe formar un programa que genere la letra mayúscula única asociada con esa forma. Esto debe funcionar para las 19 formas.
Las principales áreas vacías presentes en algunas de las 19 formas se completan completamente con espacios ( ). Las áreas vacías finales no están llenas de nada (por lo que los programas no siempre son exactamente rectangulares).
Ejemplo
Supongamos que este fuera su bloque de código:
ABC
123
Entonces, cualquier disposición del bloque en la pieza S Tetris sería un programa que imprime S
:
ABCABC
123123
ABCABC
123123
ABC
123
ABCABC
123123
ABC
123
(Observe que todo el espacio vacío inicial está lleno de caracteres de espacio, y que ninguna línea tiene espacios finales).
La misma idea se aplica a las otras 6 piezas y sus respectivas rotaciones.
Notas
- Los 19 programas finales se ejecutarán en el mismo lenguaje de programación.
- Si lo desea, puede agregar una nueva línea final a todos los programas (no solo algunos, todos o ninguno).
- Su bloque de código puede contener cualquier carácter (incluidos espacios) que no sean terminadores de línea .
- Envíe la carta a stdout (o la alternativa más cercana a su idioma) con una nueva línea final opcional.
Tanteo
El envío cuyo bloque de código tiene el área más pequeña (ancho por alto) gana. Esto esencialmente significa que gana el código más corto, razón por la cual esto se etiqueta con código de golf . Tiebreaker va a la respuesta más votada .
El ABC\n123
ejemplo tiene área 3 × 2 = 6.
Retazo
Dado un bloque de código, este fragmento generará los 19 programas:
<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>
fuente
Respuestas:
<> <(Pez) - 12 * 32 = 384
Estaba planeando buscar una solución más elegante, pero de alguna manera terminé con esto, que es bastante fuerza bruta:
Es bastante simple, verifica el código en un cuadrado de 3x3 para texto y usa los resultados para ver qué tetrimino corresponde a la forma del código. No hice mucho esfuerzo para jugar golf todavía.
Pruebe el código aquí (después de usar el fragmento para darle forma como un tetrimino)
Ejemplo de código en forma Z (v1) aquí
fuente
C (gcc) ,
26x20 = 52025x19 = 47523x17 = 391Recientemente fui informado de los atributos de función de GNU, y lo más interesante del
constructor
atributo, que permite una implementación más concisa de lo que estaba haciendo de una manera más indirecta en mi enfoque anterior de este problema.El objetivo de la idea es el mismo que antes: construir una cadena y buscarla en una lista para identificar qué bloque de tetris se presenta el código. Esto se hace llamando a funciones, cada una agregando un carácter a la cadena. La complicación fue y sigue siendo que el número de funciones varía.
La definición de una función
attribute((constructor(x)))
hace que la función se ejecute antes de quemain()
se ingrese,x
siendo la prioridad la opción opcional (menor significa que se ejecuta antes). Esto elimina la necesidad de punteros de función, lo que nos permite descartar una macro, algunas declaraciones y la cadena de llamada.Usar
__LINE__
para prioridad es dudoso, ya que los niveles de prioridad 0-100 están reservados. Sin embargo, no genera errores, solo advertencias, y son abundantes cuando se juega al golf, entonces, ¿qué más?Hubiera ayudado a eliminar otra columna para no usar prioridades en absoluto, pero el orden de ejecución no parece estar definido. (Se invierten en este caso, pero otras pruebas no son concluyentes).
Ejemplo de L v2 aquí
Enfoque más antiguo y portátil
Uno de mis problemas favoritos que he resuelto en este sitio.
Comencé imaginando que cada bloque adivinaría sus propias coordenadas de alguna manera. Las filas son fáciles
__LINE__
y el número de bloques adyacentes horizontalmente se puede encontrar usando la longitud de un literal de cadena, de esta manera:Tome la longitud de la cadena resultante y divida por un número apropiado y tendrá el ancho. Lamentablemente, cualquier espacio vacío antes del bloque es invisible por este método. Todavía sospechosos cuerdas sería la solución, ya que los espacios en blanco sólo tiene sentido fuera de cadenas muy raramente, en cosas como
a+++b
vsa+ ++b
. Brevemente consideré algo así, pero no se me ocurrió nada útil. Otra posibilidad habría sido permitir que los identificadores se "peguen" juntos donde se encuentran los bloques:No me sorprendería si esto todavía podría ser una solución interesante.
A pesar de su simplicidad, me llevó bastante tiempo encontrar la solución de cadena, que se basa en este fragmento de bloque:
Si el fragmento no tiene vecinos horizontales, la nueva línea en la segunda línea se escapa por la barra invertida, creando una cadena de longitud 2. Sin embargo, si tiene un vecino, la barra invertida escapará de la comilla al comienzo de la línea 2 del siguiente bloque:
Esto creará la cadena "\" "de longitud 5.
Más importante aún, esto también permite la detección de espacio vacío antes del bloque:
Nuevamente, la nueva línea se escapa y el espacio en blanco del bloque vacío a la izquierda se incluye en la cadena resultante "" de longitud 6.
En total, hay siete configuraciones diferentes de bloques en una fila de las que debemos preocuparnos, y todas ellas forman cadenas de longitudes únicas:
Los bloques finales, por supuesto, no tendrán una longitud tan corta, pero el principio es el mismo independientemente del tamaño del bloque. Esto también tiene la ventaja de que no es necesario un mecanismo separado para detectar el ancho. Al agregar un carácter correspondiente a la longitud de esta cadena a una cadena de resultados, cada una de las 19 configuraciones produce una cadena única, que solo necesita ser comparada con una lista adecuada una vez que se han ejecutado todos los bloques.
Una vez que esto se resolvió, el siguiente gran problema fue cómo "visitar" cada fila de bloques. En C, estamos muy limitados a lo que se puede hacer fuera de las funciones. También necesitamos
main()
aparecer, pero solo una vez. Esto último se logra fácilmente por algunos#define
s, pero si queremos que el código de los bloques posteriores esté dentromain()
, el problema de cómo saber cuándo colocar el corchete final de cierre. Después de todo, no sabemos cuántas filas de bloques se usarán realmente. Por lo tanto, necesitamos tenermain()
estática y, de alguna manera, el resto para ser dinámicos.Si las otras filas de bloques deben ser autocontenidas, deben ser funciones, pero debemos asegurarnos de que cada función tenga un nombre que sea único y, al mismo tiempo, sea lo suficientemente predecible como para ser invocable
main()
. También necesitamos un mecanismo para saber qué funciones están realmente allí para ser llamadas. La generación de nombres únicos se resuelve mediante macros de ayuda:Llamar
F
creará un identificador cuyo nombre comienza con una f y termina con el número de línea.A
hace lo mismo pero con un prefijo as, que se usa para la segunda parte de la solución, que es punteros de función. Declaramos cuatro de estos indicadores:Como se declaran como variables globales, se establecen convenientemente en NULL. Más adelante, cada fila de bloques tendrá el siguiente código:
Esto declarará primero una función, definirá el puntero de función apropiado para apuntar a esa función (solo podemos definir globales una vez, pero la declaración anterior no contaba como una definición, incluso si se inicializaba a NULL), y luego definía el real función. Esto permite
main()
llamar a cualquier puntero de función que no sea NULL (a17 nunca será NULL):Al hacerlo, se generará la cadena
r
, que luego se busca en la tabla de cadenas y, si se encuentra, se genera la letra correspondiente.El único truco que queda es que la lista de cadenas con las que se debe coincidir se acorta cada vez que se puede evitar la ambigüedad o se pueden combinar cadenas superpuestas.
Ejemplo de L v2 aquí
fuente
x86 opcode (.com),
8682 bytesEnsayador:
Fuente:
Ejecutar en win7dos donde init AX = 0, SI = 100, BX = 0 Referencias
fuente
mov bx, 100h
al inicio.