Tipps zum Golfen in MATLAB

14

Welche allgemeinen Tipps haben Sie zum Golfen in MATLAB? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas MATLAB-spezifisch sind (z. B. "Kommentare entfernen" ist keine Antwort). Bitte posten Sie einen Tipp pro Antwort.

RAM
quelle
3
Verwandte, aber kein Duplikat: Tipps zum Golfen in Octave
Dennis Jaheruddin

Antworten:

9

Das muss man wissen, bevor man mit dem Golfen beginnt:

In MATLAB-Berechnungen verhält sich ein Zeichen genauso wie sein ASCII-Code.

'abc' - 'a'  % Returns: [0 1 2]
'123' - '0'  % Returns: [1 2 3]
'“' == 8220  % Returns: 1 (logical)
'a':'e'==100 % Returns: [0 0 0 1 0] (logical)
Dennis Jaheruddin
quelle
9

Kürzen von Eigenschaftsnamen

In MATLAB können Zeichenfolgen, die Eigenschaften identifizieren, gekürzt werden, solange dies nicht zu Mehrdeutigkeiten führt.

plot(X,'C','k') % Ambiguous property found.
plot(X,'Co','k') % Expands to Color  (black)

Das hat mir tatsächlich eine Herausforderung eingebracht :)

Sanchises
quelle
2
Sehr schön, obwohl die Antwort richtig ist, möchte ich betonen, dass dies für den Namen von name, valuePaaren gilt, wie oben gezeigt. (Also nicht zu Dingen wie sort(rand(4,1),'descend'))
Dennis Jaheruddin
1
Es gilt auch für einige dieser Dinge, wie conv(1:5,[1 1],'s')zum Beispielconv(1:5,[1 1],'same')
Luis Mendo
6

Das Casting als Zeichen kann durch Verketten mit einem Zeichen erfolgen:

x='a'+magic(5) % Array with character codes of several letters

char(x) % The standard way
['' x] % The compact way

Das spart zwar nur ein Zeichen, kann aber recht häufig verwendet werden.

Dennis Jaheruddin
quelle
5

Zeichenfolgen sind nur Zeichenzeilenvektoren. Dies bedeutet, dass anstelle von

for i=numel(str)
    a=str(i)
    ...
end

du kannst einfach schreiben

for(a=str)
    ...
end

Zum ersten Mal habe ich dies verwendet: /codegolf//a/58387/32352

Sanchises
quelle
4

Wurzeln der Einheit durch diskrete Fourier-Transformation

Gegeben eine positive ganze Zahl n, der Standard - Weg , die zur Erzeugung n-te Wurzeln der Einheit ist

exp(2j*pi*(0:n-1)/n)

Dies gibt die Wurzeln an 1und bewegt sich in der positiven Winkelrichtung. Wenn die Bestellung keine Rolle spielt, kann diese auf gekürzt werden

exp(2j*pi*(1:n)/n)

Da exp(2j*pi/4)gleich der imaginären Einheit ( j) ist, kann dies wie folgt kompakter geschrieben werden (Trick aufgrund von @flawr ):

j.^(4*(0:n-1)/n)

oder

j.^(4*(1:n)/n)

Die diskrete Fourier-Transformation bietet jedoch einen noch kürzeren Weg (dank @flawr zum Entfernen von zwei unnötigen Klammern):

fft(1:n==n)

was die Wurzeln gibt, die 1in der positiven Winkelrichtung beginnen und sich bewegen; oder

fft(1:n==2)

die beginnt bei 1und bewegt sich in negativer Winkelrichtung.


Probieren Sie alle oben genannten Punkte hier aus .

Luis Mendo
quelle
Toller Trick! Sie können es sogar Golf bis zufft(1:n==2)
flawr
@flawr Ich kenne die Vorrangregeln nie ... Danke!
Luis Mendo
3

Iteration über Vektoren in Matrizen.

Wenn ein Satz von Vektoren als Matrix angegeben wird, können Sie diese tatsächlich über eine einzelne for-Schleife iterieren

for v=M
    disp(v);
end

während "traditionell" hätten Sie es wahrscheinlich gerne getan

for k=1:n
    disp(M(:,k));
end

Diesen Trick habe ich erst jetzt bei dieser Herausforderung von @Suever gelernt .

fehlerhaft
quelle
3

Verwandte, aber nicht identische Tipps für Octave .

Ein wenig bekanntes und wenig verwendetes Merkmal von MATLAB und Octave ist, dass die meisten eingebauten Funktionen ohne Klammern aufgerufen werden können. In diesem Fall behandeln sie alles, was darauf folgt, als Zeichenkette (solange es keine Leerzeichen enthält). Wenn es Leerzeichen enthält, benötigen Sie Anführungszeichen. Dies kann häufig verwendet werden, um ein Byte zu speichern, wenn Folgendes verwendet wird disp:

disp('Hello, World!')
disp 'Hello, World!'

Andere, weniger nützliche Beispiele sind:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12

Ich habe dies tatsächlich zweimal in der "Wie hoch können Sie zählen?" -Herausforderung:

strchr sssssssssssssst t

ist äquivalent zu strchr('sssssssssssssst','t')und kehrt zurück 15.

nnz nnnnnnnnnnnnnn

ist äquivalent zu nnz('nnnnnnnnnnnnnn')und kehrt zurück 14.

Sachen wie gt r sfunktioniert auch (äquivalent zu 'r'>'s'oder gt('r','s').

Stewie Griffin
quelle
2

nnz kann manchmal ein paar Bytes sparen:

  • Stellen Sie sich vor, Sie möchten die Summe einer logischen Matrix A. Anstelle von sum(sum(A))oder sum(A(:))können Sie verwenden nnz(a)( nnzimplizit gilt (:)).
  • Wenn Sie die Anzahl der Elemente eines Arrays kennen möchten und sicher sein können, dass es keine Nullen gibt, können Sie stattdessen numel(x)verwenden nnz(x). Dies gilt zum Beispiel, wenn xes sich um eine Zeichenfolge handelt.
Luis Mendo
quelle
2

2D-Faltungskerne

Dies ist vielleicht ein Nischenthema, aber anscheinend nutzen manche Leute die Faltung gern für verschiedene Dinge. [Zitat benötigt]

In 2D werden häufig folgende Kernel benötigt:

0 1 0
1 1 1
0 1 0

Dies kann mit erreicht werden

v=[1,2,1];v'*v>1 %logical
v=[1,0,1];1-v'*v  %as numbers

das ist kürzer als

[0,1,0;1,1,1;0,1,0]

Ein anderer häufig verwendeter Kernel ist

0 1 0
1 0 1
0 1 0

die mit gekürzt werden kann

v=[1,-1,1];v'*v<0   % logical
[0,1,0;1,0,1;0,1,0] % naive verison
fehlerhaft
quelle
Zweiter Kernel als Zahlen, gleiche Byteanzahl:toeplitz([0 1 0])
Luis Mendo
1

Ich finde mich ziemlich oft dabei , ein Mandelbrot-Bild zu berechnen meshgridoder ndgrid, lassen Sie uns sagen, wir initialisieren z

[x,y]=meshgrid(-2:1e-2:1,-1:1e_2,1)

Für die Mandelbrotmenge benötigen wir nun eine weitere Matrix cder Größe xund yaber mit Nullen initialisiert. Dies kann leicht durch Schreiben erfolgen:

c=x*0;

Sie können es auch auf einen anderen Wert initialisieren:

c=x*0+3;

Sie können jedoch tatsächlich einige Bytes sparen, indem Sie einfach eine weitere Dimension hinzufügen in meshgrid/ndgrid:

[x,y,c]=meshgrid(-2:1e-2:1,-1:1e_2,1, 0); %or for the value 3
[x,y,c]=meshgrid(-2:1e-2:1,-1:1e_2,1, 3);

Und Sie können dies so oft tun, wie Sie möchten:

[x,y,c1,c2,c3,c4,c5]=meshgrid(-2:1e-2:1,-1:1e_2,1, 1,pi,exp(3),1e5,-3i)
fehlerhaft
quelle
1

Die eingebauten onesund zerossind in der Regel eine Platzverschwendung. Sie können das gleiche Ergebnis erzielen, indem Sie einfach ein Array / eine Matrix (der gewünschten Größe) mit 0 multiplizieren (um die Ausgabe von zu erhalten zeros) und 1 addieren, wenn Sie die Ausgabe von möchten ones.

d = rand(5,2);

%// Using zeros
z = zeros(size(d));

%// Not using zeros
z = d*0;

%// Using ones
o = ones(size(d));

%// Not using ones
o = 1+d*0

Dies funktioniert auch, wenn Sie einen Spalten- oder Zeilenvektor mit Nullen oder Einsen in der Größe einer Dimension einer Matrix erstellen möchten.

p = rand(5,2);

z = zeros(size(p,1), 1);
z = 0*p(:,1);

o = ones(size(p, 1), 1);
o = 1+0*p(:,1);

Wenn Sie eine Matrix mit einer bestimmten Größe erstellen möchten, können Sie sie verwenden, zerosaber Sie können auch einfach das letzte Element auf 0 setzen und MATLAB den Rest ausfüllen lassen.

%// This
z = zeros(2,3);

%// vs. This
z(2,3) = 0;
Suever
quelle
2
Ich verwende gerne ~(1:n)für 1-d-Null-Vektoren.
Sintax
0

Summation einer Folge von Funktionen

  • Zum Summieren von Funktionen f (x_n), bei denen n ein Vektor aufeinanderfolgender ganzer Zahlen ist, wird feval anstelle von symsum empfohlen.

    Syms x;symsum(f(x),x,1,n);
    Sum(feval(@(x)f(x),1:n));
    

    Beachten Sie, dass eine elementare Operation .*und ./anstelle von paarweisen binären Operationen *und notwendig ist/

  • Wenn die Funktion naiv geschrieben werden kann, ist keine der beiden letzten Möglichkeiten geeignet.

    Wenn die Funktion beispielsweise lautet log, können Sie einfach Folgendes ausführen:, sum(log(1:n))was Folgendes darstellt:

    Sum(f(1:n));
    

    für relativ raffinierte Funktionen, wie log(n)/x^nSie dies tun können:

    Sum(log(1:n)./5.^(1:n))
    

    und in einigen Fällen sogar kürzer, wenn eine Funktion länger ist als f(x)=e^x+sin(x)*log(x)/x...

    Sum(feval(@(y)e.^(y)+sin(y).*log(y)./y,1:n))
    

    das ist bemerkenswert kürzer als sum(feval(@(y)e.^(1:n)+sin(1:n).*log(1:n)./(1:n),1:n))


Hinweis: Dieser Trick kann für andere inklusive Operatoren als prododer angewendet werdenmean


Abr001am
quelle