Suggerimenti per giocare a golf in MATLAB


14

Quali consigli generali hai per giocare a golf in MATLAB? Sto cercando idee che possano essere applicate ai problemi del codice golf in generale che siano almeno in qualche modo specifiche per MATLAB (ad esempio "rimuovere i commenti" non è una risposta). Si prega di inviare un suggerimento per risposta.


3
Correlati, ma non un duplicato: consigli per giocare a golf a Octave
Dennis Jaheruddin,

Risposte:


10

Qualcosa che bisogna sapere prima di iniziare a giocare a golf:

Nei calcoli MATLAB un carattere si comporta come il suo codice ASCII.

'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)

9

Accorciare i nomi delle proprietà

In MATLAB, le stringhe che identificano le proprietà possono essere abbreviate purché non risultino ambiguità.

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

Questo in realtà mi ha vinto una sfida :)


2
Molto bello, anche se la risposta è corretta, voglio sottolineare che questo vale per il nome delle name, valuecoppie come mostrato sopra. (Quindi non per cose del genere sort(rand(4,1),'descend'))
Dennis Jaheruddin il

1
Si applica anche ad alcune di queste cose, come conv(1:5,[1 1],'s')invece diconv(1:5,[1 1],'same')
Luis Mendo il

6

Il casting come carattere può essere eseguito concatenando un carattere:

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

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

Anche se salva solo un carattere, questo può essere usato abbastanza frequentemente.


5

Le stringhe sono solo vettori di righe di caratteri. Questo significa che invece di

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

puoi semplicemente scrivere

for(a=str)
    ...
end

La prima volta che l'ho usato: /codegolf//a/58387/32352


4

Radici di unità tramite trasformata discreta di Fourier

Dato un numero intero positivo n, il modo standard per generare l' nennesima radice dell'unità è

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

Questo dà alle radici a partire 1e muoversi nella direzione angolare positiva. Se l'ordine non ha importanza, questo può essere abbreviato

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

Poiché è exp(2j*pi/4)uguale all'unità immaginaria ( j), questo può essere scritto in modo più compatto come segue (trucco dovuto a @flawr ):

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

o

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

Ma la discreta trasformata di Fourier offre un modo ancora più breve (grazie a @flawr per la rimozione di due parentesi non necessarie):

fft(1:n==n)

che dà le radici partendo 1e muovendosi nella direzione angolare positiva; o

fft(1:n==2)

che inizia da 1e si muove nella direzione angolare negativa.


Prova tutto quanto sopra qui .


Ottimo trucco! Puoi persino giocare a golf fino afft(1:n==2)
flawr

@flawr Non conosco mai le regole di precedenza ... Grazie!
Luis Mendo,

3

nnz a volte può farti risparmiare qualche byte:

  • Immagina di voler la somma di una matrice logica A. Invece di sum(sum(A))o sum(A(:)), è possibile utilizzare nnz(a)( nnzsi applica implicitamente (:)).
  • Se vuoi conoscere il numero di elementi di un array e puoi essere certo che non ci sono zeri, invece di numel(x)poterlo usare nnz(x). Questo è applicabile ad esempio se xè una stringa.

3

Iterazione su vettori in matrici.

Dato un insieme di vettore come matrice, puoi effettivamente scorrere su di essi tramite un singolo ciclo come

for v=M
    disp(v);
end

mentre "tradizionalmente" probabilmente lo avresti fatto come

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

Ho imparato questo trucco solo ora da @Suever in questa sfida .


3

Suggerimenti correlati, ma non identici per Octave .

Una caratteristica poco conosciuta e poco utilizzata sia di MATLAB che di Octave è che la maggior parte delle funzioni incorporate può essere chiamata senza parentesi, nel qual caso tratteranno tutto ciò che la segue come una stringa (purché non contenga spazi). Se contiene spazi sono necessarie le virgolette. Questo può essere spesso usato per salvare un byte quando si usa disp:

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

Altri esempi meno utili includono:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12

L'ho usato due volte in "Quanto in alto puoi contare?" -sfida:

strchr sssssssssssssst t

è equivalente strchr('sssssssssssssst','t')e restituisce 15.

nnz nnnnnnnnnnnnnn

è equivalente nnz('nnnnnnnnnnnnnn')e restituisce 14.

Anche roba come gt r sfunziona (equivalente a 'r'>'s'o gt('r','s').


2

Gli integrati onese zerossono in genere uno spreco di spazio. È possibile ottenere lo stesso risultato semplicemente moltiplicando un array / matrice (della dimensione desiderata) per 0 (per ottenere l'output di zeros) e aggiungere 1 se si desidera l'output di 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

Questo funziona anche se si desidera creare un vettore di colonna o riga di zeri o uno delle dimensioni di una dimensione di una matrice.

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);

Se vuoi creare una matrice di una dimensione specifica che potresti usare zerosma puoi anche assegnare l'ultimo elemento a 0 e fare in modo che MATLAB compili il resto.

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

%// vs. This
z(2,3) = 0;

2
Mi piace usare ~(1:n)per vettori zero 1-d.
sintax,

2

Kernel convoluzione 2D

Questo è forse un argomento di nicchia, ma a quanto pare ad alcune persone piace usare la convoluzione per varie cose qui. [citazione necessaria]

In 2D sono spesso necessari i seguenti kernel:

0 1 0
1 1 1
0 1 0

Questo può essere ottenuto utilizzando

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

che è più breve di

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

Un altro kernel spesso usato è

0 1 0
1 0 1
0 1 0

che può essere abbreviato con

v=[1,-1,1];v'*v<0   % logical
[0,1,0;1,0,1;0,1,0] % naive verison

Secondo kernel come numeri, stesso conteggio dei byte:toeplitz([0 1 0])
Luis Mendo

2

Mi ritrovo abbastanza spesso a usare meshgrido ndgrid, diciamo, vogliamo calcolare un'immagine mandelbrot, quindi inizializziamo ad es

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

Ora per il set mandelbrot abbiamo bisogno di un'altra matrice cdella dimensione di xe yinizializzata con zeri. Questo può essere fatto facilmente scrivendo:

c=x*0;

Puoi anche inizializzarlo su un altro valore:

c=x*0+3;

Ma puoi effettivamente salvare alcuni byte semplicemente aggiungendo un'altra dimensione 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);

E puoi farlo tutte le volte che vuoi:

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

Si noti che nel frattempo c'è la trasmissione automatica: in molti casi il primo esempio potrebbe essere sostituito da x=-2:1d-2:1;y=x'.
Flawr

0

Somma di una sequenza di funzioni

  • Per riassumere le funzioni f (x_n) dove n è un vettore di numeri interi consecutivi, si consiglia feval anziché symsum.

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

    Si noti che l'operazione elementare .*ed ./è necessario, invece di operazioni a coppie binarie *e/

  • Se la funzione può essere scritta ingenuamente, nessuno degli ultimi due modi è adatto.

    per esempio se la funzione è logpuoi semplicemente fare:, sum(log(1:n))che rappresenta:

    Sum(f(1:n));
    

    per funzioni relativamente sofisticate come log(n)/x^npuoi fare:

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

    e ancora più breve in alcuni casi quando una funzione è più lunga come f(x)=e^x+sin(x)*log(x)/x....

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

    che è notevolmente più breve di sum(feval(@(y)e.^(1:n)+sin(1:n).*log(1:n)./(1:n),1:n))


Nota: questo trucco può essere applicato ad altri operatori inclusi come prodomean


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.