Какие общие советы у вас есть для игры в гольф в C #? Я ищу идеи, которые могут быть применены к проблемам с гольф-кодом в целом, которые, по крайней мере, несколько специфичны для C # (например, «удалить комментарии» не является ответом). Пожалуйста, оставьте один совет за ответ.
- позаимствовано у идеи Маркога;)
Ответы:
Вместо использования
.ToString()
используйте+""
для чисел и других типов, которые могут быть безопасно преобразованы в строку.источник
(1+"").DoSomethingWith1String();
String.Concat(object)
с аргументом, а не виртуальный вызовobject.ToString()
.Concat
явно преобразуетсяnull
в пустую строку ( см. справочный источник ). Никакого «нативного приведения» не происходит, вы можете преобразовать что-нибудь подобное, просто результат может быть не очень полезным в некоторых случаях! (но нулевое поведение вполне может быть).$"{n}"
Однажды я специально поместил свою программу,
namespace System
чтобы сократить доступ к определенному классу. сравнитьв
источник
System
пространстве имен.using System;class P...
.using System;
о псевдониме для класса в том же пространстве имен, что короче, чем я здесь показал.using static System.Math;
C # 6 это еще короче (добавьте, что вы можете использовать любую из этих функций, как если бы они были действительно глобальными, а не в классе). Исходное предложение может быть еще короче, чемusing static
если вам нужно получить доступ к нескольким классам.static
ключевое слово часто дольше, чем любая экономия от пропускаM.
вызовов методов, но да, это вариант, но он требует огромных первоначальных затрат, которые требуют много вызовов для амортизации.Используйте
var
для объявления и инициализации (одиночных) переменных, чтобы сохранить символы типа:становится
int
Конечно, это не обязательно .источник
var
не может иметь несколько объявлений, например,var x="x",y="y";
это невозможно.При использовании LINQ вы можете передать метод напрямую
Select
вместо создания лямбды.Итак, вместо
вы можете использовать
непосредственно.
(Обнаружен недавно при улучшении одного из ответов Тимви на C # .)
источник
Помните, что самая маленькая компилируемая программа на C # состоит из 29 символов:
Итак, начните с удаления этого из вашей длины и судите свой ответ о том, сколько это займет. C # не может конкурировать с другими языками, когда речь идет о печати или чтении ввода, что является сердцем большинства
[code-golf]
проблем, поэтому не беспокойтесь об этом. Как игрок в C #, вы действительно соревнуетесь с языком.Несколько других вещей, которые нужно иметь в виду:
if
операторы до одной строки, если это возможно, чтобы снять скобки.источник
As a C# golfer, you're really competing against the language
Невероятно связанныйstatic int Main()
28 символов.return
чего-то .Вместо
делать
Если вам нужно несколько переменных, используйте это (предложено @VisualMelon )
источник
bool a=0<1,b=!a;
Пользуйся троичным оператором
if
..else
блоками, где это уместно.Например:
эффективнее:
источник
var x = input ?? "";
(я люблю свои объединения)i < 1
это сложный оператор или когда имяj
длинное. ИМО, он также не очень хорошо передает побочные эффекты. В случае, когдаif (i < 1)
что-то вродеif (SendEmail(recipient))
этого возвращает true / false в зависимости от успешности побочных эффектов, я предпочитаю нотацию if / then.j=i<1?1:0;
достаточно.Эффективное использование использования
Вы можете заменить
float
(это псевдонимSystem.Single
) сz
помощьюz=System.Single;
Затем замените
z=System.Single;
сz=Single;
помощью размещения программы в пространстве именSystem
. (Как и с ответом Джои)Это может быть применено для других типов значений (используйте то, для чего они являются псевдонимами), структур и классов.
источник
Если вам нужно использовать
Console.ReadLine()
несколько раз в вашем коде (минимум 3 раза), вы можете сделать:а потом просто использовать
вместо
источник
()
с первой строки.auto r=Console.ReadLine;
?auto
этоC++
глагол.var
дляC#
. Причина, по которой это невозможно сделать, заключается в том, чтоConsole.ReadLine
она перегружена, поэтому необходимо указать сигнатуру функции, чтобы сообщить компилятору, какая перегрузка нужна.При чтении каждого символа аргумента командной строки, а не зацикливания до длины строки:
Вы можете сохранить символ, используя блок try / catch, чтобы найти конец:
Это относится к любому массиву в массиве, например:
string[]
int[][]
IList<IList<T>>
источник
Используйте лямбда-выражения для определения функции в C # 6
В C # 6 вы можете использовать лямбду для определения функции:
Это короче, чем определение такой функции:
источник
LINQ
Вместо того, чтобы использовать:
чтобы получить Перечислимый с результатом функции
f
для каждогоint
в[0,y]
вы можете использоватьесли вам нужно
string
или что-то, что реализуетсяEnumerable
в вашей программе, вы можете использовать их тожеисточник
Если вам нужно использовать универсальный
Dictionary<TKey, TValue>
по крайней мере два раза в вашем коде, вы можете объявить класс словаря, как в этом примере:а потом просто использовать
вместо повторения
Dictionary<int,string>
для каждого экземпляра.Я использовал эту технику в этом ответе
источник
using D = System.Collections.Generic.Dictionary<int,string>;
Вы можете использовать
float
иdouble
литералы, чтобы сохранить несколько байтов.Когда вам нужна некоторая
int
арифметика для возвратаfloat
илиdouble
вы можете использовать литералы для принудительного преобразования.Если вы когда-нибудь столкнетесь с ситуацией, когда вам нужно выполнить приведение, вы можете сохранить несколько байтов, используя вместо этого умножение.
источник
(x-y)*1d/x/y;
Помните, где частное или публичное присуще, например, следующее:
по сравнению с
источник
Main
не нужно никаких аргументов в отличие от Java, например.Для однострочных лямбда-выражений можно пропустить скобки и точку с запятой. Для однопараметрических выражений вы можете пропустить круглые скобки.
Вместо
использование
источник
SomeCall(DoSomething)
еще лучшеЦиклический:
Переменные объявления:
стали:
И если у вас есть необходимость или работа с переменной i только один раз, вы можете начать с -1 (или 0 в зависимости от обстоятельств цикла) и увеличить значение inline:
в
И это уменьшает на один символ, а также немного запутывает код. Сделайте это только для ПЕРВОЙ
i
ссылки, например, так: (если оптимизация одного символа невелика, но она может помочь)в
когда цикл не должен увеличиваться
i
(обратный цикл заказа):источник
++
В таких случаях я обычно помещаю непосредственно в заголовок цикла: заfor(;++i<max;)
ним легче следовать, а с труднее ошибиться.for
заголовок, который затем снова сохранит символ.for(;i<max;)
наwhile(i<max)
. Такое же количество байтов, но для меня это выглядит чище.Существуют обстоятельства, когда выходной параметр может сохранять символы. Вот немного надуманный пример - алгоритм 10-пинового боулинга.
С возвратом заявления:
И с выходным параметром:
Выходной параметр здесь сохраняет в общей сложности 5 символов.
источник
В C # нам не разрешено
if(n%2)
проверять,n
является ли число четным. Если мы это сделаем, мы получимcannot implicity convert int to bool
. Наивная обработка будет делать:Лучше всего использовать:
Я использовал это, чтобы получить один байт здесь .
обратите внимание, что это работает только для положительных чисел, так как
-1%2==-1
это считается даже с этим методом.источник
Строковая интерполяция
По-настоящему простым экономящим место улучшением является интерполяция. Вместо:
просто используйте
$
встроенные выражения:Это, вместе с новыми телами выражений в C # 6.0, должно сделать любую простую задачу вычисления строк довольно удобной в C #.
источник
i+$" bottles of beer";
короче$"{i} bottles of beer"
.$
, хотя.{i}
один спереди и один посередине;)Используйте C # лямбду. Поскольку PPCG позволяет использовать лямбда для ввода / вывода, мы должны их использовать.
Классические методы C # выглядят так:
Как лямбда напишем
Анонимная лямбда тоже допускается:
Убери весь шум и сфокусируйся!
Обновить:
Мы можем улучшить один шаг больше с выделкой , как @TheLethalCoder комментарий:
Пример curring от @Felix Palmen: Как вычислить ключ WPA?
Будет полезно, когда у вас будет ровно 2 параметра, тогда
_
лучше использовать пустую неиспользуемую переменную . Смотрите мета-пост об этом . Я использую этот трюк здесь . Вам придется немного изменить функцию. Пример: попробуйте онлайн!источник
s=>c=>...
s=>s.Contains
.(string s,char c)=>s.Contains(c)
Сделайте имена классов только одной буквой. Улучшение на Советы для кода игры в гольф в C # мы идем от
в
который выбивает еще 6 символов в этом случае.
источник
Метод
Compute
instanceSystem.Data.DataTable
, позволяет оценить простое строковое выражение, например:C # (компилятор Visual C #) , 166 байт
Попробуйте онлайн!
Не очень "гольф" как таковой, но иногда может быть полезным.
источник
Обмен двух переменных
Обычно, чтобы поменять местами две переменные, вы должны объявить временную переменную для хранения значения. Это будет выглядеть примерно так:
Это 16 байтов! Есть некоторые другие методы обмена, которые лучше.
Последние три работают только для числовых значений, и, как указано только в ASCII, последние два могут привести к исключению ArithmeticOverflow. Все вышеперечисленное имеет размер 12 байт, что позволяет сэкономить 4 байта по сравнению с первым примером.
источник
Использование LinqPad даст вам возможность удалить все накладные расходы программы, поскольку вы можете выполнять операторы напрямую. (И это должно быть полностью законно в Codegolf ... Никто не говорит, что вам нужен .exe)
Вывод осуществляется с использованием
.Dump()
метода расширения.источник
.Dump()
;)(Частный случай знания вашего приоритета оператора !)
Используйте
%
для плотного (несколько) ограниченного вычитания. Это может сэкономить вам пару скобок вокруг вычитания, результат которого вы хотите умножить или разделить на что-то; но будьте осторожны, у него есть серьезные ограничения.Вместо
Рассмотреть возможность
Примеры:
Я только что обнаружил это, и я чувствую, что это будет полезно помнить при работе с ASCII в будущем. (В настоящее время я играю в гольф где-то, где я использую ASCII для компактных числовых представлений, но нужно умножить на
1
или-1
на основе другого условия, и это полосатый 2 байта)источник
Если вам нужно включить несколько
using
s, которые выпадают из одной и той же иерархии, часто короче использовать самый длинный в качествеnamespace
:против:
источник
Обнаружен сегодня вечером "в окопах", улучшая при этом некоторый гольф-код ... если у вас есть класс для обработки, вы можете выполнить работу в конструкторе, чтобы сохранить объявление метода.
Я обнаружил это при сокращении консольного приложения - как было
static void Main()
, все функции и переменные должны были быть объявлены как статические. Я создал вложенный класс с функциями-членами и переменными, основная работа была выполнена в конструкторе. Это также сохраняет символы в коде вызова.например, класс с методом:
Класс с работой в конструкторе:
Этот пример сохраняет 9 символов.
источник
Используйте
Action
как,Func
чтобы установить функцию для переменной.Action
ничего не возвращает (void
), так что это отлично подходит для печати.Например:
Эти советы вдохновлены @ W0lf отличным примером использования
Func
сReadLine
.источник
Объявлять пустые / совпадающие строки вместе
Если вам нужно объявить несколько пустых / совпадающих строк, вы можете сохранить несколько байтов следующим образом:
К сожалению,
var a="",b=a,c=a;
это незаконно, так какimplicitly type variable cannot have multiple declarators
источник
var a=b=c=""
как в JavaScript?