Dibuja un fractal indexado

14

Introducción

En este desafío, una matriz 2 × 2 se indexa así:

0 1
2 3

Definimos una familia de patrones fractales F(L), donde Lhay una nlista de longitud de estos índices y F(L)tiene tamaño .2n-1 × 2n-1

  • Si L == [], entonces F(L)es el patrón 1 × 1 #.
  • Si L != [], entonces F(L)se construye de la siguiente manera. Deje Pser el patrón obtenido de Lcon el primer elemento eliminado. Tome cuatro cuadrículas de tamaño llenas de puntos y reemplace la cuadrícula indexada con el patrón . Luego, pegue las rejillas juntas usando una capa de hashes entre ellas. Aquí hay diagramas para los cuatro casos:2n-1-1 × 2n-1-1.L[0]P#

    L[0]==0  L[0]==1  L[0]==2  L[0]==3
       #...  ...#     ...#...  ...#...
    [P]#...  ...#[P]  ...#...  ...#...
       #...  ...#     ...#...  ...#...
    #######  #######  #######  #######
    ...#...  ...#...     #...  ...#   
    ...#...  ...#...  [P]#...  ...#[P]
    ...#...  ...#...     #...  ...#   
    

Ejemplo

Considere la entrada L = [2,0]. Comenzamos con la cuadrícula 1 × 1 #, y atravesamos Ldesde la derecha. El elemento más a la derecha es 0, por lo que tomamos cuatro copias de la cuadrícula 1 × 1 ., reemplazamos la primera por #y las pegamos con hashes. Esto da como resultado la cuadrícula 3 × 3

##.
###
.#.

El siguiente elemento es 2, entonces tomamos cuatro copias de la cuadrícula de 3 × 3 de .s, y reemplazamos la tercera con la cuadrícula anterior. Las cuatro cuadrículas son

...  ...  ##.  ...
...  ...  ###  ...
...  ...  .#.  ...

y pegarlos junto con #s resulta en la cuadrícula 7 × 7

...#...
...#...
...#...
#######
##.#...
####...
.#.#...

Este es nuestro resultado final.

Entrada

Su entrada es una lista Lde los índices 0, 1, 2, 3. Puede tomarlo como una lista de enteros o una cadena de dígitos. Tenga en cuenta que puede estar vacío y puede contener duplicados. El largo deL es como máximo 5.

Salida

Tu salida es el patrón F(L) como una cadena delimitada por nueva línea.

Reglas y puntaje

Puede escribir un programa completo o una función. gana el conteo de bytes más bajo y no se permiten las lagunas estándar.

Casos de prueba

[]
#

[0]
##.
###
.#.

[3]
.#.
###
.##

[2,0]
...#...
...#...
...#...
#######
##.#...
####...
.#.#...

[1,1]
...#.##
...####
...#.#.
#######
...#...
...#...
...#...

[1,2,0]
.......#...#...
.......#...#...
.......#...#...
.......########
.......###.#...
.......#####...
.......#.#.#...
###############
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......

[3,3,1]
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
###############
.......#...#...
.......#...#...
.......#...#...
.......########
.......#...#.##
.......#...####
.......#...#.#.

[0,1,2,3]
.......#...#...#...............
.......#...#...#...............
.......#...#...#...............
.......#########...............
.......#.#.#...#...............
.......#####...#...............
.......#.###...#...............
################...............
.......#.......#...............
.......#.......#...............
.......#.......#...............
.......#.......#...............
.......#.......#...............
.......#.......#...............
.......#.......#...............
###############################
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............
...............#...............

[0,0,1,2,3]
.......#...#...#...............#...............................
.......#...#...#...............#...............................
.......#...#...#...............#...............................
.......#########...............#...............................
.......#.#.#...#...............#...............................
.......#####...#...............#...............................
.......#.###...#...............#...............................
################...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
################################...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
###############################################################
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
Zgarb
fuente
En su ejemplo, ¿por qué comienza con la cuadrícula 1x1 #? L !=[]en ese ejemplo, ya que tiene 1 o más elementos. ¿Significa esto que F (L) siempre es un #al principio?
R. Kap
2
@ R.Kap Bien, el ejemplo no está muy claro. La definición es recursiva, por lo tanto L = [2,0], corta la cabeza y mira el patrón F([0]), luego corta la cabeza [0]y mira el patrón F([]), que es la cuadrícula 1x1 #. Luego, usa el índice cortado 0en él para construir el patrón 3x3, y usa el índice cortado 2en ese para construir el patrón 7x7. Para responder a su pregunta: sí, siempre comienza con la cuadrícula 1x1 ya que ese es el caso base de la recursividad.
Zgarb

Respuestas:

6

CJam, 59 47 43 41 40 bytes

Gracias a Sp3000 por guardar 1 byte.

Sal~W%{_Bff|a4*I@t2/{zSf*z}:F%F}fI3ff+N*

Pruébalo aquí.

Explicación

Ligeramente anticuado. Se arreglará más tarde.

Todos los reordenamientos de dimensiones de las listas 4D me están mareando ...

Este código implementa la especificación muy literalmente, usando el algoritmo iterativo de la sección de ejemplo en lugar de su definición recursiva. Un truco de golf importante es que estoy usando espacios en lugar de #durante el cálculo y solo los reemplazo con #al final, lo que simplifica el código en un lugar y me permite usarlo en Slugar de '#o "#"en varios.

Sa       e# Push [" "], i.e. a 1x1 grid containing only a space as the
         e# initial fractal.
l~       e# Read and evaluate input.
W%       e# Reverse the list.
{        e# For each list element, assigning the element to variable I...
  _      e#   Duplicate the grid.
  Eff|   e#   Map (OR 14) over each character in the grid, turning spaces into
         e#   periods and leaving periods unchanged.
  a4*    e#   Create an array with four copies of this cleared grid.
  I@t    e#   Replace the Ith element in this list with the previous grid.
  2/     e#   Split this array into a 2x2 grid of subgrids...
         e#   Now it's getting a bit weird... we've got 4 dimensions now, which are:
         e#    - Rows of the 2x2 meta-grid.
         e#    - Cells in each row of the 2x2 meta-grid (i.e. subgrids).
         e#    - Rows of each subgrid.
         e#    - Characters in each row of each subgrid.
  :z     e#   Transpose each outer row, i.e. swap dimensions 2 and 3.
         e#   We've now got in each row of the meta-grid, a list of pairs of
         e#   corresponding rows of the subgrids.
  Sff*   e#   Join those pairs of rows with a single space each. We're now down
         e#   to three dimensions:
         e#    - Rows of the 2x2 meta-grid.
         e#    - Rows of each 1x2 block of the meta-grid.
         e#    - Characters in each row of those blocks.
  :z     e#   Transpose the blocks, i.e. turn the 1x2 blocks into a list of
         e#   columns of their characters.
  z      e#   Transpose the outer grid, i.e. turn it into a list of pairs of
         e#   corresponding columns in the two 1x2 blocks.
  Sf*    e#   Join each pair of columns with a single space. We've now got the
         e#   new grid we're looking for, but it's a list of columns, i.e. transposed.
  z      e#   Fix that by transposing the entire grid once more.
}I
N*       e# Join the rows of the grid with linefeeds.
S'#er    e# Replace all spaces with #.
Martin Ender
fuente
3

MATL , 42 41 bytes

'.#'4:He!XIiP"Iq@=wX*1X@WZ(l5MY(]3Lt3$)Q)

Pruébalo en línea!

Explicación

Esto funciona iterativamente usando un producto Kronecker para extender la matriz en cada iteración. La matriz está construida con 0y en 1lugar de .y# , y al final se reemplazan por los caracteres apropiados.

Habrá tantas iteraciones como el tamaño de entrada. La entrada se procesa de derecha a izquierda. El índice de iteración comienza en1 .

Usando el ejemplo en el desafío, con entrada [2,0], la matriz se inicializa como

1 2
3 4

Esto corresponde al inicial 1( #) extendido por una fila y una columna, cuyo propósito se aclarará más adelante. Los valores en esas columnas no son importantes, ya que se sobrescribirán; igualmente podrían ser unos:

1 1
1 1

En cada iteración, la matriz existente se multiplica por Kronecker por una matriz 2 × 2 cero-uno que contiene 1en la posición indicada por la entrada actual de la entrada y 0en las otras entradas. En el ejemplo en la iteración i = 1, dado que la entrada de entrada más a la derecha es 0, la matriz cero-uno es

1 0
0 0

y el producto Kronecker de estas dos matrices es

 1 1 0 0
 1 1 0 0
 0 0 0 0
 0 0 0 0

A continuación, la fila y la columna con el índice 2^ise completan con unos:

 1 1 0 0
 1 1 1 1
 0 1 0 0
 0 1 0 0

Las primeras tres filas y columnas constituyen el resultado de la primera iteración. Como antes, hay una fila y una columna adicionales, que son útiles para extender la matriz en la próxima iteración.

En la iteración i = 2, dado que el valor de entrada actual contiene 2la matriz anterior, Kronecker se multiplica por

0 0
1 0

lo que da

 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 1 1 0 0 0 0 0 0
 1 1 1 1 0 0 0 0
 0 1 0 0 0 0 0 0
 0 1 0 0 0 0 0 0

Llenar la 2^ifila y la columna número con unidades da

 0 0 0 1 0 0 0 0
 0 0 0 1 0 0 0 0
 0 0 0 1 0 0 0 0
 1 1 1 1 1 1 1 1
 1 1 0 1 0 0 0 0
 1 1 1 1 0 0 0 0
 0 1 0 1 0 0 0 0
 0 1 0 1 0 0 0 0

Como esta es la última iteración, se eliminan la fila y la columna adicionales:

 0 0 0 1 0 0 0
 0 0 0 1 0 0 0
 0 0 0 1 0 0 0
 1 1 1 1 1 1 1
 1 1 0 1 0 0 0
 1 1 1 1 0 0 0
 0 1 0 1 0 0 0

y la sustitución de caracteres se realiza para producir el resultado final:

...#...
...#...
...#...
#######
##.#...
####...
.#.#...

La descripción detallada del código sigue:

'.#'      % Push this string. Will be indexed into
4:He!     % Push 2×2 array [1 2; 3 4]
XI        % Copy it into clipboard I
iP        % Input array and reverse it
"         % For each entry of the reversed input
  I       %   Push [1 2; 3 4] from clipboard I
  q       %   Subtract 1 to yield [0 1; 2 3]
  @=      %   Compare with current entry of the input. Gives 2×2 array
          %   with an entry equal to `1` and the rest `0`
  wX*     %   Swap. Kronecker product
  1       %   Push 1
  X@      %   Push iteration index, i
  W       %   Compute 2^i
  Z(      %   Write 1 into column 2^i
  l       %   Push 1
  5M      %   Push 2^i again
  Y(      %   Write 1 into row 2^i
]         % End for each
3Lt       % Push [1, -1j] (corresponding to index 1:end-1) twice
3$)       % Apply index. Removes last row and column
Q         % Add 1. Gives an array of values 1 and 2
)         % Index into initial string
Luis Mendo
fuente
2

Haskell, 123122 bytes

unlines.foldr(#)["#"]
n#p=zipWith(++)(r++h:t)$('#':)<$>u++h:s where b='.'<$p<$p;h='#'<$p;(r:s:t:u:_)=drop n$cycle[p,b,b,b]

Ejemplo de uso:

*Main> putStr $ (unlines.foldr(#)["#"]) [2,3,1]
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
.......#.......
###############
...#...#.......
...#...#.......
...#...#.......
########.......
...#.###.......
...#####.......
...#.#.#.......

Cómo funciona:

                ["#"]      -- starting with "#" 
        foldr(#)           -- fold the function # from the right into the input
unlines                    -- and join the result with newlines

n#p=                       -- helper function #
                           -- n: next index, p: fractal so far
    zipWith(++)            -- join the left and right part elementwise
       (r++h:t)            -- left part
       ('#':) <$> u++h:s   -- right part (prepend '#' to each line for vertical
                           -- separator

                           -- helper
b='.'<$p<$p                -- b is a blank square of the same size as p
h='#'<$p                   -- h is a line of '#' of the same length as p
(r:s:t:u:_)=               -- drop the first n elements of the infinite
    drop n$cycle[p,b,b,b]  --   list [p,b,b,b,p,b,b,b,p,b,b,b,...] and
                           --   assign the next 4 element to r,s,t,u.
                           --   As r,s,t,u are always inserted at the
                           --   same position in the fractal, we get the
                           --   variants by assigning different values.
nimi
fuente
1

JavaScript (ES6), 171 152 bytes

([d,...a],h=`#`,r=`replace`)=>d<4?(s=f(a)[r](/.+/g,s=>(t=s[r](/./g,`.`),d&1?t+h+s:s+h+t)),t=s[r](/.+/g,w=t+h+t),w=`
${w[r](/./g,h)}
`,d&2?t+w+s:s+w+t):h

Toma el resultado de la llamada recursiva, luego reemplaza cada línea por sí misma más un hash más una cadena de puntos de la misma longitud, en orden inverso si es necesario, luego a partir de ese resultado parcial crea una cadena de puntos a excepción de las líneas nuevas y la columna central de hashes, y también una cadena de hashes con líneas nuevas circundantes, luego une esas tres cadenas en el orden apropiado.

Neil
fuente
1

Rubí, 143 134 bytes

Una función anónima.

1 byte guardado por una reorganización de la primera línea. Se guardan 6 bytes cambiando la forma en que se incrementa z de una fórmula a una tabla. 2 bytes guardados eliminando varable w.

->a{r=-1+u=2<<a.size
s=(?.*r+$/)*r
a<<0
z=r*u/2-1
a.each{|i|r/=2
(-r..r).each{|j|s[z+j]=s[z+j*u]=?#}
z+=-r/2*[u+1,u-1,1-u,-u-1][i]}
s}

Sin golf en el programa de prueba

f=->a{
  r=w=(u=2<<a.size)-1        #w=length of line excluding newline, u=length of line including newline.
  s=(?.*w+$/)*w              #initialize string s with w rows of w dots terminated by newlines.
  z=w*u/2-1                  #z is the centre of the fractal
  a<<0                       #add a dummy value to the end of a
  a.each{|i|                 #for each element in a
    r/=2                     #r is the radius of the current iteration: ....15,7,3,1
    (-r..r).each{|j|         #for j=-r to r
      s[z+j]=s[z+j*u]=?#     #overwrite . with #, forming horizontal and vertical lines
    }
    z+=-r/2*(u+1)+           #move z to centre of upper left quarter (where it should be if i=0)
      i%2*(q=r+1)+           #move across if i=1,3
      i/2%2*q*u              #and down if i=2,3  
  }
s}                           #return string

puts $/,f[[]]

puts $/,f[[0]]

puts $/,f[[3]]

puts $/,f[[2,0]]

puts $/,f[[1,1]]

puts $/,f[[1,2,0]]

puts $/,f[[3,3,1]]

puts $/,f[[0,1,2,3]]

puts $/,f[[0,0,1,2,3]]
Level River St
fuente
0

Ruby, 150 bytes

Función anónima. Utiliza una llamada recursiva para crear una lista de cadenas, una cadena por línea, luego las une todas al final.

->i{f=->l{s=2**l.size-1;g=[[?.*s]*s]*4;m=->x,y{x.zip(y).map{|a,b|a+?#+b}}
s<1?[?#]:(g[l.shift]=f[l];m[*g[0,2]]+[?#*(2*s+1)]+m[*g[2,2]])}
f[i].join"
"}
Tinta de valor
fuente
0

Python 3.5, 1151 bytes:

No es un gran código de golf, pero bueno. Intentaré podarlo más con el tiempo donde pueda.

def x(s):
 y=[''];l=['#'];k=[' ']
 for z in s[::-1]:y.append(z)
 y=y[::-1]
 for h in range(len(y)):
  if y[-1]!='':u=(int(y.pop())&3)
  else:u=y.pop()
  if len(l)<2:k.append(u);p=((2**(len(k)-1))-1);l.append((('.'*p+'#'+'.'*p+'\n')*p)+'#'*((p*2)+1)+'\n'+(('.'*p+'#'+'.'*p+'\n')*p))
  else:
   if len(l)>2:del l[0]
   p=((2**(len(k)-1))-1);a=[[_+i for i in range(p)]for _ in range(len(l[1]))if _%((p*2)+2)==0 and _!=(((p*2)+2)*(p))];b=[[_+i for i in range(p)]for _ in range(len(l[1]))if _%(int(((p*2)+2)/2))==0 and _!=(int(((p*2)+2)/2)*((p)*2))and _ not in[g for i in a for g in i]];W=[g for i in a[:len(a)-(int(len(a)/2)):1]for g in i];B=[g for i in b[:len(b)-(int(len(b)/2)):1]for g in i];C=[g for i in a[len(a)-(int(len(a)/2)):len(a):1]for g in i];T=[g for i in b[len(b)-(int(len(b)/2)):len(b):1]for g in i];f=list(l[1])
   for i in list(''.join(l[0].split())):
    if u==0:f[W[0]]=i;del W[0]
    elif u==1:f[B[0]]=i;del B[0]
    elif u==2:f[C[0]]=i;del C[0]
    elif u==3:f[T[0]]=i;del T[0]
   del l[0];k.append(u);p=((2**(len(k)-1))-1);l.append(''.join(f));l.append((('.'*p+'#'+'.'*p+'\n')*p)+'#'*((p*2)+1)+'\n'+(('.'*p+'#'+'.'*p+'\n')*p))
 print(l[-2])

Una manera bastante ingenua de hacer esto, pero, sin embargo, actualmente funciona perfectamente y, como puede ver, no utiliza módulos / bibliotecas externas. Además, se puede tomar en forma de más de 5 artículos de la lista proporcionada ssin perder precisión (es decir, si el hardware puede manejarlo). Cumple todos los requisitos, y no podría estar más feliz con lo que obtuve. :)

¡Ahora también puede no solo aceptar cualquier número dentro del rango 0=>3como cualquiera de los valores, sino también cualquier número , punto, gracias al &operador bit a bit! Puedes leer más sobre ellos aquí . Ahora, por ejemplo, [4,4,1,2,3]ya que la lista de entrada es la misma que [0,0,1,2,3].

Nota: la entrada debe proporcionarse como una lista

Sin disculpas con la explicación:

def x(s):
 # Create 3 lists:
 # `y` is for the values of `s` (the list provided) and an empty element for the 
 # first pattern
 # `l` is reserved for the pattersn created through each item in list `y`
 # `k` is created for the value of `p` which is the main value through which the 
 # pattern is created.
 y=[''];l=['#'];k=[' ']
 # Reverse s, and then add each element from `s` to `y` 
 # (in addition to the empty element) 
 for z in s[::-1]:
     y.append(z)
 # `y` should now equal the list created, but reversed
 # If not reversed, then, if, for instance, the input is `0,1,2` and list `y` 
 # therefore contains `'',2,1,0`, the empty element will be called at the end, 
 # which is NOT what we want.
 y=y[::-1]
 # The main loop; will be iterated through the length of `y` number of times
 for h in range(len(y)):
  # Here is where each element from the end of `y` is recieved as `u` for 
  # use in the pattern in each iteration.
  # As you can also see, a bitwise operator (`&`) is used here so that 
  # ALL numbers can be accepted. Not just those in the range `0-4`.     
  # However, that will happen only if the value of y[-1] (the last elment in y) is 
  # NOT ''.
  if y[-1]!='':
      u=(int(y.pop())&3)
  else:
      u=y.pop()
  # If the length of list `l` is less than 2 
  # (which means it only contains `#`), then do the following:
  if len(l)<2:
      # Append `u` to `k`
      k.append(u)
      # Use the length of `k` as `n` in the operation `(2^(n-1)-1)` to get the 
      # length of the dot filled part of the new pattern.
      p=((2**(len(k)-1))-1)
      # Add that pattern to the list (currently empty, 
      # i.e. containing no other pattern in any other quadrant)
      l.append((('.'*p+'#'+'.'*p+'\n')*p)+'#'*((p*2)+1)+'\n'+(('.'*p+'#'+'.'*p+'\n')*p))
  # Now, if the length of l is >=2, do the following:
  else:
   # If the length of l is >2, then delete the first element in list `l` 
   # (this will happen only once, when the `#` is still the first element)
   if len(l)>2:
       del l[0]
   # Again, use the length of `k` as `n` in the operation `(2^(n-1)-1)`
   # to get the length of the dot filled part of the pattern.
   p=((2**(len(k)-1))-1)
   # Create a list with all the index values of all the dot elements on the left hand 
   # side of the grid l[-1], and the index value + i where i is every integer in 
   # the range `0-p` (this way, it will create lists within a list, each 
   # which contain `p` number of integers, which are all indexes of all the dots on 
   # the very left side of the grid) 
   a=[[_+i for i in range(p)]for _ in range(len(l[1]))if _%((p
      *2)+2)==0 and _!=(((p*2)+2)*(p))]
   # Create another list with all the index values of the dots using the same 
   # strategy as above, but this time, those in the right half of the grid. 
   b=[[_+i for i in range(p)]for _ in range(len(l[1]))if _%(int(((p*2)+2)/2))==0 
      and _!=(int(((p*2)+2)/2)*((p)*2))and _ not in[g for i in a for g in i]]
   # Create 4 lists, each containing index values specific to each of the 
   # 4 quadrants of the grid.
   # W is the list, based on A, containing all the indexes for the 1st quadrant of 
   # the grid in l[-1] containing dots (index 0 in the grid)
   W=[g for i in a[:len(a)-(int(len(a)/2)):1]for g in i]
   # B is the list, this time based on b, containing all indexes for the 2nd 
   # dot-filled quadrant of the grid l[-1] (index 1 in the grid)
   B=[g for i in b[:len(b)-(int(len(b)/2)):1]for g in i]
   # C is the list, also, like W, based on a, containg all the index values for 
   # the 3rd dot-filled quadrant of the grid in l[-1] (index 2 in the grid)
   C=[g for i in a[len(a)-(int(len(a)/2)):len(a):1]for g in i]
   # T is the final list, which, also like B, is based on b, and contains all the 
   # index values for the final (4th) dot-filled quadrant of the grid in l[-1] 
   T=[g for i in b[len(b)-(int(len(b)/2)):len(b):1]for g in i];f=list(l[1])
   # Finally, in this `for` loop, utilize all the above lists to create the new 
   # pattern, using the last two elements in list `l`, where each character of grid 
   # l[-2] (the second to last element) is added to the correct index of grid l[-1] 
   # based on the value of `u`
   for i in list(''.join(l[0].split())):
    if u==0:
        f[W[0]]=i
        del W[0]
    elif u==1:
        f[B[0]]=i
        del B[0]
    elif u==2:
        f[C[0]]=i
        del C[0]
    elif u==3:
        f[T[0]]=i
        del T[0]
   # Delete the very first element of `l`, as it is now not needed anymore
   del l[0]
   # Append `u` to list`k` at the end of the loop this time
   k.append(u)
   # Update the value of `p` with the new value of length(k)
   p=((2**(len(k)-1))-1)
   # Append the new patter created from the for-loop above to list `l`
   l.append(''.join(f))
   # Append a new, empty pattern to list `l` for use in the next iteration
   l.append((('.'*p+'#'+'.'*p+'\n')*p)+'#'*((p*2)+1)+'\n'+(('.'*p+'#'+'.'*p+'\n')*p))
 # When the above main loop is all finished, print out the second-to-last elment in 
 # list `l` as the very last element is the new, empty grid created just in case 
 # there is another iteration
 print(l[-2])

Explicación más amplia y mucho más atractiva visualmente:

Para una explicación más amplia y visualmente más atractiva, considere la segunda vez que pasa por el bucle "principal" en el código anterior, en el que se encuentra la lista de entrada [0,2]. En este caso, los elementos en la lista "principal" lserían:

.#.
###
##.

y

...#...
...#...
...#...
#######
...#...
...#...
...#...

y la lista ysolo contendría 0. Aprovechando la forma en que Python indexa el último elemento de la cuadrícula l[-1], podemos etiquetar los elementos muy a la izquierda de la cuadrícula de la siguiente manera:

 0 ...#...\n 7        
 8 ...#...\n 15
16 ...#...\n 23
   #######\n <- Ignore this as it is nothing but `#`s and a new line
32 ...#...\n 39
40 ...#...\n 47
48 ...#...\n 55

¿Qué patrón ves? Cada índice a la izquierda de la cuadrícula es un múltiplo de 8, y dado que, usando la ecuación, se 2^(n-1)-1obtiene la longitud de cada segmento de puntos en la cuadrícula, podemos hacer ((2^(n-1)-1)*2)+2para encontrar la longitud del borde superior de la cuadrícula como un todo (+2 para incluir el medio #sy \nel final). Podemos usar esa ecuación, que llamaremos ipara encontrar los valores de índice de cada elemento en el lado izquierdo de una cuadrícula de cualquier tamaño creando una lista y agregando a la lista todos los enteros, que llamaremos _, en el rango 0=>length of grid l[-1], tal que ese elemento sea un múltiplo de i, Y también tal que _NO sea igual i*(2^(n-1)-1), de modo que podamos excluir el segmento medio de#s separando la mitad superior de la mitad inferior. Pero queremos TODOS los elementos de puntos de la izquierda, y no solo los elementos del lado izquierdo. Bueno, hay una solución para eso, y eso sería simplemente agregar a la lista una lista que contiene i+hdonde h es cada número entero en el rango 0=>2^(n-1)cada vez que 0=>length of grid l[-1]se agrega un valor del rango a la lista, de modo que cada vez, habrá tantos números de valores agregados a la lista como la longitud de un cuadrante de puntos. Y esa es la lista a.

Pero ahora, ¿qué tal los puntos en la mitad derecha? Bueno, veamos la indexación de una manera diferente:

   0 ...# 4  ...\n 7        
   8 ...# 12 ...\n 15
  16 ...# 20 ...\n 23
     #######\n <- Ignore this as it is nothing but `#`s and a new line
  32 ...# 36 ...\n 39
  40 ...# 44 ...\n 47
  48 ...# 52 ...\n 55

          ^
          | 

          These are the values we are looking at now

Como puede ver, los valores ahora en el medio son los que necesitamos, ya que son el comienzo del índice de cada segmento de puntos en el lado derecho de la cuadrícula. Ahora, ¿cuál es el patrón aquí? Bueno, si aún no es lo suficientemente obvio, ¡ahora los valores medios son múltiplos de i/2! Con esa información, ahora podemos crear otra lista, ba la que i/2se agregan los múltiplos de desde el rango de 0=>length of grid l[-1]manera que cada entero de ese rango, al que llamaremos nuevamente _, NO sea igual (i/2)*(p*2)a excluir la línea de #s que separa la parte superior y mitades inferiores, Y tal que _ NO ya está en la lista a, ya que realmente no necesitamos 8,16,32, etc. en listab. Y ahora, nuevamente, no solo queremos esos índices específicos. Queremos TODOS los caracteres de punto en el lado derecho de la cuadrícula. Bueno, al igual que lo hicimos en la lista a, aquí también podemos agregar a la lista blistas de _+hdónde hestá cada número entero en el rango 0=>2^(n-1).

Ahora, tenemos ambas listas ay bempaquetadas y listas para usar. ¿Cómo los uniríamos ahora? Aquí es donde listas W, T, G, y Cvienen en. Se llevará a cabo los índices para cada cuadrante específico de puntos en la rejilla l[-1]. Por ejemplo, reservemos la lista Wcomo la lista para todos los índices iguales al cuadrante 1 (índice 0) de la cuadrícula. En esta lista, agregaríamos las primeras 2^(n-1)listas de la lista a, ya que la lista acontiene todos los índices de puntos en la mitad izquierda de la cuadrícula, y luego los dividimos todos de manera que Wahora contenga (2^(n-1))*(2^(n-1))elementos. Haremos lo mismo para la lista T, pero con la diferencia que Tcontendría elementos de la listab , ya queTestá reservado para el cuadrante 2 (índice 1). La lista Gsería igual a la lista W, excepto que contendría el resto de los elementos de la lista a, y la lista Ces la misma que la lista T, excepto que ahora contiene el resto de los elementos de la lista b. ¡Y eso es! Ahora tenemos valores de índice para cada cuadrante que contiene puntos en la cuadrícula, todos divididos en cuatro listas correspondientes a cada cuadrante. Ahora podemos usar estas 4 listas (W, T, G, C) para decirle al programa qué caracteres debe reemplazar en la cuadrícula l[-1]con cada carácter de la cuadrícula l[0], que es el primer elemento de la lista l. Como el valor está 0aquí, reemplazaría todos los puntos en el primer cuadrante (índice 0) con la l[0]lista de utilización de cuadrículaW.

Por lo tanto, finalmente tenemos lo siguiente:

.#.#...
####...
##.#...
#######
...#...
...#...
...#...

¡Uf! Proceso largo, ¿no es así? Sin embargo, funciona perfectamente y, una vez más, no podría estar más feliz. :)

R. Kap
fuente