Mathematica, 193 183 177 173 173 169 166 bytes
Yay, matemática! Estou tramando a região que satisfaz um certo conjunto (bastante complicado) de desigualdades:
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->#]&
O uso é e[height]
, por exemplo e[100]
:
Ou e[200]
:
Você pode notar que as bordas mais nítidas são ligeiramente arredondadas. Isso ocorre porque a região só pode ser plotada amostrando os pontos no espaço, e o Mathematica não mostra cada pixel por padrão. A resolução de amostragem pode ser aumentada adicionando outra opção PlotPoints->#
(que usa uma amostra por pixel), que adiciona 14 caracteres . Eu não recomendo executá-lo com essa opção, porque aumenta significativamente o tempo de execução e mal aumenta o apelo visual além #/4
disso. Portanto, (após a aprovação do PO), ele não é incluído na pontuação.
Aqui está uma versão ligeiramente não-destruída:
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
]
);
Observe que na versão golfed, escalamos o sistema de coordenadas por um fator de 2 para evitar os .5
s, mas acontece que a contagem de caracteres é realmente idêntica.
Aqui está uma explicação de como eu elaborei a fórmula. Dividi a forma em duas regiões. Um contém o anel e as listras e é cortado à direita com a BCDE
inclinação e à esquerda com as inclinações IJ
e GH
(mais sobre isso mais tarde). O outro contém o mesmo anel, mas é simplesmente cortado na coordenada x do ponto D
. As condições para as duas regiões são combinadas com ||
, que atua como uma união definida aqui.
O anel é definido apenas como 5 < r < 6
, onde r
está a distância da origem. r²
é mais fácil trabalhar com isso ( x²+y²
), então estou usando 25 < x² + y² < 36
para obter todos os pontos no ringue.
As listras estão entre ±.5
e ±1.5
. Podemos lidar com ambas as faixas ao mesmo tempo, usando o módulo de y , para que as faixas (de comprimento infinito) apenas cumpram .5 < |y| < 1.5
. Mais uma vez, para levar a união das listras e do anel, estou apenas usando ||
.
O interessante é provavelmente como obter as "máscaras". O ponto D
tem uma coordenada x de 5 cos 40°
, então a máscara cuidando da borda inferior (combinada apenas com o anel) é justa x < 5 cos 40°
. Isso pode ser aplicado via interseção de conjunto, que se traduz &&
em lógica.
As outras máscaras são a parte realmente complicada. Primeiro, vamos pegar a inclinação de BCDE
. Podemos facilmente construir pontos C
e D
, como (0, -6)
e 5 (cos 40°, sin 40°)
, respectivamente. O vetor apontando ao longo da linha é então apenas D - C = (5 cos 40°, 5 sin 40° + 6)
. Para aplicar a máscara à direita, só preciso descobrir se existe um ponto à esquerda ou à direita dessa linha (vamos chamar o vetor de linha p
). Eu posso descobrir isso levando o vetor do C
meu ponto de interesse e projetando-o em um vetor perpendicular a p
. O sinal da projeção me dirá do lado em que o assunto está. A obtenção do vetor perpendicular é bastante simples em 2D: vire as coordenadas e inverta o sinal de uma delas. Essa é a variável d
no meu código:(-5 sin 40° - 6, 5 cos 40°)
. O vetor de C
um ponto de interesse q = (x, y)
é q - C = (x, y + 6)
. A projeção é apenas o produto escalar (ou ponto) entre q
e d
. O jeito que eu escolhi d
isso acontece para apontar para a esquerda, então eu quero d.(q-C) > 0
. Esta condição aplica a máscara à direita.
Para a máscara da mão esquerda, posso usar basicamente a mesma idéia. A inclinação é a mesma e, portanto, é d
. Eu só preciso deslocar meu ponto dos cantos inferior esquerdo das listras em vez de C
. Aquelas possuem coordenadas (-7.5, 0.5)
(faixa superior) e (-7.5, -1.5)
(faixa inferior). Portanto, isso exigiria duas regras independentes para as duas faixas. No entanto, observe que todos os pontos afetados pela máscara inferior estão na faixa inferior e, portanto, têm y negativo . E todos os pontos afetados pela máscara superior têm y positivo . Então, eu posso simplesmente mudar meu deslocamento usando o Sign[y]
que é 1
positivo e -1
negativo y
. Então meu ponto de deslocamento se torna(-7.5, -0.5 + Sign[y])
. Caso contrário, a máscara funcionará exatamente como a máscara da direita. Claro, desta vez a projeção precisa ser negativa. Então, ingênuo, seria algo assim RH-projection > 0 && LH-projection < 0
(que também é o que eu originalmente tinha no código). Mas podemos encurtar isso, porque multiplicar um número positivo e um negativo tem que dar um número negativo, então é apenas RH * LH < 0
(onde RH
e quais LH
são as respectivas projeções).
É isso aí. Juntar tudo leva à seguinte estrutura lógica:
(
(is_in_circle || is_in_stripe)
&&
is_between_left_and_right_mask
)
||
(
is_in_circle && left_of_edge
)
Só para esclarecer, as coordenadas na minha explicação se referem ao diagrama de construção dado no desafio. Como mencionado acima, meu código multiplica todos eles por 2
- eu o alterei para salvar bytes, mas a contagem de bytes é realmente idêntica e não me incomodei em reverter a alteração novamente. Também números inteiros parecem melhores.