Mathematica, 193 183 177 173 169 166 байт
Ух, математика! Я строю область, которая удовлетворяет определенному (довольно сложному) набору неравенств:
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->#]&
Использование e[height]
, например e[100]
:
Или e[200]
:
Вы можете заметить, что острые края слегка закруглены. Это потому, что область может быть построена только путем выборки точек в пространстве, и Mathematica не выбирает каждый пиксель по умолчанию. Разрешение выборки можно увеличить, добавив еще одну опцию PlotPoints->#
(которая использует одну выборку на пиксель), которая добавляет 14 символов . Я не рекомендую запускать его с этим параметром, потому что он значительно увеличивает время выполнения и едва увеличивает визуальную привлекательность за пределами #/4
или около того. Следовательно, (после утверждения ОП) он не включается в оценку.
Вот немного неутешительная версия:
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
]
);
Обратите внимание, что в версии для гольфа я масштабировал систему координат в 2 раза, чтобы избежать .5
s, но оказывается, что количество символов фактически идентично.
Вот объяснение того, как я разработал формулу. Я разделил форму на две области. Один из них содержит кольцо и полосы и отрезают вправо с BCDE
наклоном и влево с IJ
и GH
наклоны (об этом позже). Другой содержит то же кольцо, но просто обрезается по координате х точки D
. Условия для двух регионов объединяются ||
, что действует здесь как единый союз.
Кольцо просто определяется как 5 < r < 6
, где r
расстояние от начала координат. r²
Легче понять, хотя ( x²+y²
), поэтому я использую, 25 < x² + y² < 36
чтобы получить все очки на ринге.
Полосы между ±.5
и ±1.5
. Мы можем обрабатывать обе полосы одновременно, беря модуль y , поэтому полосы (бесконечной длины) просто выполняются .5 < |y| < 1.5
. Опять же, чтобы взять союз полос и кольца, я просто использую ||
.
Интересно, наверное, как получить «маски», хотя. Точка D
имеет координату х5 cos 40°
, поэтому маска, заботящаяся о нижнем крае (в сочетании только с кольцом), является просто x < 5 cos 40°
. Это может быть применено через набор пересечений, который переводится &&
в логику.
Другие маски - действительно сложная часть. Во-первых, давайте получим наклон BCDE
. Мы можем легко построить точки C
и D
, как (0, -6)
и 5 (cos 40°, sin 40°)
, соответственно. Вектор, указывающий вдоль линии, тогда просто D - C = (5 cos 40°, 5 sin 40° + 6)
. Чтобы применить маску справа, мне нужно только выяснить, находится ли точка слева или справа от этой линии (давайте назовем вектор линии p
). Я могу понять это, взяв вектор из C
моей точки интереса и спроецировав его на вектор, перпендикулярный к p
. Знак проекции скажет мне ту сторону, на которой находится точка. Получить перпендикулярный вектор в 2D довольно просто: переверните координаты и поменяйте местами знак одного из них. Это переменная d
в моем коде:(-5 sin 40° - 6, 5 cos 40°)
, Вектор от C
точки интереса q = (x, y)
есть q - C = (x, y + 6)
. Проекция - это просто скалярное произведение (или точечное произведение) между q
и d
. То, как я d
его выбрал , указывает на левую сторону, поэтому я хочу d.(q-C) > 0
. Это условие применяет маску правой руки.
Для левой маски я могу использовать в основном ту же идею. Наклон такой же, а значит и так d
. Мне просто нужно сместить мою точку от нижних левых углов полос, а не от C
. Те имеют координаты (-7.5, 0.5)
(верхняя полоса) и (-7.5, -1.5)
(нижняя полоса). Так что это потребовало бы двух независимых правил для двух полос. Однако обратите внимание, что все точки, затронутые нижней маской, находятся в нижней полосе и, следовательно, имеют отрицательный у . И все точки, на которые влияет верхняя маска, имеют положительный у . Так что я могу просто переключить мое смещение с помощью Sign[y]
которых является 1
для положительных и -1
для отрицательных y
. Так что моя точка смещения становится(-7.5, -0.5 + Sign[y])
, В противном случае маска работает так же, как правая маска. Конечно, на этот раз прогноз должен быть отрицательным. Итак, наивно это было бы что-то вроде RH-projection > 0 && LH-projection < 0
(что также было у меня изначально в коде). Но мы можем сократить это, потому что умножение положительного и отрицательного числа должно дать отрицательное число, так что это просто RH * LH < 0
(где RH
и LH
соответствующие прогнозы).
Вот и все. Объединение всего этого приводит к следующей логической структуре:
(
(is_in_circle || is_in_stripe)
&&
is_between_left_and_right_mask
)
||
(
is_in_circle && left_of_edge
)
Просто чтобы прояснить, координаты в моем объяснении относятся к диаграмме построения, приведенной в задании. Как упомянуто выше, мой код фактически умножает их все на 2
- я изменил его, чтобы сохранить байты, но количество байтов фактически идентично, и я не мог потрудиться отменить изменение снова. Также целые числа выглядят лучше.