Welche allgemeinen Tipps haben Sie zum Golfen in Mathematica? Ich bin auf der Suche nach Ideen, die auf Code-Golf-Probleme im Allgemeinen angewendet werden können, die zumindest etwas spezifisch für Mathematica sind (z. B. "Kommentare entfernen" ist keine Antwort).
(Norm[#-#2]&)
alsEuclideanDistance
.Einige integrierte Funktionen mit langen Namen können durch kürzere Ausdrücke ersetzt werden.
Zum Beispiel:
Total
=>Tr
Transpose
=>Thread
oder\[Transpose]
True
=>1<2
False
=>1>2
Times
=>1##&
Alternatives
=>$|##&
IntegerQ
=>⌊#⌋==#&
a[[1]]
=>#&@@a
a[[All,1]]
=>#&@@@a
ConstantArray[a,n]
=>Array[a&,n]
oderTable[a,{n}]
Union@a
=>{}⋃a
odera⋃a
ToExpression@n
=>FromDigits@n
wennn
ist eine ZahlDivisible[n,m]
=>m∣n
FromDigits[n,2]
=>Fold[#+##&,n]
ifn
ist eine Liste von0
s und1
sComplex@z
=>{1,I}.z
woz
ist eine Liste des Formulars{x,y}
quelle
Thread[{{a,b},{c,d}}]
==Thread[List[{a,b},{c,d}]]
=={List[a,c],List[b,d]}
=={{a,c},{b,d}}
==Transpose[{{a,b},{c,d}}]
Fold
Trick fürFromDigits
funktioniert auch für jede andere Basis außer10
. ZBFromDigits[n,5]
->Fold[4#+##&,n]
(mit dem Bonus, ein zusätzliches Byte für Basen100
und zu speichern1000
).U+F3C7
.Echo
eine Option ist, da sie>>
vor dem Drucken der tatsächlichen Zeichenfolge in STDOUT gedruckt wird (und ein Leerzeichen).Complex[x,y] => {1,I}.{x,y}
denke ichx+y*I
ist viel kürzer mit dem gleichen Effekt?Listen mit wiederholten Werten
Dies ist ein weit verbreiteter Vektor, mit dem man arbeiten kann:
Es stellt sich heraus, dass dies durch ein Byte verkürzt werden kann:
Wenn der Vektor länger als zwei Nullen ist, werden noch mehr Bytes gespeichert. Dies kann auch zum Initialisieren von Nullmatrizen verwendet werden, z. B. ergibt das Folgende eine 2x2-Matrix von Nullen:
Dies kann auch für Werte ungleich Null verwendet werden, wenn sie ausreichend groß oder ausreichend viele oder negativ sind. Vergleichen Sie die folgenden Paare:
Denken Sie jedoch daran, dass Sie ab 6 Werten
1~Table~6
in diesem Fall besser dran sind (möglicherweise früher, abhängig von den Prioritätsanforderungen).Der Grund dafür ist, dass
,
zwei Argumente in die Liste eingefügt werden. Ausgelassene Argumente (überall in Mathematica) sind impliziteNull
s. Darüber hinaus istListable
und0*x
ist Multiplikation0
für fast allex
(mit Ausnahme von Dingen wieInfinity
undIndeterminate
). Hier ist also, was passiert:Für Listen mit
1
s können Sie einen ähnlichen Trick anwenden, indem Sie Exponentiationsregeln anwenden. Es gibt zwei verschiedene Möglichkeiten, um Bytes zu speichern, wenn Sie mindestens drei1
s in der Liste haben:quelle
1^{,,,}
ist ein Byte kleiner als0{,,,}+1
.{,,}^0
. Ich werde den Beitrag bearbeiten.Kennen Sie Ihre reinen Funktionsargumente
Wenn Sie Code golfen, wenden Sie häufig einen funktionalen Ansatz an, bei dem Sie anonyme (reine) Funktionen mit der
&
Kurzschreibensyntax verwenden. Es gibt viele verschiedene Möglichkeiten, auf die Argumente einer solchen Funktion zuzugreifen, und Sie können sich oft ein paar Bytes sparen, wenn Sie die Möglichkeiten genau kennen.Zugriff auf einzelne Argumente
Sie wissen dies wahrscheinlich, wenn Sie zuvor reine Funktionen verwendet haben. Die n - te Argument wird als bezeichnet
#n
und#
dient als Alias für#1
. Wenn Sie also beispielsweise eine Funktion schreiben möchten, die eine andere Funktion und ihr Argument als Parameter verwendet (um das Argument an diese Funktion zu übergeben), verwenden SieDies funktioniert nicht mit negativen Zahlen (wie Sie sie möglicherweise beim Zugriff auf Listen verwenden).
Zugriff auf benannte Argumente (neu in V10)
Eine der wichtigsten neuen Sprachfunktionen in Mathematica 10 ist
Association
s, bei denen es sich im Grunde um Schlüsselwertzuordnungen mit beliebigen Schlüsseltypen handelt, die wie folgt geschrieben wurdenWenn eine solche Zuordnung als erstes Argument an eine reine Funktion übergeben wird, können Sie auf einige ihrer Argumente als benannte Parameter zugreifen:
Beachten Sie, dass sich
#
immer noch wie erwartet auf die gesamte Zuordnung bezieht. Damit die genannten Parameter funktionieren, müssen die Schlüssel Zeichenfolgen sein (dies funktioniert beispielsweise nicht, wenn Sie nicht definierte Variablen verwenden). Diese Zeichenfolgen müssen mit einem Buchstaben beginnen und nur Buchstaben und Ziffern enthalten.Das "Selbst" -Argument
#0
Eine weniger bekannte Funktion ist die, die
#0
ebenfalls vorhanden ist und Ihnen das Funktionsobjekt selbst gibt. Dies kann in Quines und verallgemeinerten Quines sehr nützlich sein. Tatsächlich ist die kürzeste Mathematica-Quine (die ich kenne)Etwas ärgerlich ist, dass Sie nicht genau die Zeichen erhalten, die Sie eingegeben haben. Wenn Sie sie beispielsweise
@
für eine Funktionsanwendung verwenden, wird sie weiterhin als gerendert[...]
und an einigen Stellen werden Leerzeichen eingefügt. Dadurch wird das Quine normalerweise etwas länger, als Sie es gerne hätten, aber es funktioniert immer, wenn Sie zuerst das Quine golfen und dann nur dessen Ausgabe kopieren - was nun ein echtes Quine sein sollte.Abgesehen von Quines bedeutet dies auch, dass Sie rekursiven Code schreiben können, ohne Ihre Funktion benennen zu müssen. Vergleichen Sie diese drei (naiven, aber golfenen) Fibonacci-Implementierungen:
Folgen von Argumenten
Hier beginnt die wahre Magie. Sequenzen werden beim Golfen nicht oft verwendet, da
Sequence
der Name einfach zu lang ist, um ihn die meiste Zeit wert zu sein. Aber in reinen Funktionen leuchten sie. Wenn Sie mit Sequenzen nicht vertraut sind, ähneln sie im Grunde Splats in anderen Sprachen. Wenn Sie eine Sequenz in einerList
oder der Argumentliste einer Funktion verwenden, werden ihre Elemente automatisch in separate Slots erweitert. DamitNun, in reinen Funktionen
##
oder##1
ist eine Folge aller Argumente. Ebenso##2
ist eine Folge aller Argumente aus der zweiten Start,##3
alle Argumente aus der dritten etc. Also zunächst einmal gestartet wurde , können wir reimplementieren nurSequence
wie##&
, spart 5 Byte. Als Beispiel für die Verwendung bietet dies eine Alternative zuJoin@@list
(siehe diesen Tipp ), die keine Bytes speichert, aber dennoch gut zu wissen ist:Dadurch wird die erste Ebene einer verschachtelten Liste effektiv geglättet. Was können wir sonst noch damit machen? Hier ist eine 2 Bytes kürzere Alternative zu
RotateLeft
:Allein für diese Dinge lohnt es sich, diese Funktion zu berücksichtigen. Wir können es jedoch besser machen! Sequenzen werden wirklich interessant, wenn man bedenkt, dass Operatoren tatsächlich als Funktionen unter der Haube implementiert sind. ZB
a+b
wertet das eigentlich ausPlus[a,b]
. Also, wenn wir das eine Sequenz geben ...Dieser Trick wurde in diesem Tipp verwendet , um ein Byte zu sparen
Times
, da die Gegenüberstellung technisch gesehen auch nur ein Operator ist:Sie können es auch verwenden, um ein Byte zu speichern,
Unequal
wenn Sie einen Einzelzeichenwert oder eine Variable haben, von der Sie wissen, dass sie nicht in Ihren Argumenten enthalten sind (diesN
funktioniert wahrscheinlich in 99% der Fälle):Dies wird bei unären Operatoren noch interessanter
-
und/
- die beiden letzteren werden tatsächlich in Bezug auf Multiplikation und Potenzierung implementiert. Hier ist eine Liste der Aktionen, bei denen in der letzten Spalte davon ausgegangen wird, dass der Funktion die Argumente übergeben wurdena, b, c
:Andere gemeinsame Operatoren sind
!=
,==
,&&
,||
. Weniger häufig diejenigen im Auge zu behalten sind|
,@*
,/*
. Abschließend noch ein kleiner Bonus-Trick:Experimentieren Sie weiter mit diesen und lassen Sie mich wissen, wenn Sie andere nützliche oder besonders interessante Anwendungen finden!
quelle
Sqrt@2
oder2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=>Join@@a
(manchmal)Function[x,x^2]
=>xx^2
oder#^2&
a〚1;;-1;;2〛
=>a〚;;;;2〛
a〚2;;-1 ;;2〛
=>a〚2;;;;2〛
a〚All,1〛
=>a〚;;,1〛
{{1}}〚1,1〛
=>Tr@{{1}}
0&~Array~10
=>0Range@10
Range[10^3]
=>Range@1*^3
quelle
〚
und jeweils〛
3 Bytes benötigt werden (UTF8Operatoren als Funktionen
Inspiriert von Dennis 'jüngster Entdeckung für Julia dachte ich, ich würde dies für Mathematica untersuchen. Mir war bewusst, dass Mathematica eine große Anzahl nicht verwendeter Operatoren definiert, aber ich habe ihm nie viel Aufmerksamkeit geschenkt.
Als Referenz finden Sie hier die Liste aller Operatoren in Form einer Rangfolgetabelle. Das Dreieck in der letzten Spalte gibt an, ob dieser Operator eine eingebaute Bedeutung hat oder nicht. Nicht alle, die sich nicht leicht definieren lassen, können es aber die meisten.
Praktischerweise gibt es zwei nicht verwendete Operatoren mit einem Codepunkt von weniger als 256, sodass sie als einzelne Bytes in einer ISO 8859-1-codierten Quelldatei verwendet werden können:
±
(0xB1) kann entweder als unärer Präfixoperator oder als binärer Infixoperator verwendet werden.·
(0xB7) kann als variabler oder n-stelliger Infixoperator für n> 2 verwendet werden.Es gibt jedoch noch einen Haken: Aus irgendeinem Grund benötigen Sie beim Definieren dieser Operatoren ein Leerzeichen vor ihnen, oder Mathematica versucht, eine Multiplikation zu analysieren. Wenn Sie sie verwenden, benötigen Sie jedoch keine Leerzeichen:
Vergleichen Sie dies mit:
Das spart also ein Byte bei der Definition der Funktion und zwei Byte bei der Verwendung. Beachten Sie, dass die Definition von
·
keine Bytes für vier Operanden speichert und Bytes für mehr Operanden anfängt, aber die Verwendung spart möglicherweise immer noch Bytes, abhängig von der Rangfolge der in den Argumenten verwendeten Operatoren. Es ist auch zu beachten, dass Sie kostengünstig eine variable Funktion definieren können, die dann viel effizienter aufgerufen werden kann:Beachten Sie jedoch, dass es nicht einfach ist, diese variablen Funktionen mit einem einzigen Argument aufzurufen. (Sie könnten es tun
CenterDot[x]
oder##&[]·x
aber wenn Sie es tatsächlich brauchen, haben Sie eine gute Chance, mit einer anderen Lösung besser dran zu sein.)Dies spart natürlich nichts für Lösungen, bei denen eine unbenannte Funktion ausreicht, aber manchmal müssen Sie Hilfsfunktionen für die spätere Verwendung definieren, und manchmal ist es kürzer, benannte Funktionen zu definieren, z. B. um verschiedene Definitionen für verschiedene Parameter einzurichten. In diesen Fällen kann die Verwendung eines Operators eine angemessene Menge an Bytes einsparen.
Beachten Sie, dass für die Verwendung dieser ISO 8859-1-codierten Dateien
$CharacterEncoding
ein kompatibler Wert festgelegt werden muss, wie dies bei Windows der Fall istWindowsANSI
. Auf einigen Systemen ist dies die Standardeinstellung, beiUTF-8
der diese Codepunkte nicht aus einzelnen Bytes gelesen werden können.quelle
Auswählen von Werten basierend auf einer Ganzzahl
Die naive Herangehensweise, zwischen
y
und zu wählenz
, je nachdem ob esx
ist0
oder1
istEs gibt jedoch einen kürzeren Weg:
Dies funktioniert, weil in diesem Fall
[[0]]
dasHead
eines Ausdrucks gegeben wirdy
, während[[1]]
nur das erste Element gegeben wird - in diesem Fall das erste Argumentz
.Sie können dies sogar verwenden, um zwischen mehr als zwei Werten zu wählen:
Beachten Sie, dass dies nicht funktioniert, wenn
u
es sich um eine Funktion handelt, die tatsächlich etwas ergibt. Es ist wichtig, dass Mathematica so bleibt,u[v,w]
wie es ist. Dies funktioniert jedoch in den meisten Fällen, auch wennu
es sich bei a um eine Zahl, eine Zeichenfolge oder eine Liste handelt.Credits für diesen Trick gehen an Alephalpha - das habe ich in einer seiner Antworten entdeckt.
Wenn
x
1-basiert statt null-basiert ist, verwenden Sie einfachoder
In einigen seltenen Fällen können Sie sogar die Tatsache nutzen, dass die Multiplikation für einige Werte nicht ausgewertet wird:
Beachten Sie aber , dass Mathematica tatsächlich Neuordnungs die Argumente, eine Multiplikation , wenn es nicht ausgewertete bleibt, so dass die oben ist identisch zu
quelle
Alternativen zu
Length
Dies wurde mit einigen Vorschlägen von LegionMammal978 und Misha Lavrov komplett neu geschrieben. Vielen Dank an beide.
In vielen Fällen
Length
kann mit etwas gekürzt werdenTr
. Die Grundidee ist, die Eingabe in eine Liste von1
s umzuwandeln, so dass sieTr
summiert werden, was dann der Länge der Liste entspricht.Die gebräuchlichste Methode hierfür ist
1^x
(für eine Listex
). Das funktioniert , weilPower
istListable
und1^n
für die meisten Atom Werten
ist nur1
(einschließlich aller Zahlen, Strings und Symbole). Damit können wir schon ein Byte sparen:Dies setzt natürlich voraus, dass dies
x
ein Ausdruck mit höherer Priorität ist als^
.Wenn
x
nur0
s und1
s enthalten sind, können wir ein weiteres Byte mit speichernFactorial
(vorausgesetzt, esx
hat eine höhere Priorität als!
):In einigen seltenen Fällen
x
möglicherweise eine niedrigere Priorität als,^
aber immer noch eine höhere Priorität als die Multiplikation. In diesem Fall hat es auch eine niedrigere Priorität als@
, also müssen wir wirklich mit vergleichenLength[x]
. Ein Beispiel für einen solchen Operator ist.
. In diesen Fällen können Sie weiterhin ein Byte mit diesem Formular speichern:Abschließend noch einige Anmerkungen zu den Listen, auf denen dies funktioniert:
Wie oben erwähnt, funktioniert dies bei flachen Listen, die nur Zahlen, Zeichenfolgen und Symbole enthalten. Es funktioniert jedoch auch auf einigen tieferen Listen, obwohl es tatsächlich etwas anderes berechnet. Bei einem n- D-Rechteckarray erhalten
Tr
Sie mit die kürzeste Dimension (im Gegensatz zur ersten). Wenn Sie wissen, dass die äußerste Dimension die kürzeste ist, oder wenn Sie wissen, dass sie alle gleich sind, sind dieTr
-Ausdrücke immer noch äquivalent zuLength
.quelle
Length@x == Tr[1^x]
. Sollte mit den meisten Listen funktionieren.Tr[x!]
anstatt esTr[1^x]
zux
verwenden.Entdecken Sie rekursive Lösungen - Mathematica ist ein Multiparadigma, aber der funktionale Ansatz ist oft der wirtschaftlichste.
NestWhile
kann eine sehr kompakte Lösung für Suchprobleme seinNestWhileList
undFoldList
ist leistungsstark, wenn Sie die Ergebnisse von Zwischeniterationen zurückgeben oder verarbeiten müssen.Map (/@)
,Apply (@@, @@@)
,MapThread
, Und wirklich alles auf Wolframs Functional Programming Dokumentation Seite ist potent Sachen.Verkürzte Form zum Inkrementieren / Dekrementieren - Zum Beispiel, anstatt
While[i<1,*code*;i++]
Sie tun könnenWhile[i++<1,*code*]
Vergessen Sie nicht, dass Sie vorab inkrementieren / dekrementieren können - zum Beispiel
--i
anstelle voni--
. Dies kann manchmal einige Bytes im umgebenden Code einsparen, indem eine vorbereitende Operation beseitigt wird.Fazit zu David Carrahers Nr. 5: Wenn dieselbe Funktion mehrmals verwendet wird, können durch Zuweisen eines Symbols Bytes gespart werden. Wenn Sie beispielsweise
ToExpression
4-mal in einer Lösung verwenden,t=ToExpression
können Sie siet@*expression*
danach verwenden. Bevor Sie dies tun, sollten Sie jedoch prüfen, ob die wiederholte Anwendung derselben Funktion eine Möglichkeit für einen wirtschaftlicheren rekursiven Ansatz darstellt.quelle
MapThread
kann oft durch ersetzt werden\[Transpose]
. TIO .Nicht verwenden,
{}
wenn Sie verwenden@@@
.In einigen Fällen können Sie auf einen Ausdruck wie den folgenden stoßen:
Es ist möglich, Bytes durch Schreiben zu reduzieren:
Alternatives
hat eine sehr niedrige Priorität, daher ist es im Allgemeinen in Ordnung, Ausdrücke zu schreiben (eine bemerkenswerte Ausnahme sind reine Funktionen; Sie können sie nur im ganz linken Element von verwendenAlternatives
).Beachten Sie, dass
f@@a|b|c
(anstelle vonf@@{a,b,c}
) nicht funktioniert, daApply
es eine höhere Priorität als hatAlternative
.In diesem Fall sollten Sie einfach verwenden
f@@{a,b,c}
.quelle
Nur Mathematica 10
Bedienerformulare
Mathematica 10 unterstützt sogenannte "Operator-Formulare", dh es können grundsätzlich einige Funktionen ausgeführt werden. Durch das Aufrufen einer Funktion wird eine neue Funktion erstellt, indem einer ihrer Operatoren festgelegt wird. Angenommen, Sie verwenden
SortBy[list, somereallylongfunction&]
viele verschiedenelist
s. Früher hätte man wahrscheinlich zugewiesenSortBy
zus
und die reine Funktionf
soJetzt können Sie curry
SortBy
, was bedeutet, dass Sie jetzt tun könnenDas gleiche funktioniert für viele andere Funktionen, die eine Liste oder Funktionsargument nehmen, einschließlich (aber nicht beschränkt auf)
Select
,Map
,Nearest
etc.ybeltukov über Mathematica.SE konnte eine vollständige Liste dieser erstellen :
Zusammensetzung und RightComposition
Es gibt neue Abkürzungen für
Composition
(@*
) undRightComposition
(/*
). Ein offensichtlich ausgefallenes Beispiel, in dem diese Zeichen speichern können, ist in den folgenden drei entsprechenden Zeilen zu sehenquelle
Schreiben Sie keine 0-Argument-Funktionen
Code wie dieser wird nicht benötigt:
Sie können einfach eine Variable mit verwenden
:=
, um eine Neubewertung der rechten Seite zu erzwingen:Dies bedeutet auch, dass Sie jede Aktion, die Sie häufig ausführen (auch wenn es sich nur
n++
um eine Art handelt ), auf Kosten von 5 Byte einem einzelnen Zeichen zuordnen können. Im Falle, dassn++
es sich nach dem vierten Gebrauch auszahlt:quelle
Verwenden Sie
%
, um eine freie Variable zu erhaltenDieser Tipp gilt nur, wenn die REPL-Umgebung von Mathematica angenommen werden kann.
%
ist nicht definiert, wenn Code als Skript ausgeführt wird.Wenn Sie können die Verwendung der REPL Eigenschaften machen, dies nicht tun:
Denken Sie stattdessen daran, dass Mathematica den zuletzt ausgewerteten Ausdruck (mit Zeilenende) in
%
folgendem Verzeichnis speichert :Die hinzugefügte Newline kostet ein Byte, aber Sie sparen zwei, indem Sie sie entfernen
a=
, sodass insgesamt ein Byte eingespart wird .In einigen Fällen (z. B. wenn Sie den Wert von
a
ohnehin drucken möchten ) können Sie sogar die folgenden;
zwei Bytes weglassen:Ein oder zwei Bytes mögen ziemlich klein erscheinen, aber dies ist ein wichtiger Fall, da das Extrahieren von wiederholten Ausdrücken (was eine sehr häufige Technik ist) beim Golfen viel nützlicher ist:
Die normale Technik zum Extrahieren von wiederholten Ausdrücken kostet vier Bytes Overhead, die bei weiteren Verwendungen des Ausdrucks eingespart werden müssen. Hier ist eine kurze Tabelle der Mindestanzahl von Verwendungen eines Ausdrucks (nach Länge des Ausdrucks) zum Extrahieren in eine benannte Variable, um etwas zu speichern:
Mit der unbenannten Variablen können einige Bytes viel häufiger gespeichert werden:
Ich glaube nicht ,
%%
oder%n
kann für den Golfsport verwendet werden, denn wenn man sich zumindest nicht zweimal verwenden, können Sie nur den Ausdruck in Ordnung bringen , wo es gebraucht wird . Und wenn Sie es zweimal verwenden, hebt das zusätzliche Zeichen im Variablennamen die Einsparungen auf, die durch das Weglassen einiger Zeichen entstehenx=
.quelle
Prüfen, ob eine Liste sortiert ist
Dies ist im Wesentlichen eine Konsequenz aus diesem Tipp, aber dies ist eine ausreichend häufige Aufgabe, die meiner Meinung nach eine eigene Antwort rechtfertigt.
Der naive Weg zu überprüfen, ob eine Liste in Ordnung ist, ist zu verwenden
Wir können ein Byte besser machen
Dies funktioniert jedoch nicht, wenn wir nicht das haben, was wir bereits in einer Variablen einchecken möchten. (Wir brauchen etwas,
Sort[a=...]==a
das unnötig lang ist.) Es gibt jedoch eine andere Option:Das Beste daran ist, dass hiermit überprüft werden kann, ob die Eingabe für die gleiche Byteanzahl in umgekehrter Reihenfolge sortiert ist:
Ein weiteres Byte kann gespeichert werden, wenn a) wir wissen, dass die Listenelemente verschieden sind und b) wir eine Untergrenze zwischen 0 und 9 kennen (einschließlich; oder Obergrenze für umgekehrte Sortierreihenfolge):
Um herauszufinden, warum dies funktioniert, lesen Sie "Sequences of arguments" in dem oben verlinkten Tipp.
quelle
##>0&@@a
. Ähnliches gilt für die obere Schranke für sortiert.Eine Zeichenfolge wiederholen
Anstatt zu
StringRepeat[str,n]
benutzen(0Range[n]+str)<>""
. Oder wennstr
es nicht auf Slot-Argumente ankommt, ist es noch besser,Array[str&,n]<>""
wie in diesem Tipp beschrieben.quelle
StringRepeat[s,n+1]
verwendenArray[s&,n]<>s
(auch wenn Sie bereitsn+1
eine Variable haben).Table[str,n]<>""
Wenn Sie eine Liste mit in umgekehrter Reihenfolge sortierten Nummern benötigen, verwenden Sie diese nicht
aber
um sechs Bytes zu sparen. Das Sortieren nach einem negativen Wert ist auch in folgenden
SortBy
Szenarien hilfreich :quelle
-Sort@-x
?Sie können einen Ausdruck einfügen, in
Break
dem ein oder zwei Zeichen gespeichert werden können. Beispiel ( andere Details sind der Übersichtlichkeit halber nicht dargestellt ):kann in verwandelt werden
ein Zeichen speichern. Wenn der betreffende Ausdruck keine niedrigere Priorität als die Funktionsanwendung hat, können Sie sogar ein anderes Zeichen speichern:
kann in verwandelt werden
Obwohl nicht dokumentiert,
Break
scheint das Argument to von der umgebenden Schleife zurückgegeben zu werden, was möglicherweise zu noch mehr Einsparungen führen kann.quelle
s
Verwenden Sie, um alle Leerzeichen aus einer Zeichenfolge zu entfernenDas heißt, verwenden Sie
StringSplit
die Standardeinstellung (aufgeteilt in Nicht-Whitespace-Komponenten) und fügen Sie sie einfach wieder zusammen. Das gleiche ist wahrscheinlich immer noch das kürzeste, wenn Sie ein anderes Zeichen oder einen anderen Teilstring entfernen möchten:quelle
Alternativen zu
Range
Eine sehr häufige Aufgabe ist es, eine Art Funktion auf alle Zahlen von 1 bis a anzuwenden
n
(normalerweise als Eingabe angegeben). Grundsätzlich gibt es drei Möglichkeiten, dies zu tun (am Beispiel einer unbenannten Identitätsfunktion):Ich tendiere dazu, mich für den ersten zu entscheiden (aus welchem Grund auch immer), aber dies ist selten die beste Wahl.
Verwenden Sie
Array
stattdessenDas obige Beispiel zeigt, dass using
Array
dieselbe Byteanzahl hat. Es hat jedoch den Vorteil, dass es sich um einen einzelnen Ausdruck handelt. Insbesondere wenn Sie das Ergebnis mit einer Funktion weiterverarbeiten möchten, könnenf
Sie die Präfixnotation verwenden, die ein Byte darüber speichertRange
:Darüber hinaus können Sie möglicherweise Klammern um Ihre unbenannte Funktion weglassen, die Sie möglicherweise mit benötigen
Range
, zWenn Sie es nicht weiter verwenden möchten (oder mit einem Operator, der eine geringere Priorität hat), können Sie sich stattdessen
Array
selbst in Infixnotation schreiben und auch ein Byte speichern:Daher
Array
ist mit ziemlicher Sicherheit besser alsRange
.Verwenden Sie
Table
stattdessenJetzt muss die Tabelle 3 Bytes oder mindestens 2 Bytes umfassen, wenn die Infixnotation eine Option ist:
Wenn Sie keine Infix-Notation verwenden,
Table
können Sie möglicherweise Klammern weglassen, wenn Ihre Funktion aus mehreren Anweisungen besteht:Dies ist noch länger, bringt aber zusätzliche Einsparungen in dem unten genannten Fall.
Die wirklichen Einsparungen ergeben sich aus der Tatsache, dass
Table
der laufenden Variablen ein Name gegeben werden sollte. Oft haben Sie unbenannte Funktionen verschachtelt, bei denen Sie die äußere Variable in einer der inneren Funktionen verwenden möchten. Wenn das passiert,Table
ist kürzer alsRange
:Sie speichern nicht nur die Zeichen für die Zuweisung
i
, sondern können die Funktion möglicherweise auch auf eine einzelne Anweisung reduzieren, sodass Sie die Infix-Notation darüber verwenden können. Als ReferenzArray
ist auch in diesem Fall länger, aber immer noch kürzer alsRange
:Wann würden Sie tatsächlich verwenden
Range
?Wann immer Sie keinen Funktionsaufruf benötigen, um die Werte zu verarbeiten, zB wenn das Mapping über eine vektorisierte Operation durchgeführt werden kann. Zum Beispiel:
Natürlich ist es auch kürzer, wenn Sie überhaupt keine Funktion abbilden möchten, z
quelle
f/@Range[x]
regelmäßig verwendet ...Finden der kleinsten Zahl, die eine Bedingung erfüllt
Einige Konstrukte wie
i=1;While[cond[i],i++]
sind in Ordnung, aber es gibt eine Alternative, die zwei Bytes kürzer ist:Der obige Code ersetzt wiederholt eine Zahl
i
durch,i+1
solange die Bedingung erfüllt istcond[i]
. In diesem Falli
beginnt um1
.Beachten Sie, dass die standardmäßige maximale Anzahl von Iterationen 2 ^ 16 (= 65536) beträgt. Wenn Sie mehr Iterationen als das brauchen,
While
wäre besser. (MaxIterations->∞
ist zu lang)quelle
Missbrauch Kurzschlussauswertung
Sie können manchmal durch
If
einen logischen Operator ersetzen .Angenommen, Sie möchten eine Funktion erstellen, mit der überprüft wird, ob eine Zahl eine Primzahl
2*(number) - 1
ist.Es ist kürzer, wenn Sie
&&
stattdessen verwenden:Selbst wenn Sie mehrere Ausdrücke haben, speichern Sie immer noch Byte (s):
Sie können
||
für Fälle verwenden, in denen die Bedingung sein sollFalse
:Diese Tricks funktionieren, weil logische Operatoren kurzgeschlossen werden können . Das zweite Argument und danach müssen nicht einmal gültige boolesche Ausdrücke sein.
Dies funktioniert natürlich nicht, wenn Sie den Rückgabewert von
If
benötigen oder wenn Sie sowohl wahre als auch falsche Argumente von benötigenIf
.quelle
Hier ist eine Liste mit vielen Bedienereingabeformularen, die viele Dinge verkürzen können. Einige davon wurden in anderen Posts erwähnt, aber die Liste ist lang und ich bin immer überrascht, ein paar neue Dinge dort zu finden:
quelle
Verwenden
Optional (:)
Optional (:)
kann verwendet werden, um Listen in Ersetzungen zu erweitern, ohne dass eine separate Regel für die Erweiterung definiert werden muss.Diese Antwort von mir und diese Antwort von @ngenisis sind Beispiele.
Verwendungszweck
Der obige Ersatz verwendet zuerst das Muster
{p___, a_, b_, q___}
und findet eine Übereinstimmung,b
die eine bestimmte Bedingung erfüllt.Wenn keine solche Übereinstimmung gefunden wird, wird ausgelassen
a_
und stattdessen gesucht{p___, b_, q___}
.a
wird nicht in die Suche einbezogen und es wird davon ausgegangen, dass der Wert vorhanden ist0
.Beachten Sie, dass die zweite Mustersuche nur
b
am Anfang der Liste funktioniert . Wenn einb
Wert, der eine Bedingung erfüllt, in der Mitte liegt,{p___, a_, b_, q___}
würde er stattdessen (mit höherer Priorität) mit ihm übereinstimmen.Das Ersetzen entspricht dem Voranstellen von a,
0
wenn eineb
Bedingung am Anfang der Liste erfüllt ist. (dh es muss keine separate Regel definiert werden{b_, q___} /; cond[b] :> ...
)quelle
Wissen, wann (und wann nicht) benannte reine Funktionsargumente verwendet werden sollen
Für Code-Golf werden reine
Function
Argumente am häufigsten mitSlot
s referenziert . zB#
für das erste Argument,#2
für das zweite usw. (siehe diese Antwort für weitere Details).In vielen Fällen möchten Sie
Function
s verschachteln . Beispiel:1##&@@#&
is aFunction
nimmt eine Liste als erstes Argument und gibt das Produkt seiner Elemente aus. Hier ist diese Funktion inTreeForm
:An die oberste Ebene übergebene Argumente
Function
können nurSlot
s undSlotSequence
s füllen , die auf der obersten Ebene vorhanden sind. Dies bedeutet in diesem Fall, dassSlotSequence
die innerenFunction
keine Möglichkeit haben, auf Argumente auf der obersten Ebene zuzugreifenFunction
.In einigen Fällen möchten Sie jedoch möglicherweise, dass ein
Function
in einem anderen Element verschachteltesFunction
Element Argumente nach außen verweistFunction
. Zum Beispiel möchten Sie vielleicht so etwas wieArray[fun,...]&
, wo die Funktionfun
von einem Argument auf der obersten Ebene abhängtFunction
. Nehmen wir der Vollständigkeit halber an, dassfun
der Rest des Quadrats seines Eingangsmoduls den Eingang zur obersten Ebene geben sollFunction
. Eine Möglichkeit, dies zu erreichen, besteht darin, das Argument der obersten Ebene einer Variablen zuzuweisen:Wo immer es
x
im Inneren erscheintFunction
Mod[#^2,x]&
, bezieht es sich auf das erste Argument im ÄußerenFunction
, wohingegen#
es sich auf das erste Argument im Inneren beziehtFunction
. Ein besserer Ansatz besteht darin, die Tatsache zu verwenden, dassFunction
eine Form mit zwei Argumenten vorliegt, wobei das erste Argument ein Symbol oder eine Liste von Symbolen ist, die benannte Argumente für dieFunction
(im Gegensatz zu unbenanntenSlot
s) darstellen. Das spart uns in diesem Fall drei Bytes:
ist das Drei-Byte-ZeichenU+F4A1
für den privaten Gebrauch, das den binären Infix-Operator darstellt\[Function]
. Sie können auch die binäre Form einesFunction
anderen verwendenFunction
:Dies entspricht dem oben Gesagten. Der Grund ist, dass, wenn Sie benannte Argumente verwenden, von
Slot
s undSlotSequences
angenommen wird, dass sie zu den nächsthöheren gehören,Function
die keine benannten Argumente verwenden.Nur weil wir
Function
s auf diese Weise nisten können, heißt das nicht, dass wir es immer tun sollten. Wenn wir beispielsweise die Elemente einer Liste auswählen möchten, die kleiner als die Eingabe sind, könnten wir versucht sein, Folgendes zu tun:Es wäre tatsächlich kürzer zu verwenden
Cases
und die Notwendigkeit einer VerschachtelungFunction
gänzlich zu vermeiden :quelle
Sie können ein Byte speichern, indem Sie umgehen
Prepend
oderPrependTo
:oder
Leider hilft dies nicht für die häufiger
Append
, dieArray.push()
in anderen Sprachen das kürzeste Äquivalent zu einem zu sein scheint .quelle
Mathematica 10.2:
BlockMap
istPartition
+Map
Dieser Tipp könnte auch den Titel "Alle Versionshinweise lesen" tragen. (Als Referenz finden Sie hier die Versionshinweise für 10.2 und hier für die heutige Version 10.3 .)
Auf jeden Fall enthalten auch kleinere Releases eine Fülle neuer Funktionen, und eine der nützlicheren (für das Golfen) ab 10.2 ist die neue
BlockMap
Funktion. Es kombiniert im WesentlichenPartition
undMap
ist ideal für Golfer, daPartition
es ziemlich oft verwendet wird und es ist ein wirklich ärgerlich langer Funktionsname. Die neue Funktion wird sich nichtPartition
von selbst verkürzen , aber wenn Sie eine Funktion auf die Partitionen abbilden möchten (was wahrscheinlich häufig vorkommt), können Sie jetzt ein oder zwei Bytes speichern:Die Einsparungen werden noch größer, wenn Sie sich durch die neue Position der unbenannten Funktion einige Klammern sparen können:
Leider habe ich keine Ahnung, warum sie nicht auch hinzugefügt haben,
BlockApply
während sie dabei waren ...Beachten Sie auch, dass
BlockMap
der vierte Parameter, mitPartition
dem Sie eine zyklische Liste erstellen können, nicht unterstützt wird :quelle
Speichern von Funktionen und Ausdrücken in einer Variablen
Wenn Ihre Antwort dieselben Funktionen oder Ausdrücke mehrmals verwendet, können Sie sie in Variablen speichern.
Wenn Ihr Ausdruck Länge ist
l
und Sie ihnn
mal verwenden, würde er normalerweisel * n
Bytes verbrauchen.Wenn Sie es jedoch in einer Variablen der Länge 1 speichern, werden nur
3 + l + n
Bytes benötigt (oder2 + l + n
Bytes, wenn Sie die Variable dort zuweisen, wo Sie sie nicht benötigen,CompoundExpression (;)
oder Klammern).Betrachten wir zum Beispiel ein einfaches Problem, bei dem zwei Primzahlen kleiner als N sind.
Man könnte diese 54-Byte-Lösung schreiben:
In diesem Beispiel wird die Funktion
PrimeQ
dreimal verwendet.Durch die Vergabe
PrimeQ
eines Variablennamens kann die Byteanzahl reduziert werden. Beide der folgenden sind 48 Bytes (54 - 6 Bytes):quelle
Verwenden Sie
Sort
anstelle von, um eine aufsteigende Schlüsselwertliste zu erhaltenSortBy
Für Listen wie
list = {{1, "world"}, {0, "universe"}, {2, "country"}}
sind die folgenden drei Aussagen fast gleichwertig.Kombinieren
Select
undSortBy
Manchmal müssen wir Einträge aus einer größeren Menge auswählen und sortieren, um ein Minimum / Maximum zu finden. Unter bestimmten Umständen können zwei Operationen zu einer zusammengefasst werden.
Zum Beispiel sind die folgenden beiden Aussagen zumindest fast gleichwertig.
und
1/0
istComplexInfinity
, was "größer" ist als alle reellen Zahlen.Für eine Schlüsselwertliste zum Beispiel:
quelle
Abflachen
Array
mit##&
Verwenden Sie
##&
als viertes Argument ein mehrdimensionales Array, um eine Liste der Ergebnisse zu berechnen, die reduziert werden müssen. Dadurch werden die Köpfe des Arrays durch##&
(äquivalent zuSequence
) ersetztList
, sodass das Endergebnis eine (flache)Sequence
Ergebnismenge ist.Vergleichen Sie in zwei Dimensionen
Natürlich sind
Join@@Array[f,dims]
immer noch 2 (oder 3, wenn die Infixnotation verwendet werden kann) Bytes kürzer als{Array[f,dims,1,##&]}
.In drei oder mehr Dimensionen
{Array[f,dims,origin,##&]}
ist immer kürzer als die Alternative, auch wenn der Ursprung 1 ist.quelle
Standardwerte
Standardwerte behandeln fehlende Musterargumente auf effiziente Weise. Wenn wir zum Beispiel
Exp[c_*x]
eine Regel für einen beliebigen Wert vonc
, the naïve, mit einem Muster abgleichen möchtenVerwendet viel mehr Bytes, als wenn der Standardwert verwendet wird,
c
wenn er fehlt:Die Verwendung eines Standard wird mit einem Punkt nach dem Muster angegeben:
c_.
.Vorgabewerte sind mit Operationen verknüpft: Im obigen Beispiel befindet sich die Operation
Times
inc_.*x
, und ein fehlender Wert fürc_
wird daher dem mitTimes
1 verknüpften Vorgabewert entnommen . FürPlus
ist der Vorgabewert 0:Für
Power
Exponenten ist der Standardwert 1:quelle