Esta pregunta está inspirada en la portada del libro "Godel, Escher, Bach":
El desafío aquí es escribir una función que indique si tres letras dadas pueden producir una escultura en 3D que se pueda leer desde tres lados.
Para este ejercicio, las únicas letras que puede usar son 26 mapas de bits de 5px * 5px:
O en binario (de la A a la Z):
01110 11110 01111 11110 11111 11111 11111 10001 11111 11111 10001 10000 10001 10001 01110 11110 01110 11110 01111 11111 10001 10001 10001 10001 10001 11111
10001 10001 10000 10001 10000 10000 10000 10001 00100 00100 10010 10000 11011 11001 10001 10001 10001 10001 10000 00100 10001 10001 10001 01010 01010 00010
10001 11110 10000 10001 11100 11110 10011 11111 00100 00100 11100 10000 10101 10101 10001 10001 10001 11111 01110 00100 10001 01010 10001 00100 00100 00100
11111 10001 10000 10001 10000 10000 10001 10001 00100 10100 10010 10000 10001 10011 10001 11110 10011 10010 00001 00100 10001 01010 10101 01010 00100 01000
10001 11110 01111 11110 11111 10000 11111 10001 11111 11100 10001 11111 10001 10001 01110 10000 01111 10001 11110 00100 01110 00100 01010 10001 00100 11111
La escultura está formada por tres letras en el siguiente orden:
- letra uno en la parte superior,
- letra dos a la izquierda
- letra tres a la derecha
- la parte inferior de la letra uno está unida a la parte superior de la letra dos.
Ejemplo:
Su función puede aceptar como entrada tres letras mayúsculas (tres caracteres o tres cadenas de una letra) y generar un booleano (verdadero / falso o 0/1) que indica si la escultura correspondiente puede existir.
Ejemplo:
f("B","E","G") // true (because if you "sculpt out" B on top + E on the left + G on the right, and watch the three sides of the sculpture, you'll see exactly B, E and G as they are defined)
f("B","G","E") // false (because if you "sculpt out" B on top + G on the left + E on the right, and watch the three sides of the sculpture, you won't see a complete G and a complete E. Their shapes bother each other)
NB: puede volver verdadero incluso si la escultura contiene "píxeles voladores" (cubos o grupo de cubos que están unidos a nada).
Se aplican lagunas estándar.
Más precisamente, no puede usar la entrada externa además de las tres letras, y no puede codificar las 17576 respuestas posibles en su código fuente
¡La respuesta más corta en caracteres en cualquier idioma gana!
Que te diviertas :)
Respuestas:
Mathematica 423
Agregué una sección llamada "Cómo funciona el bloqueo".
Sin golf
(* Los datos binarios del alfabeto se almacenan como una sola cadena
s
. Losvars
importa y los convierte en una matriz).Ejemplo
¿Es
{"B", "G", "E"}
válido el cubo ? (es decir, ¿las tres letras se proyectarán correctamente en las paredes?)Ilustraciones
Las siguientes figuras muestran cómo se representa BGE. La fila superior de figuras toma perspectivas ortogonales, como si el espectador estuviera colocado a distancias infinitas del cubo. La fila inferior muestra cómo se verían los bloques de cerca. Las figuras en 3D se pueden girar manualmente para inspeccionar con precisión dónde se colocan los cubos de la unidad individual.
Se produce un problema con la letra "G". No hay nada que conecte el serif con el resto de la carta.
BEG, sin embargo, debería funcionar bien.
¿Cómo funciona el bloqueo?
Disculpe si esto parece obvio, pero tal vez algunas personas quieran visualizar cómo las letras interfieren entre sí, cancelando sus píxeles 3D.
Sigamos lo que sucede con la letra G, en la representación del cubo BGE.
Prestaremos especial atención al voxel (píxel 3D o cubo de la unidad) a continuación. Ese es el píxel que desaparece en el cubo BGE. Es el píxel correspondiente a la Fila 4, Columna 5 en la matriz de bits y en la gráfica de matriz correspondiente.
En el plano xy, el píxel corresponde al disco gris en el punto (5,2). Pero debido a que vamos a trabajar en 3D, debemos considerar las 5 posiciones en el eje desde (5,1,2) hasta (5,5,2). Si alguno de esos píxeles sobrevive esculpido por las letras B y E, podremos ver el píxel de interés en la proyección 3D en la pared.
Las letras interfieren cuando se eliminan los píxeles del bloque sólido. A la izquierda, la flecha negra representa el tallado de píxeles, correspondiente al bit en la parte inferior derecha; tiene el valor 0 para la letra B. La división elimina el píxel en (5,1,2), junto con los que están directamente arriba y debajo. Quedan cuatro píxeles por contabilizar.
Pero como muestra el panel derecho, la letra E esculpe los píxeles restantes de interés, (5,2,2) (5,3,2), (5,4,2) y (5,5,2). (Esto se debe al hecho de que la letra E tiene bits iguales a 0 en la cuarta fila, desde la columna 2 hasta la columna 5). Como resultado, no queda un solo píxel entre los que se necesitaban para garantizar la sombra en el punto (5 , 2) en la pared del fondo (para la letra G). En cambio, habrá un punto brillante correspondiente a un agujero en la letra G! El cubo BGE no es bueno porque representa incorrectamente G.
Golfó 423 caracteres
La función
h
desempeñaba el mismo papel quevalidQ
en el código no protegido. La función de representación,perspective
no está incluida porque no contribuye y no es requerida por el desafío.fuente
Prolog,
440, 414El programa se llama así:
Prolog
Parecía ser una buena opción, ya que es fácil representar el problema en la lógica de primer orden. TambiénProlog
proporciona una potente funcionalidad para resolver este tipo de problema.Sin embargo, dado que el código es golf, creo que debería agregar alguna explicación.
Versión ligeramente golfizada
Las coordenadas correspondientes a los píxeles a cada lado del dado se pueden convertir fácilmente en un sistema de coordenadas 3D. Yo uso
T
,L
yR
para el lado superior (1), izquierdo (2) y derecho (3).u
yv
se usan para las coordenadas en las imágenes:(u,v) -> (4-v, ?, u)
(u,v) -> (?, v, u)
(u,v) -> (u, v, ?)
Los resultados para cada píxel activo (es decir, negro) se combinan en un conjunto de "píxeles 3D" que se pueden activar sin cambiar la apariencia del objeto desde este lado. La intersección de los conjuntos para cada lado son todos píxeles en 3D, que se pueden activar sin agregar píxeles, lo que obstruiría la vista (es decir, al mirar desde al menos un lado habría un píxel que no debería estar allí).
Todo lo que queda es verificar por cada lado, si hay un píxel en la intersección que bloquea la vista, donde es necesario.
Esto lleva a los predicados en el programa:
c : comprueba el píxel en la imagen de una letra. La cadena allí puede parecer un poco extraña, pero es solo una forma compacta de almacenar los datos de la imagen. Es simplemente una secuencia de caracteres con los siguientes valores (notación hexadecimal):
Cada uno de estos caracteres almacena los datos de las filas de 3 píxeles en imágenes de letras (= 15 píxeles). Los píxeles también se reordenan para que los datos se almacenen en una ubicación y no se dividan en varias filas, como los datos del OP.
Formulación matemática
Datos de entrada
Conversión de píxel en un carácter a conjunto de píxeles 3D que obstruyen la vista de este píxel
Píxeles que se pueden agregar de forma segura (sin obstruir la vista en el lugar equivocado)
Comprueba para cada lado, que los píxeles que necesitan ser obstruidos pueden ser obstruidos de manera segura
Combinación de cheques para cada lado
fuente
J -
223197191charUna función que toma una lista de tres caracteres como argumento.
Este golf se basa en gran medida en una característica poderosa de J llamada rango , que nos da las operaciones de "esculpir" y "vigilar" casi de forma gratuita. Para simplificarlo un poco, el rango se refiere a la dimensionalidad de un sustantivo o de los argumentos naturales de un verbo.
J tiene matrices multidimensionales, y es obvio que, por ejemplo, una matriz 3D se puede interpretar como una sola matriz 3D, o como una lista de matrices, o una matriz 2D de vectores, o una matriz 3D de escalares. Por lo tanto, cada operación en J puede tener su aplicación controlada y cómo distribuirse sobre el argumento. El rango 0 significa aplicar en los escalares, el rango 1 significa aplicar en los vectores, y así sucesivamente.
Esto se vuelve muy poderoso cuando introduce funciones diádicas (dos argumentos), porque si las formas de los dos argumentos (después de considerar el rango) son agradables, J hará un bucle implícito:
Cuando todas sus formas son agradables y puede especificar el rango usted mismo, hay muchas formas de combinar argumentos. Aquí mostramos algunas de las formas en que puede multiplicar una matriz 2D y una matriz 3D.
Notarás que esto realmente no graba las letras en la orientación que hace la pregunta, solo las escribe, pero es conveniente para la lógica de rango. A menos que invirtamos o giremos las letras antes de aplicarlas, no funcionará correctamente. Pero corregir cosas así tomaría caracteres preciosos, por lo que codificaremos las letras de tal manera que, cuando J las grabe de forma natural, algunas caras triples estarán en las orientaciones y posiciones relativas correctas. Resulta que la solución más corta es rotar todas las letras un cuarto de vuelta en sentido antihorario. Teniendo en cuenta que la tercera dimensión de J representa el eje de adelante hacia atrás, el diagrama en bruto a continuación muestra por qué funciona este esquema.
Figura A: Los tres lados del cubo en el que J talla. Figura B: Los tres lados que tienen las letras orientadas como se hace la pregunta.
Esta elección en la codificación ahorra 12 caracteres sobre el método anterior y hace que todo sea más ordenado. El golf real crea el cubo fuera del
"1
y"2
talla con cierta lógica funky, debido a una optimización no relacionada.Luego tenemos que revisar las caras. Desde el bloque codificamos como 1s y 0s, sólo podemos resumir lo largo de cada eje en la forma en que queremos (estos son los
+/"1
,+/"2
y+/
bits), ajuste a booleanos (0<
), y luego comparar a todos ellos directamente a la original de 90 ° - letras convertidasEl esquema de compresión codifica cada fila de 5 píxeles de cada letra como la representación base 32 de un número binario. Al explotar una cantidad de azúcares sintácticos y sobrecargas de operadores,
".'1b',"#:
es la forma más corta de convertir la lista de caracteres en números base 36. Bueno, técnicamente, base 32, pero J piensa que es unario, entonces, ¿quién está contando?El uso está abajo. Tenga en cuenta que las cadenas son matrices de caracteres en J, por lo que
'A','B','C'
se puede escribir una lista de tres elementos'ABC'
para abreviar. Además, los booleanos son 1/0.fuente
Python,
687682671Llamar con
v
:Todo lo que sigue es de mi versión anterior sin golf que incluye útiles funciones de dibujo. Siéntase libre de usarlo como punto de partida.
Llame
valid
para ejecutarlo:En este momento, el código está configurado para probar la validez
B E G
e imprimir las caras resultantes:Ejecutándolo
B G E
podemos ver que la G es incorrecta:fuente
g=[[0 for j in s]for i in s]
se puede acortar ag=map(list,[[0]*5]*5)
. También se puede evitar la sangría de bloques si son una sola instrucción:if c[e]:g[e[a]][e[a-2]]=1
.Python 3 + numpy, 327C
Esta solución de golf necesita una biblioteca externa, numpy, que es bastante popular, así que creo que está bien usarla.
La cadena Unicode está en 41 caracteres, mientras que lo mismo en la respuesta del prólogo de @ fabian es 44.
Lo más interesante aquí es que la indexación de la matriz numpy. En
a[ix]
,ix
puede ser una matriz booleana con la misma forma quea
. Es lo mismo que decira[i, j, k] where ix[i, j, k] == True
.Versión sin golf
Script para comprimir tabla
fuente