O problema é que muitas linguagens são (geralmente de curta duração) experimentais com paradigmas muito atípicos, para os quais expressões típicas de programação não fazem nenhum sentido. Então "maioria de todas as línguas" é praticamente impossível de cumprir. Você deve restringi-lo de alguma forma, por exemplo, à "maioria dos idiomas usados regularmente no codegolf.SE". No momento, as respostas parecem muito muito parecido com "a maioria das línguas remotamente C-derivados", mas aqueles, embora a grande maioria dos todos escritos código está escrito neles, não são a maioria dos idiomas .
deixou de girar contra-
3
Ao redor, acho que todos sabemos o que eles significam. Trata-se principalmente de otimizações independentes da linguagem, ou seja, aquelas não apenas úteis no Brainfuck, mas talvez Python, C, Java e Fortran de uma só vez. Idéias gerais que você pode aplicar em vários idiomas que funcionam da mesma forma. Eu não acho que seja preciso ser tão preciso e específico nas dicas e na pergunta da CW. Trata-se de ajudar os outros a jogar golfe, não de irritá-los.
Joey #
14
Esperemos que ninguém cria uma linguagem chamada <all languages>...
mbomb007
Respostas:
72
Mesclar loops
Geralmente, você pode mesclar dois loops consequentes, ou dois loops aninhados, em um.
Antes:
for (i=0; i<a; i++) foo();
for (i=0; i<b; i++) bar();
ugoren os loops ainda não são os mesmos. @ Gaffi está certo.
kaoD
5
@kaoD, em ambos os casos, fooé chamado de ahorário, baré chamado de bhorário. Isso ocorre porque, em "depois", o loop executa os a+btempos, a primeira achamada fooe as próximas bar.
Ugoren
Estou analisando isso de novo (muito, muito mais tarde) e não entendo minha própria pergunta agora. Talvez eu não tenha entendido a operação ternária antes? Do jeito que eu vejo agora, faz sentido.
Gaffi
1
Woops, eu li isso muito tarde da noite. Você está certo!
kaoD
3
Muito semelhante: for(y=0;y<Y;++y)for(x=0;x<X;++x)muitas vezes pode tornar-se for(i=0;i<X*Y;++i)com xsubstituído por i%Xe ysubstituído por i/X.
Lynn
62
Apenas para mencionar o óbvio:
Questione sua escolha de algoritmo e tente algo totalmente novo.
Ao jogar golfe (problemas mais difíceis que resultam em programas mais longos) com muita frequência, você pode seguir o caminho que escolheu primeiro sem tentar outras opções fundamentais . Obviamente, você pode jogar minigolfe em uma ou mais linhas de uma vez ou em parte da idéia geral, mas muitas vezes não tente uma solução totalmente diferente.
Isso foi especialmente perceptível no Hitting 495 (Kaprekar), onde o desvio do algoritmo real e a procura de padrões que você pode aplicar para obter o mesmo resultado eram mais curtos em muitos idiomas (apenas não J).
A desvantagem é que você possivelmente resolve a mesma coisa meia dúzia de vezes. Mas funciona realmente em todos os idiomas, exceto no HQ9 + (onde encontrar outra maneira de produzir o Hello World seria um pouco inútil).
+1 Além de ser bom para jogar golfe, este é um bom exercício para qualquer programador em muitas situações do mundo real!
Gaffi
52
Usar desenvolvimento orientado a testes
Se o código precisar lidar com várias entradas, escreva testes abrangentes e facilite a execução de todos eles muito rapidamente. Isso permite que você tente transformações arriscadas, um passo de bebê por vez. O golfe então se torna como refatoração com intenção perversa.
Eu uso um spinoff desse método. Como os problemas em si são geralmente bastante simples, escrevo um programa que faz o trabalho. Normalmente, isso é "fácil de jogar", de forma sucinta, mas novas linhas etc. estão lá. Copio esse arquivo para um novo local e o jogo, verificando de vez em quando se os programas retornam os mesmos valores para algumas entradas escolhidas. Se eu cometer algum erro ao me deixar com um programa interrompido, sem memória do que mudei e sem entender minha peça de golfe, tenho uma "especificação" salva como fonte de referência.
Shion
2
Adoro esse método, que é uma das razões pelas quais incluo suítes de teste abrangentes para todos os problemas que escrevo.
Joey
@RubberDuck O princípio Não se repita é muitas vezes seguido rigorosamente.
Jonathan Frech 23/02
48
Tente reduzir instruções lógicas
Por exemplo, se Ae Bsão booleanos e seu idioma trata os booleanos como números até certo ponto A and (not B)e A>Bsão equivalentes. Por exemplo, em Python
B>A or foo()seria uma maneira ainda mais curta de expressar isso, aproveite a avaliação preguiçosa de expressões booleanas para garantir que apenas calcule as coisas quando necessário.
scragar
5
@ Scragar: Correto, mas este não é o objetivo desta dica. (É uma dica independente valiosa embora.)
Wrzlprmft
3
@ Scragar, B>A or fooavaliaria foose o B==Aque não é o que queremos. (Direito?)
msh210
2
Além disso, se você tiver muito tempo condições imbricado (dizer com 5/6 parâmetros), você pode usar uma tabela de verdade e um mapa de Karnaugh para encontrar o menor expressão booleana para isso
Katenkyo
33
Inicialize variáveis usando os valores que você já possui.
Em vez de x=1, tente procurar algo que já seja igual a 1.
Por exemplo, o valor de retorno de uma função: printf("..");x=0;-> x=!printf("..");. É mais fácil com 0, porque você sempre pode negar ou quando tudo que você precisa é o valor certo da verdade (e não se importa se é 1 ou 19).
@ std''OrgnlDave, True, mas esta pergunta é sobre coisas comuns a todos os idiomas.
ugoren
33
Use unário ~para x+1ex-1
Esse truque se aplica a idiomas que possuem um operador de negação bit a bit unário ~e um operador de negação regular unário -.
Se o seu programa, por acaso, contiver a expressão -x-1, você poderá substituí-lo por ~xpara salvar bytes. Isso não ocorre com muita frequência, mas observe o que acontece se negarmos ( -) ambas as expressões: x+1igual -~x! Da mesma forma, x-1é igual ~-x. (Pense em qual direção o til aponta: a direita é +, a esquerda é -.)
Isso é útil, porque em todos os idiomas que consigo pensar que possuem esses operadores, eles têm maior precedência do que a maioria dos operadores. Isso permite que você salve entre parênteses. Veja como salvamos quatro bytes aqui:
Conheça as regras para espaços em branco no seu idioma. Alguns sinais de pontuação ou outros caracteres podem não precisar de espaço em branco ao redor. Considere esta função de shell Bourne :
f () { echo a; echo b; }
No shell Bourne, ();são metacaracteres e não precisam de espaço em branco circundante. No entanto, {}são palavras e precisam de espaço em branco, a menos que estejam ao lado de metacaracteres. Podemos jogar fora 4 espaços ao lado ();, mas devemos manter o espaço entre {e echo.
f(){ echo a;echo b;}
No Common Lisp e no PicoLisp , ()são metacaracteres. Considere este código para encontrar a média de dois números:
(/ (+ a b) 2)
Podemos jogar fora 2 espaços.
(/(+ a b)2)
Alguns idiomas têm regras estranhas e sutis para espaços em branco. Considere este programa Ruby, que imprime a soma e o produto de uma linha de números inteiros.
Cada &um precisa de um espaço antes de si. Em Ruby, i=$F.map &:to_isignifica i=$F.map(&:to_i)onde &passa um parâmetro de bloco. Mas, i=$F.map&:to_isignifica i=$F.map.&(:to_i)onde &está um operador binário.
Essa estranheza acontece em idiomas, como Perl ou Ruby, que usam pontuação ambígua. Em caso de dúvida, use um REPL ou escreva programas curtos para testar as regras de espaço em branco.
Por que precisa haver um espaço entre "{" e "eco", mas não entre ";" e "eco"?
Ryan
3
Eu usei os termos do manual do OpenBSD sh (1), que diz que "{" é uma palavra reservada e ";" é um meta-personagem. Por esse motivo, "{eco" é uma palavra, mas "; eco" é duas palavras. Outros manuais podem explicar isso de maneira diferente. Além disso, o shell Z zsh possui regras diferentes.
kernigh
28
atribuir novos nomes às funções, se usados várias vezes
x = SomeLongFunctionName
x(somedata)
x(somemoredata)
etc
Você tem 52 deles; use todos eles! Não tenha medo de tentar abordagens diferentes e comparar comprimentos. Conheça o idioma e os atalhos / funções da biblioteca específicos disponíveis.
26 para idiomas que não diferenciam maiúsculas de minúsculas. :-)
Gaffi 27/03
12
Freqüentemente $e _pode ser usado como identificador.
Griffin
4
@ Gaffi: E mais do que suficiente para idiomas que permitem identificadores Unicode, a menos que a tarefa limite você para ASCII ou conte bytes em vez de caracteres.
27712 hammar
Se você está contando bytes em vez de unicode, o uso de ASCII estendido pode ser uma maneira de espremer outros ~ 120 identificadores, se você precisar deles (não para um script de golfe, você deve precisar de mais de 26)
scragar
2
@é um nome de variável válido no T-SQL, use-o em vez de @a.
BradC
25
Use o operador condicional.
Um operador condicional
bool ? condition_true : condition_false
é mais benéfico, em termos de caráter, do que uma declaração IF .
Os idiomas que não possuem um ternário podem ser usados a&&b||c. Um pouco mais, mas ainda mais curto que um if.
Michael Kohl
Por outro lado, alguns não podem usar nenhuma das opções (o VBA vem à mente), mas ambos ainda são boas sugestões. :-)
Gaffi 28/03
1
Gaffi: O VBA possui Iff, embora seja uma função, sujeito à avaliação de todos os argumentos.
Joey #
Usando ternário em if também pode ser muito útilif(a ? b : c)
Jojodmo
4
@MichaelKohl note que a&&b||cpode retornar cquando afor verdadeiro, se bfor falso, um pequeno caso extremo, mas não devemos esquecer que ^^ #
23416
24
Escreva uma explicação do seu código
Escrever uma explicação obriga a examinar cuidadosamente cada parte do seu código novamente e a tornar explícitos seus pensamentos e escolhas ao escrever uma determinada passagem. Ao fazer isso, você pode descobrir que são possíveis abordagens diferentes, que podem economizar alguns bytes, ou que você subconscientemente fez suposições que não necessariamente são válidas.
Parece um acéfalo, mas tomando cuidado, você poderá "salvar" alguns personagens sem realmente fazer nada!
Se você estiver usando o Windows, poderá estar inserindo em \r\nvez de apenas \rou \nquando clicar em Retornar - adicionando um byte extra por linha! Gire os caracteres de controle apenas para verificar se você não está fazendo isso.
No Notepad ++, você pode converter todas as \r\nterminações de linha apenas \rem Edit > EOL Conversion > UNIX/OSX Format.
Também não inclua nenhum espaço em branco à direita na contagem de caracteres! O feed de linha na linha de fundo do seu código também é irrelevante, de modo que também não precisará ser contado.
Eu não acho que eu já vi um caso em que isso tenha realmente contado ...
Jacob
4
Acabei de ter esse problema (por isso estou adicionando).
27615 Sean Latham
21
Leia a pergunta com atenção
O golfe por código tem tanto a ver com entender a pergunta (o que é perguntado e o que não é perguntado, mesmo que isso esteja implícito em qualquer outra configuração) quanto a produção de código que (pode) satisfazer apenas o que é perguntado.
Qualquer entrada diferente da solicitada explicitamente não precisa ser tratada. Se houver alguns casos de teste e nenhum requisito genérico, seu código poderá funcionar apenas nesses casos. Etc.
Eu acho que uma manchete melhor aqui seria "Não lide com casos extremos não obrigatórios". A frase "Tente encontrar brechas" evoca maneiras de evitar o que é especificado por meio de uma reinterpretação artística das regras, enquanto o que você está oferecendo é apenas um bom conselho para não implementar em excesso sua solução.
Jonathan Van Matre
1
Sim, mas uma reinterpretação artística das regras também faz parte do código do golfe! (0 soluções carvão animal, etc.)
Tobia
8
Essa seria / deveria ser uma resposta diferente, no entanto. Há uma diferença fundamental entre, por exemplo, implementar uma solução que funcione apenas para ints porque o OP não exigia suporte de flutuação e uma resposta que imprime o texto "qualquer valor maior que 100" porque "você não disse que era necessário" ser um número primo real ".
Jonathan Van Matre
Acho que alguns OPs incluem um aviso "Casos de teste sujeitos a alterações; seu código ainda deve funcionar após a alteração" e os altera realmente se eles virem apenas uma resposta codificando os casos de teste.
Erik the Outgolfer
20
Use operações bit a bit para verificar números entre 0 e qualquer 2 n -1
Pode ser um pouco complicado, mas às vezes pode ser útil. Ele se baseia no fato de que todos os números aos quais m = 2 n -1 se aplica têm os n bits mais à direita definidos como 1.
Portanto, 7 10 == 00000111 2 , 15 10 == 00001111 2 , 31 10 == 00011111 2 e assim por diante.
O truque é x&~m. Isso retornará verdadeiro sempre que nãox estiver entre 0 e (inclusive) e falso caso contrário. Ele salva 6 bytes da próxima expressão equivalente mais curta:, mas obviamente só funciona quando satisfaz 2 n -1.mx>=0&&x<=mm
Bem, por exemplo, em C, sua função principal sempre passa o número de argumentos fornecidos ao programa (que é 1 - o nome do programa - por 'padrão'), assim, main(i){...agora você tem uma variável com o valor 1 sem precisar faça quaisquer atribuições. 2 caracteres salvos lá ..
Griffin
6
Eu acho que é bastante específico para as linguagens C. Script não precisam de declarações, e na maioria das linguagens compiladas, definir uma variável não é mais do que definir um parâmetro.
ugoren
em java, quando precisar de uma matriz dentro de uma função que tenha o mesmo tipo de um parâmetro, você pode economizar alguns bytes colocando esse parâmetro como último e transformá-lo em um parâmetro vararg; (usou isso para raspar alguns bytes em uma função para encontrar maior palavra em uma frase)
Não sei se entendi o motivo disso. Do que isso reduz?
Gaffi
@Gaffi você salvar um personagem e eles fazem exatamente o mesmo
ajax333221
vs. que alternativa? Desculpe, não tentando ser obstinado, eu simplesmente não entendo. (newb, aqui, aparentemente ...)
Gaffi
1
Ah entendo. Funciona em qualquer transição de número inteiro de 9 para 10, 99 para 100, etc. Desculpe, mas demorei tanto! (Digo apenas número inteiro, porque eu posso ver um problema com n = 9,5 ...) #
315 Gaffi Gaffi
8
Também em algumas línguas (se houver suporte) se os seus números são grandes / pequenos o suficiente a notação científica pode realmente lhe poupar alguns caracteres em vez disso: if(n>99999)vsif(n<1e5)
scragar
16
Use> e <em vez de> = e <=
Ao verificar valores inteiros codificados, use >e em <vez de >=e sempre <=que possível. Por exemplo, usando
Relacionado: Se você tem certeza de que um resultado não pode ser negativo, use-o em <1vez de ==0como verificação zero (ou em >0vez da !=0verificação espelhada).
Kevin Cruijssen
1
Você não deve adicionar uma observação sobre xser um número inteiro?
Zachary
15
Evite quebras prematuras de loop
Se estiver executando um loop para verificar se há 1 ou mais instâncias de uma verificação booleana, pode ser um programa mais eficiente sair do loop no primeiro valor verdadeiro. No entanto, remover a quebra e fazer um loop em todas as iterações permite um código mais curto.
int main() {
bool m = false;
int n = 1000;
for (int i = 0; i < n; i++) {
if (i >= 100) {
m = true;
break; // remove this line
}
}
return 0;
}
Você também pode simplificar a ifdeclaração afastado nestes casos: m|=i>=100. (E você também pode simplificar o i>=100que i>99, neste caso, mas isso não é muito relevante aqui)
marinus
15
use em -vez de!=
para comparações numéricas:
Se a for igual a b, a-bresulta em 0, o que é falso. Qualquer outra coisa que não 0seja verdade; portanto,
se usado em um contexto booleano, a-b<=>a!=b
Se você usá-lo com if/elseou com o operador ternário, isso também poderá economizar um byte para a igualdade: a==b?c:d<=>a-b?d:c
A maioria dos idiomas tem uma maneira de dividir uma string em uma matriz de strings em torno de um token de algum tipo. Isso inevitavelmente será mais curto que um literal de matriz quando o comprimento atingir um limite dependente do idioma, porque a sobrecarga extra por sequência será uma cópia de um token de um caractere em vez de (pelo menos) dois delimitadores de sequência.
Por exemplo, no GolfScript
["Foo""Bar""Baz""Quux"] # 23 chars
torna-se
"Foo
Bar
Baz
Quux"n/ # 20 chars
Para alguns idiomas, o limite é tão baixo quanto uma sequência. Por exemplo, em Java,
A excepção digna de nota é Ruby, que fornece um conjunto de cordas-literais que divide automaticamente em espaços à custa de dois bytes: %w{Foo Bar Baz Quux}.
Martin Ender
1
Perl fornece algo semelhante: qw(Foo Bar Baz Quux)torna - se uma lista de strings.
BenGoldberg
12
Entenda o que outras pessoas fizeram
Além de ser divertido, se você examinar o código de outras pessoas, às vezes poderá descobrir um bom algoritmo no qual não pensou ou um truque (às vezes óbvio) que você ignora.
Às vezes, existe uma resposta que você pode traduzir para outro idioma e se beneficiar dos benefícios do outro idioma.
Sempre que você combinar várias expressões, verifique a tabela de precedência do operador em seu idioma para ver se você pode reorganizar coisas para salvar parênteses.
Exemplos:
Em todos os idiomas que eu conheço, os operadores bit a bit têm uma precedência mais alta que os operadores booleanos:
(a&b)&&cnão precisa de parênteses: a&b&&cassim como (a*b)+cnão.
a+(b<<c)pode ser reescrito como a+b*2**c.
Isso não salva nada neste exemplo, mas será cum literal inteiro pequeno (<14).
Operações bit a bit tem uma precedência mais baixa do que a maioria das operações aritméticas, por isso, se o seu idioma lança implicitamente boolean para int, você pode salvar um byte em a<b&&c<dcom a<b&c<d(a menos que você precisa a avaliação curto-circuito)
Se você tiver Xinstruções {dentro }do loop for, poderá movê- X-1las (dentro )do loop for após o segundo ponto for(blah;blah;HERE)e vírgula para salvar 3 bytes. (separe as instruções usando uma vírgula ,)
Ao invés de
for(int i=0;i<9;){s+=s.length();println(i++);}
você pode mover uma das instruções para o (aparelho do loop for )enquanto deixa a outra de fora
for(int i=0;i<9;println(i++))s+=s.length();
e salve 3 bytes (economizou mais 1 byte graças a @ETHProductions)
Pode parecer uma dica que você não usará com tanta frequência, como usar em ~xvez de -x-1não acontecer com frequência, mas eu a usei o suficiente para vê-la como uma dica útil aqui. Especialmente com a indexação de matriz, você pode usá-las acima em alguns casos.
Truque simples que inventei ao tentar espremer uma longa faixa de condições encadeadas por ands (ou ors, nesse caso, basta substituir 'all' por 'any').
Quais idiomas possuem um all(array-of-Booleans)built-in?
Peter Peter Taylor
3
Ruby tem. [a>0,a<10,a+b==4,a+3<1].all?
Kernigh # 6/14
4
Embora se fosse Python, você if 10>a>0 and a+b==4>1>a+3:
usaria
@PeterTaylor Haskell também
proud haskeller
6
Confie no compilador para fornecer o desempenho necessário.
Certifique-se de saber quais otimizações são garantidas pelo compilador e em quais níveis de otimização e use-as livremente. E mesmo que o desempenho não seja um requisito de preocupação , você ainda pode testar com otimizações ativadas e descontar apenas um caractere porque seu código ainda é tecnicamente válido sem o sinalizador do compilador.
Considere a seguinte função Haskell para calcular 2 ^ n (ignorando o fato de que Haskell já possui um operador de exponenciação interno ou três) (23 caracteres):
p 0=1;p x=p(x-1)+p(x-1)
O problema é - é terrivelmente lento, é executado em tempo exponencial. Isso pode tornar seu código não testável ou falhar em qualquer restrição de desempenho fornecida pela pergunta. Você pode ficar tentado a usar uma variável temporária ou uma literal de função imediatamente chamada para evitar chamadas de função repetidas (25 caracteres):
p 0=1;p x=(\y->y+y)$p$x-1
Mas o compilador já pode fazer isso por você, basta definir -Ocomo um sinalizador do compilador! Em vez de gastar alguns caracteres extras por site para eliminar subexpressões comuns manualmente, basta dizer ao compilador para fazer otimizações básicas para você, com um total geral de um ou dois caracteres em todo o programa.
Em qual idioma você pode fazer a atribuição dentro de uma chamada? ou isso é uma palavra-chave arg?
gato
2
Penso que atribuições são expressões (com o novo valor da variável atribuída como valor de expressão) em pelo menos C, C ++, C # e Java. a = (b=c)+1;define bcomo ce, em seguida, define acomo b+1.
Lynn
@Lynn Try a=1+b=c. E você pode adicionar PHP e JavaScript à sua lista.
Titus
2
Ruby faz isso da melhor maneira. Ela dá ao =operador uma precedência maior do lado esquerdo do que o direito, por isso 1+x=2é válido e avaliada como3
Cyoce
@Cyoce afaik é assim em todos os idiomas em que uma tarefa é uma expressão.
Titus
5
Utilize a versão do idioma / peculiaridades do compilador / ambiente / novos recursos
Isso é especialmente útil para poliglotas , mas pode ser aplicado a outros desafios. Às vezes, um bug do compilador pode obter um byte, um bug de implementação pode permitir que você salve alguns caracteres, ou um recurso realmente avançado pode melhorar sua pontuação.
Além disso, use condicionais bitty ( &, `|) para remover mais caracteres.
FUZxxl 13/08/2012
2
Embora usar bit a bit em &vez de &&remover 1 caractere em alguns casos, atrapalhe a precedência do operador e você precisará colocar parênteses para fazê-lo funcionar. Use-o com sabedoria.
Agradeço o seu contato
4
Encontre maneiras melhores de inicializar suas variáveis
Algumas outras respostas chegaram perto de mencionar isso, mas em muitos idiomas (estritamente digitados?), É mais curto inicializar xcomo uma string vazia como:
x:=""
ou xcomo runa vazia (char) como:
x:=''
do que
var x string
e
var x rune
Usar valores preexistentes é obviamente preferido, mas não tão fácil.
<all languages>
...Respostas:
Mesclar loops
Geralmente, você pode mesclar dois loops consequentes, ou dois loops aninhados, em um.
Antes:
Depois de:
fonte
foo
é chamado dea
horário,bar
é chamado deb
horário. Isso ocorre porque, em "depois", o loop executa osa+b
tempos, a primeiraa
chamadafoo
e as próximasbar
.for(y=0;y<Y;++y)for(x=0;x<X;++x)
muitas vezes pode tornar-sefor(i=0;i<X*Y;++i)
comx
substituído pori%X
ey
substituído pori/X
.Apenas para mencionar o óbvio:
Questione sua escolha de algoritmo e tente algo totalmente novo.
Ao jogar golfe (problemas mais difíceis que resultam em programas mais longos) com muita frequência, você pode seguir o caminho que escolheu primeiro sem tentar outras opções fundamentais . Obviamente, você pode jogar minigolfe em uma ou mais linhas de uma vez ou em parte da idéia geral, mas muitas vezes não tente uma solução totalmente diferente.
Isso foi especialmente perceptível no Hitting 495 (Kaprekar), onde o desvio do algoritmo real e a procura de padrões que você pode aplicar para obter o mesmo resultado eram mais curtos em muitos idiomas (apenas não J).
A desvantagem é que você possivelmente resolve a mesma coisa meia dúzia de vezes. Mas funciona realmente em todos os idiomas, exceto no HQ9 + (onde encontrar outra maneira de produzir o Hello World seria um pouco inútil).
fonte
Usar desenvolvimento orientado a testes
Se o código precisar lidar com várias entradas, escreva testes abrangentes e facilite a execução de todos eles muito rapidamente. Isso permite que você tente transformações arriscadas, um passo de bebê por vez. O golfe então se torna como refatoração com intenção perversa.
fonte
Tente reduzir instruções lógicas
Por exemplo, se
A
eB
são booleanos e seu idioma trata os booleanos como números até certo pontoA and (not B)
eA>B
são equivalentes. Por exemplo, em Pythoné o mesmo que:
fonte
B>A or foo()
seria uma maneira ainda mais curta de expressar isso, aproveite a avaliação preguiçosa de expressões booleanas para garantir que apenas calcule as coisas quando necessário.B>A or foo
avaliariafoo
se oB==A
que não é o que queremos. (Direito?)Inicialize variáveis usando os valores que você já possui.
Em vez de
x=1
, tente procurar algo que já seja igual a 1.Por exemplo, o valor de retorno de uma função:
printf("..");x=0;
->x=!printf("..");
. É mais fácil com 0, porque você sempre pode negar ou quando tudo que você precisa é o valor certo da verdade (e não se importa se é 1 ou 19).fonte
Use unário
~
parax+1
ex-1
Esse truque se aplica a idiomas que possuem um operador de negação bit a bit unário
~
e um operador de negação regular unário-
.Se o seu programa, por acaso, contiver a expressão
-x-1
, você poderá substituí-lo por~x
para salvar bytes. Isso não ocorre com muita frequência, mas observe o que acontece se negarmos (-
) ambas as expressões:x+1
igual-~x
! Da mesma forma,x-1
é igual~-x
. (Pense em qual direção o til aponta: a direita é+
, a esquerda é-
.)Isso é útil, porque em todos os idiomas que consigo pensar que possuem esses operadores, eles têm maior precedência do que a maioria dos operadores. Isso permite que você salve entre parênteses. Veja como salvamos quatro bytes aqui:
fonte
Aperte o espaço em branco
Conheça as regras para espaços em branco no seu idioma. Alguns sinais de pontuação ou outros caracteres podem não precisar de espaço em branco ao redor. Considere esta função de shell Bourne :
No shell Bourne,
();
são metacaracteres e não precisam de espaço em branco circundante. No entanto,{}
são palavras e precisam de espaço em branco, a menos que estejam ao lado de metacaracteres. Podemos jogar fora 4 espaços ao lado();
, mas devemos manter o espaço entre{
eecho
.No Common Lisp e no PicoLisp ,
()
são metacaracteres. Considere este código para encontrar a média de dois números:Podemos jogar fora 2 espaços.
Alguns idiomas têm regras estranhas e sutis para espaços em branco. Considere este programa Ruby, que imprime a soma e o produto de uma linha de números inteiros.
Cada
&
um precisa de um espaço antes de si. Em Ruby,i=$F.map &:to_i
significai=$F.map(&:to_i)
onde&
passa um parâmetro de bloco. Mas,i=$F.map&:to_i
significai=$F.map.&(:to_i)
onde&
está um operador binário.Essa estranheza acontece em idiomas, como Perl ou Ruby, que usam pontuação ambígua. Em caso de dúvida, use um REPL ou escreva programas curtos para testar as regras de espaço em branco.
fonte
atribuir novos nomes às funções, se usados várias vezes
fonte
x
.Nomes de variáveis de letra única
Você tem 52 deles; use todos eles! Não tenha medo de tentar abordagens diferentes e comparar comprimentos. Conheça o idioma e os atalhos / funções da biblioteca específicos disponíveis.
fonte
$
e_
pode ser usado como identificador.@
é um nome de variável válido no T-SQL, use-o em vez de@a
.Use o operador condicional.
Um operador condicional
é mais benéfico, em termos de caráter, do que uma declaração IF .
pode ser escrito como
fonte
a&&b||c
. Um pouco mais, mas ainda mais curto que umif
.Iff
, embora seja uma função, sujeito à avaliação de todos os argumentos.if(a ? b : c)
a&&b||c
pode retornarc
quandoa
for verdadeiro, seb
for falso, um pequeno caso extremo, mas não devemos esquecer que ^^ #Escreva uma explicação do seu código
Escrever uma explicação obriga a examinar cuidadosamente cada parte do seu código novamente e a tornar explícitos seus pensamentos e escolhas ao escrever uma determinada passagem. Ao fazer isso, você pode descobrir que são possíveis abordagens diferentes, que podem economizar alguns bytes, ou que você subconscientemente fez suposições que não necessariamente são válidas.
Essa dica é semelhante a Questionar sua escolha de algoritmo e tentar algo totalmente novo ; no entanto, descobri que o passo de realmente escrever como cada parte deve funcionar às vezes é crucial para tomar consciência de alternativas.
Como bônus, as respostas, incluindo uma explicação, são mais interessantes para outros usuários e, portanto, têm mais chances de serem votadas.
fonte
Verifique novamente a contagem de caracteres
Parece um acéfalo, mas tomando cuidado, você poderá "salvar" alguns personagens sem realmente fazer nada!
Se você estiver usando o Windows, poderá estar inserindo em
\r\n
vez de apenas\r
ou\n
quando clicar em Retornar - adicionando um byte extra por linha! Gire os caracteres de controle apenas para verificar se você não está fazendo isso.No Notepad ++, você pode converter todas as
\r\n
terminações de linha apenas\r
emEdit > EOL Conversion > UNIX/OSX Format
.Também não inclua nenhum espaço em branco à direita na contagem de caracteres! O feed de linha na linha de fundo do seu código também é irrelevante, de modo que também não precisará ser contado.
fonte
Leia a pergunta com atenção
O golfe por código tem tanto a ver com entender a pergunta (o que é perguntado e o que não é perguntado, mesmo que isso esteja implícito em qualquer outra configuração) quanto a produção de código que (pode) satisfazer apenas o que é perguntado.
Qualquer entrada diferente da solicitada explicitamente não precisa ser tratada. Se houver alguns casos de teste e nenhum requisito genérico, seu código poderá funcionar apenas nesses casos. Etc.
fonte
Use operações bit a bit para verificar números entre 0 e qualquer 2 n -1
Pode ser um pouco complicado, mas às vezes pode ser útil. Ele se baseia no fato de que todos os números aos quais m = 2 n -1 se aplica têm os n bits mais à direita definidos como 1.
Portanto, 7 10 == 00000111 2 , 15 10 == 00001111 2 , 31 10 == 00011111 2 e assim por diante.
O truque é
x&~m
. Isso retornará verdadeiro sempre que nãox
estiver entre 0 e (inclusive) e falso caso contrário. Ele salva 6 bytes da próxima expressão equivalente mais curta:, mas obviamente só funciona quando satisfaz 2 n -1.m
x>=0&&x<=m
m
fonte
Reutilizar parâmetros de função em vez de novas variáveis
fonte
main(i){...
agora você tem uma variável com o valor 1 sem precisar faça quaisquer atribuições. 2 caracteres salvos lá ..Maior / Menor que para salvar um dígito:
Lembre-se de trocar o código de
if
paraelse
e eles farão exatamente a mesma coisa (ou mudarão os lados da desigualdade)!Nota: isso pode ser aplicado com qualquer potência de 10 e seus negativos:
...-100, -10, 10, 100...
(link de origem)
fonte
if(n>99999)
vsif(n<1e5)
Use> e <em vez de> = e <=
Ao verificar valores inteiros codificados, use
>
e em<
vez de>=
e sempre<=
que possível. Por exemplo, usandoÉ 2 bytes mais curto que o uso
fonte
<1
vez de==0
como verificação zero (ou em>0
vez da!=0
verificação espelhada).x
ser um número inteiro?Evite quebras prematuras de loop
Se estiver executando um loop para verificar se há 1 ou mais instâncias de uma verificação booleana, pode ser um programa mais eficiente sair do loop no primeiro valor verdadeiro. No entanto, remover a quebra e fazer um loop em todas as iterações permite um código mais curto.
fonte
if
declaração afastado nestes casos:m|=i>=100
. (E você também pode simplificar oi>=100
quei>99
, neste caso, mas isso não é muito relevante aqui)use em
-
vez de!=
para comparações numéricas:
Se a for igual a b,
a-b
resulta em0
, o que é falso. Qualquer outra coisa que não0
seja verdade; portanto,se usado em um contexto booleano,
a-b
<=>a!=b
Se você usá-lo com
if/else
ou com o operador ternário, isso também poderá economizar um byte para a igualdade:a==b?c:d
<=>a-b?d:c
fonte
Dividir strings para matrizes longas
A maioria dos idiomas tem uma maneira de dividir uma string em uma matriz de strings em torno de um token de algum tipo. Isso inevitavelmente será mais curto que um literal de matriz quando o comprimento atingir um limite dependente do idioma, porque a sobrecarga extra por sequência será uma cópia de um token de um caractere em vez de (pelo menos) dois delimitadores de sequência.
Por exemplo, no GolfScript
torna-se
Para alguns idiomas, o limite é tão baixo quanto uma sequência. Por exemplo, em Java,
torna-se
fonte
%w{Foo Bar Baz Quux}
.qw(Foo Bar Baz Quux)
torna - se uma lista de strings.Entenda o que outras pessoas fizeram
Além de ser divertido, se você examinar o código de outras pessoas, às vezes poderá descobrir um bom algoritmo no qual não pensou ou um truque (às vezes óbvio) que você ignora.
Às vezes, existe uma resposta que você pode traduzir para outro idioma e se beneficiar dos benefícios do outro idioma.
fonte
conheça a precedência do seu operador
Sempre que você combinar várias expressões, verifique a tabela de precedência do operador em seu idioma para ver se você pode reorganizar coisas para salvar parênteses.
Exemplos:
(a&b)&&c
não precisa de parênteses:a&b&&c
assim como(a*b)+c
não.a+(b<<c)
pode ser reescrito comoa+b*2**c
.Isso não salva nada neste exemplo, mas será
c
um literal inteiro pequeno (<14).a<b&&c<d
coma<b&c<d
(a menos que você precisa a avaliação curto-circuito)fonte
Loops mais curtos
Se você tiver
X
instruções{
dentro}
do loop for, poderá movê-X-1
las(
dentro)
do loop for após o segundo pontofor(blah;blah;HERE)
e vírgula para salvar 3 bytes. (separe as instruções usando uma vírgula,
)Ao invés de
você pode mover uma das instruções para o
(
aparelho do loop for)
enquanto deixa a outra de forae salve 3 bytes (economizou mais 1 byte graças a @ETHProductions)
Simplificando,
ao invés de
mova as declarações para que você acabe com isso
e economize 3 bytes
fonte
for
for a afirmação final, ela;
se torna opcionalUse unário
~
paraa-b-1
ea+b+1
Além das sugestões de @Lynn sobre
x+1
→-~x
; ex-1
→~-x
, você também pode jogar golfea-b-1
ea+b+1
.Pode parecer uma dica que você não usará com tanta frequência, como usar em
~x
vez de-x-1
não acontecer com frequência, mas eu a usei o suficiente para vê-la como uma dica útil aqui. Especialmente com a indexação de matriz, você pode usá-las acima em alguns casos.fonte
Comprimir ou estrias
Truque simples que inventei ao tentar espremer uma longa faixa de condições encadeadas por ands (ou ors, nesse caso, basta substituir 'all' por 'any').
Por exemplo:
Torna-se
fonte
all(array-of-Booleans)
built-in?[a>0,a<10,a+b==4,a+3<1].all?
if 10>a>0 and a+b==4>1>a+3:
Confie no compilador para fornecer o desempenho necessário.
Certifique-se de saber quais otimizações são garantidas pelo compilador e em quais níveis de otimização e use-as livremente. E mesmo que o desempenho não seja um requisito de
preocupação, você ainda pode testar com otimizações ativadas e descontar apenas um caractere porque seu código ainda é tecnicamente válido sem o sinalizador do compilador.Considere a seguinte função Haskell para calcular 2 ^ n (ignorando o fato de que Haskell já possui um operador de exponenciação interno ou três) (23 caracteres):
O problema é - é terrivelmente lento, é executado em tempo exponencial. Isso pode tornar seu código não testável ou falhar em qualquer restrição de desempenho fornecida pela pergunta. Você pode ficar tentado a usar uma variável temporária ou uma literal de função imediatamente chamada para evitar chamadas de função repetidas (25 caracteres):
Mas o compilador já pode fazer isso por você, basta definir
-O
como um sinalizador do compilador! Em vez de gastar alguns caracteres extras por site para eliminar subexpressões comuns manualmente, basta dizer ao compilador para fazer otimizações básicas para você, com um total geral de um ou dois caracteres em todo o programa.fonte
p(x-1)*2
?Talvez um pouco óbvio, mas ...
Fazer uso dos valores de retorno do operador
Lembre-se de que o operador de atribuição retorna um valor!
Por exemplo, se você deseja adicionar y a x e verificar se x é maior que algo, você pode fazer
ao invés de
Ou talvez você queira encontrar o comprimento de uma sequência após apará-la:
Ao invés de
fonte
a = (b=c)+1;
defineb
comoc
e, em seguida, definea
comob+1
.a=1+b=c
. E você pode adicionar PHP e JavaScript à sua lista.=
operador uma precedência maior do lado esquerdo do que o direito, por isso1+x=2
é válido e avaliada como3
Utilize a versão do idioma / peculiaridades do compilador / ambiente / novos recursos
Isso é especialmente útil para poliglotas , mas pode ser aplicado a outros desafios. Às vezes, um bug do compilador pode obter um byte, um bug de implementação pode permitir que você salve alguns caracteres, ou um recurso realmente avançado pode melhorar sua pontuação.
fonte
Combine múltiplo / aninhado se verifica usando E / ou quando possível.
ou seja:
ao invés de:
fonte
&
, `|) para remover mais caracteres.&
vez de&&
remover 1 caractere em alguns casos, atrapalhe a precedência do operador e você precisará colocar parênteses para fazê-lo funcionar. Use-o com sabedoria.Encontre maneiras melhores de inicializar suas variáveis
Algumas outras respostas chegaram perto de mencionar isso, mas em muitos idiomas (estritamente digitados?), É mais curto inicializar
x
como uma string vazia como:ou
x
como runa vazia (char) como:do que
e
Usar valores preexistentes é obviamente preferido, mas não tão fácil.
fonte