Einige kleine Code-Golftipps
Diese Tipps waren etwas zu klein für eine separate Antwort. Daher verwende ich diese Antwort für sehr kleine Codegolf-Tipps, die ich gefunden oder mir ausgedacht habe und die in den anderen Tipps noch nicht erwähnt sind:
Entfernen des letzten Zeichens eines Strings:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
In einigen Fällen wissen Sie vorher, was das letzte Zeichen ist, und Sie wissen auch, dass dieses Zeichen nur einmal in der Zeichenfolge vorkommt. In diesem Fall können Sie .splitstattdessen Folgendes verwenden:
// As example: "100%" to "100"
s.split("%")[0] // 15 bytes
Codierungsverknüpfungen:
// 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
Alle Kodierungen haben einen kanonischen Namen, der in der java.nioAPI verwendet wird, sowie einen kanonischen Namen, der in den APIs java.iound verwendet wird java.lang. Hier ist eine vollständige Liste aller unterstützten Codierungen in Java. Verwenden Sie also immer die kürzeste von beiden. Die Sekunde ist normalerweise kürzer (wie UTF-8vs utf8, Windows-1252vs Cp1252usw.), aber nicht immer ( UTF-16BEvs UnicodeBigUnmarked).
Zufälliger Boolescher Wert:
// 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:
Es gibt viele verschiedene Möglichkeiten, nach Primzahlen zu suchen oder alle Primzahlen abzurufen , aber die Antwort von @ SaraJ ist hier die kürzeste. Hier ist ein Copy-Paste als Referenz:
// 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*/;}}
HINWEIS: Normalerweise können Sie es mit anderen vorhandenen Loops zusammenführen, je nachdem, wie Sie es verwenden möchten, sodass Sie keine separate Methode benötigen. Dies hat zum Beispiel eine Menge Bytes in dieser Antwort gespart .
Integer-Kürzung anstelle von Math.floor / Math.ceil:
Wenn Sie mit positiven Doppel / Schwimmer und Sie wollen floorsie nicht verwenden , Math.floorsondern eine Verwendung (int)-Cast statt (da Java auf ganze Zahlen kürzt):
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
Der gleiche Trick kann stattdessen auf negative Doubles / Floats angewendet ceilwerden:
double d = -54.99;
int n=(int)Math.ceil(d); // 24 bytes
int m=(int)d; // 13 bytes
// Outputs -54 for both
Verwenden &1 anstelle von %2, um Klammern zu entfernen:
Da die Operatorpräzision von &niedriger ist als die standardmäßigen arithmetischen Operatoren wie */+-und %, können Sie in einigen Fällen Klammern entfernen.
// So instead of this:
(i+j)%2 // 7 bytes
// Use this:
i+j&1 // 5 bytes
Beachten Sie, dass dies bei Booleschen Prüfungen nicht wirklich hilfreich ist, da Sie dann immer noch Klammern benötigen. Sie sind nur ein wenig verschoben:
(i+j)%2<1 // 9 bytes
(i+j&1)<1 // 9 bytes
BigInteger und Erstellen von Variablen für statische Methodenaufrufe:
Wenn Sie BigIntegers verwenden, erstellen Sie es nur einmal und können es dann wiederverwenden. Wie Sie vielleicht wissen, enthält BigInteger statische Felder für ZERO, ONEund TEN. Wenn Sie also nur diese drei verwenden, benötigen Sie kein import, können es aber java.Math.BigIntegerdirekt verwenden.
// 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
HINWEIS: Sie müssen verwenden, =nulldamit tinitialisiert wird, um zu verwenden t..
Manchmal können Sie mehrere BigInteger hinzufügen, um weitere zu erstellen und Bytes zu sparen. Nehmen wir also an, Sie möchten 1,10,12aus irgendeinem Grund die BigIntegers haben :
// 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
Wie in den Kommentaren richtig ausgeführt, kann der Trick mit BigInteger t=null;seinen statischen Methodenaufrufen auch für andere Klassen verwendet werden.
Zum Beispiel kann diese Antwort von 2011 gespielt werden:
// 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() Anstatt von toCharArray()
Wenn Sie die Zeichen eines Strings durchlaufen möchten, gehen Sie normalerweise folgendermaßen vor:
for(char c:s.toCharArray()) // 27 bytes
// or this:
for(String c:s.split("")) // 25 bytes
Das Durchlaufen der Zeichen kann nützlich sein, wenn Sie sie drucken oder an eine Zeichenfolge oder ähnliches anhängen.
Wenn Sie jedoch nur die Zeichen für einige Unicode-Nummer Berechnungen verwenden, können Sie die ersetzen charmit intund kann Sie ersetzen toCharArray()mit getBytes():
for(int c:s.getBytes()) // 23 bytes
Oder noch kürzer in Java 8+:
s.chars().forEach(c->...) // 22 bytes
In Java 10+ kann das zu druckende Zeichen jetzt auch in 22 Bytes durchlaufen werden:
for(var c:s.split("")) // 22 bytes
Zufälliger Artikel von einem 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
Überprüfen Sie, ob ein String führende / nachfolgende Leerzeichen enthält
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
Warum funktioniert das, wenn !=bei Strings auf Referenz anstatt auf Wert in Java geprüft werden soll? Denn es String#trimwird zurückgegeben: " Eine Kopie dieser Zeichenfolge mit entferntem führenden und nachfolgenden Leerzeichen oder diese Zeichenfolge, wenn sie kein führendes oder nachfolgendes Leerzeichen enthält . " Ich habe dies in meiner Antwort verwendet, nachdem mir jemand dies vorgeschlagen hat .
Palindrom:
Um zu überprüfen, ob es sich bei einer Zeichenfolge um ein Palindrom handelt (wobei sowohl gerade als auch ungerade Längen von Zeichenfolgen berücksichtigt werden), ist dies die kürzeste ( .containsfunktioniert hier, weil wir wissen, dass sowohl die Zeichenfolge selbst als auch ihre umgekehrte Form gleich lang sind):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)statt .equals(...+"")danke an @assylias 'Kommentar hier .
Entweder ist 0 oder beide sind 0?
Ich denke, die meisten kennen dieses bereits: Wenn Sie überprüfen möchten, ob entweder aoder bNull ist, multiplizieren Sie stattdessen, um Bytes zu sparen:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
Und wenn Sie überprüfen möchten, ob beide aund bNull sind, können Sie ein bitweises ODER verwenden oder sie addieren, wenn sie immer positiv sind:
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)
Gerade = 1, ungerade = -1; oder umgekehrt
// 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
Der Grund, warum ich dies hinzufüge, war, nachdem ich k+(k%2<1?1:-1)in dieser Antwort gesehen habe :
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
Wiederholungszeiten nim vollen Programm
Wenn wir eine Herausforderung haben, bei der ein vollständiges Programm obligatorisch ist und wir eine bestimmte Anzahl von Wiederholungen durchführen müssen, können wir Folgendes tun:
// 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
Gleiches gilt, wenn wir diesen Bereich als Eingabe verwenden müssen:
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
Dank an @JackAmmo in diesem Kommentar .
try-finally anstelle von try-catch (Ausnahme e) bei der Rückgabe und wann es verwendet werden soll
Wenn Sie a nicht verwenden können, throws Exceptionaber catchetwas damit tun müssen, bevor Sie zurückkehren, können Sie finallystattdessen Folgendes verwenden:
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Als Beispiel für die Verwendung von a try-catchkann ich auf meine Antwort verweisen (Gutschrift für das indirekte Golf geht an @KamilDrakari ). In dieser Herausforderung müssen wir eine NxM-Matrix diagonal durchlaufen, um zu bestimmen, ob die Anzahl der Spalten oder der Zeilen als unser Maximum in der for-Schleife am niedrigsten ist (was in Bezug auf Bytes recht teuer ist:) i<Math.min(a.length,a[0].length). Das einfache Abfangen der ArrayIndexOutOfBoundsExceptionVerwendung catch-finallyist also kürzer als diese Prüfung und spart somit Bytes:
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
ANMERKUNG: Dies funktionierte nur wegen der return r;im Endeffekt. Es wurde mir vorgeschlagen, die erste Zelle zu ändern, wie es @KamilDrakari in seiner C # -Antwort getan hat , um Bytes zu sparen. In Java bedeutet dies jedoch, dass ich es in m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 Bytes) ändern muss , um die Anzahl der Bytes zu erhöhen, anstatt sie zu verringern, wenn ich sie hätte verwenden könnenfinally .
Math.pow (2, n)
Wenn Sie eine Potenz von 2 wollen, ist ein bitweiser Ansatz viel kürzer:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
Kombinieren Sie bitweise und logische Prüfungen, anstatt Klammern zu verwenden
Ich denke , es ist bekannt durch die jetzt &und |kann anstelle verwendet werden &&und ||in Java (boolean) logischen Kontrollen. In einigen Fällen möchten Sie jedoch trotzdem Fehler vermeiden, &&anstatt diese zu verwenden . Wenn das würde geändert werden hier, wird es noch die Rolle zu bewerten , wo es um den Index in dem Array verwendet, wodurch eine , daher die Verwendung von in diesem Fall statt .&index >= 0 && array[index].doSomething&&&ArrayIndexOutOfBoundsException&&&
Bisher die Grundlagen von &&/ ||vs &/ |in Java.
Wenn Sie prüfen möchten, (A or B) and Cscheint der kürzeste die folgenden bitweisen Operatoren zu verwenden:
(A|B)&C // 7 bytes
Da jedoch die bitweisen Operatoren Vorrang vor den logischen Prüfungen haben, können Sie beide kombinieren, um hier ein Byte zu speichern:
A|B&&C // 6 bytes
Verwenden Sie n+=...-nanstelle von(long)...
Wenn Sie zum Beispiel bei der Verwendung eine lange Ein- und Ausgabe in einem Lambda haben, Math.powkönnen Sie ein Byte speichern, indem Sie n+=...-nanstelle von verwenden (long)....
Zum Beispiel:
n->(long)Math.pow(10,n) // 23 bytes
n->n+=Math.pow(10,n)-n // 22 bytes
Das sparte ein Byte in dieser Antwort von mir , und sogar zwei Bytes , die durch die Kombination von -n-1zu +~nin von mir diese Antwort .
packagekann übersprungen werden.