Ustal, czy wielokąt jest wypukły

21

Napisz program, aby ustalić, czy wejściowy wielokąt jest wypukły . Wielokąt jest określona jedną linię N , liczbę wierzchołków, a następnie N linie zawierające x oraz y współrzędnych każdego wierzchołka. Wierzchołki zostaną wyświetlone zgodnie z ruchem wskazówek zegara, zaczynając od dowolnego wierzchołka.

Przykład 1

wkład

4
0 0
0 1
1 1
1 0

wydajność

convex

przykład 2

wkład

4
0 0
2 1
1 0
2 -1

wydajność

concave

przykład 3

wkład

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

wydajność

convex

x i y są liczbami całkowitymi, n <1000 i | x |, | y | <1000 . Możesz założyć, że wejściowy wielokąt jest prosty (żadna z krawędzi się nie krzyżuje, tylko 2 krawędzie dotykają każdego wierzchołka). Najkrótszy program wygrywa.

Keith Randall
źródło
„Proste” nie obejmuje „kolejnych krawędzi nie jest współliniowych” ?! Ponadto kilka innych przypadków testowych: (0,0) (0,2) (2,2) (2,0) (1,1); oraz (1,1) (0,0) (0,2) (2,2) (2,0) - w celu przetestowania przypadków, w których znalezienie wklęsłego wierzchołka wymaga owinięcia od końca z powrotem do początku.
Peter Taylor,
To pytanie się starzeje, ale ... Rozważ dodanie wklęsłego przykładu z dwoma wyrównanymi segmentami, np. Modyfikacja przykładu 2: (0,0), (2,1), (4,2), (1,0) ( 2, -1). Mówię o tym, ponieważ kręciłem się wokół przykładu 3, nie zdając sobie z tego sprawy.
Jesse Millikan

Odpowiedzi:

4

J, 105

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

Przechodzi wszystkie trzy testy powyżej.

Edycja: (111-> 115) Obsługuj punkty współliniowe, eliminując kąty pi. Zdobyłem kilka postaci w innym miejscu.

Edycja: (115-> 105) Mniej głupi.

Objaśnienie dla osób z zaburzeniami J:

  • (1!:1)3przeczytaj STDIN do EOF. (Myślę.)
  • 0&".;._2 to fajny idiom do analizowania tego rodzaju danych wejściowych.
  • j./"1}. odciąć pierwszy wiersz wejścia (N 0) i przekształcić pary w kompleksy.
  • (,2&{.) umieść dwa pierwsze punkty na końcu listy.
  • 3(f)\ stosuje się do okna przesuwnego o długości 3 (3 punkty za kąt)
  • [:-/12 o.-@-/@}.,-/@}: to czasownik, który przekształca każde 3 punkty w kąt między -pi a pi.
    • -@-/@}.,-/@}:produkuje (p1 - p2), (p3 - p2). (Przypomnij, że są to kompleksy).
    • 12 o. daje kąt dla każdego kompleksu.
    • [:-/(...) daje różnicę dwóch kątów.
  • (o.1)([:>-.~)(o.2)| mod 2 pi, wyeliminuj kąty pi (odcinki proste) i porównaj z pi (większe niż, mniejsze niż, nie ma znaczenia, chyba że punkty mają być nawinięte w jednym kierunku).
  • 1=#= jeśli wszystkie te porównania dają wynik 1 lub 0 (z samoklasyfikacją. Wydaje się to głupie.)
  • echo>('concave';'convex'){~ druk wypukły.
Jesse Millikan
źródło
3

Python - 149 znaków

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
źródło
Myślę, że potrzebujesz <= patrz przykład 3, który właśnie dodałem.
Keith Randall,
1
cholera, ten kawałek ...
st0le,
2

Ruby 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
źródło
1

scala: 297 znaków

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))))}}
nieznany użytkownik
źródło
1
Możesz ogolić trzy znaki za pomocą def main(a:...zamiast def main(args:....
Gareth,
Tak, zauważyłem siebie, ale od 299 do 149 nie zbliża mnie do kogoś innego. Może jeśli znajdę inne ulepszenia - ah, jest jeden: n to nazwa funkcji (następna) i nazwa zmiennej.
użytkownik nieznany