Dicas para jogar golfe em Octave

18

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

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

Respostas:

9
  1. Depois que você souber, ele aestará livre de zero valores, usando nnz(a)2 poupadores em comparação com numel(a).
  2. Prefere a(a==0)a a(find(a==0)).
  3. ~té menor que t==0, e mesmo ~~tmenor que t!=0.
  4. 0*(1:n) é mais curto que zeros(1,n)
  5. Geralmente, ||e &&, diferentemente de muitos outros operadores, escalar o resultado quando o primeiro argumento for escalar. Para matrizes, apenas matrizes não vazias sem elementos iguais a zero têm o valor lógico de true .

Portanto, podemos fazer em 0||mvez de all(all(m))para qualquer matriz.

Tente com 0||[1 1;1 0]e 0||[1 1;1 1]se convencer.

  1. Quando você estiver usando um built-in várias vezes, faça um identificador de função para poupar caracteres, por exemplo. f=@find. Para nomes curtos de função, pelo menos 3 ocorrências justificam isso, para nomes longos - mesmo com duas ocorrências.

  2. Quando uma função é uma única instrução, prefira a f=@(n)dosomething(n)notação a function r=f(n)r=dosomething(n);enduma.

  3. Infelizmente, as variáveis ​​globais precisam ser declaradas no escopo global e em cada função que as utiliza. Mas há uma exceção: @(n)...funções anônimas "veem" todas as variáveis ​​do escopo de onde são chamadas.

  4. É possível fazer em f(a=0,b=0)vez de a=0;b=0;f(a,b).

  5. Parece um recurso não documentado, mas a ordem da avaliação é da esquerda para a direita (verificada na v. 3.8.1), você pode fazer zeros(a=n,b=a*a)tanto para criar a matriz ansn ^ 2 quanto para armazenar o número da linha e da coluna ae as bvariáveis.

  6. A tabela de precedência do operador é sua amiga. Não faça b=(a==0)desde que b=a==0é o mesmo.

pawel.boczarski
fonte
7

Não me lembro em que desafio vi alguém usar (por favor, diga-nos =), mas achei um truque interessante:

Normalmente, se você adicionar matrizes, terá que ter o mesmo tamanho, mas para matrizes unidimensionais (1xn e nx1), haverá um atalho (que não funciona no Matlab):

z = (1:5)+(6:10)';

produz o mesmo efeito que

[x,y]=meshgrid(1:5,6:10);
z = x+y;

Então, algo que pawel.boczarski já mencionou: No Octave, você pode (enquanto não pode no Matlab) definir variáveis ​​auxiliares nos identificadores de funções, E uma atribuição de variável em si tem o valor da atribuição para que você possa encurtar o código (bem, isso é inútil exemplo, mas você terá o truque):

f=@(n)(z=n+1)*z; %returns (n+1)^2

Então outro truque (também aplicável no Matlab) é abusar de strings para armazenar números (codificados permanentemente) (esse truque é roubado do feersum) , você só precisa de algo que interprete a string como número, o que é tão fácil quanto, por exemplo, adicionar zero:

a = 'abc';
a+0 %returns
[97 98 99]

Ou

sum('abc') == 294
flawr
fonte
Eu acredito que deveria ser a+0, não a+'0'. Outros, que as dicas são agradáveis =)
Stewie Griffin
Certo, obrigado! PS: Você poderia adicionar os += -= /=operadores etc em sua lista abaixo?
Flawr
1
+aé mais curto quea+0
Luis Mendo
7

Usando a lista de argumentos:

A oitava é capaz de obter argumentos padrão para que as expressões possam ser avaliadas na lista de argumentos.

Esse recurso é útil quando queremos calcular uma expressão e usá-la várias vezes:

f = @(x,a=sort(x))a(a>.5);

Um caso de uso é quando usamos uma atribuição indexada para modificar parte de uma matriz e queremos usar a matriz:

a=[1 2 3 4]
a(2)=5;

Mas a expressão (a(2)=5)retorna a(2), ou a expressão (a([1 3])=4)retorna uma matriz de dois elementos. Nenhum retorna a matriz inteira. Podemos usar a lista de argumentos:

f=@(a=[1 2 3 4],b=a(2)=5)a;

Aqui, o resultado da atribuição indexada é armazenado em uma variável dummy be a função retorna a matriz.

rahnema1
fonte
6

-No Octave, é possível aplicar a indexação em uma expressão temporária, um recurso proibido no MATLAB e esse recurso é muito útil para jogar golfe. exemplo:

Octave: [1 23 4 5 7](3:4) e seu equivalente MATLAB: a=[1 23 4 5 7];a(3:4)
Octave: hilb(4)(4:5,4:5) e seu equivalente MATLAB: h=hilb(4);h(4:5,4:5)
Octave: {1,4,{4 5 6},[7 ;3]}{3}e seu equivalente MATLAB: a={1,4,{4 5 6},[7 ;3]};a{3}
Octave: num2cell([1 2 3 4]){:}para criação de lista separada por vírgulas
Octave:a'(:)'

-Às vezes, em uma função anônima como uma função normal, precisamos avaliar várias expressões, que incluem atribuição. Uma abordagem é poder colocar cada expressão em uma célula (já que a célula pode conter objetos de vários tipos) e quando precisamos do valor de cada expressão, podemos usar a indexação para extrair esse elemento.

{1,4,{4 5 6},[7 ;3]}{3}
ou

{a=1,b=4,c={4 5 6},[b ;3]}{4}

rahnema1
fonte
@StewieGriffin Nice tip! Resposta atualizada!
rahnema1
5

Ignorar ponto e vírgula!

Vou usar esta resposta para ilustrar o ponto.

O código original era:

function f(x);if~movefile('f.m',x);disp("+-+\n| |\n+-+");end

Depois de remover ponto e vírgula, ele poderia ser reduzido para o seguinte, economizando três bytes:

function f(x)if~movefile('f.m',x)disp("+-+\n| |\n+-+")end

Isso pode ser usado em muitos lugares, e coisas que você nem tenta, porque parece que um erro de sintaxe geralmente funciona.

Stewie Griffin
fonte
1
coisas que você nem sequer tentar, porque ele se parece com um erro de sintaxe, muitas vezes funciona Octave em poucas palavras
Sanchises
2

Este é simples, mas útil.

Na oitava, mas não no MATLAB, você pode fazer como no C ++:

x = 0  ->  x = 0
x++    ->  ans = 0
x      ->  x = 1
++x    ->  ans = 2
x      ->  x = 2
Stewie Griffin
fonte
2

Outro simples, mas útil (não é possível no MATLAB):

Atribua o mesmo valor a várias variáveis:

a=b=c=0;
Stewie Griffin
fonte
2

Use eval!

Inspirado pela resposta de Luis Mendo aqui .


Funções anônimas são, na maioria dos casos, mais curtas que a criação de um script que precisa de uma ou mais chamadas input(''). A desvantagem é que loops e modificações variáveis ​​(como a troca de dois elementos em uma matriz) são impossíveis de serem complicados.

Com eval, você pode buscar a entrada como faz com uma função anônima normal e executar o script como faz com um script normal:

Considere isto :

c=(i=@input)('');N=i('');A=i('');for C=c,A(flip(k))=A(k=[x=find(A==C),N^2+1-x]);end,A

Comparado a isso:

@(c,N,A)eval('for C=c,A(flip(k))=A(k=[x=find(A==C),N^2+1-x]);end,A')

O código é idêntico, mas a seção de entrada é muito mais curta.


Isso também pode ser usado para modificar variáveis ​​de entrada, como esta (crédito para Luis Mendo por isso!):

f(x)eval('x([1,4])=x([4,1])`;
Stewie Griffin
fonte
3
O código é idêntico Apenas mais feio, mais lento e menos legível. O que mais você pode pedir? :-D
Luis Mendo
1

Use em rows(a)vez desize(a,1)

rahnema1
fonte
1

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

Um recurso pouco conhecido e pouco usado do Octave é que a maioria das funções internas pode ser chamada sem parênteses, caso em que tratará o que segue como uma string (desde que não contenha espaços). Se ele contiver espaços, você precisará de aspas. Isso pode ser usado com freqüência para salvar um ou dois bytes ao usar disp. Todo o trabalho a seguir e fornece o mesmo resultado:

disp('Hello')
disp Hello
disp"Hello"

Se você tiver espaços, deverá ter as aspas:

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

Outros exemplos menos úteis incluem:

nnz PPCG
ans = 4

size PPCG
ans = 1  4

str2num 12
ans = 12
Stewie Griffin
fonte