Hintergrund
Ich möchte ein Grundstück kaufen und darauf mein Haus bauen. Mein Haus sollte rechteckig und so groß wie möglich sein; Die verfügbaren Parzellen haben jedoch viele felsige Gebiete, auf denen ich nicht bauen kann, und ich habe Probleme, ein potenzielles Haus auf den Parzellen zu errichten. Ich möchte, dass Sie ein Programm schreiben, das die Handlungen für mich analysiert.
Ein- und Ausgabe
Ihre Eingabe ist ein rechteckiges 2D-Array von Bits mit einer Größe von mindestens 1 × 1 in einem angemessenen Format. Das Array stellt ein Grundstück dar; 1
s sind "gute" Gebiete, in denen ich mein Haus bauen könnte, und0
s sind "felsige" Gebiete, in denen das Haus nicht gebaut werden kann.
Ihre Ausgabe soll die maximale Fläche eines durchgezogenen Rechtecks von 1
s im Eingabearray sein. Es ist die Fläche des größten Hauses, das ich auf dem Grundstück bauen konnte. Beachten Sie, dass 1
der Ausgang ist , wenn der Eingang kein s enthält0
.
Beispiel
Betrachten Sie die Eingabe
101
011
111
Das größte Rechteck von 1
s ist das 2 × 2-Rechteck in der unteren rechten Ecke. Dies bedeutet, dass die richtige Ausgabe ist 4
.
Regeln und Wertung
Sie können ein vollständiges Programm oder eine Funktion schreiben. Die niedrigste Byteanzahl gewinnt, und Standardlücken sind nicht zulässig.
Testfälle
0
-> 0
1
-> 1
00
00
-> 0
01
10
-> 1
01
11
-> 2
111
010
111
-> 3
101
011
111
-> 4
0111
1110
1100
-> 4
1111111
1110111
1011101
-> 7
111011000
110111100
001111110
011111111
001111110
000111100
000011000
-> 20
000110000
110110010
110111110
110011100
010011111
111111111
111101110
-> 12
plow
.Antworten:
Jelly ,
21201817 BytesProbieren Sie es online! oder überprüfen Sie alle Testfälle .
Hintergrund
Sei M eine Matrix von Bits wie
Wir beginnen mit der Zählung der Anzahl von 1 Bits in jeder Spalte von M und setzen die Zählung jedes Mal zurück, wenn wir auf ein 0- Bit stoßen .
Für unsere Beispielmatrix ergibt dies
Als nächstes berechnen wir alle zusammenhängenden Unterlisten jeder Zeile. Dies erreichen wir, indem wir alle Schichten der Länge k erzeugen , wobei k zwischen 1 variiert und der Anzahl der Einträge in jeder Zeile .
Für die vorletzte Reihe ergibt dies
Als nächstes ordnen wir jedem Slice das Produkt seines Minimums und seiner Länge zu. Für jedes Slice wird der Bereich des Rechtecks aus 1 Bit maximaler Höhe berechnet, der das angegebene Slice als unterste Zeile enthält.
Für die Längenscheiben 3 der vorletzten Zeile unserer Beispielmatrix ergibt sich
Alles, was Sie tun müssen, ist, das Maximum über alle Segmente aller Zeilen zu ziehen.
Für unsere Beispielmatrix ergibt dies 12 .
Wie es funktioniert
quelle
MATL,
323127 BytesHierbei wird ein auf Brute-Force-2D-Faltung basierender Ansatz verwendet. Alle möglichen Rechteckgrößen werden mit dem Gelände erstellt und gefaltet. Das maximale Ergebnis aller Windungen ist die maximale Rechteckfläche.
Dies ist eine äußerst ineffiziente Lösung, da zum Speichern von Bytes Kernel für alle Rechtecke zwischen
[1, 1]
und erstellt werden,[numel(input) numel(input)]
anstatt die Anzahl der Zeilen / Spalten in der Eingabe zu bestimmen, um die richtigen Dimensionsbereiche für Rechtecke zu bestimmen.Vielen Dank an @Luis für den Hinweis auf die Verwendung
M
und das Weglassen des]]
.Probieren Sie es online!
Erläuterung
quelle
Julia,
83605753 BytesProbieren Sie es online! Der letzte Testfall überschreitet das Zeitlimit von TIO, aber ich habe es lokal überprüft.
Wie es funktioniert
Erstens ! überprüft , ob seine Matrix Argument M vollständig besteht aus 1 s.
Wenn ja ! Gibt die Summe der Einträge von M zurück , die der Fläche von M entspricht.
Wenn nicht ! macht folgendes:
Rotate M von 0 ° , 90 ° , 180 ° und 270 ° im Uhrzeigersinn.
Entfernen Sie die erste Zeile jeder der vier Drehungen, effektiv eine der oberen Reihe zu entfernen, untere Reihe, Spalte ganz links und am weitesten rechts liegenden Spalte von M .
Rufen Sie sich rekursiv auf jeder der Submatrizen auf.
Gibt das Maximum der Rückgabewerte aus den rekursiven Aufrufen zurück.
quelle
JavaScript (ES6), 97 Byte
Es stellt sich heraus, dass ein bisschen Twiddling noch gewinnt. Akzeptiert ein Array mit ganzen Zahlen. Ungolfed:
Das Array wird nach den anderen Antworten in Zeilen aufgeteilt, sodass jeder mögliche Zeilenbereich durchlaufen wird. Bei einem gegebenen Zeilenbereich besteht der nächste Schritt darin, die verfügbaren Rechtecke zu messen. Dies wird erreicht, indem die Zeilen bitweise UND-verknüpft werden. das Ergebnis ist eine Liste von Bits, die im gesamten Zeilenbereich gesetzt wurden. Es bleibt dann übrig, die maximale Länge der gesetzten Bits in der Reihe zu finden und diese mit der Höhe des Bereichs zu multiplizieren. Test schamlos von @ ed65 gestohlen:
quelle
Python 2.7,
9391898179 BytesInput ist eine Liste von Tupeln. Überprüfen Sie die kleineren Testfälle hier und die größeren Testfälle hier .
Ohne Memo überschreiten die letzten beiden Testfälle das Zeitlimit von Ideone, da sie Aufrufe an f erfordern ( 1.530.831.935 und 2.848.806.121) , was auf meinem Computer 39 und 72 Minuten dauert .
Algorithmus
Für eine gegebene Matrix M besteht die allgemeine Idee darin, über alle Untermatrizen von M zu iterieren, indem obere Reihen entfernt und Viertelumdrehungen gegen den Uhrzeigersinn gedreht werden, wobei die Größe der angetroffenen Untermatrizen verfolgt wird, die vollständig aus 1 Bit bestehen.
Das Golfspielen einer einfachen rekursiven Implementierung der obigen Idee führte zu einer Funktion f (M) , die das Folgende tut.
Wenn M keine enthält 0- Bits enthält, geben Sie die Anzahl der 1- Bits zurück.
Wenn wir M schon zweimal gedreht haben und es keine 1 enthält Bits enthält, geben Sie 0 zurück .
Wenn wir M bereits fünfmal gedreht haben , geben Sie 0 zurück .
Rufen Sie rekursiv f auf M ohne die oberste Zeile auf.
Rufen Sie rekursiv f auf M auf, und drehen Sie es um eine Vierteldrehung gegen den Uhrzeigersinn.
Gibt das Maximum der Rückgabewerte aus den rekursiven Aufrufen zurück.
Code
In der Implementierung verwenden wir ein zusätzliches Funktionsargument t , das standardmäßig 1 ist , um zu verfolgen, wie oft wir diese bestimmte Matrix bereits gedreht haben. Auf diese Weise können Sie die Schritte 1 bis 3 in einem einzigen Schritt zusammenfassen, indem Sie testen
`t/3`in`M`
und zurückkehren,`M`.count(`t`)
wenn der Test fehlschlägt.Wenn t = 1 ist , haben wir diese bestimmte Untermatrix zuvor in diesem Zweig nicht gedreht.
T / 3 = 0 , so
`t/3`in`M`
kehrt Wahr iff der Stringdarstellung von M enthält das Zeichen 0 .Wenn es nicht der Fall ist, fahren wir zurück
`M`.count(`t`)
, die Anzahl der Male das Zeichen 1 erscheint in der String - Darstellung von M .Es ist zu beachten, dass eine Matrix ohne 0 Bits nur dann auftreten kann, wenn t = 1 ist , da wir in diesem Fall keine Rekursion durchführen.
Wenn 3 ≤ t ≤ 5 , haben wir diese bestimmte Untermatrix zuvor mindestens zweimal in diesem Zweig gedreht.
t / 3 = 1 , so
`t/3`in`M`
wird das Rück Wahr iff die Stringdarstellung M das Zeichen 1 .Wenn es nicht der Fall ist, geht es zurück 0 berechnet , wie
`M`.count(`t`)
die Anzahl , wie oft die Zeichenfolgendarstellung t ( das heißt, das Zeichen 3 , 4 oder 5 ) erscheint in der Stringdarstellung von M .Wenn t = 6 , haben wir diese Submatrix zuvor fünfmal in diesem Zweig gedreht.
t / 3 = 2 , so
`t/3`in`M`
wird wieder falsch , weil die Stringdarstellung von M nicht den Charakter enthält 2 .Wir kehren 0 berechnet , wie
`M`.count(`t`)
die Anzahl , wie oft die Zeichen 6 erscheint in der Zeichenfolgendarstellung M .Wenn f nicht bereits zurückgekehrt ist, werden die verbleibenden Schritte ausgeführt.
f(M[1:])
ruft f auf M ohne die oberste Zeile auf. Da t nicht angegeben ist, ist es standardmäßig 1 , was signalisiert, dass dies das erste Mal ist, dass f auf diese bestimmte Untermatrix in diesem Zweig trifft.f(zip(*M)[::-1],t+1)
ruft f auf M eine viertel Umdrehung gegen den Uhrzeigersinn gedreht und erhöht t , um die Zeit zu verfolgen, die wir für diese bestimmte Untermatrix in diesem Zweig gedreht haben.Die Vierteldrehung wird erhalten, indem die Reihen von M miteinander gezippt werden , Tupel der entsprechenden Elemente der Reihen von M zurückgegeben werden , wodurch M transponiert und dann die Reihenreihenfolge umgekehrt wird (dh die obere Reihe wird unten platziert und umgekehrt) ).
Schließlich
max
gibt das Maximum der Rückgabewerte aus den rekursiven Aufrufen.quelle
zip
gibt eine Liste von Tupeln der entsprechenden Elemente seiner Argumente zurück. Bei einer entpackten 2D-Liste (Matrix)*M
werden Zeilen und Spalten im Wesentlichen transponiert, sodasszip(*M[::-1])
eine 90 ° -Drehung im Uhrzeigersinn ausgeführt wird.JavaScript (ES6), 154
176Bearbeiten versucht, ein wenig zu verkürzen, kann sich aber nicht mit der Lösung von @ Neil messen
Probieren Sie jedes mögliche Rechteck aus und geben Sie die maximale Größe zurück. Wahrscheinlich der gleiche Algorithmus wie bei der Matl-Antwort, nur 6-mal länger.
Eingabe als 2D-Array von Ganzzahlen
Weniger golfen
Dies ist der ursprüngliche Algorithmus, die Golf-Version missbraucht eine Menge Array-Traversing-Funktion anstelle von Schleifen
Prüfung
quelle
APL (Dyalog Extended) ,
272320 Bytes-3 Bytes von Adám und ngn
Probieren Sie es online!
quelle
{⌈/,(×/×1∊⍵⍷⍨⍴∘1)¨⍳⍴⍵}
ist kürzer und einfacher (benötigt nicht einmal Extended).{⌈/∊(×/×⍵⍷⍨⍴∘1)¨⍳⍴⍵}
Brachylog ,
201715 BytesDanke an Kroppeb für 2 Bytes
Probieren Sie es online!
Erläuterung
quelle
aa
kann durchs
Online testenR ,
129122 BytesProbieren Sie es online!
Schlichter und einfacher Brute-Force-Ansatz.
Abgerollter Code und Erklärung:
quelle
Stax , 14 Bytes
Führen Sie es aus und debuggen Sie es
quelle
Matlab 106 Bytes
Ungolfed:
Die Operation in der Schleife beginnt mit der 2D-Faltung
conv2()
des Eingangs-Arrays mit demp*m
Einsen-Array.==p*m
prüft, ob das resultierende Array ein Element gleich enthältp*m
. Das entsprechende Element wird gedreht1
, alle anderen Elemente werden gedreht0
.any()
verwandelt das Array in einen Vektor.1
Ansonsten werden Spalten mit mindestens einem Eintrag ungleich Null angezeigt0
.p*m*()
multipliziert den Vektor, indemp*m
all1
-s zu wirdp*m
.[__,r]
Eckige Klammern verketten das erhaltene Ergebnis mit dem vorherigen Maximalbereich, der in gespeichert istr
. Schließlichmax()
findet den Maximalwert in dem resultierenden Vektor.quelle
any()
zurück,1
ob die Spalte ein Element ungleich Null enthält,0
andernfalls.Matlab
(222)(209)Eigentlich bringt mich diese Lösung in die Schande, dass ich doppelt so groß bin wie die gleiche Sprache, aber ... verdammt, ich hatte 6 Stunden lang darüber nachgedacht! und der Trick ist ein etwas anderer Aufbau als die Antworten von Dennis und Neil.
Die Funktion heißt
Ich könnte mehr Bytes einsparen, wenn die eingeführte Matrixlänge in die Abmessungen der Funktion eingeht, obwohl mehr Golf gespielt wird.
Wie läuft das ab?
Dieser Algorithmus fügt die eigentliche Matrix selbst hinzu und verschiebt sie mit ein wenig Drehen (&) nach links. In jedem Stadium wird die resultierende Matrix als initial festgelegt und zu sich selbst hinzugefügt, wiederholt nach oben verschoben und dann von Anfang an mit der neuen Matrix neu verschoben. Alle Unterelemente aller durch diese Operation erzeugten Matrizen
(original_matrix+shifted_matrix)&shifted_and_original_matrices)
werden auf die Ausgabe maximiert.Beispiel:
quelle
Japt , 30 Bytes
Probieren Sie alle Testfälle aus
Etwa eine Portierung von Dennis 'Jelly-Antwort. Die Testfälle sind einfach 2D-Arrays von Zahlen, die mit dieser Methode aus dem Format der Frage konvertiert werden .
Erläuterung:
quelle
J , 38 Bytes
Probieren Sie es online!
Wie
quelle