Consejos para jugar golf en MATLAB

14

¿Qué consejos generales tienes para jugar al golf en MATLAB? Estoy buscando ideas que se puedan aplicar a los problemas de golf de código en general que sean al menos algo específicos de MATLAB (por ejemplo, "eliminar comentarios" no es una respuesta). Por favor, publique un consejo por respuesta.

RAM
fuente
3
Relacionado, pero no un duplicado: Consejos para jugar golf en Octave
Dennis Jaheruddin

Respuestas:

10

Algo que uno debe saber antes de comenzar a jugar golf:

En los cálculos de MATLAB, un personaje se comporta igual que su código 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
fuente
9

Acortar nombres de propiedad

En MATLAB, las cadenas que identifican propiedades pueden acortarse siempre que no genere ambigüedad.

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

Esto realmente me ganó un desafío :)

Sanchises
fuente
2
Muy bien, aunque la respuesta es correcta, quiero enfatizar que esto se aplica al nombre de los name, valuepares como se muestra arriba. (Así que no a cosas como sort(rand(4,1),'descend'))
Dennis Jaheruddin
1
También se aplica a algunas de esas cosas, como en conv(1:5,[1 1],'s')lugar deconv(1:5,[1 1],'same')
Luis Mendo
6

El casting como char se puede hacer mediante concatenación con un char:

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

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

Aunque solo ahorra un carácter, esto se puede usar con bastante frecuencia.

Dennis Jaheruddin
fuente
5

Las cadenas son solo vectores de fila de caracteres. Esto significa que en lugar de

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

simplemente puedes escribir

for(a=str)
    ...
end

La primera vez que usé esto: /codegolf//a/58387/32352

Sanchises
fuente
4

Raíces de la unidad a través de la transformada discreta de Fourier

Dado un número entero positivo n, la forma estándar para generar los n-ésimos raíces de la unidad es

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

Esto le da a las raíces que comienzan 1y se mueven en la dirección angular positiva. Si el orden no importa, esto se puede acortar a

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

Como exp(2j*pi/4)es igual a la unidad imaginaria ( j), esto se puede escribir de manera más compacta de la siguiente manera (truco debido a @flawr ):

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

o

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

Pero la transformada discreta de Fourier proporciona una forma aún más corta (gracias a @flawr por eliminar dos paréntesis innecesarios):

fft(1:n==n)

que da las raíces comenzando 1y moviéndose en la dirección angular positiva; o

fft(1:n==2)

que comienza en 1y se mueve en la dirección angular negativa.


Pruebe todo lo anterior aquí .

Luis Mendo
fuente
Gran truco! Incluso puedes jugar golf hastafft(1:n==2)
flawr
@flawr Nunca sé las reglas de precedencia ... ¡Gracias!
Luis Mendo
3

nnz a veces puede ahorrarle unos pocos bytes:

  • Imagina que quieres la suma de una matriz lógica A. En lugar de sum(sum(A))o sum(A(:)), puede usar nnz(a)(se nnzaplica implícitamente (:)).
  • Si desea saber la cantidad de elementos de una matriz, y puede estar seguro de que no hay ceros, en lugar de numel(x)usarlos nnz(x). Esto es aplicable por ejemplo six es una cadena.
Luis Mendo
fuente
3

Iteración sobre vectores en matrices.

Dado un conjunto de vectores como matriz, en realidad puede iterar sobre ellos a través de un solo bucle for como

for v=M
    disp(v);
end

mientras que "tradicionalmente" probablemente lo hubieras hecho como

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

Acabo de enterarme de este truco por @Suever en este desafío .

falla
fuente
3

Consejos relacionados, pero no idénticos para Octave .

Una característica poco conocida y poco utilizada tanto de MATLAB como de Octave es que la mayoría de las funciones incorporadas se pueden llamar sin paréntesis, en cuyo caso tratarán lo que sigue como una cadena (siempre que no contenga espacios). Si contiene espacios, necesita comillas. Esto se puede usar con frecuencia para guardar un byte cuando se usa disp:

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

Otros ejemplos menos útiles incluyen:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12

De hecho, he usado esto dos veces en "¿Qué tan alto puedes contar?" -desafío:

strchr sssssssssssssst t

es equivalente a strchr('sssssssssssssst','t')y vuelve 15.

nnz nnnnnnnnnnnnnn

es equivalente a nnz('nnnnnnnnnnnnnn')y vuelve 14.

Cosas como gt r sobras también (equivalente a 'r'>'s'o gt('r','s').

Stewie Griffin
fuente
2

Los integrados onesy zerosson un desperdicio de espacio típico. Puede lograr el mismo resultado simplemente multiplicando una matriz / matriz (del tamaño deseado) por 0 (para obtener la salida de zeros) y agregue 1 si desea la salida 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

Esto también funciona si desea crear un vector de columna o fila de ceros o unos del tamaño de una dimensión de una matriz.

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 desea crear una matriz de un tamaño específico que podría usar, zerospero también podría asignar el último elemento a 0 y hacer que MATLAB complete el resto.

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

%// vs. This
z(2,3) = 0;
Suever
fuente
2
Me gusta usar ~(1:n)para vectores cero 1-d.
sintax
2

Núcleos de convolución 2D

Este es quizás un tema de nicho, pero aparentemente a algunas personas les gusta usar la convolución para varias cosas aquí. [cita requerida]

En 2D, a menudo se necesitan los siguientes núcleos:

0 1 0
1 1 1
0 1 0

Esto se puede lograr usando

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

que es más corto que

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

Otro núcleo de uso frecuente es

0 1 0
1 0 1
0 1 0

que se puede acortar usando

v=[1,-1,1];v'*v<0   % logical
[0,1,0;1,0,1;0,1,0] % naive verison
falla
fuente
Segundo kernel como números, el mismo número de bytes:toeplitz([0 1 0])
Luis Mendo
2

A menudo me encuentro usando meshgrido ndgrid, digamos que queremos calcular una imagen de mandelbrot, luego inicializamos, por ejemplo

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

Ahora, para el conjunto de Mandelbrot necesitamos otra matriz cde la magnitud de xy ypero inicializa con ceros. Esto se puede hacer fácilmente escribiendo:

c=x*0;

También puede inicializarlo a otro valor:

c=x*0+3;

Pero en realidad puede guardar algunos bytes simplemente agregando otra dimensión en 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);

Y puede hacer esto con la frecuencia que desee:

[x,y,c1,c2,c3,c4,c5]=meshgrid(-2:1e-2:1,-1:1e_2,1, 1,pi,exp(3),1e5,-3i)
falla
fuente
Tenga en cuenta que, mientras tanto, hay transmisión automática: en muchos casos, el primer ejemplo podría reemplazarse por x=-2:1d-2:1;y=x'.
flawr hace
0

Suma de una secuencia de funciones

  • Para resumir las funciones f (x_n) donde n es un vector de enteros consecutivos, se aconseja feval en lugar de symsum.

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

    Observe que una operación elemental .*y ./es necesaria en lugar de operaciones binarias por pares *y/

  • Si la función puede escribirse ingenuamente, nadie de las dos últimas formas es adecuado.

    por ejemplo, si la función es logsimplemente puede hacer:, sum(log(1:n))que representa:

    Sum(f(1:n));
    

    para funciones relativamente sofisticadas como log(n)/x^npuedes hacer:

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

    e incluso más corto en algunos casos cuando una función es más larga como f(x)=e^x+sin(x)*log(x)/x ...

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

    eso es notablemente más corto que sum(feval(@(y)e.^(1:n)+sin(1:n).*log(1:n)./(1:n),1:n))


Nota: Este truco se puede aplicar para otros operadores inclusivos como prodomean


Abr001am
fuente