Определите, является ли многоугольник выпуклым

21

Напишите программу, чтобы определить, является ли входной многоугольник выпуклым . Многоугольник задается одной строкой, содержащей N , количество вершин, затем N строк, содержащих координаты x и y каждой вершины. Вершины будут перечислены по часовой стрелке, начиная с произвольной вершины.

пример 1

вход

4
0 0
0 1
1 1
1 0

выход

convex

пример 2

вход

4
0 0
2 1
1 0
2 -1

выход

concave

пример 3

вход

8
0 0
0 1
0 2
1 2
2 2
2 1
2 0
1 0

выход

convex

x и y являются целыми числами, N <1000 и | x |, | y | <1000 . Можно предположить, что входной многоугольник прост (ни одно из ребер не пересекается, только 2 ребра касаются каждой вершины). Кратчайшая программа выигрывает.

Кит Рэндалл
источник
«Простой» не включает «последовательные ребра неколлинеарны» ?! Также еще пара тест-кейсов: (0,0) (0,2) (2,2) (2,0) (1,1); и (1,1) (0,0) (0,2) (2,2) (2,0) - для проверки случаев, когда нахождение вогнутой вершины требует переноса с конца обратно на начало.
Питер Тейлор
Этот вопрос устарел, но ... Попробуйте добавить вогнутый пример с двумя выровненными сегментами, например, модификацию примера 2: (0,0), (2,1), (4,2), (1,0) ( 2, -1). Я поднял это, потому что я обдумал пример 3, не осознавая этого.
Джесси Милликен

Ответы:

4

J, 105

echo>('concave';'convex'){~1=#=(o.1)([:>-.~)(o.2)|3([:-/12 o.-@-/@}.,-/@}:)\(,2&{.)j./"1}.0&".;._2(1!:1)3

Проходит все три теста выше.

Редактировать: (111-> 115) Обрабатывать коллинеарные точки, устраняя углы пи. Получил несколько персонажей в другом месте.

Изменить: (115-> 105) Менее тупой.

Объяснение для J-инвалидов:

  • (1!:1)3читать STDIN для EOF. (Я думаю.)
  • 0&".;._2 хорошая идиома для анализа такого рода ввода.
  • j./"1}. Отрезать первую строку ввода (N 0) и преобразовать пары в комплексы.
  • (,2&{.) прикрепите первые две точки в конец списка.
  • 3(f)\ применяет f к скользящему окну длиной 3 (3 точки на угол)
  • [:-/12 o.-@-/@}.,-/@}: это глагол, который превращает каждые 3 точки в угол между -pi и pi.
    • -@-/@}.,-/@}:производит (p1 - p2), (p3 - p2). (Напомним, что это комплексы.)
    • 12 o. дает угол для каждого комплекса.
    • [:-/(...) дает разницу двух углов.
  • (o.1)([:>-.~)(o.2)| mod 2 pi, исключить углы pi (прямые отрезки) и сравнить с pi (больше, меньше, не имеет значения, если точки не должны быть намотаны в одном направлении).
  • 1=#= если все эти результаты сравнения 1 или 0 (С самоклассификацией. Это кажется глупым.)
  • echo>('concave';'convex'){~ печать выпуклая.
Джесси Милликен
источник
3

Питон - 149 символов

p=[map(int,raw_input().split())for i in[0]*input()]*2
print'ccoonncvaevxe'[all((a-c)*(d-f)<=(b-d)*(c-e)for(a,b),(c,d),(e,f)in zip(p,p[1:],p[2:]))::2]
gnibbler
источник
Я думаю, что вам нужно <=, см. Пример 3, который я только что добавил.
Кит Рэндалл,
1
dammn, что кусочек ...
st0le
2

Рубин 1.9, 147 133 130 124 123

gets
puts ($<.map{|s|s.split.map &:to_i}*2).each_cons(3).any?{|(a,b),(c,d),(e,f)|(e-c)*(d-b)<(d-f)*(a-c)}?:concave: :convex
Lowjacker
источник
1

Скала: 297 символов

object C{class D(val x:Int,val y:Int)
def k(a:D,b:D,c:D)=(b.y-a.y)*(c.x-b.x)>=(c.y-b.y)*(b.x-a.x) 
def main(a:Array[String]){val s=new java.util.Scanner(System.in)
def n=s.nextInt
val d=for(x<-1 to n)yield{new D(n,n)}print((true/:(d:+d.head).sliding(3,1).toList)((b,t)=>b&&k(t(0),t(1),t(2))))}}
неизвестный пользователь
источник
1
Вы можете побрить три символа, используя def main(a:...вместо def main(args:....
Гарет
Да, я заметил себя, но 299 - 149 не приводит меня в зону кого-то еще. Может быть, если я найду другие улучшения - ах, есть одно: n - это имя функции (далее) и имя переменной.
пользователь неизвестен