Bazı küçük kod golf ipuçları
Bu ipuçları, ayrılan yanıtlar için biraz fazla küçük olduğundan, bu yanıtı bulduğum veya bulduğum ve diğer ipuçlarında henüz belirtilmeyen çok küçük kodlama ipuçları için kullanacağım:
Bir Dize'nin son karakterini kaldırma:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
Bazı durumlarda, son karakterin ne olduğunu önceden biliyorsunuz ve bu karakterin de yalnızca bir kez String içerisinde gerçekleştiğini biliyorsunuz. Bu durumda .split
onun yerine kullanabilirsiniz :
// As example: "100%" to "100"
s.split("%")[0] // 15 bytes
Kodlama kısayolları:
// 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
Tüm kodlamaları kullanılan bir kurallı isme sahip java.nio
API yanı sıra kullanılan kurallı ad java.io
ve java.lang
API'ler. İşte Java'da desteklenen tüm kodlamaların tam listesi. Bu yüzden daima ikisinin en kısa olanını kullanın; ikincisi genellikle daha kısadır ( UTF-8
vs utf8
, Windows-1252
vs vs Cp1252
gibi), ancak her zaman ( UTF-16BE
vs UnicodeBigUnmarked
) değil.
Rastgele boolean:
// 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
Asal sayılar:
Asal sayıları denetlemenin veya tüm asal sayıları almanın birçok farklı yolu vardır, ancak @ SaraJ'ın buradaki cevabı en kısa yoldur . İşte referans olarak kopyala-yapıştır:
// 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*/;}}
NOT: Genellikle, nasıl kullanmak istediğinize bağlı olarak mevcut diğer döngülerle birleştirebilirsiniz, böylece ayrı bir yönteme ihtiyaç duymazsınız. Bu , örneğin bu cevapta çok fazla bayt kurtardı .
Math.floor / Math.ceil yerine tamsayı kısaltması:
Eğer kullanıyorsanız pozitif çiftlerde / yüzen ve istediğiniz floor
onlardan, kullanmayan Math.floor
ancak kullanmak (int)
(Java tamsayılar üzerinde keser beri) yerine -Cast:
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
Aynı numara, yerine yapmak istediğiniz negatif çiftlere / floatlara da uygulanabilir ceil
:
double d = -54.99;
int n=(int)Math.ceil(d); // 24 bytes
int m=(int)d; // 13 bytes
// Outputs -54 for both
Parantezden kurtulmak &1
yerine kullanın %2
:
Çünkü Operatör Önceliği ait &
gibi varsayılan aritmetik operatörler daha düşüktür */+-
ve %
, bazı durumlarda parantez kurtulmuş oluruz.
// So instead of this:
(i+j)%2 // 7 bytes
// Use this:
i+j&1 // 5 bytes
Bunun gerçekten boolean çeklerde yardımcı olmadığına dikkat edin, çünkü o zaman hala paranteze ihtiyacınız olacak, biraz hareket ettirildiler:
(i+j)%2<1 // 9 bytes
(i+j&1)<1 // 9 bytes
BigIntegers ve statik yöntem çağrıları için değişkenler oluşturma:
BigIntegers kullanırken, yalnızca bir kez oluşturun, ardından tekrar kullanabilirsiniz. Bildiğiniz gibi, BigInteger ZERO
, ONE
ve için statik alanlar içeriyor TEN
. Yani sadece bu üçünü kullandığınızda, bir ihtiyacınız yok import
ama java.Math.BigInteger
doğrudan kullanabilirsiniz .
// 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
NOT: kullanmak zorunda =null
böylece t
kullanmak için başlatılır t.
.
Bazen, baytları kurtarmak üzere başka bir tane oluşturmak için birden fazla BigInteger ekleyebilirsiniz. Diyelim ki 1,10,12
bir sebepten dolayı BigIntegers'a sahip olmak istediğinizi varsayalım :
// 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
Yorumlarda doğru bir şekilde belirtildiği gibi, BigInteger t=null;
statik yöntem çağrıları için verilen numara başka sınıflarla da kullanılabilir.
Örneğin, 2011'den itibaren bu cevap golf oynayabilir:
// 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()
onun yerine toCharArray()
Bir String karakterleri üzerinde döngü oluşturmak istediğinizde, genellikle şunu yaparsınız:
for(char c:s.toCharArray()) // 27 bytes
// or this:
for(String c:s.split("")) // 25 bytes
Karakterler üzerinde gezinmek, yazdırırken veya bunları bir Dizeye eklerken veya benzer bir şeyde kullanışlıdır.
Bununla birlikte, eğer karakterleri sadece bazı unicode-sayı hesaplamaları için kullanırsanız, char
ile değiştirebilir ve int
AND toCharArray()
ile değiştirebilirsiniz getBytes()
:
for(int c:s.getBytes()) // 23 bytes
Veya Java 8+ sürümünde daha da kısa:
s.chars().forEach(c->...) // 22 bytes
Java 10 + 'da yazdırılacak karakterin üzerine gelinmesi artık 22 byte de yapılabilir:
for(var c:s.split("")) // 22 bytes
A'dan itibaren rastgele öğe 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
Bir Dize'nin baştaki / sondaki boşlukları olup olmadığını kontrol edin
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
Neden !=
dize açıkken Java'daki değer yerine referans olup olmadığına bakılıyor? Çünkü String#trim
" Öndeki ve izleyen beyaz boşluk kaldırılmış olan bu dizenin bir kopyası ya da baştaki veya izleyen beyaz boşluk yoksa bu dizenin bir kopyası " döndürecektir . Bu cevabı birileri bana önerdikten sonra kullandım .
palindrom:
Bir String'in bir palindrom olup olmadığını kontrol etmek için (Dizelerin hem düz hem de tuhaf uzunluklarını göz önünde bulundurarak), en kısa olan budur ( .contains
burada çalışır, çünkü hem Dizenin kendisinin hem de ters formunun eşit uzunlukta olduğunu biliriz):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)
@assylias 'ın buradaki yorumuna.equals(...+"")
teşekkür etmek yerine .
Ya 0, ya da her ikisi de 0?
Ben çoğu zaten düşünüyorum bunu biliyorum: Ya olmadığını kontrol etmek istiyorsanız a
veya b
sıfırdır, bayt kaydetmek yerine çarpma:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
Ve hem olmadığını kontrol etmek istiyorsanız a
ve b
sıfır, bir cinsindendir ya da kullanabilir, ya da her zaman pozitif ise birbirine ekleyin:
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)
Çift = 1, tek = -1; ya da tam tersi
// 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
Bunu eklemek nedeni gördükten sonra oldu k+(k%2<1?1:-1)
yılında bu cevap :
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
Tam Programda döngü süreleri
Tam bir programın zorunlu olduğu bir sorunla karşılaşırsak ve belirli bir süreyi tekrarlamamız gerekiyorsa, aşağıdakileri yapabiliriz:
// 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
Aynısı bu aralığı girdi olarak almamız gerektiğinde de geçerlidir:
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
Kredi için @JackAmmo bu yorumda .
dönerken ve ne zaman kullanılacağına try-catch yerine (istisna e) try-finally
Bir kullanamazsınız throws Exception
ama catch
geri dönmeden önce onunla bir şeyler yapmak zorundaysanız, finally
onun yerine kullanabilirsiniz :
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Ne zaman ne zaman kullanılacağına dair bir örnek olarak try-catch
, benim bu cevabına başvurabilirim (dolaylı golfün kredisi @KamilDrakari'ye gider ). Bu mücadelede NxM matrisinin üzerinden çapraz olarak döngü yapmalıyız, bu yüzden sütunların veya satırların miktarının for-loop'ta maksimum değerimizden daha düşük olup olmadığını belirlememiz gerekir (bayt cinsinden oldukça pahalı i<Math.min(a.length,a[0].length)
) :. Yani, sadece alıcı ArrayIndexOutOfBoundsException
kullanarak catch-finally
bu çeki kısadır ve böylece bayt kaydeder:
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
Not: Bu sadece return r;
sonunda sonuçta çalıştı . @KamilDrakari'nin baytları kurtarmak için C # cevabında yaptığı gibi ilk hücreyi değiştirmem önerildi . Ancak, Java’da bunu değiştirmem gerekecek m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}
(73 bayt), eğer kullansaydım azalan yerine bayt sayısını arttıracağım finally
.
Math.pow (2, n)
2 güç istediğinizde, biraz akıllıca bir yaklaşım çok daha kısadır:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
Parantez kullanmak yerine bit ve mantıksal kontrollerin birleştirilmesi
Ben o artık iyi bilinen düşünüyorum &
ve |
yerine kullanılabilecek &&
ve ||
Java (boolean) mantıksal kontrollerde. Bazı durumlarda yine de hataları önlemek için kullanmak &&
yerine yine de kullanmak &
istersiniz index >= 0 && array[index].doSomething
. Eğer burada &&
değiştirilirse &
, dizideki dizini kullandığı kısmı değerlendirecek ve bu durumda bunun yerine bir ArrayIndexOutOfBoundsException
kullanımına neden &&
olacaktır &
.
Şimdiye kadar &&
/ ||
vs &
/ |
in Java temelleri .
Kontrol etmek istediğinizde (A or B) and C
, en kestirme işlem böyle bit-operatörleri kullanıyor gibi görünebilir:
(A|B)&C // 7 bytes
Ancak, bit bilge operatörleri , mantıksal kontroller üzerinde operatör önceliğine sahip olduğundan, burada bir bayt kaydetmek için her ikisini de birleştirebilirsiniz:
A|B&&C // 6 bytes
Yerine n+=...-n
kullanın(long)...
Bir lambdada hem içinde hem de çıktıda uzun bir süreye sahip olduğunuzda, örneğin kullanırken Math.pow
, n+=...-n
yerine bir bayt kaydedebilirsiniz (long)...
.
Örneğin:
n->(long)Math.pow(10,n) // 23 bytes
n->n+=Math.pow(10,n)-n // 22 bytes
Bu bir byte kaydedilen benim bu cevap ve birleştirerek daha iki bayt -n-1
için +~n
de benim bu cevap .
package
atlanabilir.