Cuadrados de arte ASCII fractales afines

9

Escribe el programa más pequeño que puedas para crear fractales afines. Puede usar cualquier método que considere que genera los mismos resultados que las reglas a continuación. ¡No tiene que usar ninguna idea de los métodos sugeridos!

Su programa tomará dos entradas, la primera para definir el patrón en el formato 074de tres dígitos del 0 al 7. La segunda entrada definirá el tamaño, 3será 8x8, 4será 16x16 y así sucesivamente (2 ^ n). Su programa debe generar el resultado correcto para todos los tamaños desde 0 (1x1) hasta al menos 5 (32x32). Si produce alguna salida para números más altos, debe ser correcta, es decir, debe producir la salida correcta hasta cierto tamaño, pero no producirá una salida por encima de ese tamaño si fuera incorrecta. ¡Puede asumir un tamaño máximo de 15 (32768x32768) ya que ese ya es un tamaño loco para el arte ASCII (1GB)!

Un patrón de 8x8 se verá más abajo (regla 160). El dígito que se encuentra más a la izquierda será para el bloque A, el dígito del medio (sin pensamientos groseros, por favor) para el bloque By el dígito que se encuentra más a la derecha para el bloque C. Para construir el fractal, reduzca a la mitad la mitad en ambas dimensiones y aplique la regla de rotación / reflejo para el bloque. Para reducir el patrón, divídalo uniformemente en áreas de 2x2. Habrá 3 caracteres visibles o ninguno en cada área. Si hay caracteres visibles, coloque un carácter en el lugar apropiado en el bloque más pequeño; de lo contrario, coloque un espacio. Reglas 0- 3no se reflejan, reglas 4- 7se reflejan. Reglas 0y 4no se giran, 1y 5se giran 90 grados en sentido horario, 2y6se giran 180 grados 3y 7se giran 270 grados en el sentido de las agujas del reloj. Unir los tres bloques en el orden que se muestra, Aen la esquina superior izquierda, Binferior izquierda e Cinferior derecha.

 AAA    
AA A    
AA      
A       
BBB CC  
B BBC   
  BBCCC 
   B CCC

Reducido, girado y reflejado por el número de regla:

 0       1       2       3       4       5       6       7  
----    ----    ----    ----    ----    ----    ----    ----
AA       BAA    CCB        C    C        BCC    AAB       AA
A       BB A     CBB      CC    CC      BBC     A BB       A
BBC     CC         A    A BB    BB A    A         CC     CBB
 BCC    C         AA    AAB      BAA    AA         C    CCB 

Reglas:

  1. No reflejado, girado 90 grados en sentido horario
  2. No reflejado, girado 180 grados en sentido horario
  3. Sin espejo, girado 270 grados en sentido horario
  4. Reflejado pero no girado
  5. Reflejado y luego girado 90 grados en sentido horario
  6. Reflejado y luego girado 180 grados en sentido horario
  7. Reflejado y luego girado 270 grados en sentido horario
  8. Regla 0: sin espejo, sin rotación

La duplicación siempre se realiza primero y se realiza diagonalmente a través de la esquina en blanco, por ejemplo, la regla 0 frente a la regla 4:

 0       4  
----    ----
AA /    C  /
A /     CC/ 
BBC     BB A
/BCC    /BAA

Sólo reglas 1, 6y 0se utilizan en el patrón anterior, en ese orden. Después de que se hayan aplicado las transformaciones y los bloques unidos, se verá como a continuación, excepto que he separado cada bloque uno del otro en un espacio. Su código no tendrá este espacio extra. Si lo compara con la imagen "principal", verá que tiene caracteres visibles en las mismas posiciones.

 BAA
BB A
CC  
C   

AAB  AA  
A BB A   
  CC BBC 
   C  BCC

Otra forma de generar la imagen sin reducir es la siguiente: Comience con un carácter:

X

Aplica las transformaciones para cada uno de los tres bloques (ninguno ya que es solo un personaje) y une los bloques:

X
XX

Aplique las transformaciones para cada uno de los tres bloques nuevamente:

1 
--
XX
X 

6     0 
--    --
XX    X 
 X    XX

Coserlos juntos:

XX
X 
XXX 
 XXX

Aplique las transformaciones para cada uno de los tres bloques nuevamente:

 1  
----
 XXX
XX X
XX  
X   

 6       0  
----    ----
XXX     XX  
X XX    X   
  XX    XXX 
   X     XXX

Coserlos juntos:

 XXX    
XX X    
XX      
X       
XXX XX  
X XXX   
  XXXXX 
   X XXX

Puede usar cualquier carácter o caracteres imprimibles (0x21 - 0x7E) para la parte visible del patrón, pero solo el carácter de espacio (0x20) para los espacios en blanco. Se permiten espacios finales, pero no debe haber espacios en blanco fuera del cuadrado completo (es decir, para un cuadrado de 8x8 no puede haber caracteres más allá de la columna 8).

Hay 512 reglas diferentes, pero algunas de ellas producen el mismo patrón. Como nota al margen, cualquier patrón que contenga solo 0y 4produzca el triángulo de Sierpinski (8 reglas diferentes).

Opcionalmente, puede publicar su patrón favorito y la regla que lo genera. Si lo hace, asegúrese de que el tamaño sea al menos 3 (8x8) para distinguirlo de reglas similares.

CJ Dennis
fuente
@trichoplax Puede comenzar con un cuadrado completamente lleno o un cuadrado con solo 1 carácter visible en él. De cualquier manera, repetir las reglas n veces, donde n es el tamaño de entrada, garantizará los mismos resultados. Sin embargo, no tiene que generar el patrón de esta manera, solo generar el mismo patrón que hacerlo de esta manera.
CJ Dennis
@trichoplax Agradezco su aporte. ¡La forma en que veo las cosas no es necesariamente la forma en que otras personas ven las cosas y no sé si se lo estoy poniendo difícil!
CJ Dennis
2
+1 ¡Gracias, has hecho la explicación mucho más clara! En el futuro, le recomendaría que revise las cosas a través de nuestro sandbox para que las personas puedan tener una idea más clara de lo que está preguntando con anticipación. Estaré trabajando en este desafío en breve :)
BrainSteel
Sí, todos ven las cosas de manera diferente. Encantado de dar su opinión, vale la pena aclarar una buena pregunta. Se lee bien ahora.
trichoplax
@BrainSteel Gracias, lo haré! ¡He estado en SE por muchos años pero todavía soy relativamente nuevo en PCG!
CJ Dennis

Respuestas:

1

CJam, 63 57 54 52 bytes

0aarari*{\f{\~7"W%z"a*3"Wf%"t<s~}({__Ser+}%\~.++}/N*

Cómo funciona :

La idea básica es que ejecute un bucle, el segundo número de entrada de veces. En cada bucle, comenzando desde una única matriz de matriz que contiene 0( [[0]]), construimos el fractal para el siguiente paso usando las tres reglas, rellenamos el cuadrante vacío y preparamos los cuadrantes para el siguiente bucle.

0aa                           e# Starting condition, equivalent to a single A
   ra                         e# Read the rule string and wrap it in an array
     ri*                      e# Repeat the rule array, second input number of times
        { ...  }/             e# Loop for each rule in the rule array
                              e# In each loop, we will have the current fractal and
                              e# then the rule on stack
\f{\~7"W%z"a*3"Wf%"t<s~}      
\f{                    }      e# Move the rule on top of stack and for each of the rule
                              e# character, run this loop on the current fractal
   \~                         e# Move the rule char on top and convert to int by face value
     7"W%z"a*3"Wf%"t          e# This is the array which has the logic to perform the rules
                              e# ["W%z" "W%z" "W%z" "Wf%" "W%z" "W%z" "W%z"]
                    <s        e# Based on the rule number value, take that many first items
                              e# from the above array and do a toString on the array
                              e# For rule 0 through 7, you will get the following strings:
                              e# 0: "", 1: "W%z", 2: "W%zW%z", 3: "W%zW%zW%z",
                              e# 4: "W%zW%zW%zWf%", 5: "W%zW%zW%zWf%W%z",
                              e# 6: "W%zW%zW%zWf%W%zW%z", 7: "W%zW%zW%zWf%W%zW%zW%z"
                              e# This works because each W%z will rotate the block of
                              e# fractal 90 degrees in clockwise direction.
                              e# For rule 4, where we need to mirror diagonally, we first
                              e# rotate it 279 degrees clock wise and then reverse each row
                              e# of the block. The rest of the rules after 4 take that
                              e# mirroring as base and rotate 90 degrees additionally
                      ~       e# Simply evaluate the string to apply the rule.
\f{ ... }                     e# After this for each loop, we get 3 copies of the fractal
                              e# block before the for loop. Each copy gets each one of the
                              e# three rule gets applied.
         ({      }%           e# We take out the first part corresponding to the 1st
                              e# quadrant and run each row through this loop to fill the
                              e# second quadrant with spaces
           __Ser              e# Take a copy of the row and replace everything in the
                              e# copy with spaces
                +             e# Append it to the original row
                   \~         e# Bring the last two quadrant array on top and unwrap it
                     .+       e# Append corresponding rows from the 4th quadrant to 3rd
                       +      e# Append the rows from lower half to the upper half
                              e# Now we have a full block ready to be run through
                              e# the next iteration which will double its size
                          N*  e# Finally, we join the rows of final fractal block with
                              e# newlines and automatically print the result

Pruébalo en línea aquí

Optimizador
fuente
¡Muy bonito! Produce muy pocos caracteres imprimibles si el patrón comienza 0y James Bond tiene una licencia para matar. 007: IndexOutOfBoundsException
CJ Dennis
@CJDennis Hay un error con ceros a la izquierda. Corregido ahora.
Optimizador
¡Bien hecho! ¡La salida se ve perfecta ahora!
CJ Dennis