Kilka małych wskazówek do gry w golfa
Te wskazówki były trochę za małe, aby rozdzielić odpowiedzi, więc wykorzystam tę odpowiedź do bardzo małych wskazówek dotyczących kodowania, które znalazłem lub wymyśliłem i nie zostały jeszcze wspomniane w innych poradach:
Usuwanie ostatniego znaku ciągu:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
W niektórych przypadkach wiesz wcześniej, jaki jest ostatni znak, a także wiesz, że ta postać występuje tylko raz w ciągu. W takim przypadku możesz .splitzamiast tego użyć :
// As example: "100%" to "100"
s.split("%")[0] // 15 bytes
Skróty kodowania:
// When you want to get the UTF-8 bytes I used to do this:
s.getBytes("UTF-8"); // 20 bytes
// But you can also use "UTF8" for the same result:
s.getBytes("UTF8"); // 19 bytes
Wszystkie kodowania mają kanoniczną nazwę używaną w java.niointerfejsie API, a także kanoniczną nazwę używaną w interfejsach API java.ioi java.lang. Oto pełna lista wszystkich obsługiwanych kodowań w Javie. Dlatego zawsze używaj najkrótszego z dwóch; drugi jest zwykle krótszy (jak UTF-8vs utf8, Windows-1252vs Cp1252itp.), ale nie zawsze ( UTF-16BEvs UnicodeBigUnmarked).
Losowa wartość logiczna:
// You could do something like this:
new java.util.Random().nextBoolean() // 36 bytes
// But as mentioned before in @Geobits' answer, Math.random() doesn't require an import:
Math.random()<.5 // 16 bytes
Liczby pierwsze:
Istnieje wiele różnych sposobów sprawdzania liczb pierwszych lub uzyskania wszystkich liczb pierwszych, ale odpowiedź @ SaraJ tutaj jest najkrótsza. Oto kopia-wklej jako odniesienie:
// Check if n is a prime:
n->{int i=1;for(;n%++i%n>0;);return n==i;}
// Which can easily be modified to loop through primes:
v->{for(int n=2,i;;){for(i=1;n%++i%n>0;);if(n++==i)/*do something with prime `i` here*/;}}
UWAGA: Zwykle możesz połączyć go z innymi istniejącymi pętlami, w zależności od tego, jak chcesz go używać, więc nie będziesz potrzebować oddzielnej metody. Na przykład zaoszczędziło to wiele bajtów w tej odpowiedzi .
Obcinanie liczb całkowitych zamiast Math.floor / Math.ceil:
Jeśli używasz dodatnich podwójnych / zmiennoprzecinkowych i chcesz floorich, nie używaj, Math.floorale (int)zamiast tego użyj -cast (ponieważ Java obcina się na liczbach całkowitych):
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
Tę samą sztuczkę można zastosować do ujemnych podwójnych / zmiennoprzecinkowych, które chcesz ceilzamiast tego:
double d = -54.99;
int n=(int)Math.ceil(d); // 24 bytes
int m=(int)d; // 13 bytes
// Outputs -54 for both
Użyj &1zamiast %2pozbyć się nawiasu:
Ponieważ Operator Pierwszeństwo od &jest niższa niż standardowych operatorów arytmetycznych, jak */+-i %można pozbyć się nawiasów w niektórych przypadkach.
// So instead of this:
(i+j)%2 // 7 bytes
// Use this:
i+j&1 // 5 bytes
Zauważ, że to naprawdę nie pomaga w kontrolach boolean, ponieważ wtedy nadal potrzebujesz nawiasów, są one tylko trochę przesunięte:
(i+j)%2<1 // 9 bytes
(i+j&1)<1 // 9 bytes
BigIntegers i tworzenie zmiennych dla statycznych wywołań metod:
Korzystając z BigIntegers, utwórz go tylko raz, abyś mógł go ponownie użyć. Jak wiadomo, BigInteger zawiera pola statyczne ZERO, ONEa TEN. Więc kiedy używasz tylko tych trzech, nie potrzebujesz, importale możesz użyć java.Math.BigIntegerbezpośrednio.
// So instead of this:
import java.math.BigInteger.*;
BigInteger a=BigInteger.ONE,b=BigInteger.ZERO; // 76 bytes
// or this:
java.math.BigInteger a=java.math.BigInteger.ONE,b=a.ZERO; // 57 bytes
// Use this:
java.math.BigInteger t=null,a=t.ONE,b=t.ZERO; // 45 bytes
UWAGA: Musisz użyć, =nullwięc tjest zainicjowany, aby użyć t..
Czasami możesz dodać wiele BigIntegerów, aby utworzyć kolejny, aby zapisać bajty. Powiedzmy, że chcesz mieć BigIntegers 1,10,12z jakiegoś powodu:
// So instead of this:
BigInteger t=null,a=t.ONE,b=t.TEN,c=new BigInteger(12); // 55 bytes
// Use this:
BigInteger t=null,a=t.ONE,b=t.TEN,c=b.add(a).add(a); // 52 bytes
Jak słusznie zaznaczono w komentarzach, sztuczka z BigInteger t=null;wywołaniami metody statycznej może być również używana z innymi klasami.
Na przykład tę odpowiedź z 2011 r. Można pograć w golfa:
// 173 bytes:
import java.util.*;class g{public static void main(String[]p){String[]a=p[0].split(""),b=p[1].split("");Arrays.sort(a);Arrays.sort(b);System.out.print(Arrays.equals(a,b));}}
// 163 bytes
class g{public static void main(String[]p){java.util.Arrays x=null;String[]a=p[0].split(""),b=p[1].split("");x.sort(a);x.sort(b);System.out.print(x.equals(a,b));}}
getBytes() zamiast toCharArray()
Kiedy chcesz zapętlić znaki ciągu, zwykle robisz to:
for(char c:s.toCharArray()) // 27 bytes
// or this:
for(String c:s.split("")) // 25 bytes
Pętlowanie znaków może być przydatne podczas ich drukowania, dołączania do ciągu znaków lub czegoś podobnego.
Jednak, jeśli używać tylko znaków dla niektórych obliczeń numerycznych Unicode można zastąpić charz intI można zastąpić toCharArray()z getBytes():
for(int c:s.getBytes()) // 23 bytes
Lub jeszcze krócej w Javie 8+:
s.chars().forEach(c->...) // 22 bytes
W Javie 10+ zapętlanie znaku do wydruku można teraz wykonywać również w 22 bajtach:
for(var c:s.split("")) // 22 bytes
Losowy przedmiot z List:
List l=...;
// When we have an `import java.util.*;` in our code, shuffling is shortest:
return l.get(new Random().nextInt(l.size())); // 45 bytes
return l.get((int)(Math.random()*l.size())); // 44 bytes
Collections.shuffle(l);return l.get(0); // 39 bytes
// When we don't have an `import java.util.*` in our code, `Math.random` is shortest:
return l.get(new java.util.Random().nextInt(l.size())); // 55 bytes
return l.get((int)(Math.random()*l.size())); // 44 bytes
java.util.Collections.shuffle(l);return l.get(0); // 49 bytes
Sprawdź, czy ciąg znaków zawiera spacje wiodące / końcowe
String s=...;
// I used to use a regex like this:
s.matches(" .*|.* ") // 20 bytes
// But this is shorter:
!s.trim().equals(s) // 19 bytes
// And this is even shorter due to a nice feature of String#trim:
s!=s.trim() // 11 bytes
Dlaczego to działa, gdy !=w Strings jest sprawdzanie referencji zamiast wartości w Javie? Ponieważ String#trimzwróci „ Kopię tego ciągu z usuniętą początkową i końcową białą spacją lub tego ciągu, jeśli nie ma wiodącej ani końcowej białej spacji . ” Użyłem tego, po tym, jak ktoś mi to zasugerował, w tej mojej odpowiedzi .
Palindrom:
Aby sprawdzić, czy Ciąg znaków jest palindromem (pamiętając o parzystych i nieparzystych długościach Ciągów), jest to najkrótszy ( .containsdziała tutaj, ponieważ wiemy, że zarówno Ciąg, jak i jego odwrócona postać są równej długości):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)zamiast .equals(...+"")dzięki komentarzowi @assylias tutaj .
Albo jest 0, albo oba są 0?
Myślę, że większość już wie to jedno: jeśli chcesz sprawdzić, czy albo aczy bjest zero, zamiast mnożyć zapisać bajtów:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
A jeśli chcesz sprawdzić, czy oba ai bsą zerowe, można użyć bitowym OR, lub dodać je razem, jeśli są zawsze pozytywne:
a==0&b==0 // 9 bytes
(a|b)==0 // 8 bytes (if either `a`, `b` or both can be negative)
a+b<1 // 5 bytes (this only works if neither `a` nor `b` can be negative)
Parzysty = 1, nieparzysty = -1; lub odwrotnie
// even = 1; odd = -1:
n%2<1?1:-1 // 10 bytes
1-n%2*2 // 7 bytes
// even = -1; odd = 1:
n%2<1?-1:1 // 10 bytes
n%2*2-1 // 7 bytes
Powodem, dla którego to dodałem, było po zobaczeniu k+(k%2<1?1:-1)w tej odpowiedzi :
k+(k%2<1?1:-1) // 14 bytes
// This would already have been shorter:
k%2<1?k+1:k-1 // 13 bytes
// But it can also be:
k%2*-2-~k // 9 bytes
nCzasy pętli w pełnym programie
Jeśli mamy wyzwanie, w którym pełny program jest obowiązkowy i musimy zapętlić określoną liczbę razy, możemy wykonać następujące czynności:
// instead of:
interface M{static void main(String[]a){for(int n=50;n-->0;)/*do something*/}} // 78 bytes
// we could do:
interface M{static void main(String[]a){for(M m:new M[50])/*do something*/}} // 76 bytes
To samo dotyczy sytuacji, gdy musimy przyjąć ten zakres jako dane wejściowe:
interface M{static void main(String[]a){for(int n=new Byte(a[0]);n-->0;)/*do something*/}} // 90 bytes
interface M{static void main(String[]a){for(M m:new M[new Byte(a[0])])/*do something*/}} // 88 bytes
Podziękowania dla @JackAmmo w tym komentarzu .
try-wreszcie zamiast try-catch (wyjątek e) podczas powrotu i kiedy go użyć
Jeśli nie możesz użyć, throws Exceptionale musisz catchcoś z tym zrobić przed powrotem, możesz finallyzamiast tego użyć :
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Jako przykład, kiedy użyć a try-catch, mogę odnieść się do mojej odpowiedzi (uznanie dla pośredniego golfa należy do @KamilDrakari ). W tym wyzwaniu musimy zapętlić po przekątnej macierz NxM, więc musimy ustalić, czy liczba kolumn czy liczba wierszy jest najniższa jako nasze maksimum w pętli for (co jest dość drogie pod względem bajtów:) i<Math.min(a.length,a[0].length). Więc po prostu złapanie ArrayIndexOutOfBoundsExceptionużycia catch-finallyjest krótsze niż ta kontrola, a tym samym oszczędza bajty:
int[] a = ...;
int r=0,i=0;for(;i<Math.min(a.length,a[0].length);)r=...i++...;return r; // 66 bytes
int r=0,i=0;try{for(;;)r=...i++...;}finally{return r;} // 48 bytes
UWAGA: Działa to tylko z powodu return r;w końcu. Sugerowano mi zmodyfikowanie pierwszej komórki, tak jak @KamilDrakari zrobił w swojej odpowiedzi w języku C #, aby zapisać bajty. Jednak w Javie oznacza to, że będę musiał zmienić go na m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 bajty), faktycznie zwiększając liczbę bajtów zamiast zmniejszać, gdybym mógł użyć finally.
Math.pow (2, n)
Jeśli potrzebujesz potęgi 2, nieco mądrzejsze podejście jest znacznie krótsze:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
Łączenie bitowych i logicznych kontroli zamiast używania nawiasów
Myślę, że do tej pory jest to dobrze znane &i |może być używane zamiast &&i ||w sprawdzeniach logicznych Java (boolean). W niektórych przypadkach nadal chcesz używać &&zamiast &zapobiegać błędom, na przykład index >= 0 && array[index].doSomething. Jeśli &&zmieniono by na &tutaj, nadal będzie oceniać część, w której używa indeksu w tablicy, powodując ArrayIndexOutOfBoundsException, stąd użycie &&w tym przypadku zamiast &.
Jak dotąd podstawy &&/ ||vs &/ |w Javie.
Gdy chcesz to sprawdzić (A or B) and C, najkrótsze mogą się wydawać operatory bitowe:
(A|B)&C // 7 bytes
Ponieważ jednak operatorzy bitowi mają pierwszeństwo operatorów przed sprawdzeniami logicznymi, możesz połączyć oba te elementy, aby zapisać bajt tutaj:
A|B&&C // 6 bytes
Użyj n+=...-nzamiast(long)...
Kiedy masz zarówno wejście, jak i wyjście w lambda, na przykład podczas używania Math.pow, możesz zapisać bajt, używając n+=...-nzamiast (long)....
Na przykład:
n->(long)Math.pow(10,n) // 23 bytes
n->n+=Math.pow(10,n)-n // 22 bytes
Ten zapisany bajt w tej odpowiedzi kopalni , a nawet dwa bajty, łącząc -n-1się +~nw tej odpowiedzi kopalni .
packagemożna pominąć.