Conseils pour jouer au golf à MATLAB

14

Quels conseils généraux avez-vous pour jouer au golf dans MATLAB? Je cherche des idées qui peuvent être appliquées aux problèmes de golf de code en général qui sont au moins quelque peu spécifiques à MATLAB (par exemple, "supprimer les commentaires" n'est pas une réponse). Veuillez poster un pourboire par réponse.

RAM
la source
3
Connexes, mais pas en double: Conseils pour jouer au golf à Octave
Dennis Jaheruddin

Réponses:

10

Quelque chose que l'on doit savoir avant de commencer à jouer au golf:

Dans les calculs MATLAB, un caractère se comporte de la même manière que son code 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)
Dennis Jaheruddin
la source
9

Raccourcir les noms de propriété

Dans MATLAB, les chaînes identifiant les propriétés peuvent être raccourcies tant qu'elles n'entraînent pas d'ambiguïté.

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

En fait, m'a en gagné un défi :)

Sanchises
la source
2
Très bien, bien que la réponse soit correcte, je tiens à souligner que cela s'applique au nom des name, valuepaires comme indiqué ci-dessus. (Donc pas pour des choses comme sort(rand(4,1),'descend'))
Dennis Jaheruddin
1
Cela s'applique également à certaines de ces choses, comme conv(1:5,[1 1],'s')au lieu deconv(1:5,[1 1],'same')
Luis Mendo
6

Le cast en tant que caractère peut être effectué par concaténation avec un caractère:

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

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

Bien qu'il n'enregistre qu'un seul caractère, cela peut être utilisé assez fréquemment.

Dennis Jaheruddin
la source
5

Les chaînes ne sont que des vecteurs de lignes de caractères. Cela signifie qu'au lieu de

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

vous pouvez simplement écrire

for(a=str)
    ...
end

La première fois que j'ai utilisé ceci: /codegolf//a/58387/32352

Sanchises
la source
4

Racines de l'unité via une transformée de Fourier discrète

Étant donné un entier positif n, la façon standard de générer les racinesn -th de l'unité est

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

Cela permet aux racines de commencer 1et de se déplacer dans la direction angulaire positive. Si la commande n'a pas d'importance, cela peut être raccourci

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

Comme exp(2j*pi/4)est égal à l'unité imaginaire ( j), cela peut être écrit de manière plus compacte comme suit (astuce due à @flawr ):

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

ou

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

Mais la transformée de Fourier discrète offre un moyen encore plus court (grâce à @flawr pour avoir supprimé deux parenthèses inutiles):

fft(1:n==n)

ce qui donne les racines commençant 1et se déplaçant dans la direction angulaire positive; ou

fft(1:n==2)

qui commence à 1et se déplace dans la direction angulaire négative.


Essayez tout ce qui précède ici .

Luis Mendo
la source
Super astuce! Vous pouvez même fft(1:n==2)
jouer
@flawr Je ne connais jamais les règles de priorité ... Merci!
Luis Mendo
3

nnz peut parfois vous faire économiser quelques octets:

  • Imaginez que vous vouliez la somme d'une matrice logique A. Au lieu de sum(sum(A))ou sum(A(:)), vous pouvez utiliser nnz(a)( nnzs'applique implicitement (:)).
  • Si vous voulez connaître le nombre d'éléments d'un tableau, et vous pouvez être sûr qu'il n'y a pas de zéros, au lieu de numel(x)vous pouvez utiliser nnz(x). Cela s'applique par exemple si xest une chaîne.
Luis Mendo
la source
3

Itération sur des vecteurs dans des matrices.

Étant donné un ensemble de vecteurs comme matrice, vous pouvez réellement les parcourir via une seule boucle for comme

for v=M
    disp(v);
end

alors que "traditionnellement" vous l'auriez probablement fait comme

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

Je viens d'apprendre cette astuce à l'instant de @Suever dans ce défi .

flawr
la source
3

Conseils liés mais pas identiques pour Octave .

Une caractéristique peu connue et peu utilisée de MATLAB et d'Octave est que la plupart des fonctions intégrées peuvent être appelées sans parenthèses, auquel cas elles traiteront tout ce qui la suit comme une chaîne (tant qu'elle ne contient pas d'espaces). S'il contient des espaces, vous avez besoin de guillemets. Cela peut fréquemment être utilisé pour enregistrer un octet lors de l'utilisation disp:

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

Voici d'autres exemples moins utiles:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12

J'ai en fait utilisé cela deux fois dans le "Combien pouvez-vous compter?" -défi:

strchr sssssssssssssst t

est équivalent à strchr('sssssssssssssst','t')et renvoie 15.

nnz nnnnnnnnnnnnnn

est équivalent à nnz('nnnnnnnnnnnnnn')et renvoie14.

Des trucs comme des gt r sœuvres aussi (équivalent à 'r'>'s'ou gt('r','s').

Stewie Griffin
la source
2

Le intégré oneset zerossont généralement une perte d'espace. Vous pouvez obtenir le même résultat en multipliant simplement un tableau / matrice (de la taille souhaitée) par 0 (pour obtenir la sortie de zeros) et ajoutez 1 si vous voulez la sortie de 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

Cela fonctionne également si vous souhaitez créer un vecteur colonne ou ligne de zéros ou de la taille d'une dimension d'une 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);

Si vous souhaitez créer une matrice d'une taille spécifique, vous pouvez utiliser zerosmais vous pouvez également affecter simplement le dernier élément à 0 et demander à MATLAB de remplir le reste.

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

%// vs. This
z(2,3) = 0;
Suever
la source
2
J'aime utiliser ~(1:n)pour les vecteurs zéro 1-d.
sintax
2

Noyaux de convolution 2D

C'est peut-être un sujet de niche, mais apparemment, certaines personnes aiment utiliser la convolution pour diverses choses ici. [citation requise]

En 2D, les noyaux suivants sont souvent nécessaires:

0 1 0
1 1 1
0 1 0

Ceci peut être réalisé en utilisant

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

qui est plus court que

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

Un autre noyau souvent utilisé est

0 1 0
1 0 1
0 1 0

qui peut être raccourci en utilisant

v=[1,-1,1];v'*v<0   % logical
[0,1,0;1,0,1;0,1,0] % naive verison
flawr
la source
Deuxième noyau sous forme de nombres, même nombre d'octets:toeplitz([0 1 0])
Luis Mendo
2

Je me retrouve assez souvent à utiliser meshgridou ndgrid, disons que nous voulons calculer une image mandelbrot, puis nous initialisons par exemple

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

Maintenant , pour l'ensemble de Mandelbrot nous avons besoin une autre matrice cde la taille xet ymais initialisées avec des zéros. Cela peut facilement se faire en écrivant:

c=x*0;

Vous pouvez également l'initialiser sur une autre valeur:

c=x*0+3;

Mais vous pouvez réellement enregistrer quelques octets en ajoutant simplement une autre dimension dans 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);

Et vous pouvez le faire aussi souvent que vous le souhaitez:

[x,y,c1,c2,c3,c4,c5]=meshgrid(-2:1e-2:1,-1:1e_2,1, 1,pi,exp(3),1e5,-3i)
flawr
la source
Notez qu'en attendant, il y a la diffusion automatique: dans de nombreux cas, le premier exemple pourrait être remplacé par x=-2:1d-2:1;y=x'.
flawr
0

Sommation d'une séquence de fonctions

  • Pour résumer les fonctions f (x_n) où n est un vecteur d'entiers consécutifs, feval est conseillé plutôt que symsum.

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

    Notez qu'une opération élémentaire .*et ./est nécessaire au lieu d'opérations binaires par paires *et/

  • Si la fonction peut être écrite naïvement, personne des deux dernières manières ne convient.

    par exemple, si la fonction est, logvous pouvez simplement faire:, ce sum(log(1:n))qui représente:

    Sum(f(1:n));
    

    pour des fonctions relativement sophistiquées comme log(n)/x^nvous pouvez le faire:

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

    et encore plus court dans certains cas quand une fonction est plus longue que f(x)=e^x+sin(x)*log(x)/x....

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

    qui est remarquablement plus court que sum(feval(@(y)e.^(1:n)+sin(1:n).*log(1:n)./(1:n),1:n))


Remarque: cette astuce peut être appliquée pour d'autres opérateurs inclusifs comme prodoumean


Abr001am
la source