Jakie masz ogólne wskazówki na temat gry w golfa w C #? Szukam pomysłów, które można by zastosować do problemów z golfem w kodzie, które są przynajmniej nieco specyficzne dla C # (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.
- zapożyczone z pomysłu marcog;)
Odpowiedzi:
Zamiast
.ToString()
używać+""
liczb i innych typów, które można bezpiecznie rzutować na łańcuch.źródło
(1+"").DoSomethingWith1String();
String.Concat(object)
argument statyczny , a nie wirtualneobject.ToString()
.Concat
jawnie konwertujenull
na pusty ciąg ( patrz źródło odwołania ). Nie ma „rodzimego castingu”, możesz przekonwertować coś takiego, po prostu wynik może być w niektórych przypadkach niezbyt użyteczny! (ale zachowanie zerowe może równie dobrze być).$"{n}"
Kiedyś celowo umieściłem swój program,
namespace System
aby móc skrócić dostęp do określonej klasy. Porównaćdo
źródło
System
przestrzeni nazw.using System;class P...
.using System;
o alias klasy w tej samej przestrzeni nazw, co jest krótsze niż pokazałem tutaj.using static System.Math;
w C # 6 (dodaj, że możesz użyć dowolnej z tych funkcji tak, jakby były naprawdę globalne - nie w klasie). Oryginalna sugestia może być jeszcze krótsza niż wusing static
przypadku konieczności uzyskania dostępu do wielu klas.static
słowo kluczowe często jest dłuższe niż jakiekolwiek oszczędności wynikające z pominięciaM.
wywołań metod, ale tak, jest to opcja, ale wiąże się z wysokimi kosztami początkowymi, które wymagają dużej liczby połączeń w celu amortyzacji.Służy
var
do deklarowania i inicjowania (pojedynczych) zmiennych w celu zapisywania znaków na typie:staje się
int
Oczywiście nie jest to szczególnie konieczne .źródło
var
nie może mieć wielu deklaratorów, na przykładvar x="x",y="y";
nie jest możliwe.Jeśli używasz LINQ, możesz przekazać metodę bezpośrednio do
Select
zamiast tworzenia lambda.Więc zamiast
możesz użyć
bezpośrednio.
(Odkryto niedawno podczas ulepszania jednej z odpowiedzi C # Timwi .)
źródło
Pamiętaj, że najmniejszy program do kompilacji w C # ma 29 znaków:
Zacznij więc od usunięcia tego z długości i oceń swoją odpowiedź na temat tego, ile to zajmie. C # nie może konkurować z innymi językami, jeśli chodzi o drukowanie lub czytanie, co jest sercem większości
[code-golf]
problemów, więc nie martw się o to. Jako golfista C # naprawdę konkurujesz z językiem.Kilka innych rzeczy, o których należy pamiętać:
if
Jeśli to możliwe, zmniejsz wszystkie pętle i instrukcje do jednej linii, aby usunąć nawiasy.źródło
As a C# golfer, you're really competing against the language
Niewiarygodnie powiązanestatic int Main()
, który miałby 28 znaków.return
czegoś .Zamiast
zrobić
Jeśli potrzebujesz wielu zmiennych, użyj tego (sugerowane przez @VisualMelon )
źródło
bool a=0<1,b=!a;
Preferuj operatora trójskładnikowego nad
if
...else
blokami, gdzie to stosowne.Na przykład:
jest bardziej wydajnie:
źródło
var x = input ?? "";
(uwielbiam moje koalescencje)i < 1
jest to złożone zdanie lub gdy nazwaj
jest długa. IMO również nie przenosi bardzo dobrze skutków ubocznych. W przypadku, gdyif (i < 1)
coś takiegoif (SendEmail(recipient))
zwraca true / false w zależności od powodzenia efektów ubocznych, wolę notację if / then.j=i<1?1:0;
wystarczy.Efektywne korzystanie z
Możesz zastąpić
float
(który jest aliasemSystem.Single
) zaz
pomocąz=System.Single;
Następnie zastąpić
z=System.Single;
zz=Single;
umieszczając program w przestrzeni nazwSystem
. (Jak w przypadku odpowiedzi Joey'a)Można to zastosować do innych typów wartości (użyj aliasu), struktur i klas
źródło
Jeśli musisz użyć
Console.ReadLine()
wielokrotnie w kodzie (co najmniej 3 razy), możesz:a następnie po prostu użyj
zamiast
źródło
()
z pierwszego wiersza.auto r=Console.ReadLine;
?auto
jestC++
czasownikiem.var
jest dlaC#
. Nie można tego zrobić, ponieważConsole.ReadLine
jest przeciążony, dlatego należy podać podpis funkcji, aby poinformować kompilator o żądanym przeciążeniu.Podczas odczytywania każdego znaku argumentu wiersza poleceń zamiast zapętlania do długości łańcucha:
Możesz zapisać postać, używając bloku try / catch, aby znaleźć koniec:
Dotyczy to dowolnej tablicy w obrębie tablicy, takiej jak:
string[]
int[][]
IList<IList<T>>
źródło
Użyj lambdas, aby zdefiniować funkcję w C # 6
W C # 6 możesz użyć lambda do zdefiniowania funkcji:
Jest to krótsze niż zdefiniowanie takiej funkcji:
źródło
LINQ
Zamiast używać:
Aby otrzymać Enumerable z wynikiem funkcji
f
dla każdegoint
z[0,y]
was może używaćjeśli potrzebujesz
string
lub cokolwiek, co implementujeEnumerable
w twoim programie, możesz ich również użyćźródło
Jeśli potrzebujesz użyć
Dictionary<TKey, TValue>
kodu generycznego co najmniej dwa razy w kodzie, możesz zadeklarować klasę słownika, jak w tym przykładzie:a następnie po prostu użyj
zamiast powtarzać
Dictionary<int,string>
dla każdej instancji.Użyłem tej techniki w tej odpowiedzi
źródło
using D = System.Collections.Generic.Dictionary<int,string>;
Możesz użyć
float
idouble
literałów, aby zaoszczędzić kilka bajtów.Gdy potrzebujesz trochę
int
arytmetyki, aby zwrócić a,float
lubdouble
możesz użyć literałów, aby wymusić konwersję.Jeśli kiedykolwiek spotkasz się z sytuacją, w której musisz rzucić, możesz zapisać kilka bajtów, używając zamiast tego mnożenia.
źródło
(x-y)*1d/x/y;
Pamiętaj, gdzie są prywatne lub publiczne, na przykład:
w porównaniu do
źródło
Main
nie potrzebuje żadnych argumentów w przeciwieństwie na przykład do Javy.W przypadku jednowierszowych wyrażeń lambda możesz pominąć nawiasy i średnik. W przypadku wyrażeń jednoparametrowych można pominąć nawiasy.
Zamiast
Posługiwać się
źródło
SomeCall(DoSomething)
jest jeszcze lepszyPętla:
Deklaracje zmienne:
stają się:
A jeśli potrzebujesz lub pracujesz ze zmienną i tylko raz, możesz zacząć od -1 (lub 0 w zależności od okoliczności pętli) i zwiększyć inline:
do
I to zmniejsza się o jeden znak, a także nieznacznie zaciemnia kod. Rób to tylko w
i
odniesieniu do PIERWSZEJ referencji, w ten sposób: (przyznane optymalizacje jednej postaci to niewiele, ale mogą pomóc)do
gdy pętla nie musi zwiększać
i
(pętla odwrotna):źródło
++
W takich przypadkach zwykle umieszczam bezpośrednio w nagłówku pętli:for(;++i<max;)
co jest łatwiejsze do naśladowania i trudniejsze do popełnienia błędu.for
nagłówka, co spowoduje zapisanie znaku ponownie.for(;i<max;)
sięwhile(i<max)
. Ta sama liczba bajtów, ale dla mnie wygląda po prostu czystiej.Istnieją okoliczności, w których parametr wyjściowy może zapisać znaki. Oto nieco wymyślony przykład, 10-pinowy algorytm kręgli.
Ze zwrotem:
I z parametrem wyjściowym:
Tutaj parametr wyjściowy zapisuje w sumie 5 znaków.
źródło
W języku C # nie wolno
if(n%2)
nam sprawdzać, czyn
jest liczbą parzystą. Jeśli to zrobimy, otrzymamycannot implicity convert int to bool
. Naiwne postępowanie polegałoby na:Lepszym sposobem jest użycie:
Użyłem tego, aby zyskać jeden bajt tutaj .
zwróć uwagę, że działa to tylko dla liczb dodatnich, ponieważ
-1%2==-1
jest rozważane nawet przy tej metodzie.źródło
Interpolacja ciągów
Naprawdę prostym ulepszeniem zajmującym mało miejsca jest interpolacja. Zamiast:
wystarczy użyć
$
do wstawienia wyrażeń:To, wraz z nowymi ciałami wyrażeń w C # 6.0, powinno sprawić, że każde proste obliczenie ciągu znaków będzie łatwe do gry w C #.
źródło
i+$" bottles of beer";
jest on krótszy niż$"{i} bottles of beer"
.$
.{i}
jeden z przodu i jeden w środku;)Użyj C # lambda. Ponieważ PPCG pozwala na wejście / wyjście lambda, powinniśmy ich użyć.
Klasyczne metody C # wygląda następująco:
Jako lambda napiszemy
Dozwolone są również anonimowe lambda:
Usuń cały hałas i skup się!
Aktualizacja:
Możemy poprawić jeden krok więcej z currying jak @TheLethalCoder komentarz:
Przykład curringowania @Felix Palmen: Jak obliczyć klucz WPA?
Będzie to pomocne, gdy masz dokładnie 2 parametry, wtedy
_
lepsza będzie pusta, nieużywana zmienna . Zobacz meta post na ten temat . Używam tej sztuczki tutaj . Trzeba będzie nieco zmienić funkcję. Przykład: Wypróbuj online!źródło
s=>c=>...
s=>s.Contains
.(string s,char c)=>s.Contains(c)
Twórz nazwy klas tylko jedną literą. Ulepszając wskazówki dotyczące gry w golfa w C #, z której pochodzimy
do
co w tym przypadku nokautuje kolejne 6 znaków.
źródło
Metoda
Compute
instancjiSystem.Data.DataTable
pozwala ocenić proste wyrażenie łańcuchowe, np .:C # (kompilator Visual C #) , 166 bajtów
Wypróbuj online!
Niezbyt „golfowy” jako taki, ale czasem może być przydatny.
źródło
Zamiana dwóch zmiennych
Zwykle, aby zamienić dwie zmienne, musisz zadeklarować zmienną tymczasową do przechowywania wartości. Wyglądałoby to tak:
To 16 bajtów! Istnieją inne metody zamiany, które są lepsze.
Trzy ostatnie działają tylko w przypadku wartości liczbowych i, jak wskazano tylko w ASCII, dwie ostatnie mogą spowodować wyjątek ArithmeticOverflow. Wszystkie powyższe mają 12 bajtów, co oznacza 4 bajty oszczędności w porównaniu z pierwszym przykładem.
źródło
Korzystanie z LinqPad da ci możliwość usunięcia całego narzutu programu, ponieważ możesz wykonywać polecenia bezpośrednio. (I to powinno być w pełni legalne w codegolf ... Nikt nie mówi, że potrzebujesz .exe)
Dane wyjściowe są wykonywane przy użyciu
.Dump()
metody rozszerzenia.źródło
.Dump()
;)(Szczególny przypadek znajomości priorytetu operatora !)
Użyj
%
do ścisłego (nieco) ograniczonego odejmowania. Może to zaoszczędzić parę nawiasów wokół odejmowania, w wyniku czego chcesz coś pomnożyć lub podzielić; ale bądź ostrożny, ma poważne ograniczenia.Zamiast
Rozważać
Przykłady:
Dopiero co to odkryłem i wydaje mi się, że warto będzie pamiętać o każdej pracy z ASCII w przyszłości. (Obecnie gram w golfa gdzieś, gdzie używam ASCII do kompaktowych reprezentacji numerycznych, ale trzeba pomnożyć przez
1
lub w-1
oparciu o inny warunek, a to pasiaste 2 bajty)źródło
Jeśli chcesz dołączyć wiele
using
s, które wypadają z tej samej hierarchii, często najdłuższym jest użycie najdłuższego jakonamespace
:vs:
źródło
Odkryte dziś „w okopach” przy jednoczesnym ulepszaniu kodu golfowego ... jeśli masz klasę do przetwarzania, możesz wykonać pracę w konstruktorze, aby zapisać deklarację metody.
Odkryłem to, redukując aplikację konsolową - ponieważ tak było
static void Main()
, wszystkie funkcje i zmienne musiały zostać zadeklarowane jako statyczne. Utworzyłem zagnieżdżoną klasę z funkcjami i zmiennymi składowymi, z główną pracą wykonywaną w konstruktorze. Zapisuje to również znaki w kodzie wywołującym.np. Klasa z metodą:
Klasa z pracą w konstruktorze:
Ten przykład zapisuje 9 znaków.
źródło
Użyj
Action
like,Func
aby ustawić funkcję na zmienną.Action
nie zwraca nic (void
), więc świetnie nadaje się do drukowania.Na przykład:
Te wskazówki są inspirowane przez @ W0lf świetny przykład użycia
Func
zReadLine
.źródło
Deklaruj puste / pasujące ciągi razem
Jeśli chcesz zadeklarować wiele pustych / pasujących ciągów, możesz zapisać kilka bajtów za pomocą:
Niestety
var a="",b=a,c=a;
jest nielegalne, jakimplicitly type variable cannot have multiple declarators
źródło
var a=b=c=""
w javascript?