Какие общие советы у вас есть для игры в гольф на C ++? Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые, по крайней мере, несколько специфичны для C ++ (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.
48
Ответы:
Тройной условный оператор
?:
может часто использоваться в качестве подставки в для простогоif
-else
заявлений на значительной экономии средств.Это имеет особое значение в том смысле, что его можно использовать для выбора альтернативных значений, как в
источник
e
иo
. Обратите внимание, что это отличается от того, как этот оператор работает в c, где этот трюк не работает, потому что он не может быть lvalue.std::endl
с ,'\n'
что экономит 5 символовИногда вы можете сохранить два символа, используя тот факт, что статические переменные продолжительности хранения (которые особенно включают в себя все глобальные переменные области видимости) автоматически инициализируются нулями в начале (в отличие от автоматических переменных, где у вас нет такой гарантии). Так что вместо
ты можешь написать
источник
Некоторые компиляторы (например, GCC) поддерживают многосимвольные константы . Это может сохранить несколько символов, когда требуется большое целочисленное значение. Пример:
Значение зависит от реализации. Обычно значение
'ab'
равно256*'a'+'b'
или'a'+256*'b'
. Вы можете указать до 4 символов между кавычками.источник
Тот, который я нашел удобным:
Воспользовавшись тем фактом, что ненулевые значения оцениваются
true
в булевых выражениях, и это имеетx&&y
значениеx*y
при работе с булевыми выражениямиоценивает
Вы просто должны знать о переполнениях, как указано ниже.
источник
x!=0 && y!=0
. Но при использовании умножения вы должны быть осторожны с переполнениями. При использовании 32-разрядных целых чисел x = y = 65536 (и несколько других комбинаций степеней двойки) также приведет к x * y = 0 .&&
имеет поведение короткого замыкания, которое*
отсутствует. Например, вы не можете заменитьi++!=0&&j++!=0
наi++*j++
.Используйте следующие типы:
Для повторяющихся слов / типов используйте
#defines
:Это того стоит, если вы используете
while
много, чтобы наверстать лишние 10 символов. ( Около 4. )источник
Если вы хотите использовать C ++ 0x, вы можете использовать новые функции, такие как лямбда-выражения .
источник
По возможности меняйте
&&
и||
на&
и|
соответственно.При использовании простых операторов if:
можно изменить на:
который сохраняет характер.
источник
Вместо того, чтобы использовать
while(1)
, используйтеfor(;;)
, сохраняя один символ :)источник
Использование оператора запятой вместо открытых и закрытых скобок может сохранить несколько символов, если у вас есть ситуация, когда в ваших предложениях содержится более одного оператора:
против
Два символа, сохраненные на простой IF, или всего три для IF / ELSE.
Как различие между C и C ++, результат выражения запятой в C ++ в целом может использоваться как lvalue ... FWIW.
источник
Поскольку элементы массива хранятся непосредственно в памяти друг за другом, а не как-то так:
Вы можете сделать что-то вроде этого:
Очевидно, что ни один из вышеперечисленных не подходит для удобства чтения, но явное использование указателей может сэкономить вам много места.
источник
for(int* i=array; i<array+25*25; i++)
? Тогда вам нужно только отслеживать одну переменную.Совершенно очевидно, но если вы используете много стандартной библиотеки, вы
using namespace std;
можете сохранить несколько символов.источник
using std::name;
возможно, будет короче.std::
пять или более раз.Полезно помнить, что
a[i]
это так же, как*(a+i)
.Замените
a[0]
на*a
для двухсимвольной экономии. Кроме того,a[i][0]
эквивалентно*a[i]
иa[0][i]
сокращается доi[*a]
. Поэтому, если вы жестко программируете0
индекс в своем массиве, возможно, существует лучший способ.источник
Вместо написания больших степеней 10, используйте электронные обозначения . Например,
a=1000000000
длиннее чемa=1e9
. Это может быть распространено на другие номера, какa=1e9+24
лучше, чемa=1000000024
.источник
1e9/x
это не то же самое, что1000000000/x
илиint(1e9)/x
.Вы можете использовать троичный оператор
?:
без каких-либо выражений в блоке true (он сохраняет байт)Проверьте это здесь
источник
Более короткий заголовок
Это специфично для GCC, оно может быть расширено другими компиляторами.
Предварительно скомпилированный заголовок.
В G ++
bits/stdc++.h
это предварительно скомпилированный заголовок состоит из всех остальных заголовков. Если вам нужноimport
2 разных, вы можете просто использовать это.Короче заголовок.
Это все заголовки, перечисленные на http://en.cppreference.com/w/cpp/header :
Показать фрагмент кода
отсортировано в порядке возрастания длины.
Некоторые из них уже длиннее
bits/stdc++.h
, а некоторые требуют поддержки C ++ 17. Некоторые другие не поддерживаются TIO G ++ (по причинам, о которых я не знаю). Отфильтровать их мы имеем:Показать фрагмент кода
Может случиться, что некоторые из них могут быть заменены на более короткие. Просто бинарный поиск, можно ли заменить тот, который вам нужен. В частности:
источник
#import
вместо того, чтобы#include
дать вам еще один байт.Кроме того, пробел между
#import
и заголовком не обязательно:И если вам нужно что-то из
stdlib
заголовка, вы можете импортировать любой заголовок с контейнером STL (предпочтительноset
илиmap
) вместоcstdlib
.источник
Арифметические операции над логическими значениями:
Несмотря на то что
Это лучше чем
это не так хорошо, как
Кроме того, использование #define для всего, что используется часто. Это часто короче, чем использование функций, так как имена типов не нужны.
Объедините вещи как можно больше:
такой же как
источник
x
в качестве lvalue иx++
в качестве rvalue. неопределенные точки поведения и последовательностиИспользуйте общие лямбды в качестве дешевых шаблонов
Для других типов
int
использование их в качестве аргументов функции может быть дорогостоящим. Тем не менее, были введены общие лямбда-выражения (в C ++ 14?), Позволяющие любой лямбда-выражению быть шаблоном - использованиеauto
типов аргументов позволяет сохранять байты. Для сравнения:Общие лямбды также очень удобны для принятия итераторов - вероятно, лучший способ принять входные данные массива в C ++
[](auto a, auto z)
, гдеa
иz
передаются какbegin()
иend()
из массива / вектора / списка / и т.д.источник
В моей первой попытке кода гольф для задачи «Вычесть следующие числа» я начал с функции (58 байт)
затем безопасно 5 байтов с переходом на лямбду и перемещением инициализации из
for
(53)и наконец после переключения с
for
наwhile
я получил 51 байт:Тестовый код ungolfed выглядит примерно так:
ОБНОВИТЬ:
На самом деле
for
может достигать той же длины, что иwhile
:источник
Вроде поздно на вечеринку, наверное ...
Если вы хотите превратить выражение в -1 и 1 вместо 0 и 1 вместо этого:
сделай это:
Это может сэкономить несколько байтов в зависимости от использования.
источник
int x=(a*10>5)*2-1;
не могли бы вы сделатьint x=a*10>5?1:-1;
, что на 1 байт короче?Если вы хотите поменять местами две целочисленные переменные a и b,
можно использовать, сохранив 5 символов, чем стандартным способом
источник
,t
в созданных ранее целых, а затемt=a;a=b;b=t;
уже на 3 байта короче, чемa+=b;b=a-b;a-=b;
. Тем не менее, вашa^=b^=a^=b;
даже короче, так что +1 от меня. Я не знаю C ++, но это действительно работает . Как игрок в код Java, мне грустно, что он там не работает . :(a^=b;b^=a;a^=b;
он отлично работает в Java.a^=b;b^=a;a^=b;
действительно работает, но длиннее,t
+t=a;a=b;b=t;
. Извините за упоминание Java, поскольку это не по теме здесь. Но хороший совет для программистов C ++!Используйте встроенные функции GCC вместо импорта
Если вы используете компилятор GCC, это иногда помогает использовать их встроенные функции, такие как
__builtin_puts
или__builtin_clz
. Например,44 байта:
50 байтов:
источник
Если вы используете C ++ 11 или новее (что всегда должно быть в настоящее время), используйте
auto
для сложных типов, если это возможно.Пример: 54 байта вместо 66
Кроме того, поскольку производительность не имеет значения, для некоторых задач
std::list
может просто выполнить работу на несколько байтов меньше:источник
Функции
<algorithm>
часто требуют передачи,a.begin(),a.end()
которая очень длинная, вместо этого вы можете использовать&a[0],&*end(a)
для сохранения 3 байта, еслиa
естьvector
илиstring
.источник
Не используйте
string("")
, используйте""
. Это экономит 8 байтов.источник
"" + 'a'
ischar* + char
- это добавление указателя, аstd::string("") + 'a'
isstd::string + char
- конкатенация строк.string()
должно сработать.