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:
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
n = 36
n = 7
n = 5
Dies ist kein Testfall, nur aus Neugier: Wie viele Kanten erhalten Sie für diese Eingabe?
quelle
Antworten:
Python 2 + PIL, kein Fehler,
313307 BytesNimmt 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,p
den neuesten Scheitelpunktv
und den neuesten "Kontrollpunkt",q
die anfangs alle gleich sindo
. Wir verfolgen auch die Richtung der Kanted
relativ zum aktuellen Pixel.d
zeigt zunächst nach Osten, was eine sichere Richtung ist, da wir wissen, dass es östlich von eine Kante gibto
oder es wäre nicht am weitesten vom Ursprung entfernt. Wir bewegen uns entlang der Kante in einer Richtung senkrecht zud
, died
nach links zeigt, dh im Uhrzeigersinn. Wann immer wir "vom Rand fallen", dh in jeder Situation, in derp
sich außerhalb des Polygons befindet, oder in der sich das Pixel links von uns (dh in Richtung vond
) innerhalb des Polygons befindet, werden wir uns anpassenp
undd
dementsprechend vor dem Fortsetzen.Jedes Mal, wenn der Abstand zwischen
p
und dem letzten Kontrollpunktq
größer als 5 wird, versuchen wir festzustellen, ob wir über einen Scheitelpunkt zwischenq
und gefahren sindp
: Wir vergleichen den Winkel zwischenvq
(dh den Vektor vonv
bisq
), der die allgemeine Richtung von ist Seite des Polygons, entlang dem wir gingen, als wir den letzten Kontrollpunkt erreichten, undqp
die 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 undv
den aktuellen Scheitelpunkt auf setzenp
. Unabhängig davon, ob wir einen Scheitelpunkt erkannt haben oder nicht, aktualisieren wir an jedem Prüfpunktq
den letzten Prüfpunkt aufp
. Wir fahren auf diese Weise fort, bis wiro
zum 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 Ausgangspunkto
selbst ein Scheitelpunkt ist.)Die Bilder unten zeigen die erkannten Scheitelpunkte. Beachten Sie, dass
p
die aktuelle Position an jedem Kontrollpunkt als Position des neuen Scheitelpunkts nicht optimal ist, da der reale Scheitelpunkt wahrscheinlich irgendwo zwischen dem letzten Kontrollpunktq
undp
entlang 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.quelle
o
, wäre das andere Ende dann nicht noch weiter vom Ursprung entfernt?o
ist das vom Ursprung am weitesten entfernte Vordergrundpixel, daher muss das östliche Pixel ein Hintergrundpixel sein, daher sagen wir, dass es eine Kante östlich von gibto
.