ASCII fraktale kwadratowe afiniczne

9

Napisz najmniejszy program do tworzenia fraktalnych fraktali. Możesz użyć dowolnej metody, która według ciebie generuje takie same wyniki jak poniższe zasady. Nie musisz używać żadnych pomysłów z sugerowanych metod!

Twój program pobierze dwa dane wejściowe, pierwsze określające wzór w formacie 074złożonym z trzech cyfr od 0 do 7. Drugie wejście określi rozmiar, 3będzie 8 4x 8 , będzie 16 x 16 itd. (2 ^ n). Twój program musi wypisać poprawny wynik dla wszystkich rozmiarów od 0 (1x1) do co najmniej 5 (32x32). Jeśli produkuje jakieś dane wyjściowe dla wyższych liczb, musi być poprawne, tj. Musi produkować prawidłowe dane wyjściowe do określonego rozmiaru, ale nie produkować żadnych wyników powyżej tego rozmiaru, jeśli byłoby to błędne. Możesz założyć maksymalny rozmiar 15 (32768 x 32768), ponieważ jest to już szalony rozmiar dla grafiki ASCII (1 GB)!

Wzór 8x8 będzie wyglądał jak poniżej (reguła 160). Lewa skrajna cyfra będzie oznaczać blok A, środkowa cyfra (bez grubiańskich myśli proszę!) Dla bloku, Ba skrajna skrajna cyfra dla bloku C. Aby zbudować fraktal, zmniejsz go o połowę w obu wymiarach i zastosuj regułę obrotu / odbicia dla bloku. Aby zmniejszyć wzór, podziel go równomiernie na 2 x 2 obszary. W każdym obszarze będą albo 3 widoczne znaki, albo żaden. Jeśli są widoczne znaki, umieść znak w odpowiednim miejscu w mniejszym bloku, w przeciwnym razie umieść spację. Reguły 0- 3nie są dublowane, reguły 4- 7są dublowane. Reguły 0i 4nie są obracane 1i 5są obracane o 90 stopni zgodnie z ruchem wskazówek zegara, 2i6są obracane o 180 stopni 3i 7są obracane o 270 stopni zgodnie z ruchem wskazówek zegara. Zszyj trzy bloki razem w pokazanej kolejności, Aw lewym górnym rogu, Blewym Cdolnym rogu i prawym dolnym rogu.

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

Zmniejszony, obrócony i dublowany według numeru reguły:

 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 

Zasady:

  1. Bez odbicia, obrócone o 90 stopni zgodnie z ruchem wskazówek zegara
  2. Bez odbicia, obrócone o 180 stopni zgodnie z ruchem wskazówek zegara
  3. Bez odbicia, obrócony o 270 stopni w prawo
  4. Odbicie lustrzane, ale nie obrócone
  5. Odbicie lustrzane, a następnie obrócone o 90 stopni zgodnie z ruchem wskazówek zegara
  6. Odbicie lustrzane, a następnie obrócone o 180 stopni zgodnie z ruchem wskazówek zegara
  7. Lustrzane, a następnie Obrócone o 270 stopni w prawo
  8. Reguła 0: Nie dublowana, Nie obrócona

Odbicie lustrzane jest zawsze wykonywane jako pierwsze i odbywa się po przekątnej przez pusty narożnik, np. Reguła 0 vs reguła 4:

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

Tylko rządzi 1, 6i 0są wykorzystywane w powyższym wzorze, w tej kolejności. Po zastosowaniu transformacji i zszyciu bloków będzie to wyglądać jak poniżej, z tym wyjątkiem, że rozstawiłem każdy blok od siebie o jedną spację. W twoim kodzie nie będzie tego dodatkowego miejsca. Jeśli porównasz go do obrazu „nadrzędnego”, zobaczysz, że ma widoczne znaki w tych samych pozycjach.

 BAA
BB A
CC  
C   

AAB  AA  
A BB A   
  CC BBC 
   C  BCC

Kolejny sposób generowania obrazu bez zmniejszania jest następujący: Zacznij od jednego znaku:

X

Zastosuj transformacje dla każdego z trzech bloków (żaden, ponieważ jest to tylko jedna postać) i zszyj bloki razem:

X
XX

Zastosuj transformacje ponownie dla każdego z trzech bloków:

1 
--
XX
X 

6     0 
--    --
XX    X 
 X    XX

Połącz je razem:

XX
X 
XXX 
 XXX

Zastosuj transformacje ponownie dla każdego z trzech bloków:

 1  
----
 XXX
XX X
XX  
X   

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

Połącz je razem:

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

Możesz użyć dowolnego drukowalnego znaku lub znaków (0x21 - 0x7E) dla widocznej części wzoru, ale tylko znak spacji (0x20) dla spacji. Końcowe spacje są dozwolone, ale nie mogą być spacjami poza całym kwadratem (tzn. Dla kwadratu 8x8 nie może być żadnych znaków za kolumną 8).

Istnieje 512 różnych zasad, ale niektóre z nich wytwarzają ten sam wzór. Na marginesie, każdy wzór zawierający tylko 0i 4utworzy trójkąt Sierpińskiego (8 różnych zasad).

Możesz opcjonalnie opublikować swój ulubiony wzór i regułę, która go generuje. Jeśli tak, upewnij się, że rozmiar wynosi co najmniej 3 (8 x 8), aby odróżnić go od podobnych reguł.

CJ Dennis
źródło
@trichoplax Możesz zacząć od całkowicie wypełnionego kwadratu lub kwadratu z tylko 1 widoczną postacią. Tak czy inaczej, powtórzenie reguł n razy, gdzie n jest rozmiarem wejściowym, zagwarantuje te same wyniki. Nie musisz jednak generować wzoru w ten sposób, a jedynie wygenerować ten sam wzór, co w ten sposób.
CJ Dennis
@trichoplax Doceniam twój wkład. Sposób, w jaki widzę rzeczy, niekoniecznie jest taki, jak widzą to inni ludzie i nie wiem, czy im to utrudniam!
CJ Dennis
2
+1 Dziękujemy, wyjaśniłeś wyjaśnienie! W przyszłości poleciłbym, abyś przeprowadził przeglądanie naszej piaskownicy , aby ludzie mogli uzyskać wyraźniejszy obraz tego, o co pytasz z wyprzedzeniem. Niedługo będę pracował nad tym wyzwaniem :)
BrainSteel
Tak, wszyscy postrzegają to inaczej. Chętnie udzielimy opinii - warto wyjaśnić dobre pytanie. Teraz czyta dobrze.
trichopaks
@BrainSteel Dziękuję, zrobi! Jestem na SE od wielu lat, ale wciąż jestem stosunkowo nowy w PCG!
CJ Dennis

Odpowiedzi:

1

CJam, 63 57 54 52 bajty

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

Jak to działa :

Podstawową ideą jest to, że uruchamiasz pętlę, drugą liczbę razy. W każdej pętli, zaczynając od pojedynczej tablicy zawierającej 0( [[0]]), budujemy fraktal dla następnego kroku, stosując trzy reguły, wypełniamy pusty kwadrant i przygotowujemy kwadranty do następnej pętli.

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

Wypróbuj online tutaj

Optymalizator
źródło
Bardzo ładny! Wytwarza zbyt mało znaków do wydrukowania, jeśli wzór zaczyna się od, 0a James Bond ma licencję na zabijanie. 007: IndexOutOfBoundsException
CJ Dennis
@CJDennis Występuje błąd z wiodącymi zerami. Naprawiono teraz.
Optymalizator
Dobra robota! Wyjście wygląda teraz idealnie!
CJ Dennis