Mathematica, 193 183 177 173 169 166 bajtów
Tak, matematyka! Planuję region, który spełnia pewien (raczej skomplikowany) zestaw nierówności:
e=RegionPlot[(1<Abs@y<3||c)&&{x,y+12}.(d=2{-5Sin@40°-6,m=5Cos@40°})*{x+15,y+1-2Sign@y}.d<0||c&&x<2m/.c->100<x^2+y^2<144,{x,-15,9},{y,-12,12},Frame->0>1,ImageSize->#]&
Zastosowanie to e[height]
np . e[100]
:
Lub e[200]
:
Można zauważyć, że ostrzejsze krawędzie są lekko zaokrąglone. Wynika to z faktu, że region można wykreślić tylko poprzez próbkowanie punktów w przestrzeni, a Mathematica domyślnie nie próbkuje każdego piksela. Rozdzielczość próbkowania można zwiększyć, dodając inną opcję PlotPoints->#
(która wykorzystuje jedną próbkę na piksel), która dodaje 14 znaków . Nie polecam uruchamiania go z tą opcją, ponieważ znacznie wydłuża czas działania i ledwo zwiększa atrakcyjność wizualną #/4
. W związku z tym (po zatwierdzeniu PO) nie jest uwzględniany w partyturze.
Oto nieco niestosowana wersja:
e[height_] := (
angle = 40°;
d = {-5 Sin[angle] - 6, 5 Cos[angle]};
RegionPlot[
(Abs[y] > .5 && Abs[y] < 1.5
||
r > 25 && r < 36)
&&
{x, y + 6}.d > 0
&&
{x + 7.5, y + .5 - Sign[y]}.d < 0
||
r > 25 && r < 36 && x < 5 Cos[angle]
/. r -> x^2 + y^2
,
{x, -7.5, 4.5},
{y, -6, 6},
Frame -> False,
ImageSize -> height
]
);
Zauważ, że w wersji golfowej przeskalowałem układ współrzędnych 2 razy, aby uniknąć .5
s, ale okazuje się, że liczba znaków jest w rzeczywistości identyczna.
Oto wyjaśnienie, jak opracowałem formułę. Podzieliłem kształt na dwa regiony. Jeden zawiera pierścień i paski i jest odcięty w prawo wraz ze BCDE
zboczem, a w lewo ze zboczami IJ
i GH
(więcej na ten temat później). Drugi zawiera ten sam pierścień, ale jest po prostu odcięty na współrzędnej x punktu D
. Warunki dla dwóch regionów są łączone ||
, co działa tutaj jak ustalony związek.
Pierścień jest po prostu zdefiniowany jako 5 < r < 6
, gdzie r
jest odległość od początku. r²
jest łatwiejsze do wypracowania ( x²+y²
), więc używam, 25 < x² + y² < 36
aby uzyskać wszystkie punkty w ringu.
Paski są pomiędzy ±.5
i ±1.5
. Możemy obsłużyć oba paski w tym samym czasie, przyjmując moduł y , więc paski (o nieskończonej długości) po prostu się spełniają .5 < |y| < 1.5
. Ponownie, aby wziąć połączenie pasków i pierścienia, po prostu używam ||
.
Ciekawe jest jednak to, jak zdobyć „maski”. Punkt D
ma współrzędną x5 cos 40°
, więc maska dbająca o dolną krawędź (w połączeniu tylko z pierścieniem) jest po prostu x < 5 cos 40°
. Można to zastosować poprzez ustawienie przecięcia, co przekłada się &&
na logikę.
Inne maski są naprawdę trudną częścią. Najpierw zdobądźmy nachylenie BCDE
. Możemy łatwo konstruować punkty C
i odpowiednio D
jako (0, -6)
i 5 (cos 40°, sin 40°)
. Wektor wskazujący wzdłuż linii jest wtedy sprawiedliwy D - C = (5 cos 40°, 5 sin 40° + 6)
. Aby zastosować maskę po prawej stronie, muszę tylko dowiedzieć się, czy punkt znajduje się po lewej lub po prawej stronie tej linii (nazwijmy wektor linii p
). Mogę to rozgryźć, biorąc wektor z C
mojego interesującego miejsca i rzutując go na wektor prostopadły do p
. Znak projekcji powie mi, po której stronie jest punkt. Uzyskanie wektora prostopadłego jest dość proste w 2D: odwróć współrzędne i odwróć znak jednego z nich. To jest zmienna d
w moim kodzie:(-5 sin 40° - 6, 5 cos 40°)
. Wektor od C
do punktu zainteresowania q = (x, y)
to q - C = (x, y + 6)
. Projekcja to po prostu iloczyn skalarny (lub iloczyn skalarny) pomiędzy q
i d
. Sposób, w jaki to wybrałem d
, wskazuje na lewo, więc chcę d.(q-C) > 0
. Ten warunek dotyczy maski po prawej stronie.
W przypadku maski po lewej stronie mogę użyć zasadniczo tego samego pomysłu. Nachylenie jest takie samo i dlatego tak jest d
. Muszę tylko przesunąć punkt od lewego dolnego rogu pasków zamiast od C
. Mają one współrzędne (-7.5, 0.5)
(górny pasek) i (-7.5, -1.5)
(dolny pasek). To wymagałoby dwóch niezależnych reguł dla dwóch pasków. Należy jednak pamiętać, że wszystkie punkty dotknięte dolną maską znajdują się w dolnym pasku, a zatem mają ujemne y . Wszystkie punkty dotknięte górną maską mają dodatnie y . Więc mogę po prostu zmienić swoje przesunięcie, używając tego, Sign[y]
który jest 1
na plus i -1
na minus y
. Więc mój punkt przesunięcia staje się(-7.5, -0.5 + Sign[y])
. W przeciwnym razie maska działa tak jak maska po prawej stronie. Oczywiście tym razem projekcja musi być negatywna. Więc naiwnie to by było coś takiego RH-projection > 0 && LH-projection < 0
(co też pierwotnie miałem w kodzie). Ale możemy to skrócić, ponieważ pomnożenie liczby dodatniej i ujemnej musi dać liczbę ujemną, więc po prostu RH * LH < 0
(gdzie RH
i gdzie LH
są odpowiednie prognozy).
Otóż to. Złożenie tego wszystkiego razem prowadzi do następującej logicznej struktury:
(
(is_in_circle || is_in_stripe)
&&
is_between_left_and_right_mask
)
||
(
is_in_circle && left_of_edge
)
Dla jasności współrzędne w moim wyjaśnieniu odnoszą się do schematu konstrukcyjnego podanego w wyzwaniu. Jak wspomniano powyżej, mój kod mnoży je wszystkie przez 2
- Zmieniłem go, aby zapisać bajty, ale liczba bajtów jest w rzeczywistości identyczna i nie mogłem sobie pozwolić na ponowne cofnięcie zmiany. Także liczby całkowite wyglądają ładniej.