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ź.
48
Odpowiedzi:
Trójskładnikowy operator warunkowy
?:
może być często używany jako zastępstwo dla prostychif
-else
wyciągów przy znacznych oszczędnościach.Ma to szczególną wartość, ponieważ może być używane do wybierania alternatywnych wartości lv, jak w
źródło
e
io
. Zauważ, że różni się to od działania tego operatora w c, w którym ta sztuczka nie działa, ponieważ nie może być wartością.std::endl
się'\n'
, że oszczędza 5 znakówCzasami można zapisać dwa znaki, wykorzystując fakt, że statyczne zmienne czasu przechowywania (w szczególności wszystkie globalne zmienne zakresu) są automatycznie inicjalizowane na początku na zero (w przeciwieństwie do zmiennych automatycznych, w których nie ma takiej gwarancji). Więc zamiast
Możesz pisać
źródło
Niektóre kompilatory (np. GCC) obsługują stałe wieloznakowe . Dzięki temu można zapisać kilka znaków, gdy wymagana jest duża liczba całkowita. Przykład:
Wartość zależy od implementacji. Zwykle wartość
'ab'
wynosi256*'a'+'b'
lub'a'+256*'b'
. Między znakami cudzysłowu można podać do 4 znaków.źródło
Jeden, który mi się przydał:
Korzystając z faktu, że wartości niezerowe są
true
wyrażane w wyrażeniach boolowskich, i tox&&y
ma znaczenie wx*y
przypadku wartości logicznychocenia na
Musisz tylko pamiętać o przepełnieniu, jak wskazano poniżej.
źródło
x!=0 && y!=0
. Ale gdy używasz mnożenia, musisz uważać na przepełnienia. Przy użyciu 32-bitowych liczb całkowitych x = y = 65536 (i kilka innych kombinacji potęg dwóch) dałoby również x * y = 0 .&&
ma zachowanie zwarciowe, którego*
brakuje. Na przykład, nie można zastąpići++!=0&&j++!=0
zi++*j++
.Użyj następujących typów:
W przypadku powtarzających się słów / typów użyj
#defines
:Warto, jeśli
while
dużo używasz, aby nadrobić dodatkowe 10 znaków. ( Około 4. )źródło
Jeśli chcesz używać C ++ 0x, możesz użyć nowych funkcji, takich jak lambdas .
źródło
Gdy jest to możliwe, należy zmienić
&&
i||
na&
i|
odpowiednio.Podczas korzystania z prostych instrukcji if:
można zmienić na:
co ratuje postać.
źródło
Zamiast używać
while(1)
, użyjfor(;;)
, zapisując jedną postać :)źródło
Używanie operatora przecinku zamiast otwierania i zamykania nawiasów klamrowych może uratować kilka znaków, jeśli masz sytuację, w której klauzule zawierają więcej niż jedną instrukcję:
vs.
Dwa znaki zapisane na zwykłym IF lub trzy łącznie dla IF / ELSE.
Jako punkt rozróżnienia między C i C ++ wynik wyrażenia przecinkowego w C ++ jako całości może być użyty jako wartość ... FWIW.
źródło
Ponieważ elementy tablic są przechowywane bezpośrednio w pamięci, zamiast czegoś takiego:
Możesz zrobić coś takiego:
Oczywiście żadne z powyższych nie jest golfem, dla czytelności, ale wyraźne użycie wskaźników może zaoszczędzić dużo miejsca.
źródło
for(int* i=array; i<array+25*25; i++)
? Następnie musisz śledzić tylko jedną zmienną.To dość oczywiste, ale jeśli używasz dużo standardowej biblioteki,
using namespace std;
może zapisać kilka znaków.źródło
using std::name;
może być ona krótsza.std::
pięć lub więcej razy.Warto pamiętać, że
a[i]
jest to to samo co*(a+i)
.Wymienić
a[0]
z*a
dwóch znaków oszczędności. Ponadtoa[i][0]
jest równoważne*a[i]
ia[0][i]
zmniejsza się doi[*a]
. Jeśli więc kodujesz0
indeks na stałe w swojej tablicy, prawdopodobnie istnieje lepszy sposób.źródło
Zamiast pisać duże potęgi 10, użyj notacji e . Na przykład
a=1000000000
jest dłuższy niża=1e9
. Można to rozszerzyć na inne liczby, takie jaka=1e9+24
lepsze niża=1000000024
.źródło
1e9/x
to nie to samo co1000000000/x
lubint(1e9)/x
.Możesz użyć operatora trójskładnikowego
?:
bez żadnych wyrażeń w bloku true (zapisuje on bajt)Sprawdź tutaj
źródło
Krótszy nagłówek
Jest to specyficzne dla GCC, może być rozszerzalne na inne kompilatory.
Wstępnie skompilowany nagłówek.
W G ++
bits/stdc++.h
nagłówek prekompilowany składa się ze wszystkich innych nagłówków. Jeśli potrzebujeszimport
2 różnych, możesz po prostu tego użyć.Krótszy nagłówek.
To są wszystkie nagłówki wymienione na stronie http://en.cppreference.com/w/cpp/header :
Pokaż fragment kodu
posortowane według rosnącej długości.
Niektóre z nich są już dłuższe
bits/stdc++.h
, a niektóre wymagają obsługi C ++ 17. Niektóre inne nie są obsługiwane przez TIO G ++ (z powodów, których nie znam). Filtruj je:Pokaż fragment kodu
Może się zdarzyć, że niektóre z nich można zastąpić krótszymi. Wystarczy wyszukać binarnie, czy tego, którego potrzebujesz, można wymienić. W szczególności:
źródło
#import
zamiast#include
daje jeszcze jeden bajt.Ponadto spacja między
#import
i nagłówkiem niekoniecznie:A jeśli potrzebujesz czegoś z
stdlib
nagłówka, możesz zaimportować dowolny nagłówek z kontenerem STL (najlepiejset
lubmap
) zamiastcstdlib
.źródło
Operacje arytmetyczne na boolach:
Mimo że
jest lepszy niż
to nie jest tak dobre jak
Używanie #define do wszystkiego, co jest często używane. Często jest krótszy niż używanie funkcji, ponieważ nazwy typów nie są konieczne.
Łącz rzeczy w jak największym stopniu:
jest taki sam jak
źródło
x
jako wartości ix++
jako wartości. niezdefiniowane zachowanie i punkty sekwencjiUżywaj ogólnych lambdas jako tanich szablonów
W przypadku typów innych niż
int
używanie ich jako argumentów funkcji może być kosztowne. Jednak wprowadzono ogólne lambdy (w C ++ 14?) I pozwalają, aby dowolna lambda była szablonem - użycieauto
typów argumentów może zaoszczędzić bajty. Porównać:Ogólne lambdy są również bardzo wygodne do akceptowania iteratorów - prawdopodobnie najlepszym sposobem na akceptację danych wejściowych z tablicy w C ++ jest
[](auto a, auto z)
, gdziea
iz
są przekazywane jakobegin()
iend()
z tablicy / vector / list / etc.źródło
W mojej pierwszej próbie kodu golfa dla zadania „Odejmij kolejne liczby” Zacząłem od funkcji (58 bajtów)
następnie bezpieczne 5 bajtów z przejściem na lambda i przeniesieniem inicjalizacji z
for
(53)i wreszcie po przejściu z
for
nawhile
mam 51 bajtów:Nie testowany kod testowy przypomina:
AKTUALIZACJA:
W rzeczywistości
for
może osiągnąć taką samą długość jakwhile
:źródło
Trochę późno na imprezę, jak sądzę ...
Jeśli chcesz zmienić wyrażenie na -1 i 1 zamiast 0 i 1, zamiast tego:
Zrób to:
Może zaoszczędzić niektóre bajty w zależności od użycia.
źródło
int x=(a*10>5)*2-1;
, nie możesz tego zrobićint x=a*10>5?1:-1;
, który jest o 1 bajt krótszy?Jeśli chcesz zamienić dwie zmienne całkowite aib, to:
można użyć, oszczędzając 5 znaków niż standardowy sposób
źródło
,t
w ints utworzonych wcześniej, a wtedyt=a;a=b;b=t;
byłyby już o 3 bajty krótsze niża+=b;b=a-b;a-=b;
. Twója^=b^=a^=b;
jest jeszcze krótszy, więc daj +1 ode mnie. Nie znam C ++, ale rzeczywiście działa . Jako golfista Java jestem smutny, że nie działa . :(a^=b;b^=a;a^=b;
działa dobrze w Javie.a^=b;b^=a;a^=b;
rzeczywiście działa, ale jest dłuższy niż,t
+t=a;a=b;b=t;
. Przepraszam, że wspomniałem o Javie, ponieważ jest tutaj nie na temat. Ale fajna wskazówka dla kodegolfów C ++!Używaj wbudowanych GCC zamiast importować
Jeśli używasz kompilatora GCC, czasem pomaga korzystanie z ich wbudowanych funkcji, takich jak
__builtin_puts
lub__builtin_clz
. Na przykład,44 bajty:
50 bajtów:
źródło
Jeśli korzystasz z C ++ 11 lub nowszej wersji (co powinno zawsze mieć miejsce teraz), użyj
auto
, jeśli to możliwe , do typów złożonych.Przykład: 54 bajty zamiast 66
Ponadto, ponieważ wydajność nie ma znaczenia, w przypadku niektórych wyzwań
std::list
może po prostu wykonać zadanie o kilka bajtów mniej:źródło
Funkcje
<algorithm>
często wymagają przekazania,a.begin(),a.end()
które jest naprawdę długie, zamiast tego można użyć&a[0],&*end(a)
do zapisania 3 bajtów, jeślia
jestvector
lubstring
.źródło
Nie używaj
string("")
, używaj""
. Oszczędza 8 bajtów.źródło
"" + 'a'
ischar* + char
, który jest dodawaniem wskaźnika, natomiaststd::string("") + 'a'
isstd::string + char
- konkatenacja ciągów znaków.string()
pracowałbym.