Dicas para jogar golfe em Röda


12

Röda é uma linguagem de script baseada em fluxo criada pelo fergusq .

Que dicas gerais você tem para jogar golfe em Röda? Estou procurando idéias que possam ser aplicadas a problemas de código-golfe e que também sejam pelo menos um pouco específicas para Röda (por exemplo, "remover comentários" não é uma resposta).

Poste uma dica por resposta.


Você está tentando obter dicas para me vencer no golfe? : P (eu provavelmente deveria olhar as dicas para a página Python) #
HyperNeutrino 28/17 /

Uau, uma pergunta do PCG.SE que entrou nas perguntas da Hot Network e não é um quebra-cabeça / desafio de programação! :)
Pedro A

1
@HyperNeutrino Shhh .... :)
user41805 Apr

Respostas:


7

Use sublinhados

Esta é provavelmente a dica mais importante. Quase todos os programas de golfe da Röda usam sublinhados.

A sintaxe de sublinhado é açúcar sintático para forloops. As seguintes linhas de código são equivalentes:

ls""|fileLength x for x|sort|pull
ls""|fileLength _|sort|pull

Cada sublinhado adiciona uma nova variável a um forloop invisível que está ao redor da instrução. O loop extrai um valor do fluxo para cada variável / sublinhado e depois se repete, até que nenhum valor seja deixado.

Os sublinhados podem ser usados ​​em qualquer lugar nas instruções:

a[x:y+1]=[1]*(1+y-x) /* Sets range x..y (inclusive) */
seq x,y|a[_]=1       /* 6 bytes less */

Se você precisar se referir ao mesmo valor de sublinhado mais de uma vez ou usar os valores na ordem inversa, poderá colocar um número após o sublinhado:

a|[_^_1]  /* maps x to x^x */
a|[_2-_1] /* maps each pair (x,y) to y-x, eg. [1,2,4,8] -> [1, 4] */

3

Alguns pontos-e-vírgulas / novas linhas são opcionais

Ao escrever o código Röda, geralmente é recomendável usar novas linhas ou ponto e vírgula para separar todas as instruções. No entanto, ao jogar golfe, vale a pena saber que nem todos os pontos e vírgulas são realmente necessários.

Aqui está uma lista incompleta de locais onde ponto e vírgula / novas linhas são opcionais . A maioria deles não se aplicam quando a seguinte declaração começa com um operador ( (, [, +, etc.).

  • Após as atribuições
  • Após chamadas de função, quando há pelo menos um argumento (por exemplo f x) ou quando parênteses são usados ​​(por exemplo f())
  • Em todos os lugares, se a próxima linha / declaração começaria com |, ), ]ou}

Se a próxima instrução começar com um operador, o ponto-e-vírgula / nova linha será opcional se

  • A instrução é uma chamada de função e parênteses são usados, por exemplo, {f(x)[y]}é o mesmo que {f(x);[y]}. Isso funciona apenas no contexto da instrução, não quando a chamada da função é uma expressão.
  • A declaração é uma atribuição e parênteses são usados, por exemplo, x=(y)[z]é o mesmo que x=(y);[z](isso não é o mesmo que x=((y)[z])).

E aqui estão alguns lugares onde as novas linhas são infelizmente necessárias :

  • Depois ++e --.
  • Depois [...].

Muitas vezes, é possível salvar bytes reorganizando as atribuições. Por exemplo:

a=0;b=""c=[""]
b=""c=[b]a=0

x=f()y=i;z=a[0]
x=f()z=a[0]y=i

1

Use estruturas de controle de sufixo

Quase nunca é ideal não usar instruções de sufixo, como você pode usar {...}no lugar de do...end.

Alguns exemplos:

x|unless[not(_ in y)]do[0]else[1]done
x|[0]unless[not(_ in y)]else[1]

if[p<0]do c+=p;a-=p done
{c+=p;a-=p}if[p<0]

Você pode fazer em if[_ in y]vez disso?
user41805

@KritixiLithos Não, porque quero que a condição seja OR, não AND. Atualmente, ele verifica se há pelo menos um valor em xque também está y, mas sua condição verificaria se todos os valores xtambém estão em y. (O exemplo foi copiado daqui ).
fergusq

1

Use o fluxo para entrada

Nos casos em que a entrada é uma lista de elementos, pode ser benéfico extrair os valores do fluxo em vez de obtê-los como uma matriz.

Na maioria dos casos, os elementos da matriz são iterados, empurrando-os para o fluxo e depois iterando-o usando um forloop (ou um sublinhado). Como os elementos são iterados a partir do fluxo de qualquer maneira, por que não definir que eles devem estar lá desde o início?

Por exemplo, para calcular a soma dos quadrados dos números na entrada:

{|a|a|[_^2]|sum} /* Removing a redundant argument */
{[_^2]|sum}      /* saves 5 bytes */

1

Os parênteses são opcionais no contexto da instrução. Isso se aplica mesmo que o argumento comece com um operador. Por exemplo, [a()|sqrt-_]é menor que [a()|sqrt(-_)]. Os parênteses a seguir asão obrigatórios, como ano contexto da expressão, não no contexto da instrução.

No entanto, a escrita [a()|sqrt(_+1)*2]não é possível, e parênteses adicionais são necessários para ajudar o analisador: [a()|sqrt((_+1)*2)]. Muitas vezes, é possível reescrever essa expressão para que não comece com parênteses:[a()|sqrt 2*(_+1)]


Também é possível passar vários parâmetros para funções sem exigir parênteses?
user41805

@KritixiLithos Yes. Por exemplo. [a()|atan2 _,_]seria permitido.
precisa saber é o seguinte

1

Use ,em vez de ..na []/ pushdeclarações

Relacionado: Use em ,vez deand

A pushfunção (assim como a printfunção) pode receber qualquer número de argumentos e gerar cada um deles sem delimitador.

Então isso significa algo como isto

["a"..b]        /*8 bytes (string "a" concatenated with variable b)*/

pode ser reduzido em apenas

["a",b]         /*7 bytes*/

economizando 1 byte.


1

[]/ push>print

Nunca use printdeclarações. []as instruções push são sempre mais eficientes. A diferença entre printe pushé que o primeiro gera uma nova linha à direita, enquanto o último não. No entanto, isso pode ser contornado.

print"a"              /* 8 bytes */
["a                   /* 6 bytes; uses a literal newline */
"]

print"a",b            /* 10 bytes */
[`a$b                 /* 8 bytes; uses a literal newline and `` strings */
`]

1

Usando ``cadeias

Nas ""strings, você terá que escapar de certos caracteres para usá-los. Por exemplo, para imprimir a barra invertida, você teria que ter uma string como "\\". Há um byte adicionado para escapar da barra invertida. No entanto, se você usar ``, não precisará escapar desse caractere e poderá salvar um byte.

print"\\"     /* 9 bytes */
print`\`      /* 8 bytes */

Não apenas isso, você pode codificar variáveis ​​e expressões dentro de ``strings usando $variableNameou ${expression}, um recurso não presente nas ""strings.

Estamos produzindo a string "a"concatenada com o valor da variável bcom uma nova linha à direita nesses exemplos.

["a",b,"      /* 11
"]               bytes   */
[`a$b         /* 8
`]               bytes; encodes b in the string using $b */

1

Use em ,vez deand

As condições em Röda são fluxos e podem consistir em vários valores. Esses valores são reduzidos para um valor booleano com and.

Isso significa que você pode substituir andpor ,condições para enviar vários valores ao fluxo:

x if[a and b]
x if[a,b]

A condição vazia é verdadeira

Também é possível ter uma condição que não contém valores, o que é verdade.

x while true
x while[]

1

Escreva listas de substituição no formulário *"...;..."/";"

A replacefunção normalmente leva uma lista de strings como argumentos. No entanto, se a lista for muito longa, é benéfico simplesmente armazenar os pares regex / substituição em uma sequência e, em seguida, dividir a sequência e usar o operador em estrela:

replace"a","b","c","d"
replace*"a;b;c;d"/";"
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.