เคล็ดลับการตีกอล์ฟเล็ก ๆ
เคล็ดลับเหล่านี้มีขนาดเล็กเกินไปสำหรับคำตอบที่แยกดังนั้นฉันจะใช้คำตอบนี้สำหรับเคล็ดลับ codegolfing ขนาดเล็กมากที่ฉันพบหรือเกิดขึ้นและยังไม่ได้กล่าวถึงในเคล็ดลับอื่น ๆ :
การลบอักขระตัวสุดท้ายของสตริง:
// I used to do something like this:
s.substring(0,s.length()-1) // 27 bytes
// But this is shorter:
s.replaceAll(".$","") // 21 bytes
ในบางกรณีคุณรู้ว่าตัวอักษรตัวสุดท้ายคืออะไรล่วงหน้าและคุณยังรู้ว่าตัวละครตัวนี้เกิดขึ้นเพียงครั้งเดียวในสตริง ในกรณีนั้นคุณสามารถใช้.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.nio
API รวมถึงชื่อมาตรฐานที่ใช้ในjava.io
และjava.lang
API นี่คือรายการทั้งหมดของการเข้ารหัสที่รองรับใน Java ดังนั้นควรใช้เวลาที่สั้นที่สุดของทั้งสอง ที่สองมักจะสั้นกว่า (เช่นUTF-8
vs utf8
, Windows-1252
vs Cp1252
และอื่น ๆ ) แต่ไม่เสมอไป ( UTF-16BE
vs 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)
-cast แทน (เนื่องจาก Java ถูกตัดทอนด้วยจำนวนเต็ม):
double d = 54.99;
int n=(int)Math.floor(d); // 25 bytes
int m=(int)d; // 13 bytes
// Outputs 54 for both
เคล็ดลับเดียวกันนี้สามารถนำไปใช้กับการลบ / การลอยคู่ที่คุณต้องการ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
BigIntegers และการสร้างตัวแปรสำหรับการเรียกเมธอดแบบสแตติก:
เมื่อใช้ BigIntegers ให้สร้างเพียงครั้งเดียวซึ่งคุณสามารถนำกลับมาใช้ใหม่ได้ ในขณะที่คุณอาจทราบ BigInteger ประกอบด้วยเขตข้อมูลแบบคงที่สำหรับZERO
, และONE
TEN
ดังนั้นเมื่อคุณใช้ทั้งสามอย่างนี้คุณไม่จำเป็นต้องมี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.
บางครั้งคุณสามารถเพิ่ม BigIntegers หลายรายการเพื่อสร้างรายการอื่นเพื่อบันทึกไบต์ ดังนั้นสมมติว่าคุณต้องการมี BigIntegers 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 คุณสามารถแทนที่char
ด้วยint
และคุณสามารถแทนที่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
จะกลับมา " สำเนาของสายนี้ที่มีชั้นนำและลากพื้นที่สีขาวลบหรือสายนี้ถ้ามันไม่เคยมีใครนำหน้าหรือต่อท้ายพื้นที่สีขาว . " ผมเคยใช้นี้หลังจากที่มีคนแนะนำนี้กับผมในคำตอบของฉันนี้
ประโยค:
ในการตรวจสอบว่า String เป็น palindrome หรือไม่ (คำนึงถึงความยาวของ Strings ทั้งคู่และคี่) นี่เป็นระยะสั้นที่สุด ( .contains
ทำงานที่นี่เพราะเรารู้ว่าทั้ง String เองและรูปแบบที่ตรงกันข้ามนั้นมีความยาวเท่ากัน):
String s=...;
s.contains(new StringBuffer(s).reverse()) // 41 bytes
.contains(...)
แทนการ.equals(...+"")
ขอบคุณที่@assyliasความคิดเห็นของที่นี่
เป็น 0 หรือทั้งคู่เป็น 0?
ฉันคิดว่าส่วนใหญ่รู้จักอันนี้แล้ว: หากคุณต้องการตรวจสอบว่ามีค่าa
หรือb
เป็นศูนย์ให้คูณเพื่อบันทึกเป็นไบต์:
a==0|b==0 // 9 bytes
a*b==0 // 6 bytes
และถ้าคุณต้องการตรวจสอบว่าทั้งสองa
และb
เป็นศูนย์คุณสามารถใช้บิต - 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ในความคิดเห็นนี้
ลองในที่สุดแทนที่จะลองจับ (ข้อยกเว้น e) เมื่อกลับมาและเมื่อจะใช้
หากคุณไม่สามารถใช้ a throws Exception
ได้ แต่ต้องcatch
ทำบางสิ่งบางอย่างด้วยมันก่อนส่งคืนคุณสามารถใช้finally
แทน:
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
สำหรับตัวอย่างของการใช้ a try-catch
ฉันสามารถอ้างถึงคำตอบของฉัน (เครดิตสำหรับการเล่นกอล์ฟทางอ้อมไปที่@KamilDrakari ) ในความท้าทายนี้เราต้องห่วงแนวทแยงมุมกว่าเมทริกซ์ NxM ดังนั้นเราจึงมีการตรวจสอบว่าจำนวนของคอลัมน์หรือจำนวนแถวที่เป็นที่ต่ำที่สุดเท่าที่สูงสุดของเราในสำหรับวง (ซึ่งเป็นราคาแพงมากในแง่ของไบต์: i<Math.min(a.length,a[0].length)
) ดังนั้นเพียงแค่การจับArrayIndexOutOfBoundsException
ใช้catch-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 bytes) finally
จริงเพิ่มขึ้นนับไบต์แทนการลดลงถ้าฉันจะได้ใช้
Math.pow (2, n)
เมื่อคุณต้องการพลัง 2 วิธีบิตที่ชาญฉลาดนั้นสั้นกว่ามาก:
(int)Math.pow(2,n) // 16 bytes
(1<<n) // 6 bytes
การรวมการตรวจสอบบิตที่ชาญฉลาดและตรรกะแทนที่จะใช้วงเล็บ
ฉันคิดว่าเป็นที่รู้จักกันดีในขณะนี้&
และ|
สามารถใช้แทน&&
และ||
ในการตรวจสอบตรรกะ Java (บูลีน) ในบางกรณีคุณยังคงต้องการที่จะใช้&&
แทน&
เพื่อป้องกันข้อผิดพลาด index >= 0 && array[index].doSomething
แต่เช่น หาก&&
จะมีการเปลี่ยนแปลงไป&
ที่นี่ก็จะยังคงประเมินส่วนหนึ่งที่จะใช้ดัชนีในอาร์เรย์ทำให้เกิดArrayIndexOutOfBoundsException
จึงใช้ในกรณีนี้แทน&&
&
จนถึงพื้นฐานของ&&
/ ||
vs &
/ |
ใน Java
เมื่อคุณต้องการตรวจสอบ(A or B) and C
สั้นที่สุดอาจใช้ตัวดำเนินการ bit-wise ดังนี้:
(A|B)&C // 7 bytes
อย่างไรก็ตามเนื่องจากตัวดำเนินการ bit-wise มีตัวดำเนินการที่สำคัญเหนือกว่าการตรวจสอบแบบลอจิคัลคุณสามารถรวมทั้งสองเพื่อบันทึกไบต์ที่นี่:
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
ที่บันทึกไว้นี้ไบต์ในคำตอบของฉันนี้และแม้กระทั่งไบต์ที่สองโดยการรวม-n-1
ไป+~n
ในคำตอบของฉันนี้
package
สามารถข้ามได้