Dicas para jogar golfe no MATLAB

14

Que dicas gerais você tem para jogar golfe no MATLAB? Estou procurando idéias que possam ser aplicadas aos problemas de código de golfe em geral que sejam pelo menos um pouco específicos do MATLAB (por exemplo, "remover comentários" não é uma resposta). Poste uma dica por resposta.

RAM
fonte
3
Relacionados, mas não uma duplicata: Dicas para golfe em Octave
Dennis Jaheruddin

Respostas:

9

Algo que se deve saber antes de começar a jogar golfe:

Nos cálculos do MATLAB, um caractere se comporta da mesma forma que seu 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
fonte
9

Encurtando nomes de propriedades

No MATLAB, cadeias de caracteres que identificam propriedades podem ser reduzidas desde que não resultem em ambiguidade.

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

Isso realmente me ganhou um desafio :)

Sanchises
fonte
2
Muito bom, embora a resposta esteja correta, quero enfatizar que isso se aplica ao nome dos name, valuepares, como mostrado acima. (Então, não a coisas como sort(rand(4,1),'descend'))
Dennis Jaheruddin
1
Também se aplica a algumas dessas coisas, como em conv(1:5,[1 1],'s')vez deconv(1:5,[1 1],'same')
Luis Mendo 27/12
6

A conversão como char pode ser feita por concatenação com um char:

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

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

Embora ele salve apenas um caractere, isso pode ser usado com bastante frequência.

Dennis Jaheruddin
fonte
5

Strings são apenas vetores de linha de caracteres. Isso significa que, em vez de

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

você pode simplesmente escrever

for(a=str)
    ...
end

Primeira vez que usei isso: /codegolf//a/58387/32352

Sanchises
fonte
4

Raízes da unidade via transformada discreta de Fourier

Dado um número inteiro positivo n, a maneira padrão de gerar as n-ésimas raízes da unidade é

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

Isso fornece as raízes começando 1e se movendo na direção angular positiva. Se a ordem não importa, isso pode ser reduzido para

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

Como exp(2j*pi/4)é igual à unidade imaginária ( j), isso pode ser escrito de forma mais compacta da seguinte maneira (truque devido a @flawr ):

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

ou

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

Mas a transformação discreta de Fourier fornece uma maneira ainda mais curta (graças a @flawr por remover dois parênteses desnecessários):

fft(1:n==n)

que dá as raízes começando 1e se movendo na direção angular positiva; ou

fft(1:n==2)

que começa 1e se move na direção angular negativa.


Tente todas as opções acima aqui .

Luis Mendo
fonte
Ótimo truque! Você pode até mesmo golf-lo parafft(1:n==2)
flawr
@ Flawr Eu nunca sei as regras de precedência ... Obrigado!
Luis Mendo
3

Iteração sobre vetores em matrizes.

Dado um conjunto de vetores como matriz, é possível iterar sobre eles por meio de um único loop for, como

for v=M
    disp(v);
end

enquanto "tradicionalmente" você provavelmente teria feito isso

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

Só aprendi sobre esse truque agora com o @Suever neste desafio .

flawr
fonte
3

Dicas relacionadas, mas não idênticas, para o Octave .

Um recurso pouco conhecido e pouco usado do MATLAB e do Octave é que a maioria das funções internas pode ser chamada sem parênteses, caso em que tratará o que quer que se segue como uma string (desde que não contenha espaços). Se ele contiver espaços, você precisará de aspas. Isso pode ser usado frequentemente para salvar um byte ao usar disp:

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

Outros exemplos menos úteis incluem:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12

Na verdade, eu usei isso duas vezes no "Quão alto você pode contar?" -desafio:

strchr sssssssssssssst t

é equivalente a strchr('sssssssssssssst','t')e retorna 15.

nnz nnnnnnnnnnnnnn

é equivalente a nnz('nnnnnnnnnnnnnn')e retorna 14.

Coisas como gt r sfunciona também (equivalente a 'r'>'s'ou gt('r','s').

Stewie Griffin
fonte
2

nnz Às vezes, você pode economizar alguns bytes:

  • Imagine que você deseja a soma de uma matriz lógica A. Em vez de sum(sum(A))ou sum(A(:)), você pode usar nnz(a)( nnzaplica-se de forma implícita (:)).
  • Se você deseja saber o número de elementos de uma matriz e pode ter certeza de que não há zeros, em vez de numel(x)usar nnz(x). Isso é aplicável, por exemplo, se xfor uma string.
Luis Mendo
fonte
2

Núcleos de convolução 2D

Talvez este seja um tópico de nicho, mas aparentemente algumas pessoas gostam de usar a convolução para várias coisas aqui. [citação necessária]

Em 2D, os seguintes kernels são frequentemente necessários:

0 1 0
1 1 1
0 1 0

Isso pode ser alcançado usando

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

que é mais curto que

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

Outro kernel frequentemente usado é

0 1 0
1 0 1
0 1 0

que pode ser reduzido usando

v=[1,-1,1];v'*v<0   % logical
[0,1,0;1,0,1;0,1,0] % naive verison
flawr
fonte
Segundo kernel como números, mesma contagem de bytes:toeplitz([0 1 0])
Luis Mendo
1

Muitas vezes me pego usando meshgridou ndgrid, digamos, queremos computar uma imagem de mandelbrot, depois inicializamos, por exemplo,

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

Agora, para o conjunto de Mandelbrot precisamos de uma outra matriz cdo tamanho xe ymas inicializado com zeros. Isso pode ser feito facilmente escrevendo:

c=x*0;

Você também pode inicializá-lo para outro valor:

c=x*0+3;

Mas você pode salvar alguns bytes apenas adicionando outra dimensão em 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 você pode fazer isso quantas vezes quiser:

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

O built-in onese zerossão tipicamente um desperdício de espaço. Você pode obter o mesmo resultado simplesmente multiplicando uma matriz / matriz (do tamanho desejado) por 0 (para obter a saída de zeros) e adicione 1 se desejar a saída 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

Isso também funciona se você deseja criar um vetor de coluna ou linha de zeros ou do tamanho de uma dimensão de uma 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);

Se você deseja criar uma matriz de um tamanho específico, pode usar, zerosmas também pode atribuir o último elemento a 0 e fazer com que o MATLAB preencha o restante.

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

%// vs. This
z(2,3) = 0;
Suever
fonte
2
Eu gosto de usar ~(1:n)para vetores zero 1-d.
sintax
0

Soma de uma sequência de funções

  • Para somar as funções f (x_n) em que n é um vetor de números inteiros consecutivos, feval é recomendado em vez de symsum.

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

    Observe que uma operação elementar .*e ./é necessária em vez de operações binárias em pares *e/

  • Se a função puder ser escrita ingenuamente, ninguém das duas últimas maneiras é adequado.

    por exemplo, se a função for, logvocê pode simplesmente fazer:, sum(log(1:n))que representa:

    Sum(f(1:n));
    

    para funções relativamente sofisticadas, como log(n)/x^nvocê pode fazer:

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

    e ainda mais curto em alguns casos quando uma função é maior que f(x)=e^x+sin(x)*log(x)/x....

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

    que é notavelmente mais curto que sum(feval(@(y)e.^(1:n)+sin(1:n).*log(1:n)./(1:n),1:n))


Nota: Esse truque pode ser aplicado a outros operadores inclusivos como prodoumean


Abr001am
fonte