Alcuni piccoli consigli sul code-golf
Questi suggerimenti erano un po 'troppo piccoli per una risposta separata, quindi userò questa risposta per suggerimenti di codegolfing molto piccoli che ho trovato o trovato, e non sono ancora menzionati negli altri suggerimenti:
Rimozione dell'ultimo carattere di una stringa:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
In alcuni casi sai in anticipo quale è l'ultimo carattere e sai anche che questo personaggio compare una sola volta nella stringa. In tal caso puoi .splitinvece utilizzare :
// As example: "100%" to "100"
s.split("%")[0] // 15 bytes
Scorciatoie di codifica:
// 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
Tutte le codifiche hanno un nome canonico utilizzato java.nionell'API, nonché un nome canonico utilizzato nelle API java.ioe java.lang. Ecco un elenco completo di tutte le codifiche supportate in Java. Quindi usa sempre il più corto dei due; il secondo è generalmente più breve (come UTF-8vs utf8, Windows-1252vs Cp1252, ecc.), ma non sempre ( UTF-16BEvs UnicodeBigUnmarked).
Booleano casuale:
// 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
Primes:
Esistono molti modi diversi per verificare la presenza di numeri primi o ottenere tutti i numeri primi, ma la risposta di @ SaraJ qui è la più breve. Ecco un copia-incolla come riferimento:
// 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*/;}}
NOTA: di solito è possibile unirlo con altri loop esistenti a seconda di come si desidera utilizzarlo, quindi non sarà necessario un metodo separato. Ciò ha consentito di risparmiare molti byte in questa risposta, ad esempio.
Troncamento intero anziché Math.floor / Math.ceil:
Se stai usando doppi / float positivi e li vuoi floor, non usare Math.floorma usa (int)invece un -cast (poiché Java si tronca su numeri interi):
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
Lo stesso trucco può essere applicato ai doppi / float negativi che vuoi ceilinvece:
double d = -54.99;
int n=(int)Math.ceil(d); // 24 bytes
int m=(int)d; // 13 bytes
// Outputs -54 for both
Usa &1invece di%2 per sbarazzarsi della parentesi:
Poiché la Precedenza operatore di &è inferiore agli operatori aritmetici predefiniti come */+-e %, in alcuni casi è possibile eliminare la parentesi.
// So instead of this:
(i+j)%2 // 7 bytes
// Use this:
i+j&1 // 5 bytes
Nota che questo non aiuta davvero nei controlli booleani, perché poi avresti ancora bisogno di parentesi, sono solo spostati un po ':
(i+j)%2<1 // 9 bytes
(i+j&1)<1 // 9 bytes
BigIntegers e creazione di variabili per chiamate a metodi statici:
Quando si utilizza BigIntegers, crearlo solo una volta che è possibile riutilizzare. Come forse sapete, BigInteger contiene campi statici per ZERO, ONEe TEN. Quindi quando usi solo quei tre, non hai bisogno di un importma puoi usarlo java.Math.BigIntegerdirettamente.
// 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
NOTA: è necessario utilizzare =nullcosì tè inizializzato per poter usaret. .
A volte puoi aggiungere più BigInteger per crearne un altro per salvare byte. Quindi supponiamo che tu voglia avere i BigIntegers 1,10,12per qualche motivo:
// 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
Come sottolineato correttamente nei commenti, il trucco con le BigInteger t=null;sue chiamate a metodi statici può essere utilizzato anche con altre classi.
Ad esempio, questa risposta del 2011 può essere giocata a golf:
// 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() invece di toCharArray()
Quando vuoi passare in rassegna i caratteri di una stringa, di solito esegui questa operazione:
for(char c:s.toCharArray()) // 27 bytes
// or this:
for(String c:s.split("")) // 25 bytes
Il ciclo sopra i caratteri può essere utile quando li si stampa o si aggiunge a una stringa o qualcosa di simile.
Tuttavia, se si utilizzano i caratteri solo per alcuni calcoli del numero unicode, è possibile sostituire il charcon int, E è possibile sostituire toCharArray()con getBytes():
for(int c:s.getBytes()) // 23 bytes
O ancora più breve in Java 8+:
s.chars().forEach(c->...) // 22 bytes
In Java 10+ è ora possibile eseguire il looping del carattere da stampare in 22 byte:
for(var c:s.split("")) // 22 bytes
Articolo casuale da un 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
Controlla se una stringa contiene spazi iniziali / finali
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
Perché questo funziona, quando !=su Stringhe è necessario verificare il riferimento anziché il valore in Java? Perché String#trimrestituirà " Una copia di questa stringa con lo spazio bianco iniziale e finale rimosso, o questa stringa se non ha spazio bianco iniziale o finale . " L'ho usato, dopo che qualcuno me l'ha suggerito, in questa mia risposta .
Palindrome:
Per verificare se una stringa è un palindromo (tenendo presente sia la lunghezza pari che quella dispari delle stringhe), questa è la più breve ( .containsfunziona qui perché sappiamo che sia la stringa stessa che la sua forma invertita sono di uguale lunghezza):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)invece di .equals(...+"")ringraziare il commento di @assylias qui .
O è 0 o entrambi sono 0?
Penso che molti lo sappiano già: se vuoi controllare se uno ao bè zero, moltiplica invece per salvare byte:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
E se vuoi controllare se entrambi ae bsono zero, puoi usare un bit-OR o aggiungerli insieme se sono sempre positivi:
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)
Pari = 1, dispari = -1; o vice versa
// 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
Il motivo per cui aggiungo questo è stato dopo aver visto k+(k%2<1?1:-1)in questa risposta :
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
nTempi di loop nel programma completo
Se abbiamo una sfida in cui un programma completo è obbligatorio e dobbiamo ripetere un determinato numero di volte, possiamo fare quanto segue:
// 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
Lo stesso vale quando dobbiamo prendere questo intervallo come input:
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
Ringraziamo @JackAmmo in questo commento .
try-finally invece di try-catch (Eccezione e) quando ritorna e quando usarlo
Se non puoi usare un throws Exceptionma catchdevi e fare qualcosa con esso prima di tornare, puoi finallyinvece usare :
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Per quanto riguarda un esempio di quando usare un try-catch, posso fare riferimento a questa mia risposta (il merito del golf indiretto va a @KamilDrakari ). In questa sfida dobbiamo passare in diagonale su una matrice NxM, quindi dobbiamo determinare se la quantità di colonne o la quantità di righe è la più bassa come la massima nel ciclo for (che è piuttosto costoso in termini di byte:) i<Math.min(a.length,a[0].length). Quindi, semplicemente catturare l' ArrayIndexOutOfBoundsExceptionutilizzo catch-finallyè più breve di questo controllo e quindi salva byte:
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
NOTA: Questo ha funzionato solo a causa di return r;in the finally. Mi è stato suggerito di modificare la prima cella, come ha fatto @KamilDrakari nella sua risposta C # per salvare byte. Tuttavia, in Java questo significa che dovrò cambiarlo in m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 byte), aumentando effettivamente il conteggio dei byte invece di diminuire se avessi potuto usare finally.
Math.pow (2, n)
Quando vuoi una potenza di 2, un approccio bit-saggio è molto più breve:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
Combinazione di controlli logici e bit bit anziché utilizzare la parentesi
Penso che ormai sia ben noto &e che |possa essere usato al posto di &&e ||nei controlli logici Java (booleani). In alcuni casi dovresti comunque utilizzare &&invece di &prevenire errori, ad esempio index >= 0 && array[index].doSomething. Se &&verrà modificato in &qui, valuterà comunque la parte in cui utilizza l'indice nell'array, causando un ArrayIndexOutOfBoundsException, quindi l'utilizzo di &&in questo caso anziché& .
Finora le basi di &&/ ||vs &/| in Java.
Quando si desidera verificare (A or B) and C, il più breve potrebbe sembrare utilizzare gli operatori bit-saggio come questo:
(A|B)&C // 7 bytes
Tuttavia, poiché gli operatori bit-wise hanno la precedenza dell'operatore sui controlli logici, è possibile combinare entrambi per salvare un byte qui:
A|B&&C // 6 bytes
Usa n+=...-ninvece di(long)...
Se hai un long sia in sia in output in lambda, ad esempio quando lo usi Math.pow, puoi salvare un byte usando n+=...-ninvece di (long)....
Per esempio:
n->(long)Math.pow(10,n) // 23 bytes
n->n+=Math.pow(10,n)-n // 22 bytes
Questo salvato un byte in questa risposta di miniera , e anche due byte combinando -n-1a +~nin questa risposta di mine .
packagepuò essere saltato.