Mathematica, 193 183 177 173 169 166 byte
Yay, matematica! Sto tramando la regione che soddisfa un certo (piuttosto complicato) insieme di disuguaglianze:
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->#]&
L'utilizzo è e[height]
, ad esempio e[100]
:
Oppure e[200]
:
Si può notare che i bordi più nitidi sono leggermente arrotondati. Questo perché la regione può essere tracciata solo campionando i punti nello spazio e Mathematica non campiona ogni pixel per impostazione predefinita. La risoluzione di campionamento può essere aumentata aggiungendo un'altra opzione PlotPoints->#
(che utilizza un campione per pixel), che aggiunge 14 caratteri . Non consiglio di eseguirlo con quell'opzione, perché aumenta in modo significativo il runtime e aumenta a malapena l'appeal visivo oltre #/4
. Pertanto, (dopo l'approvazione dell'OP) non è incluso nel punteggio.
Ecco una versione leggermente non golfata:
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
]
);
Si noti che nella versione golfata, ho scalato il sistema di coordinate di un fattore 2 per evitare la .5
s, ma risulta che il conteggio dei personaggi è in realtà identico.
Ecco una spiegazione di come ho elaborato la formula. Ho diviso la forma in due regioni. Uno contiene l'anello e le strisce e viene tagliato a destra con l' BCDE
inclinazione ea sinistra con l' inclinazione IJ
e GH
(più avanti). L'altro contiene lo stesso anello, ma viene semplicemente tagliato alla coordinata x del punto D
. Le condizioni per le due regioni sono combinate con ||
, che qui funge da unione fissa.
L'anello è appena definito come 5 < r < 6
, dov'è r
la distanza dall'origine. r²
è più facile allenarsi ( x²+y²
), quindi sto usando 25 < x² + y² < 36
per ottenere tutti i punti sul ring.
Le strisce sono tra ±.5
e ±1.5
. Possiamo gestire entrambe le strisce contemporaneamente, prendendo il modulo di y , quindi le strisce (di lunghezza infinita) si limitano a soddisfarle .5 < |y| < 1.5
. Ancora una volta, per prendere l'unione delle strisce e dell'anello, sto solo usando ||
.
La cosa interessante è probabilmente come ottenere le "maschere" però. Il punto D
ha una coordinata x di 5 cos 40°
, quindi la maschera che si prende cura del bordo inferiore (combinato solo con l'anello) è giusta x < 5 cos 40°
. Questo può essere applicato tramite intersezione impostata che si traduce &&
in logica.
Le altre maschere sono la parte davvero difficile. Innanzitutto, prendiamo la pendenza di BCDE
. Possiamo facilmente costruire punti C
e D
, come (0, -6)
e 5 (cos 40°, sin 40°)
, rispettivamente. Il vettore che punta lungo la linea è quindi giusto D - C = (5 cos 40°, 5 sin 40° + 6)
. Per applicare la maschera a destra, ho solo bisogno di capire se un punto si trova a sinistra o a destra di quella linea (chiamiamo vettore di linea p
). Posso capirlo prendendo il vettore dal C
mio punto di interesse e proiettandolo su un vettore perpendicolare a p
. Il segno della proiezione mi dirà da che parte sta il punto. Ottenere il vettore perpendicolare è piuttosto semplice in 2D: capovolgere le coordinate e invertire il segno di una di esse. Questa è la variabile d
nel mio codice:(-5 sin 40° - 6, 5 cos 40°)
. Il vettore da C
a un punto di interesse q = (x, y)
è q - C = (x, y + 6)
. La proiezione è solo il prodotto scalare (o punto prodotto) tra q
e d
. Il modo in cui l'ho scelto d
sembra puntare a sinistra, quindi voglio d.(q-C) > 0
. Questa condizione si applica alla maschera della mano destra.
Per la maschera per la mano sinistra posso usare sostanzialmente la stessa idea. La pendenza è la stessa e quindi lo è anche d
. Devo solo scostare il mio punto dagli angoli in basso a sinistra delle strisce anziché da C
. Quelle hanno coordinate (-7.5, 0.5)
(striscia superiore) e (-7.5, -1.5)
(striscia inferiore). Quindi ciò richiederebbe due regole indipendenti per le due strisce. Tuttavia, si noti che tutti i punti interessati dalla maschera inferiore si trovano nella striscia inferiore e quindi hanno y negativo . E tutti i punti interessati dalla maschera superiore hanno y positivo . Quindi posso semplicemente cambiare il mio offset usando Sign[y]
quale è 1
positivo e -1
negativo y
. Quindi il mio punto di offset diventa(-7.5, -0.5 + Sign[y])
. Altrimenti la maschera funziona proprio come la maschera della mano destra. Naturalmente, questa volta la proiezione deve essere negativa. Quindi, ingenuamente sarebbe qualcosa del genere RH-projection > 0 && LH-projection < 0
(che è anche quello che avevo originariamente nel codice). Ma possiamo accorciare questo, perché moltiplicare un numero positivo e uno negativo deve dare un numero negativo, quindi è giusto RH * LH < 0
(dove RH
e LH
sono le rispettive proiezioni).
Questo è tutto. Mettere tutto insieme porta alla seguente struttura logica:
(
(is_in_circle || is_in_stripe)
&&
is_between_left_and_right_mask
)
||
(
is_in_circle && left_of_edge
)
Giusto per essere chiari, le coordinate nella mia spiegazione si riferiscono al diagramma di costruzione fornito nella sfida. Come accennato in precedenza, il mio codice in realtà li moltiplica tutti per 2
: l'ho modificato per salvare i byte, ma il conteggio dei byte è in realtà identico e non potrei essere disturbato a ripristinare nuovamente la modifica. Anche i numeri interi sembrano più belli.