Que dicas gerais você tem para jogar golfe em C ++? Estou procurando idéias que possam ser aplicadas para codificar problemas de golfe em geral que sejam pelo menos um pouco específicos para C ++ (por exemplo, "remover comentários" não é uma resposta). Poste uma dica por resposta.
48
Respostas:
O operador condicional ternário
?:
muitas vezes pode ser usado como um carrinho na de simplesif
-else
declarações em uma economia considerável.É de valor especial, pois pode ser usado para selecionar valores alternativos como em
fonte
e
eo
. Observe que isso é diferente de como esse operador trabalha em c, onde esse truque não funciona porque não pode ser um valor l.std::endl
com'\n'
que economiza 5 caracteresÀs vezes, você pode salvar dois caracteres usando o fato de que as variáveis estáticas de duração do armazenamento (que incluem especialmente todas as variáveis de escopo global) são automaticamente inicializadas com zero no início (ao contrário das variáveis automáticas nas quais você não tem essa garantia). Então, ao invés de
você pode escrever
fonte
Alguns compiladores (por exemplo, GCC) suportam constantes de vários caracteres . Isso pode salvar alguns caracteres quando um valor inteiro grande é necessário. Exemplo:
O valor é específico da implementação. Normalmente, o valor de
'ab'
é256*'a'+'b'
ou'a'+256*'b'
. Você pode especificar até 4 caracteres entre as aspas.fonte
Um que eu achei útil:
Aproveitando o fato de que valores diferentes de zero são avaliados
true
em expressões booleanas e que sãox&&y
avaliadosx*y
quando se lida com booleanosavalia como
Você só precisa estar ciente dos estouros, como indicado abaixo.
fonte
x!=0 && y!=0
. Mas ao usar a multiplicação, você precisa ter cuidado com os estouros. Ao usar números inteiros de 32 bits, x = y = 65536 (e várias outras combinações de potências de dois) também produziriam x * y = 0 .&&
possui um comportamento de curto-circuito que*
falta. Por exemplo, você não pode substituiri++!=0&&j++!=0
pori++*j++
.Use os seguintes tipos:
Para palavras / tipos repetitivos, use
#defines
:Só vale a pena se você usar
while
muito para compensar os 10 caracteres extras. ( Cerca de 4. )fonte
Se você estiver disposto a usar o C ++ 0x, poderá usar novos recursos, como lambdas .
fonte
Quando possível, altere
&&
e||
para&
e|
respectivamente.Ao usar instruções if simples:
pode ser alterado para:
que salva um personagem.
fonte
Em vez de usar
while(1)
, usefor(;;)
, salvando um caractere :)fonte
O uso do operador de vírgula no lugar de chaves de abertura e fechamento pode salvar alguns caracteres, se você tiver uma situação em que suas cláusulas contenham mais de uma instrução:
vs.
Dois caracteres salvos em um IF simples ou três no total para um IF / ELSE.
Como ponto de distinção entre C e C ++, o resultado de uma expressão de vírgula no C ++ como um todo pode ser usado como um valor l ... FWIW.
fonte
Como os elementos da matriz são armazenados diretamente um após o outro na memória, em vez de algo como isto:
Você pode fazer algo assim:
Obviamente, nenhuma das opções acima é jogada no golfe, para facilitar a leitura, mas o uso explícito de ponteiros pode economizar muito espaço.
fonte
for(int* i=array; i<array+25*25; i++)
? Então você só precisa acompanhar uma variável.Bastante óbvio, mas se você estiver usando grande parte da biblioteca padrão,
using namespace std;
poderá salvar alguns caracteres.fonte
using std::name;
pode ser mais curto.std::
cinco ou mais vezes.É útil lembrar que
a[i]
é o mesmo que*(a+i)
.Substitua
a[0]
por*a
para economizar dois caracteres. Além disso,a[i][0]
é equivalente a*a[i]
ea[0][i]
diminui parai[*a]
. Portanto, se você estiver codificando um0
índice em sua matriz, provavelmente existe uma maneira melhor.fonte
Em vez de escrever grandes potências de 10, use a notação . Por exemplo,
a=1000000000
é maior quea=1e9
. Isso pode ser estendido para outros números, comoa=1e9+24
é melhor quea=1000000024
.fonte
1e9/x
não é o mesmo que1000000000/x
ouint(1e9)/x
.Você pode usar o operador ternário
?:
sem nenhuma expressão no bloco verdadeiro (ele salva um byte)Veja aqui
fonte
Cabeçalho mais curto
Isso é específico do GCC, pode ser extensível a outros compiladores.
Cabeçalho pré-compilado.
No G ++,
bits/stdc++.h
o cabeçalho pré-compilado consiste em todos os outros cabeçalhos. Se você precisar deimport
2 diferentes, basta usar isso.Cabeçalho mais curto.
Todos os cabeçalhos listados em http://en.cppreference.com/w/cpp/header :
Mostrar snippet de código
classificados em ordem crescente de comprimento.
Alguns deles já são mais longos
bits/stdc++.h
e outros requerem suporte ao C ++ 17. Alguns outros não são suportados pelo TIO G ++ (por razões que não conheço). Filtre-os, temos:Mostrar snippet de código
Pode acontecer que alguns deles possam ser substituídos por outros mais curtos. Basta procurar binário se o que você precisa pode ser substituído. Em particular:
fonte
#import
em vez de#include
fornecer mais um byte.Além disso, o caractere de espaço entre
#import
e cabeçalho não é necessariamente:E se você precisar de algo do
stdlib
cabeçalho, poderá importar qualquer cabeçalho com o contêiner STL (preferívelset
oumap
) em vez decstdlib
.fonte
Operações aritméticas em booleanos:
Apesar
é melhor que
não é tão bom quanto
Além disso, usar #define em qualquer coisa usada muito. Geralmente é mais curto que o uso de funções, pois os nomes dos tipos não são necessários.
Combine as coisas o máximo possível:
é o mesmo que
fonte
x
como lvalue ex++
como rvalue. comportamento indefinido e sequência de pontosUse lambdas genéricas como modelos baratos
Para tipos diferentes de
int
, usá-los como argumentos de função pode ser caro. No entanto, lambdas genéricas foram introduzidas (em C ++ 14?) E permitem que qualquer lambda seja um modelo - o usoauto
para os tipos de argumento pode salvar bytes. Comparar:Lambdas genéricos também são muito convenientes para aceitar iteradores - provavelmente a melhor maneira de aceitar entradas de array em C ++ é
[](auto a, auto z)
, ondea
ez
são passados comobegin()
eend()
da matriz / vetor / lista / etc.fonte
Na minha primeira tentativa de codificar golf para a tarefa "Subtrair os próximos números" , iniciei da função (58 bytes)
5 bytes seguros, mudando para lambda e movendo a inicialização para fora de
for
(53)e, finalmente, depois de mudar
for
parawhile
, obtive 51 bytes:O código de teste ungolfed é algo como:
ATUALIZAR:
Na verdade,
for
pode atingir o mesmo comprimento quewhile
:fonte
Meio atrasado para a festa, eu acho ...
Se você deseja transformar uma expressão em -1 e 1 em vez de 0 e 1, em vez disso:
fazem isto:
Pode salvar alguns bytes, dependendo do uso.
fonte
int x=(a*10>5)*2-1;
, você não poderia fazerint x=a*10>5?1:-1;
, que é 1 byte menor?Se você deseja trocar duas variáveis inteiras aeb, então,
pode ser usado, economizando 5 caracteres do que o modo padrão
fonte
,t
nas entradas criadas anteriormente e, em seguidat=a;a=b;b=t;
, já teria sido 3 bytes mais curto que oa+=b;b=a-b;a-=b;
. Ainda assim, o seua^=b^=a^=b;
é ainda mais curto do que isso, então +1 de mim. Eu não sei C ++, mas realmente funciona . Como jogador de código Java, estou triste por não parecer funcionar lá . :(a^=b;b^=a;a^=b;
está funcionando bem em java.a^=b;b^=a;a^=b;
de fato funciona, mas é mais longo que o,t
+t=a;a=b;b=t;
. Desculpe por mencionar o Java, pois está fora de tópico aqui. Mas boa dica para codegolfers C ++!Use os recursos internos do GCC em vez de importar
Se você estiver usando um compilador GCC, às vezes é útil usar as funções internas, como
__builtin_puts
ou__builtin_clz
. Por exemplo,44 bytes:
50 bytes:
fonte
Se você estiver usando o C ++ 11 ou mais recente (o que deve ser sempre o caso agora), use
auto
para tipos complexos, se possível.Exemplo: 54 bytes em vez de 66
Além disso, como o desempenho não importa, para alguns desafios, um
std::list
pode apenas fazer o trabalho por alguns bytes a menos:fonte
As funções
<algorithm>
geralmente requerem uma passagema.begin(),a.end()
realmente longa; em vez disso, você pode&a[0],&*end(a)
salvar 3 bytes sea
forvector
oustring
.fonte
Não use
string("")
, use""
. Ele economiza 8 bytes.fonte
"" + 'a'
ischar* + char
, que é adição de ponteiro, enquantostd::string("") + 'a'
isstd::string + char
- string concatenação.string()
podia funcionar.