Policz liczbę boków wielokąta
Robot liczący po stronie wielokąta postanowił podróżować po świecie bez uprzedzenia, ale ważne jest, aby proces liczenia wielokątów nie był zatrzymywany zbyt długo. Masz więc następujące zadanie: Biorąc pod uwagę czarno-biały obraz wielokąta, twój program / funkcja powinna zwrócić liczbę stron.
Program zostanie dostarczony do starego komputera z kartami dziurkacza, a ponieważ karty dziurkacze są obecnie bardzo drogie, lepiej postaraj się, aby twój program był jak najkrótszy.
Krawędzie mają co najmniej 10 pikseli długości, a kąty utworzone przez dwie sąsiednie krawędzie wynoszą co najmniej 10 °, ale nie więcej niż 170 ° (lub ponownie więcej niż 190 °). Wielokąt jest całkowicie zawarty w obrazie, a wielokąt i jego dopełnienie są połączone (nie ma izolowanych wysp), więc to wejście nie byłoby poprawne:
Punktacja
To jest kodegolf, co oznacza, że wygrywa najkrótsza przesyłana bajtowa przesyłka, która musi znaleźć prawidłową liczbę krawędzi dla każdego przypadku testowego. (Przesyłanie powinno działać również w innych przypadkach, optymalizacja tylko tych przypadków testowych jest niedozwolona).
Jeśli chcesz przesłać rozwiązanie, które za każdym razem nie znajduje poprawnego numeru, możesz je również przesłać, ale będzie ono umieszczane w rankingu za wszystkimi przesłanymi, które działają lepiej.
Podaj całkowitą liczbę w tytule zgłoszenia. (Błąd całkowity suma różnic bezwzględnych między rzeczywistą liczbą stron a każdym wyjściem).
Odpowiedzi:
Python 2 + PIL, bez błędów,
313307 bajtówPobiera nazwę pliku obrazu w wierszu polecenia i drukuje wynik do STDOUT.
Podaje poprawny wynik dla wszystkich testów, a n = 28 dla koła.
Wyjaśnienie
Algorytm działa, idąc wzdłuż obwodu wielokąta i licząc liczbę napotkanych wierzchołków (wykrytych jako zmiany kierunku). Zaczynamy od piksela najbardziej oddalonego od początku,
o
który z pewnością jest wierzchołkiem, a zatem przylega do krawędzi (tj. Granicy między pikselem pierwszego planu i pikselem tła). Śledzimy naszą pozycję,p
najnowszy wierzchołekv
i najnowszy „punkt kontrolny”,q
z których wszystkie są początkowo równeo
. Śledzimy również kierunek krawędzid
względem bieżącego piksela;d
początkowo wskazuje wschód, co jest bezpiecznym kierunkiem, ponieważ wiemy, że jest krawędź na wschód odo
, inaczej nie byłoby to najdalsze od pochodzenia. Poruszamy się wzdłuż krawędzi, w kierunku prostopadłym do punktów po naszej lewej stronie, tj. W kierunku zgodnym z ruchem wskazówek zegara. Ilekroć „spadamy z krawędzi”, tj. W każdej sytuacji, w której znajduje się poza wielokątem lub gdy piksel po naszej lewej stronie (tj. W kierunku ) znajduje się wewnątrz wielokąta, dostosowujemy i odpowiednio przed wznowieniem.d
takiego, któryd
p
d
p
d
Za każdym razem, gdy odległość między
p
ostatnim punktem kontrolnym, aq
staje się większa niż 5, staramy się ustalić, czy minęliśmy wierzchołek międzyq
ip
: Porównujemy kąt międzyvq
(tj. Wektorem odv
doq
), który jest ogólnym kierunkiem bok wieloboku, którym szliśmy, gdy dotarliśmy do ostatniego punktu kontrolnego, orazqp
przesunięcie między ostatnim punktem kontrolnym a bieżącą pozycją. Jeśli kąt jest większy niż około 10 °, dochodzimy do wniosku, że idziemy wzdłuż innej strony wielokąta, zwiększamy liczbę wierzchołków i ustawiamyv
bieżący wierzchołek nap
. W każdym punkcie kontrolnym, niezależnie od tego, czy wykryliśmy wierzchołek, czy nie, aktualizujemyq
ostatni punkt kontrolny dop
. Kontynuujemy w ten sposób, aż wrócimyo
do punktu początkowego i zwrócimy liczbę znalezionych wierzchołków (zauważ, że liczba wierzchołków wynosi początkowo 1, ponieważ punktem początkowymo
jest sam wierzchołek).Poniższe obrazy pokazują wykryte wierzchołki. Zauważ, że biorąc
p
, bieżąca pozycja w każdym punkcie kontrolnym, ponieważ pozycja nowego wierzchołka nie jest optymalna, ponieważ prawdziwy wierzchołek jest prawdopodobnie gdzieś pomiędzy ostatnim punktem kontrolnymq
ip
wzdłuż obwodu. Jak widać, wszystkie wierzchołki inne niż pierwszy (ogólnie prawy dolny wierzchołek) są nieco oddalone. Naprawienie tego kosztowałoby więcej bajtów, ale wydaje się, że działa wystarczająco dobrze, jak jest. Biorąc to pod uwagę, trudno jest nie nadużywać tylko czterech przypadków testowych.źródło
o
, czy drugi koniec nie byłby jeszcze dalej od źródła?o
jest najdalszym pikselem pierwszego planu od początku, więc piksel na wschodzie musi być pikselem tła, dlatego mówimy, że na wschód jest krawędźo
.