Ваша цель - определить, находится ли данная 2D точка X в области треугольника с заданными вершинами A, B, C.
Напишите функцию, которая принимает координаты контрольной точки X и трех вершин треугольника (итого всего 8 координат) и возвращает True, если точка находится внутри этого треугольника, и False, если она находится снаружи.
Не беспокойтесь о крайних случаях. Если точка лежит на границе треугольника (ребра или вершины) или треугольник на самом деле является отрезком линии, ваш код может делать все, что угодно, включая сбой. Также не беспокойтесь о числовой стабильности или точности с плавающей точкой.
Ваш код должен быть именованной функцией. Фрагменты кода не принимаются.
Побеждает несколько персонажей.
Входные данные:
Восемь действительных чисел, представляющих координаты. Числа будут лежать в диапазоне (-1,1)
.
Точный формат ввода является гибким. Вы можете, например, взять восемь чисел, список из восьми чисел, список из четырех точек, каждой из которых присваивается кортеж, матрицу 2 * 4, четыре комплексных числа, два списка из x-координат и y-координат, и так далее.
Входные данные должны быть просто числами в некотором контейнере, без каких-либо дополнительных данных. Вы не можете использовать входные данные для выполнения какой-либо предварительной обработки, а также не можете требовать каких-либо ограничений на ввод, например, требовать, чтобы точки задавались в восходящей координате y. Ваш ввод должен позволять любые восемь координат (хотя ваш код может вести себя произвольно в случаях краев, упомянутых ранее).
Пожалуйста, укажите ваш формат ввода.
Выход:
Либо соответствующий логический True
/ False
, соответствующий номер 1
/0
, либо аналоги на вашем языке.
Контрольные примеры
Входные данные получают список [X,A,B,C]
из четырех кортежей, сначала контрольную точку, а затем три вершины треугольника. Я сгруппировал их в тех, чьи результаты должны быть True
и те, которые должны бытьFalse
.
True
экземпляры:
[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
False
экземпляры:
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]
Ответы:
Javascript / ECMAScript 6,
161159158/152Javascript:
Версия ECMAScript 6 (спасибо m.buettner, сохраняет 6 символов)
Назовите это так (возврат
true
илиfalse
):Использует некоторую причудливую барицентрическую координатную математику на основе кода из этого ответа . Ниже приведена версия для вашего чтения:
источник
(a*(l-n)+i*(g-e)+n*e-g*l)
вместо(-g*l+a*(-n+l)+i*(g-e)+n*e)
?Python 2,7
1281271171101091039995949190Моя первая попытка игры в гольф!
Код
Принимает в качестве входных данных (x, y, t) где (x, y) - точка, которую мы проверяем, а t - треугольник t = ((x1, y1), (x2, y2), (x3, y3)).
объяснение
Я рассчитываю определители матриц
Эти детерминанты представляют подписанные расстояния от сторон треугольника до точки (x, y). Если все они имеют одинаковый знак, то точка находится на одной стороне каждой линии и, следовательно, содержится в треугольнике.
В приведенном выше коде,
a*y+c*b+d*x-d*a-c*y-b*x
является определителем одной из этих матриц.Я использую тот факт, что
True+True+True==3
иFalse+False+False==0
для определения, все ли эти детерминанты имеют один и тот же знак.Я использую отрицательные индексы списка Python, используя
t[-1]
вместоt[(i+1)%3]
.Спасибо Питеру за идею использовать
s%3<1
вместо того,s in(0,3)
чтобы проверить, является ли s 0 или 3!Версия Sagemath
Не совсем другое решение, поэтому я включаю его в этот ответ, решение Sagemath с использованием 80 символов:
где
p=[x,y]
иt=[[x1,y1],[x2,y2],[x3,y3]]
источник
s in (0,3)
быть сокращено доs%3<1
?-1,0,1 ... t[i]+t[i+1]
эквивалентно0,1,2 ... t[i-1]+t[i]
in -1,0,1
прежде чем читать это. На самом деле ваш путь более читабелен, поэтому я все равно буду его использовать.sum
если вы заключите0,1,2
в скобки, в этом случае символ заменяя пробел. Причина в том, что Python допускает передачу функций без скобок в функции, но запятые в обнаженном кортеже1,2,3
путают его, потому что он пытается проанализировать их как отдельные аргументы.Mathematica, 67 байт
Функция принимает два аргумента: точку
X
и список точек{A,B,C}
, которые называются#
и#2
соответственно. Это если вы позвонитетогда вы получите
#
какX
и#2
как{A,B,C}
. (Обратите внимание, что в коде есть две другие анонимные функции -#
и#2
имеют другое значение в них.)Вот объяснение самой функции:
Обратите внимание, что эта функция будет фактически работать для любого выпуклого n-угольника, если его вершины заданы либо по часовой стрелке, либо против часовой стрелки.
источник
Det
?CJam,
66635952463432313028 символовПосле преобразования строки Unicode вычисляется следующий код ( 33 байта ):
Ожидается в
X [A B C]
качестве входных данных, где каждая точка имеет форму[double double]
. Выход 1 или 0.Попробуйте онлайн.
Большое спасибо пользователю 23233 за сохранение 6 символов (13 байт несжатого кода)!
Контрольные примеры
источник
{
и}
и рассматриваются как единое целое. Подобно кодовым блокам в C / java, за исключением того, что блоки являются первоклассными объектами и могут быть назначены переменным (таким образом определяя функции).1m<@m*
готовит 3 пары X и следующую (i+1
th) вершину треугольника.@-@@-
перемещает текущую (i
th) вершину в начало координат (и отражается, если это не так@-\@-
, но это не имеет значения).@@*@@*>
вычисляет ось Z перекрестного произведения, известного как определитель, и возвращает значение,1
если оно отрицательное.:+3%!
возвращает, являются ли они все одинаковыми, то есть все 3 являются отрицательными или неотрицательными, что означает положительное значение, за исключением крайних случаев. Я думаю, что читать CJam сложнее, чем играть в гольф.{[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T
. Используйте2m>
илиWm<
для безопасности Unicode.{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T
C - 156 байт
Входные данные представляют собой массив из 3 чисел с плавающей запятой в X, 3 поплавков в Y и отдельных x и y для контрольной точки. Бонус: обрабатывает все крайние случаи!
Адаптировано из PNPOLY.
источник
i;j;c;f(float*X,float*Y,float x,float y){for(c=i=0,j=2;i<3;)c^=(Y[i]>y)-(Y[j]>y)&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[j=i++]);return c;}
137 - проверено в javascriptPyth 1.0.5 ,
575451Определяет функцию g, которая принимает два входа: контрольную точку, а затем список вершин треугольника. Выходы
True
иFalse
. Примечание. Уничтожает ввод, в частности, b, список вершин треугольника.Попробуй это здесь . Последние несколько символов,
gvwvw
вызовите функцию с контрольным примером на следующих двух строках.На основе этого алгоритма
Объяснение:
Война CJam - Pyth продолжается!
источник
w
принимать ввод STDIN?Z
пустым набором, с которым вы накопилиZ|=
, а затем проверьте его длину, чтобы увидеть, были ли только0
или1
были замечены? В Python стратегия получилась более длинной, но, возможно, она того стоит, используя примитивы Pyth.J
6445 (42 без присвоения)Присвоение не обязательно для того, чтобы вещь была функцией, поэтому не знаете, считать это или нет. Воспользовавшись гибким вводом: я хотел бы иметь массив (1 + количество вершин) x (размерность пространства).
Надеясь набрать здесь несколько дополнительных очков ...: Это работает для любого измерения симплекса, не только для треугольников на плоскости, но также для 3-сторонней пирамиды в трехмерном пространстве и так далее. Он также работает, когда число вершин симплекса меньше (n + 1), тогда он вычисляет, находится ли проекция точки на симплекс внутри или нет.
Он преобразуется в барицентрические координаты , затем проверяет наличие отрицательных координат , указывая, что точка находится снаружи. Не возражаете, J использует _ для отрицательного
Прогон на приведенных примерах:
источник
N+1
вершинами. Например, 4-вершинная пирамида в 3-мерном пространстве или 5-вершинный симплекс в 4-мерном пространстве. Число вершин может быть меньше, чемN+1
, и в этом случае алгоритм проверяет, находится ли ортогональная проекция на гиперплоскость, в которой находится симплекс, внутри симплекса или нет (например, 2-точечный симплекс в 2-D будет проецироваться на линию и проверяться лежит ли эта проекция между конечными точками)HTML5 + JS, 13b + 146b / 141b / 114 символов
HTML:
JS (146b):
или ES6 (141b):
или ES6, зашифрованный в Unicode (114 символов):
демо: http://jsfiddle.net/xH8mV/
Обфускация Юникода сделана с помощью: http://xem.github.io/obfuscatweet/
источник
Питон (65)
Люди, кажется, закончили отправку, поэтому я опубликую свое собственное решение моего вопроса.
X
это комплексное число, представляющее контрольные точки, иL
представляет собой список из трех точек, каждая из которых представляет собой комплексное число.Сначала я объясню менее понятную версию кода;
Мы смещаем точки
A,B,C,X
так, чтобы ониX
находились в начале координат, используя преимущества встроенной сложной арифметики Python. Нам нужно проверить, содержится ли источник в выпуклой оболочкеA,B,C
. Это равносильно тому, что начало координат всегда лежит на одной стороне (слева или справа) отрезков AB, BC и AC.Сегмент
AB
имеет начало слева, если он движется против часовой стрелки менее чем на 180 градусов, чтобы добраться от А до В, и справа в противном случае. Если рассматривать углыa
,b
иc
соответствующие этим точкам, это означаетb-a < 180 degrees
(взятые углы в диапазоне от 0 до 360 градусов). Как комплексные числаangle(B/A)=angle(B)/angle(A)
. Кроме того,angle(x) < 180 degrees
именно для точки в верхней полуплоскости, которую мы проверяем черезimag(x)>0
.То, лежит ли происхождение слева от AB, выражается как
(A/B).imag>0
. Проверка, все ли они равны для каждой циклической пары,A,B,C
говорит нам,ABC
содержит ли треугольник начало координат.Теперь вернемся к полному коду игры
Мы генерируем каждую циклическую пару
(A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X)
, используя отрицательные индексы списка Python, заключающиеся в (L[-1]
=L[2]
). Чтобы проверить, что Bools - это всеTrue
(1
) или всеFalse
(0
), мы добавляем их и проверяем делимость на 3, как это делали многие решения.источник
Фортран -
232218195174Чертовски ужасно. Эта функция ужасна из-за требования, что данные передаются ей, и мы не можем предварительно обработать ее.
Уменьшение на 14 символов связано с тем, что я забыл сыграть название функции в моих тестовых прогонах. Дальнейшее уменьшение связано с неявной типизацией и забывчивостью менять имя функции. Следующие 20 символов исчезли из-за чтения в точках в виде одного массива. Полная программа
источник
logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);o=r*v-u*s;T=ALL([p*(s-v)+q*(u-r)+o,p*v-q*u,q*r-p*s]>=o);end
я попытался сократить это далее, используя операции со списками, но, к сожалению, это не сработало очень хорошо.logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);a=r*v-u*s;b=p*v-q*u;d=q*r-p*s;T=ALL([a-b-d,b,d]>=a);end
надеюсь, я не допустил ошибок в преобразованиях! Хотя, похоже, ваш исходный код не прошел все тестовые случаи.True
пример в OP дает,False
если я меняюB
иC
меняю значения, даваяTrue
исходную ориентацию.a < 0
, которая эффективно инвертирует условие, которое вы должны проверить. К сожалению, это не может быть просто исправлено путем оборачивания всего вabs
, а затем подразумеваемое состояниеb
иd
наличие того же знака, что иa
утерян. Это можно исправить, используя что-то вроде (опять же, повторное использование обозначений и предопределенных переменных из моего последнего комментария)e=a-b-d;T=ALL([a*a-b*b,a*a-d*d,a*a-e*e,a*b,a*d,a*e]>=0)
- что, вероятно, может быть более удачным.МАТЛАБ: 9!
Не много мне писать здесь
Можно назвать так:
Выход назначен переменной с именем
ans
Если бы я действительно должен был написать функцию, это может быть что-то вроде этого, возможно, может быть оптимизировано:
источник
f=@(a,b,c,d)inpolygon(a,b,c,d)
К # 218 (149?)
Вероятно, не так эффективно, как математический метод, но это забавное использование библиотек. Кстати, тоже довольно медленно.
Также воспользоваться преимуществом «Также не беспокойтесь о числовой стабильности или точности с плавающей точкой». - к несчастью,
GraphicsPath
используетint
s внутри, поэтому значение в диапазоне -1 <f <1 может иметь только три возможных значения. Поскольку значения с плавающей точкой имеют только 7 цифр, я просто умножаю их на 1e7, чтобы превратить их в целые числа. Хм, я думаю, это не совсем потеряло точность. Это также можно использовать по-другому: я, вероятно, мог бы воспользоваться игнорированием точности и просто дать «неправильный» ответ.Если мне позволено игнорировать стоимость символьной импортирующих библиотек, 149 (по крайней мере,
System.Linq
иSystem.Drawing
довольно стандартные для большинства WinForms проектов, ноSystem.Drawing.Drawing2D
может быть немного натянуто):Тестовая программа (да, это некрасиво):
источник
Хаскелл -
233127Использование перекрестных продуктов, как описано здесь :
Предыдущее решение, реализованное с использованием барицентрических координат и формул, описанных в ответе на Stack Exchange :
Обе функции
g
иh
принимают четыре пары, первая из которых - это точка, которую нужно проверить на включение, а остальные - координаты вершин треугольника.Чтобы проверить с вводом образца:
Нежелательные решения:
источник
JavaScript (ES6) 120
Непосредственно скопировано с моего ответа на этот другой вопрос
Тест в консоли FireFox / FireBug
Вывести все 1с
Вывести все 0
источник
SmileBASIC,
111100 знаковРисует треугольник и проверяет цвет пикселя в точке. Треугольник увеличен до 99999x и смещен таким образом, чтобы проверяемая точка находилась в точке (0,0) перед рисованием, чтобы минимизировать потерю точности.
источник
Intel 8087 FPU в сборе,
222220 байтДля расчета используется только аппаратное обеспечение 8087 FPU. Вот несобранная (в данном случае также не разграбленная) версия в виде MACRO (сэкономит вам 220 шестнадцатеричных байтовых кодов):
объяснение
Использует определитель для вычисления площади треугольника ABC, а затем треугольник, образованный точкой X и двумя другими точками треугольника ABC. Если площадь треугольника ABC равна сумме площадей треугольников XBC + AXC + ABX, то точка находится внутри треугольника. Результат возвращается как ZF.
Что в этом хорошего
Все математические операции и операции с плавающей запятой выполняются аппаратно с 80-битной расширенной точностью. Окончательное сравнение с плавающей запятой также выполняется аппаратно, поэтому будет очень точным.
При этом также используются все восемь регистров стека 8087 одновременно.
Что не так хорошо в этом
Поскольку точки треугольника должны быть подключены обратно в формулы несколько раз во время вычисления, необходимо, чтобы каждая переменная в памяти загружалась в регистры стека FPU по одному в правильном порядке. Хотя это может быть довольно легко смоделировано как функция как MACRO, это означает, что код расширяется каждый раз при сборке, создавая избыточный код. 41 байт был сохранен путем перемещения некоторых повторяющихся сегментов кода в PROC. Однако это делает код менее читабельным, поэтому приведенный выше листинг не содержит его (поэтому он помечен как «ungolfed»).
тесты
Вот тестовая программа, использующая IBM DOS, показывающая вывод:
Выход
источник
C 414 (было 465)
Golfed
Добавлено оригинальное объявление функции для объяснения
Переписан как именованная функция: ввод через stdin по одной в каждой строке или через одну строку через пробел.
источник
double
переопределили как,D
но вы все еще используетеdouble
в коде.Java, 149 символов
Ужасно, учитывая, что я должен написать «Математика». каждый раз. Это актуальная программа:
где a - это x точки a, b - это x точки b, c для x of c, d - это y of a, e - это y of b, f - это y of c, а x и y - x и у точки. Логическое значение k определяет, является ли оно истинным или нет.
источник
100*
?JavaScript 125/198
Если точки указаны в 8 аргументах:
Если точки представлены в двухмерном массиве:
Этот код не использует ни одной из этих причудливых математических задач. Вместо этого он использует только простую алгебраическую уловку, чтобы определить, находится ли точка внутри треугольника или нет. Формула:
который говорит, точка находится на какой стороне линии , получается путем изменения определения наклона:
Если мы проверим все 3 стороны, все 3 должны привести к некоторым числам с одним и тем же знаком только тогда, когда точка находится внутри треугольника, поскольку мы проверяем ее вокруг треугольника. Если точка находится на стороне, то один из тестов должен вернуть 0.
Тестовый код jsFiddle: http://jsfiddle.net/DerekL/zEzZU/
97 символов (не считая пробелов и табуляций) подсчитываются при конвертации в CoffeeScript:
115 символов при конвертации в ES6:
источник
d=(x,y,...)=>{...}
. В вашем случае вы можете сэкономить еще больше, используя CoffeeScript, который не требуетreturn
: pastebin.com/RVFk1D5k ... и в любом случае вы можете сохранить один байт, используя<1
вместо==0
.R, 23
Вдохновленный MATLAB ,
называется как
SDMTools::pnt.in.poly(point,triangle)
гдеpoint
вектор длины 2 иtriangle
является матрицей вершин 3x2. SDMTools доступен на CRAN.источник
Mathematica, 38 символов
Пример:
(* Правда *)
источник
C (gcc) , 108 байтов
Попробуйте онлайн!
Принимает три перекрестных продукта и возвращает,
1
если знакk̂
компонента не изменяется.источник