Das ist Code Golf. Der Gewinner ist der gültige Code mit der geringsten Anzahl von Bytes.
Herausforderung
Bei den Eingaben M und N , der Breite und Höhe eines rechteckigen Quadratrasters, wird ein Polygon ausgegeben, das die folgenden Anforderungen erfüllt:
- Die Polygonkanten bestehen nur aus quadratischen Kanten: Es gibt keine diagonalen Kanten - alle sind vertikal oder horizontal.
- Das Polygon hat keine Löcher: Jedes Quadrat außerhalb des Polygons kann durch orthogonale Schritte auf Quadraten außerhalb des Polygons erreicht werden, beginnend mit einem Quadrat außerhalb des Polygons an der äußeren Begrenzung des Rechtecks.
- Das Polygon hat keine Selbstüberschneidung: Von den quadratischen Kanten, die sich an einem Scheitelpunkt treffen, dürfen nicht mehr als 2 Teile des Polygonumfangs sein.
- Das Polygon ist verbunden: Jedes Quadrat im Polygon muss über orthogonale Schritte, die innerhalb des Polygons bleiben, von jedem anderen Quadrat im Polygon aus erreichbar sein.
- Das Polygon hat den maximal möglichen Umfang: gemäß der unten gezeigten Formel.
Ihr Code muss für M und N von 1 bis 255 funktionieren .
Formel für maximalen Umfang
Die Herausforderung besteht darin, das am besten geeignete Polygon mit dem maximalen Umfang zu finden. Der maximale Umfang selbst wird immer durch die Formel definiert:
Dies ist richtig, da für einen maximalen Umfang jeder quadratische Eckpunkt auf dem Umfang liegen muss. Für eine ungerade Anzahl von Scheitelpunkten ist dies nicht möglich und das Beste, was erreicht werden kann, ist ein Scheitelpunkt weniger (da der Umfang immer gerade ist).
Ausgabe
Geben Sie die Form als Zeichenfolge mit Zeilenumbrüchen aus ( N Zeilen mit genau M Zeichen). Hier verwende ich Platz für Quadrate außerhalb des Polygons und '#' für Quadrate innerhalb des Polygons. Sie können jedoch zwei beliebige visuell unterschiedliche Zeichen verwenden, sofern deren Bedeutung für alle Eingaben konsistent ist.
Sie können bis zu eine führende und bis zu eine nachfolgende Zeile einfügen.
Wenn Sie möchten, können Sie stattdessen Ausgang M Reihen von genau N Zeichen, und Sie können wählen M von N für einige Ein- und Ausgang N von M für die anderen Ausgang.
Beispiele
Ungültig wegen einer Lücke:
###
# #
###
Ungültig wegen Schnittpunkt (diagonal berühren - ein Scheitelpunkt mit 4 quadratischen Kanten am Umfang) und im Übrigen ein Loch:
##
# #
###
Ungültig , da die Verbindung getrennt wurde:
#
# #
#
Gültiges Polygon mit maximalem Umfang:
# #
# #
###
Credits
Ich habe anfangs unterschätzt, wie schnell der Wert des maximalen Umfangs berechnet werden kann, und wollte nur diesen Wert als Ausgabe anfordern. Vielen Dank an die wunderbar hilfreichen Personen im Chat, die erklärt haben, wie man den maximalen Umfang für beliebiges N und M errechnet und dabei hilft, dies zu einer Herausforderung zu machen, die für mehr als eine Antwort Bestand hat ...
Speziell danke an:
Sparr , Zgarb , Feersum , Jimmy23013 .
Antworten:
CJam, 47 Bytes
Probieren Sie es online aus
Erläuterung:
Es gibt zwei Hauptfälle für das Ergebnis. Wenn mindestens eine der Größen ungerade ist, ist das Muster ein einfacher "Rechen". Zum Beispiel für die Eingabe
7 6
:Wenn beide Größen gerade sind, gibt es eine zusätzliche Spalte, in der jedes zweite Quadrat "an" ist. Zum Beispiel für die Eingabe
8 6
:Um zu zeigen, dass diese Muster das theoretische Maximum des Umfangs erreichen, wie in der Problembeschreibung angegeben, müssen wir bestätigen, dass das erste Muster den Umfang
(M + 1) * (N + 1)
und das zweite den gleichen Wert minus 1 hat.Für das erste Muster haben wir für den Umfang mit
M
einer ungeraden Dimension:M
für die Oberkante.2
an der Seite der obersten Reihe.(M - 1) / 2
für die Lücken zwischen den Zähnen.(M + 1) / 2
Zähne mit Umfang2 * (N - 1) + 1
.Dies summiert sich zu:
Für den zweiten Fall, in dem beide
M
und geradeN
sind, addiert sich der Umfang aus:M
für die Oberkante.2
an der Seite der obersten Reihe.M / 2
für das offene # in der oberen Reihe.M / 2
Zähne mit Umfang2 * (N - 1) + 1
jeweils für die einfachen Zähne.2 * (N / 2 - 1)
Umfang für die Zacken.Alles zusammen addieren:
quelle
Ruby, Rev. 1, 66
Wird verwendet,
m
um 0 oder 1 zu erhöhen , um zu entscheiden, ob 1 oder 1m
#
gedruckt wird.Dient
>
zum Testen der letzten Zeile anstelle von==
.Ich kann weder den Platz nach dem Put noch irgendwelche Klammern loswerden!
Ruby, Rev 0, 69
Dies ist eine anonyme Lambda-Funktion. Benutze es so:
Am Ende brauchte ich es nicht, nachdem ich gefragt hatte, ob M und N vertauscht werden könnten.
Typische Ausgänge für N ungerade. Wenn wir die
#
auf der rechten Seite einzeln löschen , haben wir eindeutig (N + 1) (M + 1). Wenn Sie sie zum Verbinden der Form hinzufügen, werden 2 Quadrate des horizontalen Umfangs entfernt und 2 Quadrate des vertikalen Umfangs hinzugefügt, sodass keine Änderung erfolgt.Hier verlassen wir uns auf den Ausdruck
"#"*(i%2==0?m:1)
, um abwechselnde Reihen von M-#
Symbolen und ein#
Symbol zu geben und M-Zeichen rechtsbündig auszurichten.Typische Ausgänge für N gerade.
5 6
hat eindeutig den gleichen Umfang wie6 5
oder ein Inkrement von M + 1 = 6, verglichen mit5 5
der Addition des vertikalen Umfangs aufgrund der Zinnenbildung der unteren Reihe.6 6
hat das gleiche wie6 5
plus ein Inkrement von (M + 1) -1 = 6 im vertikalen Umfang. Sie stimmen also mit der Formel überein.Es ist sehr praktisch, dass Sie mit Ruby den
rjust
Abstand festlegen können, der für die leeren Zellen verwendet werden soll. Normalerweise ist das Auffüllen auf eingestellt," "
aber für die letzte Zeile, zu der wir wechseln"# "
(beachten Sie, dass das Auffüllen nur in der letzten Zeile erforderlich ist, wenn N gerade ist. Wenn N ungerade ist, ist die letzte Zeile vollständig und es gibt keine Rechtfertigung, also Sie werde die Zinnen nicht sehen.)Schau es dir hier an.
quelle
i%2==0
umi%2<1
ein Byte (Ich habe diese Änderung der ideone Link) zu speichern.#
Polsterung für die gerade letzte Reihe? Ist beispielsweise in der allerletzten Abbildung der Umfang ohne den#
in der unteren rechten Ecke identisch ?#
einfach weil es bereits die Art und Weise ist, wie jede Zeile beendet wird, also sind es weniger Bytes als ein Leerzeichen. (Ich weiß aber nicht, Rubin ...)."# "
nicht" #"
daran, dass letztere 2 benachbarte#
für ungerade M ergeben würde, was definitiv nicht erwünscht ist. 2 nebeneinander#
für sogar M schadet nicht, also bin ich damit gegangen. Ich habe es nicht ausprobiertljust
, es ist vielleicht möglich, es sauberer damit zu machen, aber es wäre nicht so offensichtlich, dass ich genau M Zeichen pro Zeile drucke.C,
10997 Bytes und KorrektheitsnachweisIch habe meine Lösung geschrieben, aber @steveverrill hat mich geschlagen. Ich dachte, ich würde es trotzdem teilen, da ich einen Korrektheitsnachweis für die verwendete Strategie beigefügt habe.
Reduzierter Code:
Vor der Reduktion:
Strategie und Beweis:
Unter der Annahme, dass die maximale Perimiter-Gleichung (M + 1) (N + 1) - ((M + 1) (N + 1)) mod 2 korrekt ist , wird im Folgenden die optimale Strategie erläutert und ihre Richtigkeit durch Induktion bewiesen:
Für ungerades M zeichnen wir eine handähnliche Form mit M / 2 + 1 Fingern, zum Beispiel:
Wir beweisen nun, dass diese Strategie für alle ungeraden M durch Induktion optimal ist:
Basisfall: M = N = 1
Die einzelne Zelle ist gefüllt. Die Lösung ist korrekt, da (1 + 1) * (1 + 1) = 2 * 2 = 4 und ein Quadrat 4 Seiten hat.
Induktion über die Breite:
Nehmen Sie an, dass die Handformstrategie für (N, M-2) funktioniert , wobei M ungerade ist, das heißt, sein Perimiter optimal ist und (N + 1) (M - 2 + 1) + ((M -1) (N + 1)) mod 2 . Wir zeigen nun, dass es für (N, M) funktionieren wird .
Beim Hinzufügen eines Fingers wird eine Kante aus dem Polygon entfernt und 3 + 2N hinzugefügt . Beispielsweise:
In Kombination mit unserer Hypothese, dass der vorherige Umfang optimal war, lautet der neue Umfang:
Da es sich um Modulo 2-Arithmetik handelt,
Der Beweis, dass eine Vergrößerung der Breite durch Hinzufügen von Fingern zu einem optimalen Umfang führt.
Induktion auf Höhe:
Angenommen, die Handformstrategie funktioniert für (N-1, M) , wobei M ungerade ist, das heißt, sein Umfang optimal ist und N (M + 1) + ((M + 1) N) mod ist 2 . Wir zeigen nun, dass es für (N, M) funktionieren wird .
Das Erhöhen der Hand verlängert lediglich die Finger, die sich am ersten und an jedem zweiten x-Index befinden. Für jede Höhenzunahme addiert jeder Finger zwei zum Umfang, und es gibt (M + 1) / 2 Finger, daher führt eine Zunahme von N zu einer Zunahme von 2 (M + 1) / 2 = M + 1 in der Umfang.
Wenn wir dies mit der Hypothese kombinieren, ist der neue Umfang:
Modulare Arithmetik erlaubt es uns, den letzten Term zu vereinfachen, so dass wir erhalten:
Beweis, dass die Lösung für alle N> 0 und ungeraden M> 0 optimal ist.
Für gerade M füllen wir die Tafel genauso aus wie für ungerade M, aber wir fügen dem letzten Segment Zinnen hinzu, zum Beispiel:
Wir beweisen nun, dass diese Strategie optimal ist.
Induktion für gerade M:
Angenommen, die Lösung ist korrekt für (N, M-1) mit ungerader M-1 (wie im letzten Fall bewiesen), die einen optimalen Umfang von (N + 1) M - (hat. M (N + 1)) mod 2 . Wir zeigen nun, dass es für (N, M) funktionieren wird.
Wie bei der Vergrößerung der Finger erhöht jede Zinnenordnung den Umfang des Polygons um zwei. Die Gesamtzahl der Zinnen ist (N + N mod 2) / 2 , wobei insgesamt N + N mod 2 Perimeter hinzugefügt werden.
Wenn wir dies mit der Hypothese kombinieren, ist der neue Umfang:
Wir haben das
Denn wenn N ungerade ist, verringert sich dies auf 0 = 0, und wenn N gerade ist, verringert sich dies auf
Somit ist die Strategie für alle M, N> 0 optimal .
quelle