Javaでのゴルフのヒント


86

Javaで使用できる便利なショートカットはありますか?

以下に示すように、importすでに少なくとも17文字がプログラムに追加されています。

import java.io.*;

簡単な解決策は別の言語を使用することであることを理解していますが、Javaプログラムを短縮することは本当に難しいようです。


ヒントはJavaに固有である必要があります。ほとんどのCライクな言語に適用できる場合は、より一般的なヒントのリストに属します


9
packageスキップできます。
st0le

回答では、インポートがあると仮定して、単にインポートを省略できませんか?
ファブリシオ

1
@Fabricio OPがそう指定しない限り、そうではありません。
nyuszika7h 14

32
Javaのゴルフに関する最高のヒント:使用しないでください。;)
kirbyfan64sos

4
「ジャワでゴルフをしたい」幸運
-sagiksp

回答:


85
  • 可能な限り最新のjavaを使用してください。Java 8ではラムダ式を使用できるため、機能オブジェクトのようなものが必要な場合に使用します。

  • よく使うものの短縮機能を定義します。たとえば、を100回呼び出してexampleClassInstance.doSomething(someParameter)、新しい関数void d(ParameterType p){exampleClassInstance.doSomething(p)}を定義し、それを使用していくつかの文字を保存します。

  • 特定の長いクラス名を複数回使用している場合、たとえば

    MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory

    代わりに、新しいクラスを定義します。

    class X extends MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory{}

    そのクラスの特定のメソッドを1つだけ使用している場合(それでもインスタンス化する必要がある場合)、同時に新しいクラス内で短縮バージョンを定義できます。

  • 可能な場合は、次のように関数型パラメーターを使用して短縮します。

    <T>void p(T o){System.out.println(o);}
  • for(;;)代わりに使用しますwhile(true)

  • 絶対に必要でない限り、アクセス修飾子を使用しないでください。

  • final何にも使用しないでください。

  • forループの後にブロックを配置しないでください(ただしforeachループfor(x:y)は異なります)。のforように、ステートメント自体の中に追加のステートメントを配置する必要がありますfor(int i=0;i<m;a(i),b(++i))c(i);

  • インラインの割り当て、増分、インスタンス化を使用します。必要に応じて、匿名のインラインクラスを使用します。可能であれば、代わりにラムダを使用してください。ネスト関数呼び出し。一部の関数は、親オブジェクトを返すことが保証されています。これらの関数は、実際にはチェーン化されることさえ意図されています。

  • あなたのmain方法throws Exceptionの、それらをキャッチしていません。

  • Errorはより短いException。何らかの理由で本当にthrowメッセージをスタックに上げる必要があるError場合は、完全に正常な状況であってもを使用します。

  • すぐに終了する必要がある条件がある場合int a=1/0;は、throw null;またはではなくを使用しますSystem.exit(0);。実行時に、これはをスローしArithmeticExceptionます。コードに数値変数が既にある場合は、代わりに使用します。(既にお持ちの場合はimport static java.lang.System.*;、に進みexit(0);ます。)

  • のようなインターフェースを実装する代わりに、ほとんどのメソッドのデフォルトの実装を提供し、以下の実装のみを必要とするのようなList<E>即時の(または、そうすることに利点がある場合はそれほど即時ではない)子クラスを拡張AbstractList<E>しますいくつかの重要な部分。

  • 改行、インデント、および完全な変数名を使用して、最初に手書きでコードを記述します。作業コードを作成したら、名前を短縮したり、宣言を移動したり、ショートカットメソッドを追加したりできます。開始するまで長く書くことで、プログラム全体を単純化する機会が増えます。

  • コードのごくわずかな変更で最適な戦略が劇的に変わる可能性があるため、代替の最適化をコードと比較してください。例えば:

    • の呼び出しが2つまでのArrays.sort(a)場合、最も効率的な方法は、完全修飾名で呼び出すことjava.util.Arrays.sort(a)です。
    • 3回以上の呼び出しでは、代わりにショートカットメソッドを追加する方が効率的void s(int[]a){java.util.Arrays.sort(a);}です。この場合、これでも完全修飾名を使用する必要があります。(複数のオーバーロードが必要な場合は、おそらく間違っています。)
    • ただし、コードで配列をコピーする必要がある場合(通常for、ゴルフの短いループで、簡単にアクセスできるライブラリメソッドがない場合)、Arrays.copyOfタスクを実行するために利用できます。複数のメソッドが使用され、3つ以上の呼び出しがある場合、実行import static java.util.Arrays.*;がこれらのメソッドを参照する最も効率的な方法です。その後、8つ以上の個別の呼び出しがsortある場合にのみ、ショートカットメソッドを使用する必要があり、5つ以上の呼び出しでのみ、ショートカットが保証されcopyOfます。

    コードでこのような分析を実行する唯一の実際の方法は、コードのコピーで潜在的な変更を実際に実行し、結果を比較することです。

  • someTypeValue.toString();メソッドの使用を避け、代わりに単にappendしますsomeTypeValue+""

  • ウィンドウが必要な場合は、Swingを使用せず、AWTを使用します(Swingの何かが本当に必要な場合を除く)。とを比較import javax.swing.*;import java.awt.*;ます。さらに、Swingのコンポーネントには、J名前の前に追加されます(JFrameJLabelなど)が、AWTのコンポーネントがいない(FrameLabelなど)


43

interface代わりに使用しますclass

Java 8では、静的メソッドがインターフェイスに追加されました。インターフェイスでは、すべてのメソッドはデフォルトでパブリックです。その結果

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

今に短縮することができます

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

これは明らかに短いです。

たとえば、Hello、World!でこの機能を使用しましたチャレンジ。


8
私はそれを知りませんでした!+1、ナイストリック
-HyperNeutrino

イェーイ、定型文が少ない!
電卓

3
私は部分的に反対しなければなりません(また、「Hello、World!」チャレンジで、そのテクニックを使用してあなたを打ち負かしました)。
オリビエグレゴワール

37

では可変引数あなたは、同じ型の配列にパラメータを「キャスト」することができます:

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

の代わりに

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

31

静的インポート

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

後から定型句を保存できますが、見返りを得るには複数の呼び出しが必要です。

public static void main (String[] args) {
    out.println ("foo");    
    out.println ("bar");    
    out.println ("baz");    
}

8
:O。あなたはこれを行うことができます?!そしてこの間、私はこれが不可能だと思ったJava
ジャスティン

12
あなたも使用することができますimport static java.lang.System.*
ヨハネ

1
私は、これは古い答えですけど、Javaの10であなたが今できるvar o=System.out;唯一それが報わ前に2回使用する必要がある
ルーク・スティーヴンス

@LukeStevens:ええと、Java10で可能な他の改善点を見つけて、Java10に関して別の答えを見つけられるかもしれません。
ユーザー不明

1
@LukeStevens var o=System.out.println動作しますか?
MilkyWay90

25

の引数をmain呼び出す必要はありません。args空白を削除できます。

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

うまくいくでしょう。


1
完全なプログラムを書くことを明示的に述べていない場合、答えにはmain関数を含める必要がありますか ラムダ式を答えとして使用しています。
マコトサン

3
@Makotosanいいえ、そうではありません。ラムダは通常大丈夫です。
daniero

21

ブール式trueまたはを使用する必要がある場合は、それぞれfalse1>0and に置き換えます1<0

例えば:

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

この線形検索の例は、

boolean f=1<0;
for(i=0;i<10;)if(a[i++]==42)f=1>0;

11
あなたが多くを必要とするつもりならtrue/false、単に追加してくださいboolean t=1>0,f=1<0;。次に、の代わりに1>0、使用tごとに2つの文字を使用して保存します。支払い1>0方法は10回使用できます。
Geobits

24
@Geobits:-1 boolean t=1>0,f=!t;文字短く!
ボベル

6
この例はあまり良くありません。この場合と他の多くの(!)他の方法でとにかくtrue/をfalse直接使用することを避けることができます:f|=a[i++]==42;かなり節約できます。
インゴバーク14

@IngoBürkはい。私がこれを書いているとき、私はほとんどを使用するライブラリ関数について考えbooleanていましたが、執筆時にどんな例も思いつかなかったので(私は通常Javaでコーディングしません)、私は簡単な例を書いただけです。
ace_HongKongIndependence 14

1
@GeobitsはJavaにあまり馴染みがありませんが、1を定義してtと!tを使用することができます(Javaについては知りませんが、好奇心が強いです)
アルバートレンショー

20

何らかのメソッドを頻繁に使用する場合は、その常駐クラスを変数に割り当てます。たとえばSystem.out、変数に割り当てます。

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

また、用Integer.parseInt()

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

これにより、「変数から静的メソッドにアクセスする」というIDE警告がほぼ確実にトリガーされます。


((Integer)1).parseInt("1")も動作します。
魔法のタコUr

5
@carusocomputing new Integer("1")はさらに短くなります。しかし、Justinが彼の答えで意味したのは、既に持っている変数を静的呼び出しに再利用できるということです。この答えの一番下で説明するように。
ケビンCruijssen

19

このimport static java.lang.System.*手法を使用してprintln()ステートメントを保存するよりも、次のメソッドを定義する方が文字を保存するのにはるかに効果的であることがわかりました。

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

これは、はるかに速く、より劇的なキャラクターの見返りがあるとp(myString)いうよりも、out.println(myString)それを呼び出すことができるためです。


19

これは明白に思えるかもしれませんが、一部のMath機能には短いオプションがあります。

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

14

Integer.MAX_VALUE(2147483647)が必要な場合は、を使用します-1>>>1Integer.MIN_VALUE(-2147483648)は、より適切に記述されてい1<<31ます。


14

引数(または他の文字列)から数値を取得する必要がある場合、通常は次のように表示されます。

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

多くの場合、あなたはしていない必要がありますInteger。たくさんの課題が大きな数字を使うことはありません。以来ShortByteの両方のVHS版はなりint、より適切なを使用valueOf()代わり、数バイト節約します。

ただし、実際の変数はとして保持します。intこれは、byteおよびの両方よりも短いためshortです。

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

複数の番号に対してこれを行う必要がある場合は、このメソッドと組み合わせることができます。

Byte b=1;
int n=b.valueOf(a[0]),m=b.valueOf(a[1])...

9
int n=new Byte(a[0]);3つ短いです。数値が大きくなる可能性がある場合は、を使用しますがlong n=new Long(a[0])intほとんどの場合はs よりも優れています。
Ypnypn 14年

14

使用しないでくださいpublic class。メインメソッドはパブリックである必要がありますが、そのクラスはパブリックではありません。このコードは機能します:

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

あなたは実行できjava Sていてもclass S公共のクラスではありません。(更新:このヒントを書いたときにJava 7を使用していました。Java8では、メインメソッドはインターフェイスにある必要があります。Java5または6では、メインメソッドはenumにある必要があります。)

多くのJavaプログラマーはこれを知りません!非パブリッククラスのメインに関するStack Overflowの質問に対する回答の約半分は、メインメソッドがパブリッククラスにある必要があると誤って主張しています。今、あなたはよく知っています。削除public中のpublic class7つの文字を保存します。


1
1.8より前のJavaをターゲットにしている場合を除き、コンストラクトinterface s{static void main(String[]...は短くなります。コンパイル可能なソースファイルとメインメソッドが必要な場合。Java 1.8インターフェースでは、すべてのメソッドがパブリックであるため、メソッドの修飾子をスキップできます。
ダグラス

私は最近Javaを使用していませんので、私の答えは時代遅れになっています。インターフェースがJava 8のメソッドを持つことができることを忘れていました。
kernigh

私はプログラミングからそれを学びませんでした。私はゴルフからそれを学んだ:)
ダグラス

14

いくつかの小さなコードゴルフのヒント

これらのヒントは個別の回答には少し小さすぎたので、この回答を、私が見つけた、または思いついた非常に小さなコードゴルフのヒントに使用します。他のヒントにはまだ触れていません。

文字列の最後の文字を削除する:

// I used to do something like this:
s.substring(0,s.length()-1)     // 27 bytes

// But this is shorter:
s.replaceAll(".$","")           // 21 bytes

場合によっては、最後の文字が何であるかを事前に知っており、この文字が文字列で1回しか出現しないことも知っています。その場合、.split代わりに使用できます:

// As example: "100%" to "100"
s.split("%")[0]                 // 15 bytes

エンコードのショートカット:

// 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

すべてのエンコーディングには、java.nioAPIで使用される正規名と、APIで使用される正規名がjava.ioありjava.langます。以下は、Javaでサポートされているすべてのエンコーディングの完全なリストです。したがって、常に2つのうち最短のものを使用してください。2番目は通常短い(UTF-8vs utf8Windows-1252vs Cp1252など)ですが、常に(UTF-16BEvs UnicodeBigUnmarked)ではありません。

ランダムブール:

// 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

プライム:

プライムをチェックしたり、すべてのプライムを取得したりする方法はたくさんありますが、ここでの@SaraJの答えは最短です。参照用のコピー&ペーストは次のとおりです。

// 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*/;}}

注:通常、使用方法に応じて、他の既存のループとマージできます。そのため、別の方法は必要ありません。これにより、たとえばこの回答で多くのバイトが節約されました。

Math.floor / Math.ceilの代わりに整数の切り捨て:

あなたが使用している場合は、正ダブルス/山車を、あなたがしたいfloorそれら、使用していないMath.floorが、使用(int)(Javaは、整数に切り捨てので)代わりに-castを:

double d = 54.99;

int n=(int)Math.floor(d);     // 25 bytes

int m=(int)d;                 // 13 bytes

// Outputs 54 for both

代わりに、同じトリックを負の double / floatに適用できますceil

double d = -54.99;

int n=(int)Math.ceil(d);     // 24 bytes

int m=(int)d;                // 13 bytes

// Outputs -54 for both

&1代わりに使用して%2、括弧を取り除きます。

なぜなら演算子の優先順位&のようなデフォルトの算術演算子よりも低くなっている*/+-%、あなたはいくつかのケースでは括弧を取り除くことができます。

// So instead of this:
(i+j)%2     // 7 bytes

// Use this:
i+j&1       // 5 bytes

これはブールチェックでは実際には役に立たないことに注意してください。そうすれば、括弧が必要になりますが、それらは少し移動するだけです。

(i+j)%2<1    // 9 bytes
(i+j&1)<1    // 9 bytes

BigIntegerと静的メソッド呼び出しの変数の作成:

BigIntegerを使用する場合は、一度だけ作成してから再利用できます。ご存知かもしれませんが、BigIntegerにはZEROONEおよびの静的フィールドが含まれていますTEN。したがって、これら3つだけを使用する場合は、必要はありませんimportが使用できますjava.Math.BigInteger直接。

// 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                  

注:使用する必要があります =nullためにtはを初期化する必要がありますt.

バイトを節約するために、複数のBigIntegerを追加して別のBigIntegerを作成できる場合があります。だから、BigIntegerを持ちたいとしましょう1,10,12、何らかの理由で:

// 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

コメントで正しく指摘されているように、BigInteger t=null;静的メソッド呼び出しのトリックは他のクラスでも使用できます。
たとえば、2011年の次の回答はゴルフにかけることができます。

// 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() の代わりに toCharArray()

文字列の文字をループするには、通常これを行います。

for(char c:s.toCharArray())    // 27 bytes
// or this:
for(String c:s.split(""))      // 25 bytes

文字をループすることは、文字を印刷したり、文字列などに追加するときに便利です。

あなたが唯一のいくつかのUnicode-数の計算のための文字を使用する場合は、あなたは置き換えることができcharint、そして、あなたは置き換えることができtoCharArray()getBytes()

for(int c:s.getBytes())        // 23 bytes

または、Java 8以降ではさらに短くなります。

s.chars().forEach(c->...)      // 22 bytes

Java 10以降では、印刷する文字をループすることも22バイトで実行できるようになりました。

for(var c:s.split(""))         // 22 bytes

からのランダムアイテム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

文字列に先頭/末尾のスペースが含まれているかどうかを確認します

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

!=StringsでJavaの値の代わりに参照をチェックする場合、なぜこれが機能するのですか?のでString#trim戻ります「先頭とホワイトスペースを削除末尾、またはでこの文字列のコピーを、それが何の先頭または末尾に空白がない場合、この文字列誰かが私にこれを提案した後、」私はで、これを使ってきた私のこの回答

パリンドローム:

文字列が回文であるかどうかを確認するには(文字列の偶数と奇数の両方の長さを念頭に置いて)、これが最短です(.contains文字列自体とその逆の形式が等しい長さであるため、ここで動作します)。

String s=...;
s.contains(new StringBuffer(s).reverse())    // 41 bytes

.contains(...)ここで@assyliasのコメント.equals(...+"")感謝する代わりに。

どちらかが0、または両方が0ですか?

私はすでにこれを知っていると思います:どちらかaまたはbゼロかどうかを確認したい場合は、代わりに乗算してバイトを節約します:

a==0|b==0    // 9 bytes
a*b==0       // 6 bytes

そして、あなたは両方のかどうかを確認したい場合abゼロであり、あなたはビット単位-ORを使用することができ、または、彼らは常に正であればそれらを一緒に追加します。

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)

偶数= 1、奇数= -1; またはその逆

// 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

私がこれを追加する理由はk+(k%2<1?1:-1)この答えを見た後です:

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

nフルプログラムのループ時間

完全なプログラムが必須であり、特定の回数ループする必要があるという課題がある場合、次のことができます。

// 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

この範囲を入力として取得する必要がある場合も同じです。

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

功績@JackAmmoこのコメントに

戻るとき、および使用するとき、try-catch(Exception e)の代わりにtry-finally

あなたが使用できない場合throws Exceptionだけに持っているcatchと、あなたが使用することができます返す前にそれで何かを行うfinally代わりに:

try{...}catch(Exception e){return ...;}    // 33 bytes
try{...}finally{return ...;}               // 22 bytes

を使用する場合の例として、この答えをtry-catch参照できます(間接ゴルフのクレジットは@KamilDrakariになります)。この課題では、NxM行列を斜めにループする必要があるため、列の量または行の量がforループの最大値として最も低いかどうかを判断する必要があります(バイトの点で非常に高価です)。したがって、単にusingをキャッチすることは、このチェックよりも短いため、バイトを節約できます。i<Math.min(a.length,a[0].length)ArrayIndexOutOfBoundsExceptioncatch-finally

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

注:これreturn r;は、最終的にのみ機能しました。@KamilDrakariがC#の回答でバイトを節約するためにしたように、最初のセルを変更することを提案されました。ただし、Javaでは、これをm->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73バイト)に変更する必要があることを意味しますfinally

Math.pow(2、n)

2の累乗が必要な場合、ビット単位のアプローチははるかに短くなります。

(int)Math.pow(2,n)    // 16 bytes
(1<<n)                // 6 bytes

括弧を使用する代わりにビット単位のチェックと論理チェックを組み合わせます

Java(ブール)論理チェックの代わりに、およびJava(ブール)論理チェックで使用できることが今ではよく知られている&と思います。場合によっては、エラーを防ぐためにの代わりに使用したい場合もあります。がここに変更される場合、配列内のインデックスを使用する部分を評価するため、が発生するため、この場合はの代わりにが使用されます。|&&||&&&index >= 0 && array[index].doSomething&&&ArrayIndexOutOfBoundsException&&&

これまでのJavaの&&/ ||vs &/の基本|

をチェックする(A or B) and C場合、最も短いものは次のようなビット単位の演算子を使用しているように見えます。

(A|B)&C    // 7 bytes

ただし、ビット単位の演算子は論理チェックより演算子の優先順位が高いため、両方を組み合わせてここでバイトを保存できます。

A|B&&C     // 6 bytes

n+=...-n代わりに使用(long)...

を使用する場合など、ラムダの入力と出力の両方が長い場合Math.pow、のn+=...-n代わりにを使用してバイトを保存できます(long)...
例えば:

n->(long)Math.pow(10,n)    // 23 bytes
n->n+=Math.pow(10,n)-n     // 22 bytes

これは、内のバイト保存された鉱山のこの答え組み合わせることで、さらに2バイト-n-1+~nして私のこの回答


より一般的には、最後のポイントとして、オブジェクトのインスタンスなどの非静的コンテキストから静的メンバーにアクセス/呼び出すことができます。
ポケ

1
私はあなたの最高のヒントを理解していません。なぜあなたは封鎖したいのpositive integersですか?また、ceilの実装が機能するかどうかもわかりません。
ジョナサンフレッチ

1
since Java automatically floors on integers; 適切な用語は、フローリングではなく切り捨てだと思います。
ジョナサンフレッチ

1
別のパリンドローム戦略String t="";for(int i=s.length();--i>=0;t+=s.charAt(i));return s.equals(t);
ロベルトグラハム

1
@RobertoGraham実際に間違ったチャレンジから元のコードをコピーしました。それでs.equals(new StringBuffer(s).reverse()+"")十分です。
ケビンCruijssen

11

入力を必要としないゴルフでは、静的ブロックを使用し、メインメソッドなしで問題なく実行できます。Java6でコンパイルするだけです。

public class StaticExample{
    static {
        //do stuff
    }
}

1
コンパイルして実行しようとしましたか?このブロックは、クラスがクラスローダーによってロードされるときに実行されます。ただし、クラスローダーは、メインメソッドを持つクラスを認識するまで何もロードしません。
ランチャー

@Cruncher自分でjavaコマンドライン/マニフェストファイルでロードするクラスを伝えることで、それを回避できます。
AJMansfield

6
@Cruncher、これはJava 6で機能しました。Java7は動作方法を変更しました。
ピーターテイラー

1
最後に例外をスローしますが、動作します!でも、Javaの7中
stommestack

2
@JopVernooijあなたがあなたの顔にスローされた例外を持ってしたくない場合は、System.exitとすることができます()、しかし、あなたは文字を無駄だろう、何のゴルフの課題は、これまで例外を回避するように要求されますしない;)
Fabinout

11

私たちは皆ビット単位のxor(^)について知っていますが、論理的なxorでもあります。

だから、(a||b)&&!(a&&b)単純になりa^b

これでxorを使用できます。

さらに、演算子|& workも、演算子の優先順位が変わることを覚えておいてください。


5
優先順位を覚えている限り、and も使用できます 。条件が既に括弧内にある場合、または既にブール値を使用している場合に役立ちます。&|
ジオビット14

1
(はるかに)低い優先順位が必要な場合!=^、xorの代わりに==、xnorの代わりに使用できます
Cyoce

11

を使用する必要はありませんCharacter.toLowerCase(char c)。代わりにを使用してください(c|32)Character.toUpperCase(char c)使用する代わりに(c&~32)。これはASCII文字でのみ機能します。


c|~32-1 ...を使用する方が良い結果になる傾向がありますc-32
feersum 14

5
@feersum大文字を大文字にしたい場合は機能しません。
TheNumberOne 14

11

文字列を数値に変換

文字列を数値に変換する方法は複数あります。

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

新しいABC

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

したがって、コードゴルフでは、文字列を数値に変換するときにコンストラクターを使用するのが最適です。

同じことが当てはまりDoubleます。Float; およびByte


既に存在するプリミティブをオブジェクトとして再利用できる場合、これは必ずしも当てはまりません。
例として、次のコードがあるとしましょう:

// 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
}

.decodeパラメータをオブジェクトとして再利用することで、より短いコンストラクタの代わりに使用できます。

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
}

10

使用しないでくださいRandom

一般的に、乱数が必要な場合Randomは、それを試す恐ろしい方法です*。Math.random()代わりに使用することをお勧めします。を使用Randomするには、これを行う必要があります(が必要だとしましょうint):

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

それと比較してください:

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

そして:

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

最初のメソッドは41+15n文字を受け取ります(n呼び出しの数です)。2番目は25n文字で、3番目は43+7nです。

したがって、1回か2回だけ必要な場合は、インラインMath.random()メソッドを使用します。3回以上の呼び出しの場合、関数を使用して保存します。どちらかが最初の使用時に文字を保存しRandomます。


すでにMath.random()for を使用している場合doubleは、4回使用しても、次のように引き出すことで節約できることに注意してください。

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

33文字の場合、次の呼び出しごとに10を保存します r()


更新

整数が必要で、キャストを節約したい場合は、キャストしないでください!割り当ての代わりに操作を行うと、Javaが自動キャストします。比較:

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

* 予測可能な結果を​​得るためにPRNGをシードする必要がない限り。それから、私はそれのまわりの多くの方法を見ない。


2
でも忘れないでくださいRandom#nextGaussian
ジャスティン14

@Quincunx確かに、適切な正規分布を得るために数学を行うと、得られた節約は失われます。ルールを証明する例外としてそれを参照します;)
Geobits 14

2 53の可能な値を返し、2 53は9の倍数ではない(int)(Math.random()*9)ため、モジュロバイアスは非常に小さいことに注意してください。各数値の確率は1/9プラスまたはマイナス5 /(9 * 2 ** 53)以内です。エラーは非常に小さいため、ほぼ正確に1/9です。Math.random()
カーニグ14年

@kernigh右、私は9ちょうど例として使用していました、それは何でもありえます。JavaのPRNGがどのように機能するかという理由だけで、nextInt()(または他のRandom方法でも)バイアスが小さいと確信しています。
ジオビット14年

1
ランダムなブール値が必要な場合に関連するもの:代わりにnew java.util.Random().nextBoolean()を使用できますMath.random()<.5
ケビンCruijssen 16年

7

この「純粋な」Javaを検討するかどうかはわかりませんが、Processingを使用すると、初期セットアップをほとんど必要とせずにプログラムを作成できます(自動的に完了します)。

コンソール出力の場合、次のような単純なものを使用できます。

println("hi"); //done

グラフィカル出力の場合、もう少し:

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
}

1
+1優れたリソース!私はそれをいじりましょう。
ロブ

これに他の人の答えを追加しても大丈夫でしょうか?または、それはコミュニティwikiの目的を無効にしますか?
ロブ

2
ところで、あなたはまったく電話sizeをする必要さえありません。デフォルトは100 x 100ピクセルの正方形です。ほとんどのOSでは、その周囲のフレームは約2倍の大きさで、正方形は中央にあり、残りの領域はデスクトップから取得したコンテンツで満たされています。
AJMansfield

1
グラフィカル出力の場合、アニメーションが必要ない場合はsetup()draw()「静的モード」の外ですべてを記述して使用できます。あなたはまた、6桁の16進の色を使用することができますし、通訳が時々 (報われ、それらを変更します#FF8000< 255,128,0)、そしてあなたがグレースケールを使用している場合のみ、1番号を指定する必要があります(255< 255,255,255
クアット

7

帰りの短縮

以下を使用して、文字列のreturnステートメントをバイト単位で短縮できます。

return "something";

return"something";

そして、もし括弧でreturnステートメントを始めたら、それらで同じことをすることができます:

return (1+taxRate)*value;

return(1+taxRate)*value;

引用符は括弧のように考えられていると思いますか?私は実際にAppleScriptでこれを拾い上げました。


1
同じことが同じように、番号記号に適用されるreturn-n;の代わりに、return -n;またはreturn~n;代わりにreturn ~n;。二重引用符ではなく単一引用符:return'A';
ケビンクルーッセン

1
基本的に、識別子の一部になれないもの(つまり、非文字と非数字)に対して機能します。
パエロエベルマン

7

科学表記法を使うことを恐れないでください

doubleまたはfloatを扱う場合は、数値に科学表記法を使用できます。だから書くのでdouble a=1000はなく、それを変更することができますdouble a=1e3 1バイトを節約にます。


7

int代わりに使用してみてくださいboolean

場合によっては、Cプログラムで行われることと同様に、通常ブール値を返すメソッドから整数値を返す方が短いことがわかりました。

すぐに、int4バイトより短くなりbooleanます。return 0代わりに書くたびにreturn 1<0、追加の2バイトを保存return 1return 1>0ます。

ここでの落とし穴は、戻り値をブール値として直接使用するたびに2バイト(if(p(n))v。if(p(n)>0))かかります。これは、ブール演算を使用して補うことができます。書きたいという人為的なシナリオを考える

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

代わりに書くことができます

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

2バイトを節約するため。


6
私はゴルフをするときにこれをかなり頻繁に行いますが、一般的なコンセンサスはそれで0あり1、Javaではfalse / trueを構成しないことを覚えておいてください(そしてJLSもそれらをそのように考慮しません)。したがって、ゴルフが特に真実/偽物を求めている場合は、それをブール化する必要があります(そして、残念ながら、それをboolean機能にして、さらに多くのバイトを投げます)。
ジオビット

2
t[0]+=p(n):10?0;これも有効ですか?
ドルカハン

@dorukayhanいや、それはするためのものt[0]+=p(n)?10:0;です。(私はそれを編集しました。)
PaŭloEbermann

6

classの代わりにenumを使用すると、1文字が保存されます。

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

    }
}

ただし、少なくとも1つの列挙型インスタンス(この例ではF、G、H)を導入する必要があり、それらは自分自身で成果を上げる必要があります。


2
列挙型インスタンスは必要ないようです。私はenum M{;public static void main(String[]a){...}問題なくやった。
ダニー

3
@Dannyしかし、それは文字を保存しません。class M{は、とまったく同じ長さenum M{;です。その場合、私はclassそれがきれいだから行きます(IMO)
ジャスティン14

1
少なくとも私にとってenum{は、;アフターなしで働いていました。そこにエラーがあるbuttheコンパイラがそれを受け入れることうめき声その唯一のIDE
masterX244

@ masterX244どのコンパイラ/バージョンですか?私はかんしゃくを投げて、それをしません。
ジオビット

(それが動作を停止0.8へのアップデートでさらに原因を調査するために定義さ、Sが登場)私のためのJava 1.7で働いていた
masterX244

5

booleanまたはを返すメソッドがある場合Boolean、つまり:

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

boolean/ Booleanreturn-typeを変更して、Object1バイトを節約できます。

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

さらに、お気づきかもしれませんが、バイトを保存する<1代わりにチェックを使用でき==0ます。ただし、これはJava固有ではなく、より一般的なコードゴルフのヒントです。
これは、長さのチェックなど、整数を負にできない場合に主に使用されます。

a.length<1

の代わりに

a.length==0

1
素敵なヒント!「負の値にできない場合」セクションに別の例を追加して、それを説明することができc(-21)ますtrue。これは、現在の例で返されるためです。
ジオビット

明確にした。また、c(-20)代わりにの意味ではないです-21か?-21 % 5 = 4および-20 % 5 = 0
ケビンCruijssen

1
いいえ、私は意味しました-21-21 % 5 != 4私のポイントであるJavaで。モジュラスが常に非負を返した場合、5で割り切れる関数正しく機能します、そうではありません。このサンプルスニペットを参照してください。
ジオビット

@Geobitsああ、例に感謝します。私は負の数を使用することはほとんどない%..ので、私は、Javaの代わりモジュラスの剰余を返し忘れ、従って差
ケビンCruijssen

5

Javaで描画する方法...

以下は、最短のGUIペイントボイラープレートです。

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

111バイトのゴルフ:

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

5

避けStringBuilder

にデータを追加すると、String必要なバイト数がはるかに少なくなります。

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

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

文字列を反転してすぐに印刷する必要がある場合は、を使用し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

文字列を反転し、それを印刷する以外のことをする必要がある場合は、for各ループを使用します。

String b=new StringBuffer("Hello, World!").reverse().toString();
String B="";for(String c:"Hello, World!".split(""))B=c+B;

3
foreachループは、StringBuffer文字列を反転する場合よりも短くなります。String b="";for(char c:"Hello, World!".toCharArray()){b=c+b;}
ポケ

1
{}そのメソッドを使用する場合は、foreachループからも削除する必要があります。
ジオビット

1
String s:"".split("")代わりに2バイトを保存しますchar c:"".toCharArray()
チャーリー

あなたがいる場合はjava.util.stream.Stream、すでにインポートされ、あなたがチェーンに結果への別のコール(等が必要な場合B.chartAt(42))、またはあなただけの機能(のように結果を渡す必要がある場合f(B))、その後、使用してはfor(:)とequallですStream.of("Hello, World!".split("")).reduce("",(a,b)->b+a)
チャーリー

for-eachを使用した例の両方の行は、ゴルフが可能です。最初の行はString b=new StringBuffer("Hello, World!").reverse()+"";(に.toString置き換えられ+""ます)になり、2行目はString B="";for(String c:"Hello, World!".split(""))B=c+B;charto String.toCharArray()to .split(""))になります。
ケビンCruijssen

5

Java 10を使用する var

特定のタイプの単一の変数を定義する場合は、を使用しますvar

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

次の例では使用できません

var 多くの例では使用できません

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)

なぜこれがメソッド参照では機能しないのか、署名の小さなセットのみに標準の機能インターフェイスがあることに注意してください(そしてメソッドはチェック済み例外をスローできます)。
ヤコブ


4

ほとんどの場合、プログラムはシングルスレッドです。つまり、実行中のスレッドは1つだけです。returnすぐに終了する必要がある場合は、メインメソッドからingすることでこの事実を活用できます。

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

プログラムを「適切に」終了することと比較してください。

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

または次を指すnull

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

または0で割る:

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

4

場合によっては、単一のforループステートメントが置き換え可能になる場合があります。次のコードを検討してください。

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

これは、この質問の解決策である単純なforループです。

iStackOverflowエラーを引き起こすほど大きくないことがわかっているため、代わりにforループを再帰に置き換えることができます。

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

returnステートメントで三項演算子を使用して再帰を引き起こすことにより、ループをシミュレートできます。

この削減はかなり具体的ですが、これが便利になる状況が想像できます。


4

を使用して ...パラメータとして(varags)

場合によっては、パラメータとしてJavaの可変引数を使用する方が、緩やかなものの代わりに短いことがあります。
例えば:

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

ほとんどの人がこれにゴルフをするでしょう:

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

しかし、これに追加のバイトをゴルフすることができます:

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

3つの整数はすべて、メソッド自体で1回しかアクセスされないことに注意してください。以来int、かなり短いですあなたはメソッド内で一度だけそれらそれぞれを使用し、パラメータとしてそれらの3以上を持っている場合にのみ有益です。

長いパラメーターでは、これは通常より便利です。たとえば、これはこのチャレンジに対する最初の答えでした(入力文字列の入力文字の出現を計算します):

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

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

そして、私はこれにゴルフすることを勧められました:

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

しかし、私はこれを使ってこれにゴルフをしました...

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

注:質問/チャレンジが柔軟な入力を要求する場合、もちろん...短縮できます[]。質問/チャレンジが特に3つのString入力を要求し、String3つの値を含む-arrayを許可しない場合、のString...代わりに使用できますString a,String b,String c


2
String[]可変引数を使用する代わりにを使用することはできませんか?(さらに1バイトを保存)
Kritixi Lithos

@KritixiLithosうーん。良い点。しかし、それは主に、チャレンジに対する入力の柔軟性に依存します。入力形式が許可されている場合、それよりも実際には短くなります。これをこのヒントに追加します、ありがとう。
ケビンCruijssen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.