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 .split
stattdessen 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.nio
API verwendet wird, sowie einen kanonischen Namen, der in den APIs java.io
und 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-8
vs utf8
, Windows-1252
vs Cp1252
usw.), aber nicht immer ( UTF-16BE
vs 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 floor
sie nicht verwenden , Math.floor
sondern 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 ceil
werden:
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
, ONE
und TEN
. Wenn Sie also nur diese drei verwenden, benötigen Sie kein import
, können es aber java.Math.BigInteger
direkt 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, =null
damit t
initialisiert 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,12
aus 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 char
mit int
und 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#trim
wird 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 ( .contains
funktioniert 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 a
oder b
Null 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 a
und b
Null 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 n
im 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 Exception
aber catch
etwas damit tun müssen, bevor Sie zurückkehren, können Sie finally
stattdessen Folgendes verwenden:
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Als Beispiel für die Verwendung von a try-catch
kann 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 ArrayIndexOutOfBoundsException
Verwendung catch-finally
ist 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 C
scheint 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+=...-n
anstelle von(long)...
Wenn Sie zum Beispiel bei der Verwendung eine lange Ein- und Ausgabe in einem Lambda haben, Math.pow
können Sie ein Byte speichern, indem Sie n+=...-n
anstelle 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-1
zu +~n
in von mir diese Antwort .
package
kann übersprungen werden.