Zählen Sie die Anzahl der Seiten eines Polygons

18

Zählen Sie die Anzahl der Seiten eines Polygons

Der Polygonseiten-Zählroboter hat beschlossen, die Welt zu bereisen, ohne es zuvor jemandem zu sagen, aber es ist entscheidend, dass der Prozess des Polygons nicht zu lange gestoppt wird. Sie haben also folgende Aufgabe: Bei einem Schwarz-Weiß-Bild eines Polygons sollte Ihr Programm / Ihre Funktion die Anzahl der Seiten zurückgeben.

Das Programm wird einem alten Lochkartencomputer zugeführt, und da Lochkarten heutzutage sehr teuer sind, sollten Sie versuchen, Ihr Programm so kurz wie möglich zu halten.

Die Kanten sind mindestens 10 Pixel lang, und die von zwei benachbarten Kanten gebildeten Winkel betragen mindestens 10 °, jedoch nicht mehr als 170 ° (oder wiederum mehr als 190 °). Das Polygon ist vollständig im Bild enthalten, und das Polygon sowie sein Komplement sind verbunden (es gibt keine isolierten Inseln), sodass diese Eingabe nicht gültig wäre:

Bildbeschreibung hier eingeben

Wertung

Dies ist Codegolf, dh die kürzeste Übermittlung in Bytes gewinnt, Ihre Übermittlung muss für jeden Testfall die richtige Anzahl von Kanten finden. (Und die Einreichung sollte auch für andere Fälle funktionieren, eine Optimierung nur für diese Testfälle ist nicht zulässig.)

Wenn Sie eine Lösung einreichen möchten, bei der nicht jedes Mal die richtige Nummer gefunden wird, können Sie diese auch einreichen, sie wird jedoch hinter allen Einreichungen mit einer besseren Leistung eingestuft.

Bitte geben Sie die Gesamtzahl in Ihrem Beitragstitel an. (Der Gesamtfehler ist die Summe der absoluten Differenzen zwischen der tatsächlichen Anzahl der Seiten und den einzelnen Ausgaben).

Testfälle

n = 10

Bildbeschreibung hier eingebenBildbeschreibung hier eingeben

n = 36

Bildbeschreibung hier eingebenBildbeschreibung hier eingeben

n = 7

Bildbeschreibung hier eingebenBildbeschreibung hier eingeben

n = 5

Bildbeschreibung hier eingebenBildbeschreibung hier eingeben

Dies ist kein Testfall, nur aus Neugier: Wie viele Kanten erhalten Sie für diese Eingabe?

Bildbeschreibung hier eingeben

fehlerhaft
quelle
Ich sehe in Ihren Testfällen viele Winkel, die größer als 170 ° sind. Zum Beispiel alle "Nicht-Punkt" -Winkel (die näher am Zentrum liegen) in Ihrem Stern.
Türknauf
@Doorknob Es ist der kleinere Winkel, der kleiner als 170 ° sein sollte.
Lirtosiast
Ja, aber sie sind wieder größer als 190 °. Ziel dieser Einschränkung ist es, Beispiele zu eliminieren, bei denen die beiden angrenzenden Seiten nur schwer voneinander zu unterscheiden sind.
Fehler
2
Welche Farbe hat das Innere des Polygons?
Feersum
1
Das Programm wird an einen alten Lochkartencomputer weitergeleitet, und da Lochkarten heutzutage sehr teuer sind, sollten Sie versuchen, Ihr Programm so kurz wie möglich zu halten :-)
Luis Mendo

Antworten:

12

Python 2 + PIL, kein Fehler, 313 307 Bytes

from Image import*
I=open(sys.argv[1])
w,h=I.size;D=I.getdata()
B={i%w+i/w*1j for i in range(w*h)if D[i]!=D[0]}
n=d=1;o=v=q=p=max(B,key=abs)
while p-w:
 p+=d*1j;e=2*({p}<B)+({p+d}<B)
 if e!=2:e%=2;d*=1j-e*2j;p-=d/1j**e
 if abs(p-q)>5:
    t=(q-v)*(p-q).conjugate();q=p;w=o
    if.98*abs(t)>t.real:n+=1;v=p
print n

Nimmt einen Bilddateinamen in die Befehlszeile und gibt das Ergebnis an STDOUT aus.

Gibt das korrekte Ergebnis für alle Tests und n = 28 für den Kreis an.

Erläuterung

Der Algorithmus wandert entlang des Umfangs des Polygons und zählt die Anzahl der angetroffenen Scheitelpunkte (die als Richtungsänderungen erkannt wurden). Wir beginnen an dem Pixel, das am weitesten vom Ursprung entfernt ist o, der garantiert ein Scheitelpunkt ist und daher an eine Kante angrenzt (dh an eine Grenze zwischen einem Vordergrundpixel und einem Hintergrundpixel). Wir verfolgen unsere Position, pden neuesten Scheitelpunkt vund den neuesten "Kontrollpunkt", qdie anfangs alle gleich sind o. Wir verfolgen auch die Richtung der Kante drelativ zum aktuellen Pixel. dzeigt zunächst nach Osten, was eine sichere Richtung ist, da wir wissen, dass es östlich von eine Kante gibtooder es wäre nicht am weitesten vom Ursprung entfernt. Wir bewegen uns entlang der Kante in einer Richtung senkrecht zu d, die dnach links zeigt, dh im Uhrzeigersinn. Wann immer wir "vom Rand fallen", dh in jeder Situation, in der psich außerhalb des Polygons befindet, oder in der sich das Pixel links von uns (dh in Richtung von d) innerhalb des Polygons befindet, werden wir uns anpassen pund ddementsprechend vor dem Fortsetzen.

Jedes Mal, wenn der Abstand zwischen pund dem letzten Kontrollpunkt qgrößer als 5 wird, versuchen wir festzustellen, ob wir über einen Scheitelpunkt zwischen qund gefahren sind p: Wir vergleichen den Winkel zwischen vq(dh den Vektor von vbis q), der die allgemeine Richtung von ist Seite des Polygons, entlang dem wir gingen, als wir den letzten Kontrollpunkt erreichten, und qpdie Verschiebung zwischen dem letzten Kontrollpunkt und der aktuellen Position. Wenn der Winkel größer als ungefähr 10 ° ist, schließen wir, dass wir entlang einer anderen Seite des Polygons gehen, die Scheitelpunktanzahl erhöhen und vden aktuellen Scheitelpunkt auf setzen p. Unabhängig davon, ob wir einen Scheitelpunkt erkannt haben oder nicht, aktualisieren wir an jedem Prüfpunkt qden letzten Prüfpunkt aufp. Wir fahren auf diese Weise fort, bis wir ozum Ausgangspunkt zurückkehren und die Anzahl der gefundenen Scheitelpunkte zurückgeben (beachten Sie, dass die Anzahl der Scheitelpunkte anfänglich 1 beträgt, da der Ausgangspunkt oselbst ein Scheitelpunkt ist.)

Die Bilder unten zeigen die erkannten Scheitelpunkte. Beachten Sie, dass pdie aktuelle Position an jedem Kontrollpunkt als Position des neuen Scheitelpunkts nicht optimal ist, da der reale Scheitelpunkt wahrscheinlich irgendwo zwischen dem letzten Kontrollpunkt qund pentlang des Umfangs liegt. Wie Sie sehen können, sind alle Scheitelpunkte außer dem ersten (im Allgemeinen der untere rechte Scheitelpunkt) etwas versetzt. Dies zu beheben würde mehr Bytes kosten, aber dies scheint so gut wie es ist zu funktionieren. Davon abgesehen ist es ein wenig schwierig, nur vier Testfälle nicht zu übertreiben.

n = 10 n = 36 n = 7 n = 5 Kreis

Ell
quelle
Vielen Dank für diese ausführliche Erklärung! Ich liebe deine Illustrationen!
Fehler
Wenn es eine Kante östlich von gibt o, wäre das andere Ende dann nicht noch weiter vom Ursprung entfernt?
Aditsu
1
@Aditsu Ich denke, die Terminologie könnte hier ein wenig verwirrend sein. Wir sprechen von den Seiten des Polygons im geometrischen Sinne und den Kanten des (das) Polygons umfassenden (Satz von Pixeln) als Rastergrafik. oist das vom Ursprung am weitesten entfernte Vordergrundpixel, daher muss das östliche Pixel ein Hintergrundpixel sein, daher sagen wir, dass es eine Kante östlich von gibt o.
Ell