Oft erfordert eine Aufgabe echte Arrays. Nehmen Sie zum Beispiel die Aufgabe, Befunge oder> <> zu implementieren. Ich habe versucht, das Array
Modul dafür zu verwenden, aber es ist wirklich umständlich, da ich das Gefühl habe, viel zu ausführlich zu programmieren. Kann mir jemand helfen, wie man solche Code-Golf-Aufgaben weniger ausführlich und funktionaler löst?
11
Antworten:
Zunächst empfehle ich Data.Vector , in einigen Fällen eine schönere Alternative zu Data.Array .
Array
undVector
sind ideal für einige Memoisierungsfälle, wie in meiner Antwort auf "Finden maximaler Pfade" gezeigt . Einige Probleme lassen sich jedoch nicht einfach in einem funktionalen Stil ausdrücken. Zum Beispiel fordert Problem 28 in Project Euler die Summierung der Zahlen auf den Diagonalen einer Spirale. Sicher, es sollte ziemlich einfach sein, eine Formel für diese Zahlen zu finden, aber die Konstruktion der Spirale ist schwieriger.Data.Array.ST bietet einen veränderlichen Array-Typ. Allerdings ist die Art Situation ein Chaos: Es verwendet eine Klasse Marray jeden einzelnen seiner Methoden mit Ausnahme zu überlasten runSTArray . Sofern Sie nicht vorhaben, ein unveränderliches Array von einer veränderlichen Array-Aktion zurückzugeben, müssen Sie eine oder mehrere Typensignaturen hinzufügen:
Trotzdem fiel meine Lösung für Euler 28 ziemlich gut aus und erforderte diese Typensignatur nicht, weil ich sie verwendete
runSTArray
.Verwenden von Data.Map als "veränderbares Array"
Wenn Sie einen veränderlichen Array-Algorithmus implementieren möchten , können Sie auch Data.Map verwenden . Wenn Sie ein Array verwenden, wünschen Sie sich eine Funktion wie diese, die ein einzelnes Element eines Arrays ändert:
Leider würde dies das Kopieren des gesamten Arrays erfordern, es sei denn, die Implementierung verwendete eine Copy-on-Write-Strategie, um dies nach Möglichkeit zu vermeiden.
Die gute Nachricht ist,
Data.Map
hat eine Funktion wie diese, einfügen :Da
Map
es intern als ausgeglichener Binärbaum implementiert ist, benötigt esinsert
nur O (log n) Zeit und Raum und behält die Originalkopie bei. Daher bietet esMap
nicht nur ein etwas effizientes "veränderbares Array", das mit dem funktionalen Programmiermodell kompatibel ist, sondern ermöglicht es Ihnen sogar, "in die Vergangenheit zu reisen", wenn Sie dies wünschen.Hier ist eine Lösung für Euler 28 mit Data.Map:
Die Knallmuster verhindern einen Stapelüberlauf, der dadurch verursacht wird, dass die Akkumulatorelemente (Cursor, Nummer und Karte) erst am Ende verwendet werden. Bei den meisten Code-Golfspielen sollten Eingabefälle nicht groß genug sein, um diese Bestimmung zu benötigen.
quelle
Die glatte Antwort lautet: Verwenden Sie keine Arrays. Die nicht ganz so klare Antwort lautet: Versuchen Sie, Ihr Problem so zu überdenken, dass keine Arrays erforderlich sind.
Oft kann ein Problem mit einigen Gedanken überhaupt ohne Array-ähnliche Struktur gelöst werden. Hier ist zum Beispiel meine Antwort auf Euler 28:
Was hier im Code ausgedrückt wird, ist das Muster der Folge von Zahlen, wenn sie um die rechteckige Spirale wachsen. Die Zahlenmatrix selbst musste nicht dargestellt werden.
Der Schlüssel zum Denken über Arrays hinaus besteht darin, darüber nachzudenken, was das vorliegende Problem tatsächlich bedeutet und nicht, wie Sie es als Bytes im RAM darstellen könnten. Dies kommt nur mit Übung (vielleicht ein Grund, warum ich so viel Code-Golf spiele!)
Ein anderes Beispiel ist, wie ich das Finden maximaler Pfade Code-Golf gelöst habe . Dort wird das Verfahren zum zeilenweisen Durchleiten der Teillösungen als Welle durch die Matrix direkt durch die Faltoperation ausgedrückt. Denken Sie daran: Auf den meisten CPUs können Sie das Array nicht als Ganzes gleichzeitig bearbeiten: Das Programm muss es im Laufe der Zeit durchlaufen. Möglicherweise wird zu keinem Zeitpunkt das gesamte Array auf einmal benötigt.
Natürlich werden einige Probleme so angegeben, dass sie von Natur aus Array-basiert sind. Sprachen wie> <>, Befunge oder Brainfuck haben Arrays im Herzen. Auf Arrays kann jedoch auch dort häufig verzichtet werden. Siehe zum Beispiel meine Lösung zur Interpretation von Brainfuck . Der eigentliche Kern seiner Semantik ist ein Reißverschluss . Um so zu denken, konzentrieren Sie sich auf die Zugriffsmuster und die Struktur, die näher an der Bedeutung des Problems liegt. Oft muss dies nicht in ein veränderliches Array gezwungen werden.
Wenn alles andere fehlschlägt und Sie ein Array verwenden müssen, sind die Tipps von @ Joey ein guter Anfang.
quelle