Generowanie zbioru Cantora oraz dywanu Sierpińskiego w C++
Napisz program, który wygeneruje i narysuje na standardowym wyjściu fraktale – Zbiór Cantora oraz Dywan Sierpińskiego.
Porównaj swoje rozwiązanie z przedstawionym w filmie.

Film dostępny pod adresem /preview/resource/RSMXwVsNT7LTP
Film nawiązujący do treści materiału: Fraktale w matematyce - zbiór Cantora, dywan Sierpińskiego.
Trójkąt Sierpińskiego w języku C++ generowany rekurencyjnie
Aby napisać algorytm pozwalający narysować na ekranie fraktalfraktal zwany trójkątem Sierpińskiego, musimy zastanowić się, w jaki sposób chcemy przechowywać tę strukturę w programie. Utworzymy dwuwymiarową tablicę, w której wielokrotnie umieścimy znaki składające się na trójkąty. Wynikiem działania programu będzie wypisanie struktury podobnej do przedstawionej niżej (różniącej się rozmiarem lub użytymi znakami):
Struktura taka może zostać utworzona za pomocą globalnej tablicy typu bool, zadeklarowanej w następujący sposób:
Wiele osób może zdziwić taka deklaracja, ale za chwilę wszystko się wyjaśni. Operator << oznacza, że dokonujemy przesunięcia bitowegoprzesunięcia bitowego. Na potrzeby bieżącego e‑materiału możemy przyjąć, że prawdziwa jest następująca zależność:
Dzięki zastosowaniu operacji przesunięcia bitowego jesteśmy w stanie obliczyć kolejne potęgi liczby 2 bez potrzeby użycia funkcji. W rezultacie możemy zadeklarować tablicę, której rozmiar zostanie obliczony w momencie kompilacji. Warto zapamiętać powyższą własność, gdyż zostanie ona wykorzystana również w dalszej części programu.
Operacja przesunięcia bitowego jest wykonywana znacznie szybciej niż potęgowanie, ponieważ wymaga tylko zmodyfikowania zapisu binarnego liczby (usunięcia n cyfr z przodu, dopisania n zer z tyłu). Potęgowanie wymaga z kolei wielokrotnego wykonywania operacji mnożenia, która jest o wiele bardziej czasochłonna (procesor wykonuje ją dłużej).
Po zadeklarowaniu tablicy globalnie, możemy przejść do realizacji głównej części programu. Napiszmy funkcję, która wypełni tablicę znakami składającymi się na trójkąt Sierpińskiego. Ponieważ chcemy wykorzystać rekurencję, funkcja musi przyjmować odpowiednie parametry. W wypadku fraktala najważniejszy jest jego stopień. Trójkąt Sierpińskiego składa się z trzech mniejszych trójkątów Sierpińskiego oraz z jednego „białego” (pustego) trójkąta w środku; potrzebnymi parametrami będą zatem współrzędne, od których tablica zostanie wypełniona kolejnym trójkątem. Przez współrzędne rozumiemy górny wierzchołek trójkąta, który rysujemy. Deklaracja funkcji może wyglądać następująco:
W każdej funkcji rekurencyjnej należy określić moment zakończenia jej działania. W rozpatrywanym przypadku będzie to etap, gdy stopień fraktala osiągnie wartość 0. Uzupełnimy wówczas pojedynczy element tablicy (zawierający opis pojedynczego elementu trójkąta) wartością true. Zapiszmy zatem warunek, dzięki któremu zostanie wykryty moment zakończenia rekurencji:
W tablicach wielowymiarowych w programowaniu zwyczajowo przyjmuje się, że pierwsza współrzędna oznacza wiersz, a druga kolumnę. Jest to sytuacja odwrotna niż w przypadku układu współrzędnych, gdzie współrzędne oznaczamy przez x oraz y. Z tego powodu w powyższym programie przyjmujemy, że y oznacza wiersz, a x kolumnę.
Obecnie funkcję można wywołać tylko z parametrem stopien = 0. W przeciwnym razie nie zostanie wykonana żadna operacja. Zastanówmy się, w jaki sposób należy uruchomić kolejne etapy rekurencji.
Musimy zlecić narysowanie trzech trójkątów Sierpińskiego (których stopień będzie o 1 mniejszy) przy użyciu odpowiednich współrzędnych tablicy, a także narysować „białą” część trójkąta wewnątrz. Współrzędne pierwszego trójkąta są oczywiste, ponieważ musimy narysować go w górnym wierzchołku, czyli w tym samym miejscu, w którym się znajdujemy. Pierwsze wywołanie kolejnej rekurencji będzie wyglądać zatem następująco:
Chcąc narysować kolejne trójkąty, musimy najpierw obliczyć ich rozmiary. Określą one przesunięcie w kierunku następnych współrzędnych. W tym celu ponownie posłużymy się przesunięciem bitowym. Wówczas możemy zlecić rysowanie kolejnych trójkątów w następujący sposób:
Teraz pozostaje już tylko wypełnić środkowy „biały” trójkąt. Można to zrobić np. za pomocą dwóch zagnieżdżonych pętli for. Pamiętajmy, że środkowy trójkąt w powstałej strukturze ma mieć rozmiar o 1 mniejszy niż pozostałe trzy trójkąty.
Należy także przygotować funkcję, która wypisze zawartość utworzonej tablicy. Znowu posłużymy się przesunięciem bitowym oraz dwiema zagnieżdżonymi pętlami for:
Po połączeniu wszystkich elementów oraz napisaniu funkcji main() otrzymujemy następujący kod:
Po uruchomieniu programu na ekranie pojawi się figura:
Taką właśnie strukturę chcieliśmy uzyskać. Można jeszcze uzupełnić funkcję wypiszTrojkat() o kolejną pętlę for dopisującą spacje (oraz dodać spacje podczas odczytywania elementów tablicy trojkat). W rezultacie powstanie lustrzane odbicie trójkąta.
Efekt działania zmodyfikowanego programu będzie następujący:
Co to znaczy, że figury są podobne? O figurach możemy powiedzieć, że są podobne, jeśli mają takie same kąty i proporcjonalne boki, które przy nich leżą.
Fraktale są samopodobne, co oznacza, że kształt całego zbioru (fraktala) jest podobny do kształtu fragmentu tego zbioru (jednego lub kilku).
Słownik
obiekt samopodobny (taki, którego poszczególne części są podobne do całości)
operacja polegająca na przesunięciu cyfr liczby zapisanej binarnie o określoną liczbę pozycji w lewo lub prawo