Trójkąt Sierpińskiego to fraktal utworzony przez wzięcie trójkąta, zmniejszenie wysokości i szerokości o 1/2, utworzenie 3 kopii wynikowego trójkąta i umieszczenie ich tak, aby każdy trójkąt dotykał dwóch pozostałych w rogu. Proces ten powtarza się w kółko z powstającymi trójkątami, tworząc trójkąt Sierpińskiego, jak pokazano poniżej.
Napisz program do wygenerowania trójkąta Sierpińskiego. Możesz użyć dowolnej metody, aby wygenerować wzór, albo poprzez narysowanie rzeczywistych trójkątów, albo za pomocą losowego algorytmu do wygenerowania obrazu. Możesz rysować w pikselach, grafice ascii lub cokolwiek zechcesz, pod warunkiem, że wydruk będzie wyglądał podobnie do ostatniego obrazu pokazanego powyżej. Wygrywa niewiele postaci.
Odpowiedzi:
HTML + JavaScript, 150 znaków (patrz uwagi na 126 znaków)
Wstawiono białe znaki w celu zapewnienia czytelności i nie jest liczone.
Jego rdzeniem jest stosowanie reguły kolorowania pikseli, dla których
x & y == 0
przez warunekx&y||
, który tworzy „trójkąt prostokątny Sierpińskiego”; ix-~y/2,k-y
są transformacją współrzędnych, aby uzyskać w przybliżeniu równoboczny obraz.Mniej poprawna (HTML) wersja ma 126 znaków:
(Sposób, w jaki jest to mniej poprawne, polega na tym, że pomija
title
element i znacznik końcowycanvas
elementu, które są wymagane dla poprawnego dokumentu, nawet jeśli ich pominięcie nie zmienia interpretacji dokumentu.)Trzy postacie można uratować, eliminując
k
na korzyść stałej64
, kosztem mniejszego wyniku; Nie liczyłbym tej8
opcji, ponieważ nie ma wystarczających szczegółów.Zauważ, że rozmiar 256 lub większy wymaga atrybutów,
<canvas>
aby zwiększyć rozmiar płótna z domyślnego.źródło
<canvas id=c>
a potemc.getContext
. Skróć pętle:for(x=k=128;x--;)for(y=k;y--;)
x&y?0:
można ją zastąpićx&y||
innym fajnym rozwiązaniem.GolfScript (
4342 znaków)Wynik:
Zmień „3” na większą liczbę, aby uzyskać większy trójkąt.
źródło
Python (234)
Maksymalny golf, malutki obraz:
Wymaga
python3-cairo
.Aby uzyskać ładny duży obraz, potrzebowałem 239 znaków.
źródło
import cairo as c
może uratować ci kilka znakówMathematica - 32 znaki
Mathematica - 37 znaków
Spowoduje to utworzenie tabeli 2D 0 i 1, gdzie 1 s rysują Trójkąt Sierpińskiego.
źródło
ArrayPlot@CellularAutomaton[90, {{1}, 0}, 31]
lubMatrixPlot@CellularAutomaton[90, {{1}, 0}, 31]
.ReliefPlot@
...Python,
10186Korzysta z automatu reguły 90.
To jest dłuższe, ale ładniejsze.
Edycja: bezpośrednia gra ze strunami, pozbycie się nieprzyjemnie długiego krojenia, sprawiając, że wyjście jest ładniejsze.
Wynik:
źródło
jot
Nie jest to idealne, ponieważ trójkąt jest przekrzywiony, a po nim mnóstwo białych znaków - ale mimo to ciekawe.
Wynik:
Szybkie wyjaśnienie:
Czasownik
(,~,.~)
tutaj wykonuje pracę. Jest to haczyk, który najpierw zszywa,.
argument do siebie (o
->oo
), a następnie dołącza oryginalny argument do wyniku:staje się
Ten czasownik powtarza się 6 razy,
^:6
a wynik każdej iteracji staje się wejściem następnej iteracji. Więcstaje się
który z kolei staje się
itd. Następnie użyłem skośnego przysłówka na append,
,/.
aby odczytać rzędy po przekątnej, aby wyprostować (ish) trójkąt. Jak podkreśla randomra , nie musiałem tego robić . Mógłbym właśnie odwrócić|.
los, aby uzyskać ten sam wynik. Co więcej, mógłbym po prostu(,,.~)^:6,'o'
całkowicie zapisać krok wstecz.Ach, żyjesz i uczysz się. :-)
źródło
|.(,~,.~)^:6,'o'
jest krótszy i bez dodatkowych spacji. A(,~,.~)^:6,1
także zapewnia przyzwoity wkład w zaledwie 12 znaków!APL (51)
Wyjaśnienie:
A←67⍴0
: A jest wektorem 67 zerA[34]←1
: 34. element to 1{...}A
: zaczynając od A, wykonaj:~⊃⍵:
: jeśli pierwszy element bieżącego wiersza ma wartość zero⍵,∇
: dodaj bieżący wiersz do odpowiedzi i powtórz z:(1⌽⍵)≠¯1⌽⍵
: wektor, w którym każdy element jest XOR jego sąsiadów w poprzedniej generacji⋄⍬
: w przeciwnym razie skończymy32 67⍴
: sformatuj to w macierzy 67x321+
: dodaj jeden, aby wybrać odpowiednią wartość z tablicy znaków' ○'[
...]
: wyprowadza spację (nie jest częścią trójkąta) lub okrąg (gdy jest częścią trójkąta)Wynik:
źródło
Haskell (291)
Nie jestem zbyt dobry w golfowym haskellu.
Dane wyjściowe
solve 4
to:źródło
QBasic 151 znaków
Jako przykład, oto jak można to zrobić w QBasic.
źródło
Python (42)
Początkowo chciałem opublikować kilka sugestii dotyczących rozwiązania boothbys (który faktycznie stosuje regułę 18 :), ale nie miałem wystarczającej reputacji, aby komentować, więc znalazłem inną odpowiedź. Ponieważ zmienił podejście, dodałem wyjaśnienia. Moje sugestie byłyby następujące:
co doprowadziłoby do następującego kodu (93 znaki):
Ale zoptymalizowałem dalej, najpierw używając longinta zamiast tablicy liczb całkowitych i po prostu drukując reprezentację binarną (75 znaków):
I na koniec, drukując reprezentację ósemkową, która jest już obsługiwana przez interpolację printf (42 znaki):
Wszystkie wydrukują:
Oczywiście istnieje również rozwiązanie graficzne (131 znaków):
:RE
źródło
x=8**31;exec"print'%o'%x;x^=x/8;"*32
8086 Kod maszynowy - 30 bajtów.
UWAGA: To nie jest mój kod i nie należy go akceptować jako odpowiedzi . Znalazłem to podczas pracy nad innym problemem CG w celu emulacji procesora 8086 . Dołączony plik tekstowy napisał David Stafford , ale to najlepsze, co mogłem wymyślić.
Publikuję to, ponieważ jest sprytne, krótkie i pomyślałem, że chciałbyś to zobaczyć.
Wykorzystuje nakładające się kody, aby spakować więcej instrukcji na mniejszej przestrzeni. Niezwykle sprytny. Oto kod maszynowy:
Prosty dekod wygląda następująco:
Po uruchomieniu, gdy nastąpi skok o wartości 0x0115, zauważ, że przeskakuje z powrotem do 0x010C, w sam środek poprzedniej instrukcji:
Znakomity! Mam nadzieję, że nie macie nic przeciwko, żebym to udostępnił. Wiem, że nie jest to odpowiedź sama w sobie, ale interesuje ją wyzwanie.
Oto jest w akcji:
źródło
C
12711911610865Ten wykorzystuje sztuczkę z odpowiedzi HTML
^ i & j
, aby uzyskać ładny wydruk, zajęłoby 1 znak więcej (możesz uzyskać naprawdę brzydki wynik, poświęcając goa^
).Żeby było całkiem obrócić
(32^i&j)
się(32|!(i&j))
i obrócić go od++i<a
celu++i<=a
. Jednak marnowanie znaków na wygląd wydaje mi się niemiłe.Brzydka wydajność:
Właściwie to podoba mi się jak to wygląda. Ale jeśli nalegasz, aby była ładna, możesz zadokować cztery znaki. Ładna wydajność:
Pozostawiając starszą wersję 108 znaków, automatów komórkowych.
Więc nie sądzę, że skracam to znacznie, więc wyjaśnię kod.Wyjaśnię to wyjaśnienie, ponieważ niektóre sztuczki mogą być przydatne.Niektóre dane wyjściowe
źródło
Kod 80x86 / MsDos - 10 bajtów
Jako sizecoder specjalizujący się w bardzo małych wejściach na MsDos udało mi się wymyślić program, który zajmuje tylko 10 bajtów.
w hex:
w asm:
Pierwsza kodowana przeze mnie wersja to „Colpinski”, która ma rozmiar 16 bajtów, a nawet interaktywna w sposób umożliwiający zmianę koloru za pomocą klawiatury i myszy. Razem z „Frag” - innym sizecoderem - obniżyliśmy ten rozmiar do 13 bajtów, pozwalając na 10-bajtowy program, który zawiera tylko podstawową procedurę.
To staje się trochę bardziej interesujące, gdy rzeczy są animowane, więc wspomnę o innej wersji, Zoompinski 64 - próbując naśladować dokładne zachowanie „Zoompinski C64” w 512 bajtach - również dla MsDos, 64 bajty wielkości, jak sugeruje nazwa.
Możliwe jest zoptymalizowanie tego dalszego downto do 31 bajtów, jednocześnie tracąc elegancję, kolory i symetrię (źródło i plik wykonywalny dostępne za linkiem powyżej)
Pobierz oryginał i skomentuj „Pouet”
źródło
PostScript, 120 znaków
Wyjście Ghostscript:
To rysuje rysunek poprzez rekurencyjne potrojenie tego, co już zostało narysowane.
Pierwszym krokiem jest narysowanie linii. Linia jest zapisywana jako ścieżka użytkownika, następnie ścieżka użytkownika jest dodawana jeszcze dwa razy po każdym obrocie o 120 stopni.
[2 0 0 2 7 4]concat
przesuwa „punkt obrotu” na środek następnego dużego białego „trójkąta środkowego”, który ma być ujęty w replikacje trójkąta, który już mamy. Wracamy do kroku 1 (tworzenie wzniesienia potrojonego przez obrót).Liczba iteracji jest kontrolowana przez pierwszą liczbę w wierszu 3.
źródło
J (9 znaków)
Łatwo najbrzydszy, naprawdę musisz zmrużyć oczy, aby zobaczyć wynik;)
produkuje dane wyjściowe
oczywiście możesz to wyświetlić graficznie:
źródło
APL,
3732 (2823)Trójkąt pionowy (
3732 znaków)Wyjaśnienie
1 2⍴'/\'
: Utwórz macierz znaków 1 × 2/\
{((-1⌷⍴⍵)⌽⍵,∊⍵)⍪⍵,⍵}
: Funkcja wypełniająca spacje prawym argumentem po obu stronach spacjami, aby utworzyć matrycę podwójnie szeroką, a następnie laminuje sam argument podwojony na dole.Np. Stałby
/\
się⍣⎕
: Ponów funkcję (wprowadzane przez użytkownika) razy.Przykładowe dane wyjściowe
Skośny trójkąt (
2823 znaków)Wyjaśnienie
1 1⍴'○'
: Utwórz macierz znaków 1 × 1○
{(⍵,∊⍵)⍪⍵,⍵}
: Funkcja wypełniająca spacje prawym argumentem spacjami, aby utworzyć matrycę podwójnie szeroką, a następnie laminuje sam argument podwojony na dole.Np. Stałby
○
się⍣⎕
: Ponów funkcję (wprowadzane przez użytkownika) razy.Przykładowe dane wyjściowe
źródło
Python (75)
Jestem spóźniona na przyjęcie o dwa lata, ale jestem zaskoczona, że nikt jeszcze nie przyjął takiego podejścia
Używa produktu Kronecker do zastąpienia macierzy wieloma jej kopiami.
Mógłbym zapisać dwa znaki, używając
x=kron(x,x);x=kron(x,x)
linii trzeciej, aby uzyskać obraz 16 x 16 pikseli z trzema widocznymi poziomami lub dodać kolejny znak do iteratora i uzyskać obraz 2 ^ 16 x 2 ^ 16 = 4,3 gigapiksela i 15 poziomów trójkąta.źródło
Logo, 75 znaków
59 znaków dla pierwszej funkcji, druga wywołuje pierwszą z rozmiarem i głębokością / liczbą iteracji. Możesz więc po prostu wywołać pierwszą funkcję z interpretera za pomocą polecenia: e 99 5 lub dowolnego rozmiaru, który chcesz wyprowadzić
źródło
to f
iend
wokółe 99 5
, masz kompletny program, który można uruchomić w mniejszej liczbie znaków. Ponadto w UCBLogo (choć nie w innych wersjach) możesz stracić dwukropki na zmiennych, aby zapisać więcej znaków.Matlab 56
źródło
J (18 znaków)
Wynik
źródło
Python (90 znaków)
Wypróbuj online
Narysuj linię fraktalną wypełniającą Trójkąt Sierpińskiego
źródło
ht();speed(0);up();goto(20-window_width()/2, 20-window_height()/2);down()
po imporcie. Spowoduje to uruchomienie go znacznie szybciej i upewni się, że dane wyjściowe mieszczą się na płótnie.Mathematica 67
Mathematica 92
źródło
Mathematica , 29 bajtów
Czworościan Sierpińskiego można narysować w podobny sposób:
źródło
J ,
3735 bajtów-2 bajty dzięki FrownyFrog
Wypróbuj online!
To jest ascii artystyczna wersja Petera Taylora przekonwertowana na J. Mógłby zapisać bajty z mniej ładną wersją, ale dlaczego?
źródło
@]^:[
->@[&0
i' /\ '
->' /\'
&0
udokumentowano sztuczkę?,~
dookoła.Skrypt Lua w Golly , 54 bajty
Golly to symulator automatów komórkowych z obsługą skryptów Lua i Python.
Ten skrypt ustawia regułę na regułę 60 Wolfram, ustawia komórkę na (0,0) na 1 i wykonuje 512 kroków.
źródło
Postscriptum,
205203Przepisywanie przy użyciu łańcuchów i rekurencji kończy się dokładnie w tej samej liczbie. Jednak ograniczenia dotyczące makro-podejścia zostały przezwyciężone.
Edycja:
fill
jest krótsza niżstroke
.Wcięte i skomentowane.
Dodanie
0 setlinewidth
daje lepsze wyobrażenie o głębokości tego.źródło
APL (Dyalog Classic) , 12 bajtów
Wypróbuj online!
źródło
Asymptote, 152 bajty
Dodam to, głównie dlatego, że nie widziałem mniej więcej odpowiedzi w asymptocie na tej stronie. Kilka zmarnowanych bajtów na ładne formatowanie i ogólność, ale mogę z tym żyć. Zmiana A, B i C zmieni się tam, gdzie są narożniki trójkąta zawierającego, ale prawdopodobnie nie w taki sposób, jak myślisz. Zwiększ liczbę w nierówności, aby zwiększyć głębokość.
lub bez golfa i czytelne
Tak więc asymptota jest zgrabnym językiem grafiki wektorowej z nieco podobną do C składnią. Całkiem przydatne w przypadku nieco technicznych diagramów. Dane wyjściowe mają oczywiście domyślnie format wektorowy (eps, pdf, svg), ale można je przekonwertować na właściwie wszystko, co obsługuje imagemagick. Wynik:
źródło
Haskell ,
166154 bajtów(-12 bajtów dzięki Laikoni, (zapis zip i listy zamiast zipWith i lambda, lepszy sposób generowania pierwszego wiersza))
Wypróbuj online!
Wyjaśnienie:
Funkcja
i#n
rysuje trójkąt ASCII wysokości2^n
poi
krokach iteracji.Zastosowane kodowanie koduje wewnętrznie puste pozycje jako
1
i pełne pozycje jako0
. W związku z tym, pierwsza linia trójkąta jest zakodowany jako[1,1,1..0..1,1,1]
z2^n-1
tych po obu stronach zera. Aby zbudować tę listę, zaczynamy od listyx=1<$[2..2^n]
, tj. Listy[2..2^n]
ze wszystkim, na co mapowane1
. Następnie tworzymy pełną listę jakox++0:x
Operator
k!p
(szczegółowe wyjaśnienie poniżej), podany indeks liniik
i odpowiadająca mup
generuje nieskończoną listę kolejnych liniip
. Wzywamy go za pomocą1
i linii początkowej opisanej powyżej, aby uzyskać cały trójkąt, a następnie wziąć tylko pierwsze2^n
linie. Następnie po prostu drukujemy każdą linię, zastępując1
ją spacją i0
znakiemM
(uzyskując dostęp do listy"M "
w lokalizacji0
lub1
).Operator
k!p
definiuje się w następujący sposób:Po pierwsze, możemy wygenerować trzy wersje
p
:1:p
co jestp
z1
poprzedzany,p
sam itail p++[1]
co jest wszystko, ale pierwszy elementp
, z1
dołączone. Następnie spakowujemy te trzy listy, dając nam skutecznie wszystkie elementyp
z ich lewym i prawym sąsiadem, as(l,m,r)
. Używamy rozumienia listy, aby następnie obliczyć odpowiednią wartość w nowym wierszu:Aby zrozumieć to wyrażenie, musimy zdać sobie sprawę z tego, że należy wziąć pod uwagę dwa podstawowe przypadki: albo po prostu rozszerzamy poprzednią linię, albo jesteśmy w punkcie, w którym zaczyna się puste miejsce w trójkącie. W pierwszym przypadku mamy wypełnione miejsce, jeśli któreś z miejsc w okolicy jest wypełnione. Można to obliczyć jako
m*l*r
; jeśli którykolwiek z tych trzech jest równy zero, to nowa wartość wynosi zero. Drugi przypadek jest nieco trudniejszy. W zasadzie potrzebujemy wykrywania krawędzi. Poniższa tabela podaje osiem możliwych sąsiedztw z wynikową wartością w nowym wierszu:Prosta formuła umożliwiająca uzyskanie tej tabeli byłaby
1-m*r*(1-l)-m*l*(1-r)
prostszam*(2*l*r-l-r)+1
. Teraz musimy wybrać między tymi dwoma przypadkami, w których używamy numeru liniik
. Jeślimod k (2^(n-i)) == 0
musimy użyć drugiego przypadku, w przeciwnym razie użyjemy pierwszego przypadku. Terminem0^(mod k(2^n-i))
jest zatem,0
jeśli musimy użyć pierwszego przypadku i1
jeśli musimy użyć drugiego przypadku. W rezultacie możemy użyćw sumie - jeśli użyjemy pierwszego przypadku, po prostu otrzymamy
m*l*r
, podczas gdy w drugim przypadku zostanie dodany dodatkowy termin, który daje sumę całkowitąm*(2*l*r-l-r)+1
.źródło
C, 106 znaków
(Wciąż mnie to bawi, że
puts("")
jest to najkrótszy sposób na wygenerowanie nowego wiersza w C.)Należy pamiętać, że można tworzyć większe (lub mniejsze) uszczelki zastępując
32
w tegofor
testu pętli jest z większej (mniejszej) moc dwóch, tak długo, jak również wymienić33
w środku malowniczegoprintf()
z power-of-two-Plus- jeden.źródło