Czasami, podczas gry w golfa, w kodzie należy przedstawiać duże liczby. Zapisywanie ich w obecnej postaci może znacznie zwiększyć liczbę bajtów.
Jakie masz 1 ogólne wskazówki na temat zwięzłego przedstawiania długich liczb w kodzie?
Proszę zamieścić jedną wskazówkę na odpowiedź.
1 W ogóle , to znaczy wskazówek, które mogą być stosowane w odniesieniu do więcej niż jednego języka. Aby uzyskać wskazówki dotyczące języka, publikuj posty w odpowiednich wątkach.
Odpowiedzi:
Zwróć uwagę na numery specjalne
Niektóre języki mają wbudowane funkcje kwadratów, potęgowania z bazą 2, n-tą liczbą pierwszą, silnią lub innymi procedurami, które mogą generować duże liczby. Sprawdź, czy Twój numer przypadkowo należy do którejkolwiek z tych kategorii.
A jeśli nie, może się zdarzyć, że większa liczba będzie pasować do twoich celów i może zostać użyta zamiast tego.
źródło
1.01e6
wystarczą iteracje,1e7
oszczędza 3 bajty kosztem czasu działania.Użyj bitowych operatorów logicznych
Niektóre języki mają bitowe AND, OR, XOR, a czasem NIE.
Wyrażenie określonej dużej liczby jako bitowej kombinacji wyniku potęgowania lub przesunięcia w lewo i innej liczby może doprowadzić do dokładnie takiej liczby, jakiej potrzebujesz. Jest to zwykle warte zachodu tylko wtedy, gdy liczby stają się dość duże.
Na przykład
2147483722
ma 10 bajtów, ale2<<30^74
(2 ^ 31 bitowo-XOR z 74) ma tylko 8.źródło
bc
.). XOR nigdy nie jest bardziej użyteczny niż+
i-
: w tym przypadku xor i add dają ten sam wynik, ale we wszystkich przypadkach istnieje pewna liczba całkowita, którą można dodać lub odjąć, aby uzyskać taki sam wynik jak xor z liczbą całkowitą, a dodatek jest nie większy, a czasem krótszy.1e9^2e9
.9<<49^7<<19
użycie dodawania zamiast XOR?1286561280
w JavaScript i Perlu (i prawdopodobnie w innych językach) i jest to krótsze wyrażenie do wygenerowania tej wartości niż ekwiwalent za pomocą+
lub-
.Użyj ciągów znaków dla powtarzających się liczb
W przypadku liczb, które mają bardzo powtarzalny charakter, możesz użyć ciągów znaków i rzucić je na liczbę całkowitą. Na przykład w JavaScript
źródło
1e100/9
W tym przypadku możesz użyć bardzo dużej frakcji .Użyj notacji naukowej
Notacja naukowa może oszczędzać bajty w przypadku długich liczb. Na przykład:
źródło
3564e-8
w takim przypadku?.00003564
, która również jest o jeden bajt krótsza.Zamiast tego poszukaj innej liczby
Może to zabrzmieć jak brak odpowiedzi, ale nie zawsze jest oczywiste, że większą liczbę można obliczyć za pomocą krótszego kodu. Przykład, który pamiętam, to wypisywanie googolowych kopii ciągu znaków , gdzie oczywiste odpowiedzi wymagają obliczenia 10 100 . Jak się okazuje, obliczenie dowolnej wielokrotności 10 100 prowadzi do równie poprawnej, ale w niektórych językach, krótszej odpowiedzi. Odpowiedź Dennisa używa tam 100 100 , moje własne 250 255 .
źródło
es
jeśli potrzebujesz tylko dużej liczby, ale nie przejmujesz się jej wartością (lub tym, że zawsze jest taka sama).Kompresja podstawowa
Podstawowy kod dekompresyjny może być dość złożony, ale jeśli masz naprawdę ogromną liczbę, czasami może pomóc skompresować go w bazie większej niż 10.
Pomaga również, że w niektórych językach podstawowy kod kompresji jest bardzo prosty. Na przykład PHP ma
base64_decode(_)
, Python maint(_,36)
, JavaScript maparseInt(_,36)
, a wiele języków golfa ma wbudowane podstawowe dekompresje. Na przykład w CJam:Zawiera to niedrukowalne. Wypróbuj online!
To daje:
źródło
Użyj ułamków wykładniczych dla dużych powtarzalnych liczb
Załóżmy, że chcesz wygenerować liczbę 100 100. Można użyć
int("1"*100)
,+"1".repeat(100)
itp, ale można również skorzystać z faktu, że jest bardzo bliskoDziała to najlepiej w przypadku bardzo powtarzalnych liczb, takich jak liczby jednocyfrowe. Kilka powtarzających się cyfr również działa całkiem dobrze:
Czasami można znaleźć jakiś inny dziwny wzór, który również może być dość zwięźle przedstawiony w tej metodzie. Jeśli potrzebujesz
int("123456790"*11)
, na przykład:Uważaj jednak: liczby takie
int("1234567890"*10)
nie mają tak łatwej reprezentacji.źródło
Użyj Bitowego Lewego Przesunięcia dla potęgowania 2
Chociaż istnieje wiele języków, które obsługują potęgowanie potęgowania, niektóre nie. A te, które tego nie wymagają, zazwyczaj wymagają wywoływania funkcji (lub metod klasy / obiektu), co może kosztować kilka bajtów.
Ale możesz zaoszczędzić kilka bajtów, gdy musisz podnieść 2 do potęgi n , używając operatora Bitowego Lewego Przesunięcia
<<
jako1<<n
. Zauważ, że pozwoli to zaoszczędzić bajty tylko wtedy, gdy n jest większe lub równe 17. Jednak to zawsze zaoszczędzi ci bajtów, jeśli n jest dynamiczne. Kilka przykładów:źródło
8<<9 // 4096
więc możemy uzyskać maksymalnie99<<61
6 bajtów, co oznacza6,917,529,027,641,081,856
oszczędność 13 bajtów!Twierdzenie o chińskiej reszcie
Jeśli często pojawiają się arbitralne duże liczby całkowite lub reprezentacja dużej liczby całkowitej w docelowym języku programowania kosztuje zbyt wiele bajtów, możesz rozważyć użycie twierdzenia o chińskim reszcie.
Wybierz kilka par względnie pierwszych liczb całkowitych m i > = 2, a możesz wyrazić dużą liczbę od 0 do lcm (m 1 , m 2 , ..., m i ) -1
Na przykład wybieram 2, 3, 5, 11, 79, 83, 89, 97, a następnie mogę jednoznacznie wyrazić liczbę mniejszą niż 18680171730. 10000000000 (1e10) można wyrazić jako 0,1,0,1,38,59,50,49 (1e10 mod 2, 3 ..., 97), które nie muszą być wyrażane jako specjalna klasa / struktura Big Integer, która mogłaby zaoszczędzić niektóre bajty w jakimś języku programowania.
Dodawanie i odejmowanie można wykonać bezpośrednio przy użyciu tej reprezentacji. Przykład:
źródło
Użyj dopełnienia sznurka (tam, gdzie to możliwe)
Jeśli duża liczba zawiera powtarzającą się cyfrę na początku lub na końcu, możesz być w stanie zaoszczędzić bajty, używając jednej z metod wypełniania w swoim języku do skonstruowania ciągu szukanej liczby, który możesz następnie przekonwertować na liczba całkowita.
Przykład
Aby wygenerować liczbę
1111111111111111111111112
(25 bajtów) w JavaScript (ES8):źródło
Użyj wykładników
Jeśli twój język ma operator wykładnika, możesz go użyć do wygenerowania, jeśli nie pożądanej liczby, przynajmniej liczby, którą możesz wykonać prostym obliczeniem lub 2, aby otrzymać swój numer. Nawet bez operatora nadal możesz zapisywać bajty za pomocą wbudowanej funkcji lub metody.
Przykład
Maksymalna bezpieczna całkowitą w JavaScript to
9007199254740991
, co jest 16 cyfr. W ES7 można to obliczyć za pomocą następujących 7 bajtów:Odpowiednik w ES6 i wcześniejszych wersjach, mimo że w tym przypadku ma taką samą długość jak sama liczba całkowita, pokazuje, że użycie bardziej szczegółowej metody niekoniecznie kosztuje więcej bajtów.
Powyższe może jednak działać krócej, jeśli na przykład już
Math
aliasujesz do jednego znaku w innym miejscu w kodzie.źródło
Zamiast frakcji używaj ułamków
Przykład:
1./3
zamiast0.333333333
źródło