Determinar se um polígono é convexo

21

Escreva um programa para determinar se o polígono de entrada é convexo . O polígono é especificado com uma linha contendo N , o número de vértices, em seguida, N linhas que contêm o x e y coordenadas de cada vértice. Os vértices serão listados no sentido horário a partir de um vértice arbitrário.

Exemplo 1

entrada

4
0 0
0 1
1 1
1 0

saída

convex

exemplo 2

entrada

4
0 0
2 1
1 0
2 -1

saída

concave

exemplo 3

entrada

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

saída

convex

x e y são números inteiros, N <1000 e | x |, | y | <1000 . Você pode assumir que o polígono de entrada é simples (nenhuma das arestas se cruza, apenas duas arestas tocam em cada vértice). O programa mais curto vence.

Keith Randall
fonte
"Simples" não inclui "arestas consecutivas não são colineares" ?! Além disso, mais alguns casos de teste: (0,0) (0,2) (2,2) (2,0) (1,1); e (1,1) (0,0) (0,2) (2,2) (2,0) - para testar os casos em que a localização do vértice côncavo exige o empacotamento do fim ao início.
21411 Peter
Esta questão está envelhecendo, mas ... Considere adicionar um exemplo côncavo com dois segmentos alinhados, por exemplo, uma modificação do exemplo 2: (0,0), (2,1), (4,2), (1,0) ( 2, -1). Eu trago isso à tona porque eu enganei o exemplo 3 sem perceber.
precisa

Respostas:

4

J, 105

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

Passa nos três testes acima.

Editar: (111-> 115) Lide com pontos co-lineares eliminando ângulos de pi. Ganhou alguns caracteres em outro lugar.

Editar: (115-> 105) Menos burro.

Explicação para os deficientes em J:

  • (1!:1)3leia STDIN para EOF. (Eu acho que.)
  • 0&".;._2 é um bom idioma para analisar esse tipo de entrada.
  • j./"1}. corte a primeira linha de entrada (N 0) e converta pares em complexos.
  • (,2&{.) coloque os dois primeiros pontos no final da lista.
  • 3(f)\ aplica-se f à janela deslizante de comprimento 3 (3 pontos para um ângulo)
  • [:-/12 o.-@-/@}.,-/@}: é um verbo que transforma cada 3 pontos em um ângulo entre -pi e pi.
    • -@-/@}.,-/@}:produz (p1 - p2), (p3 - p2). Lembre-se de que são complexos.
    • 12 o. dá um ângulo para cada complexo.
    • [:-/(...) dá a diferença dos dois ângulos.
  • (o.1)([:>-.~)(o.2)| mod 2 pi, elimine ângulos de pi (segmentos retos) e compare com pi (maior que, menor que, não importa, a menos que os pontos devam ser enrolados em uma direção).
  • 1=#= se todas essas comparações resultarem 1 ou 0 (com auto-classificação. Isso parece idiota.)
  • echo>('concave';'convex'){~ impressão convexa.
Jesse Millikan
fonte
3

Python - 149 caracteres

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]
mordedor
fonte
Eu acho que você precisa <=, veja o exemplo 3 que acabei de adicionar.
Keith Randall
11
dammn, essa fatia ...
st0le
2

Ruby 1.9, 147 133 130 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
fonte
1

scala: 297 caracteres

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))))}}
Usuário desconhecido
fonte
11
Você pode fazer a barba de três caracteres usando em def main(a:...vez de def main(args:....
Gareth
Sim, eu notei a mim mesmo, mas 299 a 149 não me traz na área de outra pessoa. Talvez se eu encontrar outras melhorias - ah, existe uma: n é um nome de função (próximo) e um nome de variável.
usuário desconhecido