Фон
Выпуклая оболочка конечного числа точек является наименьшим выпуклым многоугольником , который содержит все точки, либо в качестве вершин или на внутренней. Для получения дополнительной информации см. Этот вопрос о PGM, который очень хорошо его определяет .
вход
N+1
N >= 3
Через 2-D координаты ( ) STDIN
(с другими обычными входами для гольфа тоже разрешены) в следующем формате (количество десятичных знаков может варьироваться, но можно предположить, что оно остается «разумным», и каждое число может быть представлено как число с плавающей точкой):
0.00;0.00000
1;0.00
0.000;1.0000
-1.00;1.000000
Вывод
Истинное значение, напечатанное в STDOUT
(или эквивалентное), если первая точка в списке ( (0.00;0.00000)
в примере выше) находится в выпуклой оболочке других N точек, и ложное значение в противном случае.
Это код-гольф , поэтому выигрывает самое короткое решение в байтах.
Граничные случаи : вы можете вернуть любое значение (но не потерпите крах), если точка лежит на границе выпуклой оболочки (т. Е. На стороне или на вершине на внешней границе корпуса), так как это нулевая вероятность событие (при любой разумной вероятности).
Запрещено : все (язык, оператор, структура данных, встроенный или пакет), которое существует только для решения геометрических задач (например, ConvexHull Mathematica ). Допускаются математические инструменты общего назначения (векторы, матрицы, комплексные числа и т. Д.).
тесты
- Должен вернуться
TRUE
: spiralTest1-TRUE , squareTest1-TRUE - Должен вернуться
FALSE
: spiralTest2-FALSE , squareTest2-FALSE
sort
илиround
. Я думаю, что яснее просто сказать, что ничего специально сделанного для геометрии не допускается. Что же делать с функцией добавления двух списков в качестве векторов? Или функция, чтобы найти аргумент (угол) комплексного числа?Ответы:
J,
403934 байтаАнонимная двоичная функция, принимающая точку p в качестве одного из своих аргументов и список точек P в качестве другого аргумента (не имеет значения, какой аргумент является каким), и возвращающая
0
или1
, если p находится вне или внутри выпуклой оболочки Р , соответственно. Точка p и точки в P принимаются за комплексные числа.пример
или...
Python 2, функция,
121103, полная программа,162Python 3, 149 байт
Принимает ввод в том же формате, что и исходное сообщение, через STDIN и печатает логическое значение, указывающее, находится ли p в выпуклой оболочке P
объяснение
Программа проверяет, составляет ли разница между максимальным и минимальным (знаковыми) углами между любой точкой r в P , p и фиксированной произвольной точкой q в P (мы просто используем первую точку в P ) менее 180 °. Другими словами, он проверяет, содержатся ли все точки в P под углом 180 ° или меньше вокруг p . p находится в выпуклой оболочке P тогда и только тогда, когда это условие ложно.
Ценой еще нескольких байтов мы можем использовать аналогичный метод, который не требует от нас явного вычисления углов: обратите внимание, что вышеприведенное условие эквивалентно утверждению, что p находится вне выпуклой оболочки P, если и только если он существует прямая от l до p , так что все точки в P находятся на одной стороне от l . Если такая линия существует, то есть также такая линия, которая инцидентна одной (или более) из точек в P (мы можем вращать l, пока она не коснется одной из точек в P ).
Для того, чтобы (предварительно) найти эту линию, мы начнем, позволяя л быть прямой , проходящей через р и первая точка P . Затем мы перебираем остальные точки в P ; если одна из точек находится слева от l (мы предполагаем, что некоторая направленность повсеместно, влево или вправо не имеет значения), мы заменяем l на линию, проходящую через p и эту точку, и продолжаем. После того, как мы итерировали по всей P , если (и только если) p находится вне выпуклой оболочки, то все точки в P должны быть справа от (или на) l . Мы проверяем это, используя второй проход по точкам в P,
Python 2, 172 байта
В качестве альтернативы, чтобы сделать то же самое за один проход, пусть слева-от- другого будет реальность между любыми двумя точками q и r в P , так что q слева от r, если q слева линии, проходящей через р и р . Обратите внимание , что к-влево от является отношение порядка P тогда и только тогда , когда все точки Р находятся на одной и той же стороны некоторой линии , проходящей через р , то есть, если р находится вне выпуклой оболочки P . Процедура, описанная выше, находит минимальную точку в PWRT этот порядок, то есть «крайний левый» точку P . Вместо того, чтобы выполнить два прохода, мы можем найти максимум (т. Е. «Самую правую» точку), а также минимум, точки в P по одному и тому же порядку за один проход, и убедиться, что минимум находится слева от максимум, т. е. фактически то, что слева от является переходным.
Это будет хорошо работать, если p находится за пределами выпуклой оболочки P , и тогда слева направо на самом деле является отношение порядка, но оно может нарушиться, когда p находится внутри выпуклой оболочки (например, попытайтесь выяснить, что будет произойдет, если мы запустим этот алгоритм, где точки в P - это вершины правильного пятиугольника, бегущего против часовой стрелки, а p - его центр.) Чтобы приспособиться, мы немного изменим алгоритм: мы выбираем точку q в P и делим пополам P вдоль линии, проходящей через p и q (т.е. мы разбиваем P вокруг qпо левому краю.) Теперь у нас есть «левая часть» и «правая часть» P , каждая из которых содержится в полуплоскости, так что слева направо есть отношение порядка на каждой; мы находим минимум левой части и максимум правой части и сравниваем их, как описано выше. Конечно, нам не нужно физически делить пополам P , мы можем просто классифицировать каждую точку в P, поскольку мы ищем минимум и максимум, за один проход.
Python 2, 194 байта
источник
Октава,
8272 байтаИдея состоит в том, чтобы проверить, имеет ли решение линейная программа min {c'x: Ax = b, e'x = 1, x> = 0}, где e - вектор всех единиц, столбцы A - координаты облако точек, а b - контрольная точка, а c - произвольная. Другими словами, мы пытаемся представить b как выпуклую комбинацию столбцов A.
Чтобы запустить скрипт, используйте
octave -f script.m <input.dat
источник
R 207 байт
Сценарий берет свои входные данные из STDIN, например
Rscript script.R < inputFile
.Он генерирует все треугольники из
N
последних точек (последней линииapply(combn(...
) и проверяет, находится ли первая точка в треугольнике, используяt
функцию.t
использует метод области, чтобы решить, еслиU
находится вABC
: (запись(ABC)
для областиABC
)U
вABC
iff(ABC) == (ABU) + (ACU) + (BCU)
. Кроме того, площади рассчитываются по формуле детерминанта (см. Здесь хорошую демонстрацию от Wolfram).Я подозреваю, что это решение более подвержено ошибкам, чем мои другие, но оно работает на моих тестовых примерах.
источник
R, 282 байта
Сценарий берет свои входные данные из STDIN, например
Rscript script.R < inputFile
.Он генерирует все треугольники из
N
последних точек (последней линииapply(combn(...
) и проверяет, находится ли первая точка в треугольнике, используяt
функцию.t
использует барицентрический метод, чтобы решить,U
находится ли вABC
: (записьXY
для вектораX
toY
), поскольку(AB,AC)
является базисом для плоскости (за исключением вырожденных случаев, когда A, B, C выровнены),AU
может быть записан какAU = u.AB + v.AC
иU
находится в треугольнике, еслиu > 0 && v > 0 && u+v < 1
, Смотрите, например, здесь для более подробного объяснения и хороший интерактивный график. NB: чтобы сэкономить несколько символов и ошибок избежать div0, мы только вычислить ярлыкu
иv
и модифицированный тест (min(u*k,v*k,k-u-v)>0
).Единственный математические операторы используются
+
,-
,*
,min()>0
.источник