Narysuj indeksowany fraktal

14

Wprowadzenie

W tym wyzwaniu macierz 2 × 2 jest indeksowana w następujący sposób:

0 1
2 3

Definiujemy rodzinę wzorów podobnych do fraktali F(L), gdzie Lznajduje się nlista tych wskaźników i F(L)ma ona rozmiar .2n-1 × 2n-1

  • Jeśli L == [], to F(L)jest wzór 1 × 1 #.
  • Jeśli L != [], to F(L)jest zbudowany w następujący sposób. Niech Pbędzie wzorem uzyskanym Lpo usunięciu pierwszego elementu. Weź cztery siatki wielkości wypełnione kropkami i zastąp siatkę indeksowaną wzorem . Następnie sklej siatki razem za pomocą jednej warstwy haszów między nimi. Oto schematy czterech przypadków: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]
    ...#...  ...#...     #...  ...#   
    

Przykład

Rozważ dane wejściowe L = [2,0]. Zaczynamy od siatki 1 × 1 #i przesuwamy Lod prawej. Najbardziej wysunięty na prawo element to 0, więc bierzemy cztery kopie siatki 1 × 1 ., zastępujemy pierwszą #i sklejamy je haszami. Daje to siatkę 3 × 3

##.
###
.#.

Kolejnym elementem jest 2, więc bierzemy cztery kopie siatki 3 × 3 .s i zastępujemy trzecią powyższą siatką. Cztery siatki są

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

i sklejenie ich razem z #wynikami s w siatce 7 × 7

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

To jest nasz końcowy wynik.

Wejście

Twój wkład jest listą Lindeksów 0, 1, 2, 3. Możesz wziąć to jako listę liczb całkowitych lub ciąg cyfr. Pamiętaj, że może być pusty i może zawierać duplikaty. Długość Lwynosi co najwyżej 5.

Wynik

Twój wynik to wzorzec F(L)jako ciąg rozdzielany znakiem nowej linii.

Zasady i punktacja

Możesz napisać pełny program lub funkcję. wygrywa najniższa liczba bajtów, a standardowe luki są niedozwolone.

Przypadki testowe

[]
#

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

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

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

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

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

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

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

[0,0,1,2,3]
.......#...#...#...............#...............................
.......#...#...#...............#...............................
.......#...#...#...............#...............................
.......#########...............#...............................
.......#.#.#...#...............#...............................
.......#####...#...............#...............................
.......#.###...#...............#...............................
################...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
.......#.......#...............#...............................
################################...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
...............#...............#...............................
###############################################################
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
...............................#...............................
Zgarb
źródło
W twoim przykładzie, dlaczego zaczynasz od siatki 1x1 #? L !=[]w tym przykładzie, ponieważ ma 1 lub więcej elementów. Czy to znaczy, że F (L) jest zawsze# w pierwszej kolejności?
R. Kap.
2
@ R.Kap Dobra, przykład nie jest bardzo jasny. Definicja jest rekurencyjna, więc L = [2,0]odetniesz głowę i spojrzysz na wzór F([0]), a następnie odetniesz głowę [0]i spojrzysz na wzór F([]), który jest siatką 1x1 #. Następnie użyj na nim odciętego indeksu 0, aby zbudować wzór 3x3, i użyj na nim odciętego indeksu 2, aby zbudować wzór 7x7. Aby odpowiedzieć na twoje pytanie: tak, zawsze zaczynasz od siatki 1x1, ponieważ jest to podstawowy przypadek rekurencji.
Zgarb

Odpowiedzi:

6

CJam, 59 47 43 41 40 bajtów

Dzięki Sp3000 za oszczędność 1 bajtu.

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

Sprawdź to tutaj.

Wyjaśnienie

Nieco przestarzałe. Naprawię później.

Wszystkie zmiany kolejności wymiarów list 4D powodują zawroty głowy ...

Ten kod implementuje specyfikację bardzo dosłownie, używając iteracyjnego algorytmu z sekcji przykładu zamiast jego rekurencyjnej definicji. Jedną z głównych sztuczek golfowych jest to, że używam spacji zamiast #podczas obliczeń i zastępuję je tylko #na końcu, co upraszcza kod w jednym miejscu i pozwala mi używać Szamiast '#lub "#"w kilku.

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
źródło
3

MATL , 42 41 bajtów

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

Wypróbuj online!

Wyjaśnienie

Działa to iteracyjnie przy użyciu produktu Kronecker w celu rozszerzenia tablicy w każdej iteracji. Tablica jest zbudowana z 0i 1zamiast .i #, a na końcu są one zastępowane odpowiednimi znakami.

Będzie tyle iteracji, co rozmiar wejściowy. Dane wejściowe są przetwarzane od prawej do lewej. Indeks iteracji zaczyna się od 1.

Korzystając z przykładu w wyzwaniu, z [2,0]danymi wejściowymi tablica jest inicjalizowana jako

1 2
3 4

Odpowiada to początkowej 1( #) rozszerzonej o jeden wiersz i jedną kolumnę, której cel zostanie wyjaśniony później. Wartości w tych kolumnach nie są ważne, ponieważ zostaną zastąpione; mogą to być również:

1 1
1 1

Przy każdej iteracji istniejąca tablica jest mnożona przez Kroneckera przez tablicę 2 × 2 zero-jeden, która zawiera 1w pozycji wskazanej przez bieżącą pozycję wejścia, a 0przy innych pozycjach. W przykładzie z iteracją i = 1, ponieważ pozycja wejściowa najbardziej na prawo to 0tablica zero-jedynkowa

1 0
0 0

a produktem Kronecker tych dwóch tablic jest

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

Następnie wiersz i kolumna z indeksem 2^isą wypełniane jednymi:

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

Pierwsze trzy wiersze i kolumny stanowią wynik pierwszej iteracji. Tak jak poprzednio, istnieje dodatkowy wiersz i kolumna, które są przydatne do rozszerzenia tablicy w następnej iteracji.

Przy iteracji i = 2, ponieważ bieżąca wartość wejściowa zawiera 2tablicę powyżej, pomnożono przez Kroneckera

0 0
1 0

co daje

 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

Wypełnienie 2^i-tego wiersza i kolumny jedynkami daje

 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

Ponieważ jest to ostatnia iteracja, dodatkowy wiersz i kolumna są usuwane:

 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

a zmiana postaci odbywa się w celu uzyskania końcowego wyniku:

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

Szczegółowy opis kodu wygląda następująco:

'.#'      % 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
źródło
2

Haskell, 123 122 bajtów

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]

Przykład użycia:

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

Jak to działa:

                ["#"]      -- 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
źródło
1

JavaScript (ES6), 171 152 bajtów

([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

Pobiera wynik wywołania rekurencyjnego, a następnie zastępuje każdą linię samym sobą oraz skrót i ciąg kropek o tej samej długości, w razie potrzeby w odwrotnej kolejności, a następnie z tego wyniku częściowego tworzy ciąg kropek z wyjątkiem znaków nowej linii i środkowej kolumny skrótów, a także ciąg skrótów z otaczającymi znakami nowej linii, a następnie łączy te trzy ciągi razem w odpowiedniej kolejności.

Neil
źródło
1

Rubin, 143 134 bajtów

Anonimowa funkcja.

1 bajt zapisany przez przegrupowanie pierwszej linii. 6 bajtów zapisanych przez zmianę sposobu zwiększania wartości z z formuły do ​​tabeli. 2 bajty zapisane przez wyeliminowanie zmiennej 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}

Niegolfowany w programie testowym

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
źródło
0

Rubinowy, 150 bajtów

Funkcja anonimowa. Używa wywołania rekurencyjnego, aby zbudować listę ciągów, jeden ciąg w wierszu, a następnie łączy je wszystkie razem na końcu.

->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"
"}
Wartość tuszu
źródło
0

Python 3.5, 1151 bajtów:

Niewiele golfa kodowego, ale no cóż. Postaram się przycinać to z czasem, gdy będę mógł.

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])

Jest to dość naiwny sposób, ale jednak obecnie działa idealnie i, jak widać, nie używa zewnętrznych modułów / bibliotek. Dodatkowo, można go wziąć na drodze więcej niż 5 pozycji w podanej listy sbez utraty dokładności (czyli jeśli Twój sprzęt może obsłużyć). Spełnia wszystkie wymagania i nie mógłbym być bardziej zadowolony z tego, co dostałem. :)

Może teraz akceptować nie tylko dowolną liczbę w zakresie 0=>3jako dowolną z wartości, ale także dowolną liczbę , kropkę, dzięki &operatorowi bitowemu! Możesz przeczytać więcej o nich tutaj . Teraz, na przykład, [4,4,1,2,3]ponieważ lista wejściowa jest taka sama jak [0,0,1,2,3].

Uwaga: Dane wejściowe należy podać w postaci listy

Nieoznakowany z wyjaśnieniem:

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])

Szersze i znacznie bardziej atrakcyjne wizualnie wyjaśnienie:

Aby uzyskać szersze i znacznie bardziej atrakcyjne wizualnie wyjaśnienie, rozważ drugi raz przejście przez „główną” pętlę w powyższym kodzie, w którym znajduje się lista wejściowa [0,2]. W takim przypadku elementy na liście „głównej” lto:

.#.
###
##.

i

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

i lista yzawierałaby tylko 0. Korzystając ze sposobu, w jaki Python indeksuje ostatni element siatki l[-1], możemy oznaczyć skrajnie lewe elementy siatki w następujący sposób:

 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

Jaki widzisz wzór? Każdy indeks po lewej stronie siatki jest wielokrotnością liczby 8, a ponieważ przy użyciu równania 2^(n-1)-1uzyskuje się długość każdego segmentu kropek w siatce, możemy ((2^(n-1)-1)*2)+2znaleźć długość górnej krawędzi siatki jako całości (+2, aby uwzględnić środkowe #s i \nkoniec). Możemy użyć tego równania, które wywołamy, iaby znaleźć wartości indeksu każdego elementu po lewej stronie siatki o dowolnym rozmiarze, tworząc listę i dołączając do niej każdą liczbę całkowitą, którą nazwiemy _w zakresie 0=>length of grid l[-1], tak, że ten element jest wielokrotnością i, ORAZ również taki, _który NIE jest równy i*(2^(n-1)-1), abyśmy mogli wykluczyć środkowy segment#s oddzielając górną połowę od dolnej połówki. Ale chcemy WSZYSTKICH elementów kropkowych od lewej, a nie tylko elementów po lewej stronie. Cóż, jest to poprawka, a byłoby to po prostu dołączyć do listy listę zawierającą, i+hgdzie h jest każdą liczbą całkowitą w zakresie za 0=>2^(n-1)każdym razem, gdy wartość z zakresu 0=>length of grid l[-1]jest dodawana do listy, aby za każdym razem pojawiała się tyle wartości dodanych do listy, ile długość jednej ćwiartki kropek. I to jest lista a.

Ale teraz, co powiesz na kropki po prawej stronie? Spójrzmy na indeksowanie w inny sposób:

   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

Jak widać, wartości znajdujące się pośrodku to te, których potrzebujemy, ponieważ są one początkiem indeksu każdego segmentu kropek po prawej stronie siatki. Jaki jest tutaj wzór? Cóż, jeśli nie jest to wystarczająco oczywiste, teraz wszystkie środkowe wartości są wielokrotnościami i/2! Dzięki tym informacjom możemy teraz utworzyć kolejną listę, bdo której i/2dodawane są wielokrotności z zakresu, 0=>length of grid l[-1]tak że każda liczba całkowita z tego zakresu, który ponownie wywołamy _, NIE jest równa (i/2)*(p*2)wykluczeniu linii #s oddzielającej górę i dolne połówki ORAZ takie, że _ NIE jest już na liście a, ponieważ tak naprawdę nie potrzebujemy 8,16,32 itd. na liścieb. A teraz znowu nie chcemy tylko tych konkretnych indeksów. Chcemy WSZYSTKICH znaków kropek po prawej stronie siatki. Cóż, tak jak zrobiliśmy to na liście a, tutaj możemy również dodać do list blisty, _+hgdzie hjest liczba całkowita z zakresu 0=>2^(n-1).

Teraz mamy obie listy ai bzapakowane i gotowe do pracy. Jak moglibyśmy je teraz połączyć? To gdzie wymienia W, T, G, i Cprzyjść. Będą one posiadać indeksy do każdej ćwiartce określonej ilości punktów w siatce l[-1]. Na przykład, zarezerwujmy listę Wjako listę dla wszystkich indeksów równych kwadrancie 1 (indeks 0) siatki. Na tej liście dodalibyśmy wtedy pierwsze 2^(n-1)listy z listy a, ponieważ lista azawiera wszystkie indeksy kropek w lewej połowie siatki, a następnie dzieli je wszystkie, aby Wteraz zawierały (2^(n-1))*(2^(n-1))elementy. Zrobilibyśmy to samo dla listy T, ale z tą różnicą, Tże zawierałaby elementy z listy b, ponieważTjest zarezerwowany dla kwadrantu 2 (indeks 1). Lista Gbyłaby taka sama jak lista W, z tym że zawierałaby resztę elementów z listy a, a lista Cjest taka sama jak lista T, z tym że zawiera teraz resztę elementów z listy b. I to wszystko! Mamy obecnie wartości indeksu dla każdej ćwiartki zawierającej kropki w siatce, wszystkie podzielone na cztery listy odpowiadające każdej ćwiartce. Teraz możemy użyć tych 4 list (W, T, G, C), aby powiedzieć programowi, które znaki powinien zastąpić w siatce l[-1]przy każdym znaku z siatki l[0], co jest pierwszym elementem listy l. Ponieważ wartość jest 0tutaj, zastąpiłaby wszystkie kropki w pierwszej ćwiartce (indeks 0) l[0]listą wykorzystującą siatkęW.

Dlatego wreszcie mamy następujące:

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

Uff! Długi proces, prawda? Działa to jednak doskonale i znów nie mogę być szczęśliwszy. :)

R. Kap
źródło