Tipps zum Golfen in Java

86

Gibt es nützliche Verknüpfungen, die in Java verwendet werden können?

Wie unten gezeigt, werden importeinem Programm bereits mindestens 17 Zeichen hinzugefügt.

import java.io.*;

Ich verstehe, dass die einfache Lösung darin besteht, eine andere Sprache zu verwenden, aber es scheint eine echte Herausforderung zu sein, Java-Programme zu verkürzen.


Tipps sollten spezifisch für Java sein: Wenn sie auf die meisten C-ähnlichen Sprachen anwendbar sind, gehören sie in die allgemeinere Liste der Tipps .

rauben
quelle
9
packagekann übersprungen werden.
st0le
Kann ich in einer Antwort die Importe nicht einfach weglassen, vorausgesetzt, sie sind da?
Fabricio
1
@Fabricio Nicht, wenn das OP dies nicht spezifiziert.
Nyuszika7h
32
Der beste Tipp zum Golfen mit Java: Verwenden Sie es nicht. ;)
kirbyfan64sos
4
"Ich möchte in Java Golf spielen"
Viel

Antworten:

85
  • Verwenden Sie das neueste Java. Java 8 können Sie Lambda - Ausdrücke verwenden, so ist es , wenn Sie alles selbst brauchen wie funktionale Objekte.

  • Definieren Sie verkürzte Funktionen für Dinge, die Sie häufig verwenden. Beispielsweise müssen Sie hundert Anrufe tätigen exampleClassInstance.doSomething(someParameter), eine neue Funktion definieren void d(ParameterType p){exampleClassInstance.doSomething(p)}und sich damit einige Zeichen sparen.

  • Wenn Sie einen bestimmten langen Klassennamen mehrmals verwenden, z

    MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory

    definieren Sie stattdessen eine neue Klasse:

    class X extends MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory{}

    Wenn Sie nur eine bestimmte Methode dieser Klasse verwenden (diese aber immer noch instanziieren müssen), können Sie gleichzeitig eine verkürzte Version in der neuen Klasse definieren.

  • Verwenden Sie Funktionstyp-Parameter, um Dinge zu verkürzen, wo dies möglich ist:

    <T>void p(T o){System.out.println(o);}
  • Verwenden Sie for(;;)anstelle von while(true).

  • Verwenden Sie keine Zugriffsmodifikatoren, es sei denn, dies ist unbedingt erforderlich.

  • Verwenden Sie finalfür nichts.

  • Setzen Sie niemals einen Block hinter eine forSchleife (aber eine foreach-Schleife for(x:y)ist anders). Zusätzliche Anweisungen sollten wie folgt in die forAnweisung selbst eingefügt werden for(int i=0;i<m;a(i),b(++i))c(i);.

  • Verwenden Sie Inline-Zuweisung, Inkrementierung und Instantiierung. Verwenden Sie gegebenenfalls anonyme Inline-Klassen. Verwenden Sie nach Möglichkeit stattdessen Lambdas. Funktionsaufrufe verschachteln. Es ist garantiert, dass einige Funktionen ihr übergeordnetes Objekt zurückgeben. Diese Funktionen sind sogar dazu gedacht , miteinander verkettet zu werden.

  • Ihre mainMethode throws Exceptionfängt sie nicht.

  • Errorist kürzer als Exception. Wenn Sie aus irgendeinem Grund wirklichthrow Nachrichten auf dem Stack benötigen , verwenden Sie eine Error, auch wenn dies eine ganz normale Situation ist.

  • Wenn eine Bedingung eine sofortige Kündigung erfordert, verwenden Sie int a=1/0;statt throw null;oder System.exit(0);. Zur Laufzeit wirft dies eine ArithmeticException. Wenn Sie bereits eine numerische Variable in Ihrem Code haben, verwenden Sie sie stattdessen. (Wenn Sie bereits haben import static java.lang.System.*;, gehen Sie mit exit(0);.)

  • Anstatt Schnittstellen wie zu implementieren List<E>, erweitern Sie eine untergeordnete Klasse wie AbstractList<E>, die Standardimplementierungen der meisten Methoden bereitstellt und nur die Implementierung von erfordert ein paar Schlüsselstücke.

  • Schreiben Sie Ihren Code zuerst in Langschrift mit Zeilenumbrüchen, Einrückungen und vollständigen Variablennamen. Sobald Sie über Arbeitscode verfügen, können Sie Namen kürzen, Deklarationen verschieben und Verknüpfungsmethoden hinzufügen. Wenn Sie es von Anfang an aufschreiben, erhalten Sie mehr Gelegenheit, das Programm insgesamt zu vereinfachen.

  • Vergleichen Sie alternative Optimierungen mit einem Codeteil, da sich die optimalste Strategie mit sehr kleinen Änderungen am Code dramatisch ändern kann. Zum Beispiel:

    • Wenn Sie nur bis zu zwei Anrufe haben, Arrays.sort(a)ist es am effizientesten, ihn mit seinem vollqualifizierten Namen anzurufen java.util.Arrays.sort(a).
    • Bei drei oder mehr Aufrufen ist es effizienter, stattdessen eine Verknüpfungsmethode hinzuzufügen void s(int[]a){java.util.Arrays.sort(a);}. Dies sollte in diesem Fall immer noch den vollqualifizierten Namen verwenden. (Wenn Sie mehr als eine Überlastung benötigen, machen Sie es wahrscheinlich falsch.)
    • Wenn Ihr Code jedoch irgendwann auch ein Array kopieren muss (in der Regel mit einer kurzen forSchleife beim Golfen, da keine leicht zugängliche Bibliotheksmethode vorhanden ist), können Arrays.copyOfSie die Aufgabe ausführen. Wenn mehr als eine Methode verwendet wird und 3 oder mehr Aufrufe vorhanden sind, import static java.util.Arrays.*;ist dies die effizienteste Methode, um auf diese Methoden zu verweisen. Danach sortsollten Sie nur dann eine Abkürzungsmethode verwenden , wenn Sie mehr als 8 separate Anrufe haben, und nur bei 5 oder mehr Anrufen ist eine Abkürzung gerechtfertigt copyOf.

    Die einzige Möglichkeit, eine solche Analyse für Code durchzuführen, besteht darin, potenzielle Änderungen an Kopien des Codes vorzunehmen und die Ergebnisse dann zu vergleichen.

  • Vermeiden Sie die Verwendung der someTypeValue.toString();Methode, sondern hängen Sie sie einfach an someTypeValue+"".

  • Wenn Sie Windows benötigen, verwenden Sie nicht Swing, sondern AWT (es sei denn, Sie benötigen wirklich etwas von Swing). Vergleichen import javax.swing.*;und import java.awt.*;. Zusätzlich Komponenten in Swing haben eine Jvoran ihren Namen ( JFrame, JLabelusw.), aber Komponenten in AWT nicht ( Frame, Labelusw.)

AJMansfield
quelle
43

Verwenden Sie interfaceanstelle von class.

In Java 8 wurden statische Methoden zu Interfaces hinzugefügt. In Interfaces sind standardmäßig alle Methoden öffentlich. Folglich

class A{public static void main(String[]a){}}

kann jetzt auf gekürzt werden

interface A{static void main(String[]a){}}

das ist offensichtlich kürzer.

Zum Beispiel habe ich diese Funktion in der Hello, World! Herausforderung.

Die Nummer eins
quelle
8
Ich wusste das nicht! +1, schöner Trick
HyperNeutrino
Ja, weniger Boilerplate!
CalculatorFeline
3
Ich muss teilweise anderer Meinung sein (außerdem habe ich dich in der "Hallo Welt!" - Herausforderung mit dieser Technik besiegt).
Olivier Grégoire
37

Mit varargs können Sie einen Parameter in ein Array desselben Typs " umwandeln ":

void f(String...x){
    x=x[0].split("someregex");
    // some code using the array
}

Anstatt von

void f(String s){
    String[]x=s.split("someregex");
    // some code using the array
}
masterX244
quelle
31

Bei einem statischen Import :

import static java.lang.System.out;
// even shorter (thanks to Johannes Kuhn):
import static java.lang.System.*;

Sie können später einige Boilerplate speichern, aber Sie benötigen mehrere Aufrufe, um eine Auszahlung zu erreichen:

public static void main (String[] args) {
    out.println ("foo");    
    out.println ("bar");    
    out.println ("baz");    
}
Benutzer unbekannt
quelle
8
:O. Du kannst das?! Und die ganze Zeit dachte ich, dass das unmöglich ist Java!
Justin
12
Sie können sogar verwenden import static java.lang.System.*.
Johannes Kuhn
1
Ich weiß, dass dies eine alte Antwort ist, aber in Java 10 können Sie jetzt etwas tun, var o=System.out;das nur zweimal verwendet werden muss, bevor es sich auszahlt
Luke Stevens,
@ LukeStevens: Nun, vielleicht finden Sie einige andere Verbesserungen, die mit Java10 möglich sind, und bilden eine separate Antwort für Java10?
Benutzer unbekannt
1
@LukeStevens Würde var o=System.out.printlnfunktionieren?
MilkyWay90
25

Das Argument to mainmuss nicht aufgerufen werden args, und Sie können Leerzeichen entfernen:

public static void main(String[]a){}

wird gut tun.

daniero
quelle
1
Müssen Antworten die Hauptfunktion enthalten, wenn nicht ausdrücklich angegeben wird, dass ein vollständiges Programm geschrieben werden soll? Ich habe Lambda-Ausdrücke als Antworten verwendet.
Makotosan
3
@Makotosan Nein, tun sie nicht; Lambdas sind normalerweise in Ordnung.
Daniero
21

Wenn Sie jemals die booleschen Ausdrücke trueoder verwenden müssen false, ersetzen Sie sie durch 1>0und 1<0.

Zum Beispiel:

boolean found=false;
for(i=0; i<10; i++) if(a[i]==42) found=true;

Dieses lineare Suchbeispiel kann auf reduziert werden

boolean f=1<0;
for(i=0;i<10;)if(a[i++]==42)f=1>0;
ace_HongKongIndependence
quelle
11
Wenn Sie viel brauchen true/false, fügen Sie einfach hinzu boolean t=1>0,f=1<0;. 1>0Verwenden tund speichern Sie dann stattdessen zwei Zeichen pro Verwendung. Die Auszahlungsmethode 1>0kommt bei 10 Einsätzen.
Geobits
24
@Geobits: boolean t=1>0,f=!t;- Ein Zeichen kürzer!
Bobbel
6
Das Beispiel ist nicht wirklich gut. In diesem Fall und bei vielen (!) Anderen können Sie die Verwendung von true/ falsedirect sowieso vermeiden : f|=a[i++]==42;Spart ziemlich viel.
Ingo Bürk
@ IngoBürk Stimmt. Als ich dies schrieb, dachte ich hauptsächlich über Bibliotheksfunktionen nach, die verwendet booleanwurden. Da ich zum Zeitpunkt des Schreibens jedoch keine Beispiele finden konnte (ich programmiere normalerweise nicht in Java), habe ich nur ein einfaches Beispiel geschrieben.
ace_HongKongIndependence
1
@ Geobits nicht allzu vertraut mit Java, aber könnten Sie einfach 1 definieren und t und! T (wieder kenne ich kein Java, nur neugierig)
Albert Renshaw
20

Wenn Sie eine Methode häufig verwenden, weisen Sie deren residente Klasse einer Variablen zu. Weisen Sie beispielsweise System.outeiner Variablen zu:

java.io.PrintStream o=System.out;
//now I can call o.print() or o.println() to the same effect as System.out.println()

Auch für Integer.parseInt():

Integer i=1;
i.parseInt("some string");

Dies wird mit ziemlicher Sicherheit eine ide-Warnung über den Zugriff auf statische Methoden von Variablen auslösen.

Justin
quelle
((Integer)1).parseInt("1")funktioniert auch.
Magic Octopus Urn
5
@carusocomputing new Integer("1")ist noch kürzer. Mit seiner Antwort meinte Justin jedoch, dass Sie bereits vorhandene Variablen für statische Aufrufe wiederverwenden können. Wie ich am Ende dieser Antwort erkläre.
Kevin Cruijssen
19

Anstatt die import static java.lang.System.*Technik zum Speichern von println()Anweisungen zu verwenden, habe ich festgestellt, dass das Definieren der folgenden Methode beim Speichern von Zeichen viel effektiver ist:

static<T>void p(T p){
    System.out.println(p);
}

Dies liegt daran, dass es aufgerufen werden kann, p(myString)anstatt out.println(myString)dass es eine viel schnellere und dramatischere Charakterauszahlung hat.

Asteri
quelle
19

Dies mag offensichtlich erscheinen, für einige MathFunktionen gibt es jedoch kürzere Optionen :

a=Math.max(b,c);
a=b>c?b:c;

a=Math.min(b,c);
a=b<c?b:c;

a=Math.abs(b);
a=b<0?-b:b;

a=Math.round(b);
a=(int)(b+.5);          // watch for precision loss if it matters
Geobits
quelle
14

Wenn Sie Integer.MAX_VALUE(2147483647) benötigen , verwenden Sie -1>>>1. Integer.MIN_VALUE(-2147483648) ist besser geschrieben 1<<31.

dfeuer
quelle
14

Wenn Sie eine Zahl aus einem Argument (oder einer anderen Zeichenfolge) abrufen müssen, sehen Sie normalerweise Folgendes:

public static void main(String[]a){
    int n=Integer.valueOf(a[0]);
    ...
}

Viele Male, dass Sie nicht brauchen ein Integer. Viele Herausforderungen verbrauchen keine großen Zahlen. Da Shortund Bytewerden beide zu einem Unbox int, verwenden Sie die besser geeignete valueOf()statt und sparen Sie ein paar Bytes.

Behalten Sie jedoch Ihre tatsächliche Variable als bei int, da sie kürzer als beide ist byteund short:

int n=Byte.valueOf(a[0]);

Wenn Sie dies für mehrere Zahlen tun müssen, können Sie mit dieser Methode kombinieren :

Byte b=1;
int n=b.valueOf(a[0]),m=b.valueOf(a[1])...
Geobits
quelle
9
int n=new Byte(a[0]);ist drei kürzer. Wenn die Zahl größer sein könnte, verwenden Sie long n=new Long(a[0]), es ist intin den meisten Fällen immer noch besser als s.
Ypnypn
14

Nicht verwenden public class. Die Hauptmethode muss öffentlich sein, die Klasse jedoch nicht. Dieser Code funktioniert:

class S{public static void main(String[]a){System.out.println("works");}}

Sie können laufen java S, obwohl class Ses keine öffentliche Klasse ist. ( Update: Ich habe Java 7 verwendet, als ich diesen Tipp geschrieben habe. In Java 8 sollte sich Ihre Hauptmethode in einer Schnittstelle befinden . In Java 5 oder 6 sollte sich Ihre Hauptmethode in einer Aufzählung befinden .)

Viele Java-Programmierer wissen das nicht! Ungefähr die Hälfte der Antworten auf eine Stapelüberlauf-Frage zu main in einer nicht öffentlichen Klasse besagen fälschlicherweise, dass die main-Methode in einer öffentlichen Klasse sein muss. Jetzt weißt du es besser. Löschen Sie die publicin public classund 7 Zeichen speichern.

Kernigh
quelle
1
Das Konstrukt interface s{static void main(String[]...ist kürzer, es sei denn, Sie haben Java vor 1.8 als Ziel angegeben. Wenn Sie eine kompilierbare Quelldatei und Hauptmethode haben müssen. Da in einer Java 1.8-Schnittstelle alle Methoden öffentlich sind, können Sie den Modifikator für die Methode (n) überspringen.
Douglas Held
Ich habe in letzter Zeit kein Java verwendet, daher ist meine Antwort veraltet. Ich habe vergessen, dass Interfaces Methoden in Java 8 haben können.
Kernigh
Ich habe es nicht durch Programmieren gelernt. Ich habe es durch Golfen gelernt :)
Douglas Held
14

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 .

Kevin Cruijssen
quelle
Im Allgemeinen können Sie für Ihren letzten Punkt auf statische Elemente aus einem nicht statischen Kontext wie einer Instanz des Objekts zugreifen bzw. diese aufrufen.
Poke
1
Ich verstehe deinen Ceil-Tipp nicht. Warum willst du Ceil positive integers? Ich bin mir auch nicht sicher, ob die Ceil-Implementierung funktioniert .
Jonathan Frech
1
since Java automatically floors on integers; Ich denke, der richtige Begriff ist Verkürzung , nicht Bodenbelag .
Jonathan Frech
1
Eine andere Palindrome-StrategieString t="";for(int i=s.length();--i>=0;t+=s.charAt(i));return s.equals(t);
Roberto Graham
1
@RobertoGraham Ich habe tatsächlich meinen Originalcode von der falschen Herausforderung kopiert. Nur s.equals(new StringBuffer(s).reverse()+"")ist genug.
Kevin Cruijssen
11

Für das Golfen, für das keine Eingabe erforderlich ist, können Sie statische Blöcke verwenden und es ohne Hauptmethode problemlos ausführen. Kompilieren Sie es einfach mit Java 6.

public class StaticExample{
    static {
        //do stuff
    }
}
Fabinout
quelle
1
Haben Sie versucht, es zu kompilieren und auszuführen? Dieser Block wird ausgeführt, wenn die Klasse vom Klassenladeprogramm geladen wird. Der Klassenladeprogramm lädt jedoch erst dann etwas, wenn es eine Klasse mit einer Hauptmethode kennt.
Cruncher
@Cruncher Sie können das umgehen, indem Sie javain der Befehlszeile / in einer Manifestdatei angeben, welche Klasse geladen werden soll.
AJMansfield
6
@Cruncher, dies funktionierte mit Java 6. Java 7 hat die Funktionsweise geändert.
Peter Taylor
1
Wirft am Ende eine Ausnahme, aber es funktioniert! Auch in Java 7
Stommestack
2
@JopVernooij Wenn Sie nicht möchten, dass eine Ausnahme auf Ihr Gesicht geworfen wird, können Sie system.exit () verwenden, aber Sie verschwenden Zeichen. Bei keiner Golfherausforderung werden Sie aufgefordert, Ausnahmen zu vermeiden.
Fabinout
11

Wir alle kennen das bitweise xor ( ^), aber es ist auch ein logisches xor.

So wird (a||b)&&!(a&&b)einfach a^b.

Jetzt können wir xor verwenden.

zusätzlich müssen die Operatoren |und & auch die Arbeit daran denken, dass sich die Rangfolge der Operatoren ändert.

Justin
quelle
5
Solange Sie sich an den Vorrang erinnern, können Sie & und |auch verwenden. Dies kann hilfreich sein, wenn Ihre Bedingungen bereits in Klammern angegeben sind oder wenn Sie bereits mit Booleschen Werten arbeiten.
Geobits
1
Wenn Sie eine (viel) niedrigere Priorität benötigen, können Sie !=anstelle von ^für xor und ==für xnor
Cyoce 29.11.16
11

Sie müssen nicht verwenden Character.toLowerCase(char c). Verwenden Sie stattdessen (c|32). Anstatt zu Character.toUpperCase(char c)benutzen (c&~32). Dies funktioniert nur mit ASCII-Buchstaben.

Die Nummer eins
quelle
c|~32würde tendenziell zu -1 führen ... besser zu verwenden c-32.
Feersum
5
@feersum Das würde nicht funktionieren, wenn du einen Großbuchstaben in Großbuchstaben schreiben möchtest.
TheNumberOne
11

Konvertiere String in Zahl

Es gibt mehrere Möglichkeiten, einen String in einen numerischen Wert zu konvertieren:

String s = "12";

ABC.parseABC :

Short.parseShort(s); // 20 bytes
Integer.parseInt(s); // 20 bytes
Long.parseLong(s);   // 18 bytes

ABC.valueOf :

Short.valueOf(s);    // 17 bytes
Integer.valueOf(s);  // 19 bytes
Long.valueOf(s);     // 16 bytes

ABC.decode :

// Note: does not work for numeric values with leading zeros,
// since these will be converted to octal numbers instead
Short.decode(s);     // 16 bytes
Integer.decode(s);   // 18 bytes
Long.decode(s);      // 15 bytes

neues ABC :

new Short(s);        // 13 bytes
new Integer(s);      // 15 bytes
new Long(s);         // 12 bytes

Für Code-Golf ist es daher am besten, den Konstruktor zu verwenden, wenn Sie einen String in einen numerischen Wert konvertieren.

Gleiches gilt für Double; Float; und Byte.


Dies gilt nicht immer, wenn Sie ein bereits vorhandenes Grundelement als Objekt wiederverwenden können.
Nehmen wir als Beispiel an, wir haben den folgenden Code:

// NOTE: Pretty bad example, because changing the short to int would probably be shorter..
//       but it's just an example to get the point across

short f(short i,String s){
  short r=new Short(s);  // 21 bytes
  ... // Do something with both shorts
}

Sie können .decodeanstelle des kürzeren Konstruktors auch den Parameter als Objekt verwenden:

short f(Short i,String s){   // Note the short parameter has changed to Short here
  short r=i.decode(s);   // 20 bytes
  ... // Do something with both shorts
}
Kevin Cruijssen
quelle
10

Nicht verwenden Random!

Wenn Sie Zufallszahlen benötigen, Randomist dies im Allgemeinen ein schrecklicher Weg *. Viel besser zu benutzen Math.random(). Um zu verwenden Random, müssen Sie dies tun (sagen wir, wir brauchen eine int):

import java.util.*;
Random r=new Random();
a=r.nextInt(9);
b=r.nextInt(9);

Vergleichen Sie das mit:

a=(int)(Math.random()*9);
b=(int)(Math.random()*9);

und:

int r(int m){return(int)(Math.random()*m);}
a=r(9);
b=r(9);

Die erste Methode akzeptiert 41+15nZeichen ( nAnzahl der Anrufe). Der zweite ist 25nZeichen, und der dritte ist43+7n .

Wenn Sie es also nur ein- oder zweimal benötigen, verwenden Sie die Inline- Math.random()Methode. Bei drei oder mehr Anrufen speichern Sie mithilfe einer Funktion. Entweder speichert man Zeichen bei der ersten Verwendung über Random.


Wenn Sie bereits Math.random()für verwenden double, denken Sie daran, dass es bei vier Verwendungszwecken immer noch eine Ersparnis ist, dies herauszuholen:

double r(){return Math.random();}

Bei 33 Zeichen sparen Sie 10 bei jedem Anruf an r()


Aktualisieren

Wenn Sie eine Ganzzahl benötigen und beim Casting sparen möchten, casten Sie sie nicht! Java-Auto-Casts, wenn Sie eine Operation anstelle einer Zuweisung ausführen. Vergleichen Sie:

a=(int)(Math.random()*9);
a=9;a*=Math.random();

* Es sei denn, Sie müssen den PRNG-Wert festlegen, um vorhersehbare Ergebnisse zu erzielen. Dann sehe ich kaum einen Ausweg.

Geobits
quelle
2
Vergiss das aber nicht Random#nextGaussian.
Justin
@Quincunx Richtig, wenn Sie nachrechnen, um eine gute Normalverteilung zu erhalten, verlieren Sie alle Einsparungen, die Sie erhalten. Ich werde das nur als die Ausnahme bezeichnen, die die Regel bestätigt;)
Geobits
Beachten Sie, dass (int)(Math.random()*9)die Modulo-Verzerrung sehr klein ist, da sie Math.random()2 53 mögliche Werte zurückgibt und 2 53 kein Vielfaches von 9 ist. Die Wahrscheinlichkeit für jede Zahl liegt bei 1/9 plus oder minus 5 / (9 * 2 ** 53). Ein Fehler, der so klein ist, dass er fast genau 1/9 beträgt.
Kernigh
@kernigh Richtig, ich habe 9nur als Beispiel verwendet, es könnte alles sein. Ich bin mir relativ sicher, dass nextInt()(oder eine andere RandomMethode) auch eine geringe Tendenz aufweist, nur weil Java PRNG funktioniert.
Geobits
1
Etwas, das damit zusammenhängt, wann Sie einen zufälligen Booleschen Wert möchten: stattdessen new java.util.Random().nextBoolean()können Sie verwenden Math.random()<.5.
Kevin Cruijssen
7

Ich weiß nicht, ob Sie dieses "reine" Java in Betracht ziehen würden, sondern die Verarbeitung ermöglicht es Ihnen, Programme mit wenig anfänglicher Einrichtung (automatisch abgeschlossen) zu erstellen.

Für die Konsolenausgabe können Sie Folgendes verwenden:

println("hi"); //done

für die grafische Ausgabe etwas mehr:

void setup() {
  size(640,480);
}
void draw() {
  fill(255,0,0); //color used to fill shapes
  rect(50,50,25,25); //25x25 pixel square at x=50,y=50
}
Noah
quelle
1
+1 Ausgezeichnete Ressource! Ich werde sicher damit herumspielen.
Rob
Wäre es in Ordnung, wenn ich die Antworten anderer Leute hinzufügen würde? Oder hat das den Zweck eines Community-Wikis zunichte gemacht?
Rob
2
Übrigens müssen Sie nicht einmal anrufen size; Standardmäßig wird ein Quadrat von 100 x 100 Pixel verwendet. In den meisten Betriebssystemen ist der Rahmen ungefähr doppelt so groß, wobei das Quadrat zentriert ist und der Rest des Bereichs mit Inhalten gefüllt ist, die vom Desktop stammen.
AJMansfield
1
Wenn Sie für die grafische Ausgabe keine Animation benötigen, können Sie einfach alles außerhalb von schreiben setup()und draw()den "statischen Modus" verwenden. Sie können auch 6-stellige Hex-Farben verwenden. Der Interpreter ändert diese, was sich manchmal auszahlt ( #FF8000< 255,128,0). Wenn Sie Graustufen verwenden, muss nur eine Zahl angegeben werden ( 255< 255,255,255)
wie
7

Verkürzung der Rückkehr

Sie können return-Anweisungen von Strings durch ein Byte verkürzen mit:

return "something";

zu

return"something";

Und wenn Sie Ihre return-Anweisung zufällig mit einer Klammer beginnen, können Sie dasselbe mit ihnen tun:

return (1+taxRate)*value;

zu

return(1+taxRate)*value;

Ich denke, Zitate gelten als Klammer? Ich habe das tatsächlich über AppleScript aufgegriffen und dachte, es wäre erwähnenswert.

Addison Crump
quelle
1
Gleiches gilt für Zahlenzeichen, wie return-n;statt return -n;oder return~n;statt return ~n;. Sowie einfache statt doppelte Anführungszeichen:return'A';
Kevin Cruijssen
1
Funktioniert grundsätzlich für alles, was nicht Teil eines Bezeichners sein kann (dh kein Buchstabe und keine Ziffer).
Paŭlo Ebermann
7

Haben Sie keine Angst, wissenschaftliche Notation zu verwenden

Wenn Sie es mit Doubles oder Floats zu tun haben, können Sie die wissenschaftliche Notation für Zahlen verwenden. Anstatt also zu schreiben double a=1000, können Sie es in ändern double a=1e3, um 1 Byte zu sparen.

user902383
quelle
7

Versuchen Sie es mit intanstelle vonboolean

In einigen Fällen habe ich festgestellt, dass es kürzer ist, einen Ganzzahlwert von einer Methode zurückzugeben, die normalerweise einen Booleschen Wert zurückgibt, ähnlich wie dies in C-Programmen möglich ist.

Auf Anhieb intsind 4 Bytes kürzer als boolean. Jedes Mal , wenn Sie schreiben return 0statt return 1<0, sparen Sie zusätzlich 2 Bytes und das gleiche gilt für return 1 über return 1>0.

Der Nachteil hierbei ist, dass jedes Mal, wenn Sie den Rückgabewert direkt als Booleschen Wert verwenden möchten, 2 Byte ( if(p(n))v. if(p(n)>0)) Anfallen . Dies kann durch Verwendung von Boolescher Arithmetik ausgeglichen werden. In einem erfundenen Szenario, in dem Sie schreiben möchten

void a(int[]t){t[0]+=p(n)?10:0;}

du kannst stattdessen schreiben

void a(int[]t){t[0]+=p(n)*10;}

um 2 Bytes zu sparen.

Ankh-Morpork
quelle
6
Ich mache das ziemlich oft, wenn ich Golf spiele, aber denke daran, dass dies der allgemeine Konsens ist 0und 1in Java nicht falsch / wahr ist (und das JLS betrachtet sie auch nicht so). Wenn der Golf also speziell nach Wahrhaftigkeit / Falschheit fragt, müssen Sie ihn booleanisieren (und ihn leider zu einer booleanFunktion machen, indem Sie noch mehr Bytes darauf werfen).
Geobits
2
t[0]+=p(n):10?0;Ist das überhaupt gültig?
Dorukayhan
@ Dorukayhan nein, es soll sein t[0]+=p(n)?10:0;. (Ich habe es bearbeitet.)
Paŭlo Ebermann
6

Wenn Sie enum anstelle von class verwenden , speichern Sie ein Zeichen.

enum NoClass {
    F, G, H;    
    public static void main (String[] args) {

    }
}

Sie müssen jedoch mindestens eine Enum-Instanz (in diesem Beispiel F, G, H) einführen, die sich selbst auszahlen muss.

Benutzer unbekannt
quelle
2
Anscheinend brauchen Sie keine Enum-Instanzen. Das habe ich enum M{;public static void main(String[]a){...}ohne Probleme gemacht.
Danny
3
@Danny Aber dann werden keine Zeichen gespeichert. class M{ist genau so lang wieenum M{; . In diesem Fall würde ich mit dem gehen, classweil es schöner ist (IMO)
Justin
1
zumindest für mich enum{hat es ohne ;nachher geklappt; Es ist nur die IDE stöhnt, dass es einen Fehler gibt, aber der Compiler akzeptiert es
masterX244
@ masterX244 Welcher Compiler / welche Version? Meiner löst einen Wutanfall aus und wird es nicht tun.
Geobits
arbeitete an Java 1.7 für mich (erschien s, ned, um weitere Ursache mit einem Update auf .8 zu untersuchen, es funktioniert nicht mehr)
masterX244
5

Wenn Sie eine Methode haben, die ein booleanoder zurückgeben soll Boolean, dh:

// Return true if the (non-negative) input is dividable by 5
boolean c(int i){return i%5<1;}

Sie können den boolean/ Booleanreturn-Typ ändern Object, um 1 Byte zu sparen:

Object c(int i){return i%5<1;}

Darüber hinaus können Sie, wie Sie vielleicht bemerkt haben, ein <1Häkchen verwenden, anstatt ==0ein Byte zu speichern. Das ist zwar eher ein allgemeiner Code-Golftipp als ein Java-spezifischer.
Dies wird meistens verwendet, wenn die Ganzzahl nicht negativ sein kann, z. B. beim Überprüfen der Länge:

a.length<1

Anstatt von

a.length==0
Kevin Cruijssen
quelle
1
Schöner Tipp! Sie können ein anderes Beispiel in der hinzufügen möchten Abschnitt „ wenn es nicht negativ sein kann“ , um es zu illustrieren, da c(-21)kehrt truemit der aktuellen.
Geobits
Geklärt. Meinst du nicht auch c(-20)statt -21? -21 % 5 = 4und -20 % 5 = 0.
Kevin Cruijssen
1
Nein, ich meinte -21. -21 % 5 != 4in Java, das ist mein Punkt. Die durch fünf teilbare Funktion würde korrekt funktionieren , wenn der Modul immer nicht negativ zurückgegeben würde, dies ist jedoch nicht der Fall. Siehe dieses Beispiel-Snippet .
Geobits
@ Geobits Ah, danke für das Beispiel. Ich verwende fast nie negative Zahlen mit %, also habe ich vergessen, dass Java den Rest anstelle des Moduls zurückgibt, daher der Unterschied.
Kevin Cruijssen
5

Wie zeichnet man in Java ...

Hier ist die kürzestmögliche GUI-Farbkesselplatte:

import java.awt.*;
static void main(String[]x){
    new Frame(){
        public void paint(Graphics g){
            // Draw your stuff here.
        }    
    }.show();
}

Golf für 111 Bytes:

import java.awt.*;static void main(String[]x){new Frame(){public void paint(Graphics g){/*CodeHere*/}}.show();}
Magische Kraken-Urne
quelle
5

Vermeiden Sie StringBuilders

Das Anhängen von Daten an a Stringnimmt viel weniger Bytes in Anspruch.

// s is a StringBuilder
s.append("Hello, World!");

// S is a String
S+="Hello, World!";

Wenn Sie eine Zeichenfolge umkehren und sofort ausdrucken müssen, verwenden Sie a StringBuffer.

System.out.print(new StringBuilder("Hello, World!").reverse());
System.out.print(new StringBuffer("Hello, World!").reverse()); // Note that you can omit toString() when printing a non-String object

Wenn Sie eine Zeichenfolge umkehren und dann etwas anderes tun müssen als sie zu drucken, verwenden Sie eine forSchleife für jede Zeichenfolge .

String b=new StringBuffer("Hello, World!").reverse().toString();
String B="";for(String c:"Hello, World!".split(""))B=c+B;
Dorukayhan
quelle
3
Eine foreach-Schleife ist kürzer als StringBufferbeim Umkehren von Strings.String b="";for(char c:"Hello, World!".toCharArray()){b=c+b;}
Poke
1
Sie sollten auch die {}foreach-Schleife entfernen , wenn Sie diese Methode verwenden möchten.
Geobits
1
Speichern Sie 2 Bytes mit String s:"".split("")anstelle von char c:"".toCharArray().
Charlie
Wenn Sie java.util.stream.Streambereits importiert haben und einen weiteren Aufruf an das Ergebnis (wie B.chartAt(42)) ketten müssen oder wenn Sie das Ergebnis nur an eine Funktion (wie f(B)) übergeben müssen, ist using for(:)gleich Stream.of("Hello, World!".split("")).reduce("",(a,b)->b+a).
Charlie
Beide Linien in Ihrem Beispiel mit dem For-Each können golfen werden. Erstens kann man werden: String b=new StringBuffer("Hello, World!").reverse()+"";( .toStringersetzt durch +""), und Ihre zweite Zeile kann werden: String B="";for(String c:"Hello, World!".split(""))B=c+B;( charnach Stringund .toCharArray()nach .split("")).
Kevin Cruijssen
5

Verwenden Sie Java 10 var

Wenn Sie eine einzelne Variable eines bestimmten Typs definieren, verwenden Sie var .

Beispiele

var i=0;                        // int
var l=0L;                       // long
var s="";                       // String
var a=new int[]{1,2,3};         // int[]
var i=java.math.BigInteger.ONE; // BigInteger
var m=new java.util.HashMap();  // HashMap
var i=3+"abc".length()          // int
var a="a b c".split(" ");       // String[]
for(var a:"a b c".split(" "))   // String

In keinem der folgenden Beispiele verwendbar

var kann nicht in vielen Beispielen verwendet werden

var i=1,j=2;           // only one variable is accepted at a time
var a={1,2,3};         // arrays must be explicitly declared
var f=a->a+" ";        // can't know what type a is.
var f=String::replace; // method references aren't properly implied (weirdly, though)
Olivier Grégoire
quelle
Wenn dies mit Methodenreferenzen nicht funktioniert, beachten Sie, dass es Standardfunktionsschnittstellen nur für einen kleinen Satz von Signaturen gibt (und Methoden überprüfte Ausnahmen auslösen können).
Jakob
4

In den meisten Fällen handelt es sich bei Ihrem Programm um ein Single-Thread-Programm, dh es wird nur ein Thread ausgeführt. Sie können diese Tatsache ausnutzen, indem returnSie die Hauptmethode verlassen, wenn Sie sofort beenden müssen.

static void main(String[]a){if(condition)return;}

Vergleichen Sie es mit dem "richtigen" Beenden des Programms:

static void main(String[]a){if(condition)System.exit(0);}

Oder zeigen auf null:

static void main(String[]a){if(condition)throw null;}

Oder durch 0 teilen:

static void main(String[]a){if(condition)int A=1/0;}
Dorukayhan
quelle
4

Manchmal kann eine einzelne for-loop-Anweisung ersetzt werden. Betrachten Sie den folgenden Code:

int m(int x){int i=1;for(;x%++i==0;);return i;}

Dies ist eine einfache for-Schleife, die eine Lösung für diese Frage darstellt .

Da wir wissen, dass dies inicht groß genug ist, um StackOverflow-Fehler zu verursachen, können wir stattdessen die for-Schleife durch eine Rekursion ersetzen:

int m(int x,int i){return x%++i>0?i:m(x,i);}

Wir können eine Schleife simulieren, indem wir einen ternären Operator in der return-Anweisung verwenden, um eine Rekursion zu verursachen.

Diese Reduzierung ist ziemlich spezifisch, aber ich kann mir mehr Situationen vorstellen, in denen dies nützlich wäre.

Addison Crump
quelle
4

Verwenden ... (varags) als Parameter

In einigen Fällen ist es kürzer, Java-Variablen als Parameter anstelle von losen zu verwenden.
Zum Beispiel:

// Example input/output: 5, 4, 3 -> 60000
int calculateVolumeInLiters(int width, int height, int depth){
  return width * height * depth * 1000;
}

Würde von den meisten dazu golfen werden:

int c(int w,int h,int d){return w*h*d*1000;} // 44 bytes

Aber kann ein zusätzliches Byte dazu gespielt werden:

int c(int...a){return a[0]*a[1]*a[2]*1000;}  // 43 bytes

Beachten Sie, dass auf alle drei Ganzzahlen in der Methode selbst nur einmal zugegriffen wird. Schon seitint es ziemlich kurz ist, ist es nur von Vorteil, wenn Sie sie jeweils nur einmal in der Methode verwenden und drei oder mehr von ihnen als Parameter haben.

Bei längeren Parametern ist dies jedoch in der Regel sinnvoller. Dies war zum Beispiel meine ursprüngliche Antwort auf diese Herausforderung (Berechnen Sie das Vorkommen von Eingabezeichen in der Eingabezeichenfolge):

// Example input/output: tttggloyoi, t -> 3

int c(String a,char b){return a.replaceAll("[^"+b+"]","").length();} // 68 bytes

Und mir wurde empfohlen, es zu diesem Golf zu spielen:

int c(String a,char b){return a.split(b+"").length-1;}               // 54 bytes

Am Ende habe ich es aber so gemacht ...:

int c(String...a){return a[0].split(a[1]).length-1;}                 // 52 bytes

HINWEIS: Wenn die Frage / Herausforderung eine flexible Eingabe erfordert, ...kann diese []natürlich auf gekürzt werden . Wenn die Frage / Herausforderung speziell nach drei StringEingaben fragt und ein String-array mit drei Werten nicht zulässt, können Sie String...statt verwenden String a,String b,String c.

Kevin Cruijssen
quelle
2
Kannst du nicht a String[]anstelle von varargs verwenden? (speichert 1 weiteres Byte)
Kritixi Lithos
@KritixiLithos Hmm .. guter Punkt. Das hängt aber vor allem davon ab, wie flexibel der Input für die Herausforderung ist. Wenn irgendein Eingabeformat erlaubt ist, wäre das in der Tat kürzer. Ich werde dies zu diesen Tipps hinzufügen, danke.
Kevin Cruijssen