Beberapa tips kode-golf kecil
Kiat-kiat ini agak terlalu kecil untuk jawaban yang terpisah, jadi saya akan menggunakan jawaban ini untuk kiat kodegolf yang sangat kecil yang saya temukan atau hasilkan, dan belum disebutkan dalam kiat lain:
Menghapus karakter terakhir dari String:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
Dalam beberapa kasus Anda tahu apa karakter terakhir sebelumnya, dan Anda juga tahu karakter ini hanya muncul sekali di String. Dalam hal ini Anda dapat menggunakan .split
sebagai gantinya:
// As example: "100%" to "100"
s.split("%")[0] // 15 bytes
Pintasan penyandian:
// 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
Semua penyandian memiliki nama kanonik yang digunakan dalam java.nio
API, serta nama kanonik yang digunakan dalam API java.io
dan java.lang
. Berikut adalah daftar lengkap semua penyandian yang didukung di Jawa. Jadi selalu gunakan yang terpendek dari keduanya; yang kedua biasanya lebih pendek (seperti UTF-8
vs utf8
, Windows-1252
vs Cp1252
, dll), tetapi tidak selalu ( UTF-16BE
vs UnicodeBigUnmarked
).
Boolean acak:
// 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
Bilangan prima:
Ada banyak cara berbeda untuk memeriksa bilangan prima atau mendapatkan semua bilangan prima, tetapi jawaban @ SaraJ di sini adalah yang terpendek. Berikut ini adalah copy-paste sebagai referensi:
// 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*/;}}
CATATAN: Biasanya Anda dapat menggabungkannya dengan loop lain yang ada tergantung pada bagaimana Anda ingin menggunakannya, sehingga Anda tidak perlu metode terpisah. Ini menyimpan banyak byte dalam jawaban ini misalnya.
Pemotongan bilangan alih-alih Math.floor / Math.ceil:
Jika Anda menggunakan doubl / float positif dan Anda menginginkannya floor
, jangan gunakan Math.floor
tetapi gunakan (int)
-cast sebagai gantinya (karena Java memotong bilangan bulat):
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
Trik yang sama dapat diterapkan pada dobel / mengapung negatif yang Anda inginkan ceil
:
double d = -54.99;
int n=(int)Math.ceil(d); // 24 bytes
int m=(int)d; // 13 bytes
// Outputs -54 for both
Gunakan &1
alih-alih %2
untuk menyingkirkan tanda kurung:
Karena Operator Precedence dari &
lebih rendah dari operator aritmatika standar seperti */+-
dan %
, Anda dapat menyingkirkan kurung dalam beberapa kasus.
// So instead of this:
(i+j)%2 // 7 bytes
// Use this:
i+j&1 // 5 bytes
Perhatikan bahwa ini tidak benar-benar membantu dalam pemeriksaan boolean, karena Anda masih membutuhkan tanda kurung, mereka hanya bergerak sedikit:
(i+j)%2<1 // 9 bytes
(i+j&1)<1 // 9 bytes
BigIntegers dan membuat variabel untuk panggilan metode statis:
Saat menggunakan BigIntegers, buat hanya sekali yang kemudian dapat Anda gunakan kembali. Seperti yang Anda ketahui, BigInteger berisi bidang statis untuk ZERO
, ONE
dan TEN
. Jadi saat Anda hanya menggunakan ketiganya, Anda tidak perlu import
tetapi bisa menggunakannya java.Math.BigInteger
secara langsung.
// 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
CATATAN: Anda harus menggunakan =null
begitu t
diinisialisasi untuk menggunakan t.
.
Terkadang Anda dapat menambahkan beberapa BigIntegers untuk membuat yang lain untuk menyimpan byte. Jadi katakanlah Anda ingin memiliki BigIntegers 1,10,12
karena beberapa alasan:
// 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
Seperti yang ditunjukkan dengan benar dalam komentar, trik dengan BigInteger t=null;
untuk panggilan metode statis juga dapat digunakan dengan kelas lain.
Misalnya, jawaban dari 2011 ini dapat di-golf:
// 173 bytes:
import java.util.*;class g{public static void main(String[]p){String[]a=p[0].split(""),b=p[1].split("");Arrays.sort(a);Arrays.sort(b);System.out.print(Arrays.equals(a,b));}}
// 163 bytes
class g{public static void main(String[]p){java.util.Arrays x=null;String[]a=p[0].split(""),b=p[1].split("");x.sort(a);x.sort(b);System.out.print(x.equals(a,b));}}
getBytes()
dari pada toCharArray()
Saat Anda ingin mengulang karakter String, biasanya Anda akan melakukan ini:
for(char c:s.toCharArray()) // 27 bytes
// or this:
for(String c:s.split("")) // 25 bytes
Melonggarkan karakter dapat berguna saat mencetaknya, atau menambahkannya ke String, atau yang serupa.
Namun, jika Anda hanya menggunakan karakter untuk beberapa perhitungan angka unikode, Anda bisa mengganti char
dengan int
, DAN Anda bisa mengganti toCharArray()
dengan getBytes()
:
for(int c:s.getBytes()) // 23 bytes
Atau bahkan lebih pendek di Java 8+:
s.chars().forEach(c->...) // 22 bytes
Di Java 10+ pengulangan karakter untuk dicetak sekarang juga dapat dilakukan dalam 22 byte:
for(var c:s.split("")) // 22 bytes
Item acak dari 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
Periksa apakah sebuah String berisi spasi awal / akhir
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
Mengapa ini bekerja, ketika !=
di Strings adalah untuk memeriksa referensi alih-alih nilai di Jawa? Karena String#trim
akan mengembalikan " Salinan string ini dengan spasi putih awal dan akhir dihapus, atau string ini jika tidak memiliki spasi putih awal atau akhir . " Saya telah menggunakan ini, setelah seseorang menyarankan ini kepada saya, dalam jawaban saya ini .
Palindrome:
Untuk memeriksa apakah suatu String adalah palindrome (dengan mengingat panjang Strings yang genap dan ganjil), ini adalah yang terpendek ( .contains
bekerja di sini karena kita tahu baik String itu sendiri maupun bentuknya yang dibalik memiliki panjang yang sama):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)
alih-alih .equals(...+"")
terima kasih atas komentar @assylias di sini .
Entah 0, atau keduanya 0?
Saya pikir sebagian besar sudah tahu yang ini: jika Anda ingin memeriksa apakah salah a
atau b
nol, gandakan untuk menyimpan byte:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
Dan jika Anda ingin memeriksa apakah keduanya a
dan b
nol, Anda bisa menggunakan bitwise-OR, atau menambahkannya bersama jika keduanya selalu positif:
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)
Even = 1, odd = -1; atau sebaliknya
// 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
Alasan saya menambahkan ini setelah melihat k+(k%2<1?1:-1)
di jawaban ini :
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
Loop n
kali dalam Program Lengkap
Jika kita memiliki tantangan di mana program lengkap wajib, dan kita perlu mengulang sejumlah waktu tertentu, kita dapat melakukan hal berikut:
// 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
Hal yang sama berlaku ketika kita harus mengambil rentang ini sebagai input:
interface M{static void main(String[]a){for(int n=new Byte(a[0]);n-->0;)/*do something*/}} // 90 bytes
interface M{static void main(String[]a){for(M m:new M[new Byte(a[0])])/*do something*/}} // 88 bytes
Kredit ke @JackAmmo dalam komentar ini .
try-akhirnya alih-alih try-catch (Exception e) saat kembali, dan kapan menggunakannya
Jika Anda tidak dapat menggunakan throws Exception
tetapi harus catch
dan melakukan sesuatu dengannya sebelum kembali, Anda dapat menggunakan finally
:
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Adapun contoh kapan harus menggunakan try-catch
, saya bisa merujuk ke jawaban saya ini (kredit untuk golf tidak langsung masuk ke @KamilDrakari ). Dalam tantangan ini kita harus mengulang secara diagonal pada matriks NxM, jadi kita harus menentukan apakah jumlah kolom atau jumlah baris adalah yang terendah sebagai maksimum kita dalam for-loop (yang cukup mahal dalam hal byte:) i<Math.min(a.length,a[0].length)
. Jadi, hanya menangkap ArrayIndexOutOfBoundsException
penggunaan catch-finally
lebih pendek dari pemeriksaan ini, dan dengan demikian menghemat byte:
int[] a = ...;
int r=0,i=0;for(;i<Math.min(a.length,a[0].length);)r=...i++...;return r; // 66 bytes
int r=0,i=0;try{for(;;)r=...i++...;}finally{return r;} // 48 bytes
CATATAN: Ini hanya berhasil karena return r;
pada akhirnya. Saya disarankan untuk memodifikasi sel pertama, seperti yang dilakukan @KamilDrakari dalam jawaban C # untuk menyimpan byte. Namun, di Jawa ini berarti saya harus mengubahnya ke m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}
(73 byte), sebenarnya meningkatkan jumlah byte bukannya menurun jika saya bisa menggunakan finally
.
Math.pow (2, n)
Saat Anda menginginkan kekuatan 2, pendekatan sedikit lebih bijaksana:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
Menggabungkan pemeriksaan bit-bijaksana dan logis alih-alih menggunakan tanda kurung
Saya pikir ini sudah terkenal sekarang &
dan |
dapat digunakan sebagai pengganti &&
dan ||
dalam Java (boolean) pemeriksaan logis. Dalam beberapa kasus, Anda tetap ingin menggunakan &&
alih-alih &
mencegah kesalahan, misalnya index >= 0 && array[index].doSomething
. Jika &&
akan diubah ke &
sini, ia masih akan mengevaluasi bagian di mana ia menggunakan indeks dalam array, menyebabkan ArrayIndexOutOfBoundsException
, maka penggunaan &&
dalam kasus ini bukan &
.
Sejauh ini dasar-dasar &&
/ ||
vs &
/ |
di Jawa.
Saat Anda ingin memeriksa (A or B) and C
, yang terpendek mungkin menggunakan operator bit-bijaksana seperti ini:
(A|B)&C // 7 bytes
Namun, karena operator bit-wise memiliki prioritas operator atas pemeriksaan logis, Anda dapat menggabungkan keduanya untuk menyimpan byte di sini:
A|B&&C // 6 bytes
Gunakan n+=...-n
sebagai ganti(long)...
Ketika Anda memiliki panjang masuk dan keluaran dalam lambda, misalnya saat menggunakan Math.pow
, Anda dapat menyimpan byte dengan menggunakan n+=...-n
alih-alih (long)...
.
Sebagai contoh:
n->(long)Math.pow(10,n) // 23 bytes
n->n+=Math.pow(10,n)-n // 22 bytes
Ini menyimpan satu byte dalam jawaban saya ini , dan bahkan dua byte dengan menggabungkan -n-1
ke +~n
dalam jawaban saya ini .
package
bisa dilewati.