Mẹo chơi gôn trong Java


86

Có bất kỳ phím tắt hữu ích nào có thể được sử dụng trong Java không?

Như được hiển thị bên dưới, importđã thêm ít nhất 17 ký tự vào một chương trình.

import java.io.*;

Tôi hiểu rằng giải pháp đơn giản sẽ là sử dụng ngôn ngữ khác, nhưng dường như đó là một thách thức thực sự để rút ngắn các chương trình Java.


Các mẹo nên dành riêng cho Java: nếu chúng có thể áp dụng cho hầu hết các ngôn ngữ giống như C, chúng sẽ thuộc danh sách mẹo chung hơn .


9
packagecó thể bỏ qua
st0le

Trong một câu trả lời, tôi không thể bỏ qua hàng nhập khẩu giả sử chúng ở đó sao?
Fabricio

1
@Fovenio Không trừ khi OP chỉ định như vậy.
nyuszika7h

32
Mẹo hay nhất về chơi golf Java: không sử dụng nó. ;)
kirbyfan64sos

4
"Tôi muốn chơi gôn trong java" chúc may mắn
sagiksp

Câu trả lời:


85
  • Sử dụng java gần đây nhất có thể. Java 8 cho phép bạn sử dụng các biểu thức lambda, vì vậy hãy sử dụng nó nếu bạn cần bất cứ thứ gì ngay cả như các đối tượng chức năng.

  • Xác định các chức năng rút ngắn cho những thứ bạn sử dụng nhiều. Chẳng hạn, bạn có hàng trăm cuộc gọi đến exampleClassInstance.doSomething(someParameter), xác định một chức năng mới void d(ParameterType p){exampleClassInstance.doSomething(p)}và sử dụng nó để lưu cho mình một số ký tự.

  • Nếu bạn đang sử dụng một tên lớp dài cụ thể nhiều lần, như

    MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory

    thay vì định nghĩa một lớp mới:

    class X extends MyEventHandlerProxyQueueExecutorServiceCollectionAccessManagerFactory{}

    Nếu bạn chỉ sử dụng một phương thức cụ thể của lớp đó (nhưng vẫn cần khởi tạo nó), bạn có thể định nghĩa một phiên bản rút gọn bên trong lớp mới cùng một lúc.

  • Sử dụng tham số loại chức năng để rút ngắn mọi thứ, nếu có thể, như thế này:

    <T>void p(T o){System.out.println(o);}
  • Sử dụng for(;;)thay vì while(true).

  • Không sử dụng sửa đổi truy cập trừ khi thực sự cần thiết.

  • Không sử dụng finalcho bất cứ điều gì.

  • Không bao giờ đặt một khối sau một forvòng lặp (nhưng vòng lặp foreach for(x:y)là khác nhau). Các câu lệnh bổ sung nên được đặt bên trong forchính câu lệnh, như thế for(int i=0;i<m;a(i),b(++i))c(i);.

  • Sử dụng phân công nội tuyến, tăng, khởi tạo. Sử dụng các lớp nội tuyến ẩn danh khi thích hợp. Sử dụng lambdas thay thế nếu có thể. Chức năng gọi yến. Một số chức năng được đảm bảo trả về đối tượng cha của chúng, những hàm này thực sự thậm chí có nghĩa là bị xích lại với nhau.

  • mainPhương pháp của bạn throws Exception, không bắt chúng.

  • Errorngắn hơn Exception. Nếu vì lý do nào đó bạn thực sự cần thrownhắn tin lên ngăn xếp, hãy sử dụng một Error, ngay cả khi đó là tình huống hoàn toàn bình thường.

  • Nếu một số điều kiện sẽ yêu cầu chấm dứt ngay lập tức, sử dụng int a=1/0;chứ không phải throw null;hoặc System.exit(0);. Trong thời gian chạy, điều này ném một ArithmeticException. Nếu bạn đã có một biến số trong mã của mình, hãy sử dụng nó để thay thế. (Nếu bạn đã có import static java.lang.System.*;, hãy đi với exit(0);.)

  • Thay vì triển khai các giao diện, như List<E>, mở rộng một lớp con ngay lập tức (hoặc không phải ngay lập tức, nếu có bất kỳ lợi thế nào để làm như vậy), lớp AbstractList<E>này cung cấp triển khai mặc định của hầu hết các phương thức và chỉ yêu cầu thực hiện một vài mảnh quan trọng

  • Viết mã của bạn ra bằng tay trước, với dòng mới, thụt lề và tên biến đầy đủ. Khi bạn có mã làm việc, sau đó bạn có thể rút ngắn tên, di chuyển khai báo xung quanh và thêm các phương thức phím tắt. Bằng cách viết nó ra lâu để bắt đầu, bạn cho mình nhiều cơ hội hơn để đơn giản hóa toàn bộ chương trình.

  • So sánh tối ưu hóa thay thế với một đoạn mã, bởi vì chiến lược tối ưu nhất có thể thay đổi đáng kể với những thay đổi rất nhỏ đối với mã. Ví dụ:

    • Nếu bạn chỉ có tối đa hai cuộc gọi đến Arrays.sort(a), cách hiệu quả nhất là gọi nó với tên đầy đủ java.util.Arrays.sort(a).
    • Với ba cuộc gọi trở lên, hiệu quả hơn là thay vào đó thêm một phương thức phím tắt void s(int[]a){java.util.Arrays.sort(a);}. Điều này vẫn nên sử dụng tên đủ điều kiện trong trường hợp này. (Nếu bạn cần nhiều hơn một lần quá tải, có lẽ bạn đang làm sai.)
    • Tuy nhiên, nếu mã của bạn cũng cần sao chép một mảng tại một số điểm (thường được thực hiện với một forvòng lặp ngắn trong việc chơi gôn, trong trường hợp không có phương thức thư viện dễ truy cập), bạn có thể tận dụng Arrays.copyOfđể thực hiện tác vụ. Khi có nhiều hơn một phương thức được sử dụng và có từ 3 cuộc gọi trở lên, thực hiện import static java.util.Arrays.*;là cách hiệu quả nhất để tham khảo các phương thức đó. Sau đó, chỉ khi bạn có nhiều hơn 8 cuộc gọi riêng biệt sortthì bạn mới nên sử dụng phương thức phím tắt cho nó và chỉ với 5 cuộc gọi trở lên là một phím tắt được bảo hành copyOf.

    Cách thực sự duy nhất để thực hiện phân tích như vậy trên mã là thực sự thực hiện các sửa đổi tiềm năng trên các bản sao của mã, và sau đó so sánh kết quả.

  • Tránh sử dụng someTypeValue.toString();phương pháp, thay vào đó chỉ là chắp thêm someTypeValue+"".

  • Nếu bạn cần cửa sổ, đừng sử dụng Swing, hãy sử dụng AWT (trừ khi bạn thực sự cần thứ gì đó từ Swing). So sánh import javax.swing.*;import java.awt.*;. Thêm vào đó, các thành phần trong Swing có một Jthêm vào phía trước tên của họ ( JFrame, JLabel, vv), nhưng thành phần trong AWT không ( Frame, Label, vv)


43

Sử dụng interfacethay vì class.

Trong java 8, các phương thức tĩnh đã được thêm vào giao diện. Trong các giao diện, tất cả các phương thức được công khai theo mặc định. hậu quả là

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

bây giờ có thể rút ngắn thành

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

mà rõ ràng là ngắn hơn.

Ví dụ: tôi đã sử dụng tính năng này trong Hello, World! thử thách.


8
Tôi không biết điều đó! +1, mẹo hay
HyperNeutrino 14/2/2016

Yay, ít nồi hơi!
Máy

3
Tôi phải không đồng ý một phần ( đồng thời, tôi đã đánh bại bạn trong thử thách "Xin chào, thế giới!", Sử dụng kỹ thuật đó).
Olivier Grégoire

37

Với varargs, bạn có thể "truyền" một tham số thành một mảng cùng loại:

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

thay vì

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

31

Với nhập tĩnh :

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

bạn có thể lưu một số bản tóm tắt sau, nhưng bạn cần nhiều lệnh để đạt được kết quả:

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

8
: O. Bạn có thể làm được việc này?! Và tất cả thời gian này tôi nghĩ rằng điều này là không thể Java!
Justin

12
bạn thậm chí có thể sử dụng import static java.lang.System.*.
Julian Kuhn

1
Tôi biết đây là một câu trả lời cũ, nhưng trong Java 10 bây giờ bạn có thể làm điều var o=System.out;đó chỉ cần sử dụng hai lần trước khi nó được đền đáp
Luke Stevens

@LukeStevens: Chà, có thể bạn tìm thấy một số cải tiến khác, có thể với Java10 và tạo thành một câu trả lời riêng xung quanh Java10?
người dùng không xác định

1
@LukeStevens Sẽ var o=System.out.printlnlàm việc?
MilkyWay90

25

Đối số mainkhông cần phải được gọi argsvà bạn có thể cắt một số khoảng trắng:

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

sẽ làm tốt thôi


1
Các câu trả lời có cần bao gồm chức năng chính nếu nó không nêu rõ để viết một chương trình đầy đủ không? Tôi đã sử dụng biểu thức lambda làm câu trả lời.
Makotosan

3
@Makotosan Không họ không; Lambdas thường là tốt.
daniero

21

Nếu bạn phải sử dụng các biểu thức boolean truehoặc false, thay thế chúng bằng 1>01<0tương ứng.

Ví dụ:

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

Ví dụ tìm kiếm tuyến tính này có thể được giảm xuống

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

11
Nếu bạn sẽ cần rất nhiều true/false, chỉ cần thêm boolean t=1>0,f=1<0;. Sau đó, thay vì 1>0sử dụng tvà lưu hai ký tự mỗi lần sử dụng. 1>0Phương thức chi trả cho 10 lần sử dụng.
Geobits

24
@Geobits: boolean t=1>0,f=!t;- một char ngắn hơn!
bobbel

6
Ví dụ không thực sự tốt. Trong trường hợp này và nhiều (!) Khác bạn có thể tránh sử dụng true/ falsetrực tiếp bằng mọi cách: f|=a[i++]==42;tiết kiệm khá nhiều.
Ingo Bürk

@ IngoBürk Đúng. Khi tôi viết bài này, tôi chủ yếu nghĩ về các hàm thư viện sử dụng boolean, nhưng vì tôi không thể đưa ra bất kỳ ví dụ nào tại thời điểm viết (tôi thường không viết mã bằng Java) nên tôi chỉ viết một ví dụ đơn giản.
ace_HongKongInependence

1
@Geobits không quá quen thuộc với java nhưng bạn có thể chỉ cần xác định 1 và sử dụng t và! T (một lần nữa tôi không biết Java, chỉ tò mò)
Albert Renshaw

20

Nếu bạn sẽ sử dụng một số phương thức rất nhiều, hãy gán lớp thường trú của nó cho một biến. Ví dụ: gán System.outcho một biến:

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

Cũng cho Integer.parseInt():

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

Điều này gần như chắc chắn sẽ kích hoạt một cảnh báo ide về "truy cập phương thức tĩnh từ biến"


((Integer)1).parseInt("1")làm việc quá
Bạch tuộc ma thuật Urn

5
@carusocomputing new Integer("1")thậm chí còn ngắn hơn. Nhưng ý nghĩa của Justin với câu trả lời của anh ấy là bạn có thể sử dụng lại các biến bạn đã có cho các cuộc gọi tĩnh. Như tôi giải thích ở dưới cùng của câu trả lời này.
Kevin Cruijssen

19

Thay vì sử dụng import static java.lang.System.*kỹ thuật để lưu vào các println()câu lệnh, tôi đã thấy rằng việc xác định phương thức sau sẽ hiệu quả hơn trong việc lưu các ký tự:

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

Điều này là bởi vì nó có thể được gọi p(myString)thay vì out.println(myString)có phần hoàn trả nhân vật nhanh hơn và kịch tính hơn nhiều.


19

Điều này có vẻ rõ ràng, nhưng có các tùy chọn ngắn hơn cho một số Mathchức năng:

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

Nếu bạn cần Integer.MAX_VALUE(2147483647), hãy sử dụng -1>>>1. Integer.MIN_VALUE(-2147483648) được viết tốt hơn 1<<31.


14

Nếu bạn cần lấy một số từ một đối số (hoặc bất kỳ chuỗi nào khác), thông thường bạn sẽ thấy một số thứ như:

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

Nhiều lần, bạn không cần một Integer. Rất nhiều thách thức không sử dụng số lượng lớn. Vì ShortBytesẽ bỏ cả hộp đến một int, valueOf()thay vào đó hãy sử dụng một vài byte thích hợp hơn .

Tuy nhiên, hãy giữ biến thực của bạn là một biếnint vì nó ngắn hơn cả hai byteshort:

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

Nếu bạn cần làm điều này cho nhiều số, bạn có thể kết hợp với phương pháp này :

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

9
int n=new Byte(a[0]);là ba ngắn hơn. Nếu số lượng có thể lớn hơn, hãy sử dụng long n=new Long(a[0]), nó vẫn tốt hơn so với ints trong hầu hết các trường hợp.
Ypnypn

14

Đừng sử dụng public class. Phương thức chính cần được công khai, nhưng lớp của nó thì không. Mã này hoạt động:

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

Bạn có thể chạy java Sngay cả khi class Skhông phải là một lớp học công cộng. ( Cập nhật: Tôi đã sử dụng Java 7 khi tôi viết mẹo này. Trong Java 8, phương thức chính của bạn phải ở trong một giao diện . Trong Java 5 hoặc 6, phương thức chính của bạn phải ở dạng enum .)

Rất nhiều lập trình viên Java không biết điều này! Khoảng một nửa câu trả lời cho câu hỏi Stack Overflow về main trong lớp ngoài công khai tuyên bố sai rằng phương thức chính phải nằm trong lớp công khai. Bây giờ bạn biết rõ hơn. Xóa publictrong public classvà lưu 7 ký tự.


1
Trừ khi bạn đang nhắm mục tiêu Java trước 1.8, cấu trúc interface s{static void main(String[]...sẽ ngắn hơn. Nếu bạn phải có một tệp nguồn có thể biên dịch và phương thức chính. Bởi vì trong giao diện Java 1.8, tất cả các phương thức đều công khai nên bạn có thể bỏ qua công cụ sửa đổi trên (các) phương thức.
Douglas Held

Gần đây tôi không sử dụng Java, vì vậy câu trả lời của tôi đã trở nên lỗi thời. Tôi quên rằng các giao diện có thể có các phương thức trong Java 8.
kernigh

Tôi đã không học nó từ lập trình; Tôi đã học được nó từ việc chơi golf :)
Douglas Held

14

Một số mẹo chơi gôn nhỏ

Các mẹo này hơi nhỏ đối với các câu trả lời riêng biệt, vì vậy tôi sẽ sử dụng câu trả lời này cho các mẹo mã hóa rất nhỏ mà tôi đã tìm thấy hoặc đưa ra và chưa được đề cập trong các mẹo khác:

Xóa ký tự cuối cùng của Chuỗi:

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

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

Trong một số trường hợp, bạn biết ký tự cuối cùng là gì trước đó và bạn cũng biết ký tự này chỉ xảy ra một lần trong Chuỗi. Trong trường hợp đó, bạn có thể sử dụng .splitthay thế:

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

Phím tắt mã hóa:

// 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ất cả các mã hóa đều có tên chính tắc được sử dụng trong java.nioAPI, cũng như tên chính tắc được sử dụng trong java.iojava.langAPI. Dưới đây là danh sách đầy đủ tất cả các mã hóa được hỗ trợ trong Java. Vì vậy, luôn luôn sử dụng ngắn nhất trong hai; cái thứ hai thường ngắn hơn (như UTF-8vs utf8, Windows-1252vs Cp1252, v.v.), nhưng không phải lúc nào cũng ( UTF-16BEvs UnicodeBigUnmarked).

Boolean ngẫu nhiên:

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

Số nguyên tố:

Có rất nhiều cách khác nhau để kiểm tra các số nguyên tố hoặc nhận tất cả các số nguyên tố, nhưng câu trả lời của @ SaraJ ở đây là ngắn nhất. Đây là một bản sao-dán làm tài liệu tham khảo:

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

LƯU Ý: Thông thường bạn có thể hợp nhất nó với các vòng lặp hiện có khác tùy thuộc vào cách bạn muốn sử dụng nó, vì vậy bạn sẽ không cần một phương pháp riêng. Điều này đã lưu rất nhiều byte trong câu trả lời này chẳng hạn.

Cắt bớt số nguyên thay vì Math.floor / Math.ceil:

Nếu bạn đang sử dụng nhân đôi / số dương và bạn muốn floorsử dụng chúng, đừng sử dụng Math.floor(int)thay vào đó hãy sử dụng một -cast (vì Java cắt ngắn trên các số nguyên):

double d = 54.99;

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

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

// Outputs 54 for both

Thay vào đó, mẹo tương tự có thể được áp dụng cho các lần tăng / giảm âm mà bạn muốn ceil:

double d = -54.99;

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

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

// Outputs -54 for both

Sử dụng &1thay vì %2để thoát khỏi dấu ngoặc đơn:

Bởi vì Phương thức ưu tiên của &là thấp hơn so với các nhà khai thác số học mặc định như */+-%, bạn có thể thoát khỏi dấu ngoặc đơn trong một số trường hợp.

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

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

Lưu ý rằng điều này không thực sự hữu ích trong kiểm tra boolean, bởi vì sau đó bạn vẫn cần dấu ngoặc đơn, chúng chỉ được di chuyển một chút:

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

BigIntegers và tạo các biến cho các cuộc gọi phương thức tĩnh:

Khi sử dụng BigIntegers, chỉ tạo một lần mà sau đó bạn có thể sử dụng lại. Như bạn đã biết, BigInteger chứa các lĩnh vực tĩnh cho ZERO, ONETEN. Vì vậy, khi bạn chỉ sử dụng ba thứ đó, bạn không cần importnhưng có thể sử dụng java.Math.BigIntegertrực tiếp.

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

LƯU Ý: Bạn phải sử dụng =nullđể tđược khởi tạo để sử dụng t..

Đôi khi bạn có thể thêm nhiều BigIntegers để tạo một cái khác để lưu byte. Vì vậy, hãy nói rằng bạn muốn có BigIntegers 1,10,12vì một số lý do:

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

Như đã chỉ ra một cách chính xác trong các bình luận, mẹo với BigInteger t=null;các cuộc gọi phương thức tĩnh cũng có thể được sử dụng với các lớp khác.
Ví dụ, câu trả lời từ năm 2011 này có thể được đánh gôn:

// 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() thay vì toCharArray()

Khi bạn muốn lặp qua các ký tự của Chuỗi, bạn sẽ thường làm điều này:

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

Vòng lặp trên các ký tự có thể hữu ích khi in chúng hoặc nối chúng vào Chuỗi hoặc một cái gì đó tương tự.

Tuy nhiên, nếu bạn chỉ sử dụng ký tự cho một số phép tính số unicode, bạn có thể thay thế charbằng int, VÀ bạn có thể thay thế toCharArray()bằng getBytes():

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

Hoặc thậm chí ngắn hơn trong Java 8+:

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

Trong Java 10+, việc lặp lại ký tự cần in giờ cũng có thể được thực hiện bằng 22 byte:

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

Mục ngẫu nhiên từ một 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

Kiểm tra xem Chuỗi có chứa khoảng trắng ở đầu / cuối không

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

Tại sao điều này hoạt động, khi !=trên Chuỗi là để kiểm tra tham chiếu thay vì giá trị trong Java? Bởi vì String#trimsẽ trả về " Một bản sao của chuỗi này với khoảng trắng ở đầu và cuối bị xóa hoặc chuỗi này nếu nó không có khoảng trắng ở đầu hoặc cuối . " Tôi đã sử dụng nó, sau khi ai đó gợi ý cho tôi, trong câu trả lời này của tôi .

Palindrom:

Để kiểm tra xem Chuỗi có phải là một palindrom hay không (lưu ý cả độ dài chẵn và lẻ của Chuỗi), đây là đoạn ngắn nhất ( .containshoạt động ở đây vì chúng ta biết cả chính Chuỗi và dạng đảo ngược của nó có độ dài bằng nhau):

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

.contains(...)thay vì .equals(...+"")cảm ơn bình luận của @assylias ở đây .

Hoặc là 0, hoặc cả hai đều là 0?

Tôi nghĩ rằng hầu hết đã biết điều này: nếu bạn muốn kiểm tra xem một trong hai ahoặc bbằng 0, thay vào đó hãy nhân lên để lưu byte:

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

Và nếu bạn muốn kiểm tra xem cả hai abbằng không, bạn có thể sử dụng bit-OR hoặc thêm chúng lại với nhau nếu chúng luôn dương:

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)

Chẵn = 1, lẻ = -1; hoặc ngược lại

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

Lý do tôi thêm điều này là sau khi thấy k+(k%2<1?1:-1)trong câu trả lời này :

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

nThời gian lặp trong chương trình đầy đủ

Nếu chúng tôi có một thách thức trong đó một chương trình đầy đủ là bắt buộc và chúng tôi cần lặp một số lần cụ thể, chúng tôi có thể làm như sau:

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

Điều tương tự cũng áp dụng khi chúng ta phải lấy phạm vi này làm đầu vào:

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

Tín dụng cho @JackAmmo trong bình luận này .

thử-cuối cùng thay vì thử bắt (Ngoại lệ e) khi quay lại và khi nào sử dụng nó

Nếu bạn không thể sử dụng throws Exceptionnhưng phải catchvà làm một cái gì đó với nó trước khi quay lại, bạn có thể sử dụng finallythay thế:

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

Ví dụ về thời điểm sử dụng a try-catch, tôi có thể tham khảo câu trả lời này của tôi (tín dụng cho môn đánh gôn gián tiếp được gửi tới @KamilDrakari ). Trong thử thách này, chúng tôi phải lặp theo đường chéo trên ma trận NxM, vì vậy chúng tôi phải xác định xem số lượng cột hoặc số lượng hàng có thấp nhất là mức tối đa của chúng tôi trong vòng lặp for (khá tốn kém về byte i<Math.min(a.length,a[0].length)). Vì vậy, chỉ cần nắm bắt việc ArrayIndexOutOfBoundsExceptionsử dụng catch-finallyngắn hơn kiểm tra này và do đó tiết kiệm 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

LƯU Ý: Điều này chỉ hoạt động vì return r;cuối cùng. Tôi đã được đề nghị sửa đổi ô đầu tiên, như @KamilDrakari đã làm trong câu trả lời C # của mình để lưu byte. Tuy nhiên, trong Java, điều này có nghĩa là tôi sẽ phải thay đổi nó thành m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 byte), thực sự tăng số byte thay vì giảm nếu tôi có thể sử dụng finally.

Math.pow (2, n)

Khi bạn muốn có sức mạnh bằng 2, cách tiếp cận khôn ngoan sẽ ngắn hơn nhiều:

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

Kết hợp kiểm tra bit-khôn ngoan và logic thay vì sử dụng dấu ngoặc đơn

Tôi nghĩ rằng bây giờ nó đã được biết đến &|có thể được sử dụng thay vì &&||trong kiểm tra logic (boolean) của Java. Trong một số trường hợp, bạn vẫn muốn sử dụng &&thay vì &để tránh lỗi, như thế index >= 0 && array[index].doSomething. Nếu &&thay đổi &ở đây, nó vẫn sẽ đánh giá phần mà nó sử dụng chỉ mục trong mảng, gây ra một ArrayIndexOutOfBoundsException, do đó việc sử dụng &&trong trường hợp này thay vì &.

Cho đến nay những điều cơ bản của &&/ ||vs &/ |trong Java.

Khi bạn muốn kiểm tra (A or B) and C, dường như ngắn nhất có thể sử dụng các toán tử bit khôn ngoan như thế này:

(A|B)&C    // 7 bytes

Tuy nhiên, vì các toán tử bit-bit có quyền ưu tiên toán tử so với các kiểm tra logic, bạn có thể kết hợp cả hai để lưu một byte ở đây:

A|B&&C     // 6 bytes

Sử dụng n+=...-nthay vì(long)...

Khi bạn có cả đầu vào và đầu ra trong lambda, ví dụ như khi sử dụng Math.pow, bạn có thể lưu một byte bằng cách sử dụng n+=...-nthay vì (long)....
Ví dụ:

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

Đây lưu một byte trong câu trả lời này của tôi , và thậm chí cả hai byte bằng cách kết hợp -n-1để +~ntrong câu trả lời này của tôi .


Tổng quát hơn cho điểm cuối cùng của bạn, bạn có thể truy cập / gọi các thành viên tĩnh từ ngữ cảnh không tĩnh, chẳng hạn như một thể hiện của đối tượng.
Chọc

1
Tôi không hiểu mẹo trần của bạn. Tại sao bạn muốn trần positive integers? Ngoài ra, tôi không chắc chắn nếu việc thực hiện trần nhà hoạt động .
Jonathan Frech

1
since Java automatically floors on integers; Tôi nghĩ thuật ngữ thích hợp là cắt ngắn , không phải sàn .
Jonathan Frech

1
Một chiến lược Palindrome khácString t="";for(int i=s.length();--i>=0;t+=s.charAt(i));return s.equals(t);
Roberto Graham

1
@RobertoGraham Tôi thực sự đã sao chép mã gốc của mình từ thử thách sai .. Chỉ cần s.equals(new StringBuffer(s).reverse()+"")là đủ.
Kevin Cruijssen

11

Để chơi golf không yêu cầu đầu vào, bạn có thể sử dụng các khối tĩnh và chạy tốt mà không cần bất kỳ phương thức chính nào, chỉ cần biên dịch nó với Java 6.

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

1
Bạn đã thử biên dịch và chạy nó? Khối này được chạy khi lớp được tải bởi trình nạp lớp. Nhưng trình nạp lớp sẽ không tải bất cứ thứ gì cho đến khi nó biết về một lớp với một phương thức chính.
Cruncher

@Cruncher Bạn có thể tự mình khắc phục điều đó bằng cách nói javatrên dòng lệnh / trong tệp kê khai sẽ tải lớp nào.
AJMansfield

6
@Cruncher, cái này hoạt động với Java 6. Java 7 đã thay đổi cách nó hoạt động.
Peter Taylor

1
Ném một ngoại lệ ở cuối nhưng nó hoạt động! Ngay cả trong Java 7
stommestack

2
@JopVernooij Nếu bạn không muốn có một ngoại lệ ném vào mặt mình, bạn có thể system.exit (), nhưng bạn sẽ lãng phí các nhân vật, không có thách thức golf nào yêu cầu bạn tránh ngoại lệ;)
Fabinout

11

Chúng ta đều biết về bitwise xor ( ^), nhưng nó cũng là một xor logic.

Vì vậy, (a||b)&&!(a&&b)đơn giản trở thành a^b.

Bây giờ chúng ta có thể sử dụng xor.

Ngoài ra , các toán tử |& cũng hoạt động , chỉ cần nhớ rằng ưu tiên toán tử thay đổi.


5
Miễn là bạn nhớ quyền ưu tiên, bạn có thể sử dụng &|cũng có thể. Nó có thể hữu ích nếu các điều kiện của bạn đã có trong ngoặc đơn hoặc nếu bạn đã làm việc với booleans.
Geobits

1
Nếu bạn cần một ưu tiên thấp hơn (nhiều), bạn có thể sử dụng !=thay vì ^cho xor và ==cho xnor
Cyoce

11

Bạn không phải sử dụng Character.toLowerCase(char c). Thay vì sử dụng (c|32). Thay vì Character.toUpperCase(char c)sử dụng (c&~32). Điều này chỉ hoạt động với các chữ cái ASCII.


c|~32sẽ có xu hướng dẫn đến -1 ... tốt hơn để sử dụng c-32.
frageum

5
@feersum Điều đó sẽ không hoạt động nếu bạn muốn viết hoa chữ thường viết hoa.
TheNumberOne

11

Chuyển đổi chuỗi thành số

Có nhiều cách để chuyển đổi Chuỗi thành giá trị số:

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 mới :

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

Vì vậy, để chơi golf mã, tốt nhất nên sử dụng hàm tạo khi chuyển đổi Chuỗi thành giá trị số.

Áp dụng tương tự cho Double; Float; và Byte.


Điều này không phải lúc nào cũng áp dụng khi bạn có thể sử dụng lại một đối tượng nguyên thủy đã có mặt như đối tượng.
Ví dụ: giả sử chúng ta có đoạn mã sau:

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

Bạn có thể sử dụng .decodethay cho hàm tạo ngắn hơn bằng cách sử dụng lại tham số làm đối tượng:

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

Đừng sử dụng Random!

Nói chung, nếu bạn cần số ngẫu nhiên, Randomlà một cách khủng khiếp để đi về nó *. Tốt hơn nhiều để sử dụng Math.random()thay thế. Để sử dụng Random, bạn cần làm điều này (giả sử chúng ta cần một int):

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

So sánh với:

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

và:

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

Phương thức đầu tiên lấy 41+15nký tự ( nlà số lượng cuộc gọi). Thứ hai là 25nnhân vật, và thứ ba là 43+7n.

Vì vậy, nếu bạn chỉ cần một hoặc hai lần, hãy sử dụng Math.random()phương thức nội tuyến . Đối với ba cuộc gọi trở lên, bạn sẽ lưu bằng cách sử dụng một chức năng. Hoặc là một tiết kiệm ký tự trên sử dụng đầu tiên trên Random.


Nếu bạn đã sử dụng Math.random()cho double, hãy nhớ rằng tại bốn công dụng, nó vẫn còn một khoản tiết kiệm để kéo nó ra thành:

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

Đối với 33 ký tự, bạn sẽ lưu 10 cho mỗi cuộc gọi đến r()


Cập nhật

Nếu bạn cần một số nguyên và muốn tiết kiệm khi truyền, đừng bỏ nó! Tự động chuyển Java nếu bạn thực hiện một thao tác thay vì gán. So sánh:

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

* Trừ khi bạn phải chọn PRNG để có kết quả dự đoán. Sau đó, tôi không thấy nhiều cách xung quanh nó.


2
Đừng quên về Random#nextGaussianmặc dù.
Justin

@Quincunx Đúng, làm toán để có được một bản phân phối bình thường tốt sẽ làm bạn mất bất kỳ khoản tiết kiệm nào bạn có. Tôi sẽ chỉ coi đó là ngoại lệ chứng minh quy tắc;)
Geobits

Lưu ý rằng (int)(Math.random()*9)có độ lệch modulo rất nhỏ, vì Math.random()trả về 2 53 giá trị có thể và 2 53 không phải là bội số của 9. Xác suất của mỗi số nằm trong 1/9 cộng hoặc trừ 5 / (9 * 2 ** 53), một lỗi rất nhỏ, nó gần như chính xác là 1/9.
hạt nhân

@kernigh Phải, tôi đã sử dụng 9như một ví dụ, nó có thể là bất cứ điều gì. Tôi tương đối chắc chắn rằng nextInt()(hoặc bất kỳ Randomphương thức nào khác ) cũng có một sai lệch nhỏ, chỉ do cách PRNG của Java hoạt động.
Geobits

1
Một cái gì đó liên quan khi bạn muốn một boolean ngẫu nhiên: thay vì new java.util.Random().nextBoolean()bạn có thể sử dụng Math.random()<.5.
Kevin Cruijssen

7

Tôi không biết liệu bạn có xem xét Java 'thuần túy' này không, nhưng Xử lý cho phép bạn tạo các chương trình với ít thiết lập ban đầu (hoàn thành tự động).

Đối với đầu ra giao diện điều khiển, bạn có thể có một cái gì đó đơn giản như:

println("hi"); //done

cho đầu ra đồ họa, một chút nữa:

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 Tài nguyên tuyệt vời! Tôi chắc chắn sẽ chơi xung quanh nó.
Cướp

Sẽ ổn chứ nếu tôi thêm câu trả lời của người khác vào câu hỏi này? Hay điều đó đánh bại mục đích của wiki cộng đồng?
Cướp

2
Nhân tiện, bạn thậm chí không phải gọi sizegì cả; nó sẽ mặc định là một hình vuông 100 x 100 pixel. Trong hầu hết các hệ điều hành, khung xung quanh nó sẽ lớn gấp đôi, với hình vuông ở giữa và phần còn lại của khu vực chứa đầy nội dung được lấy từ máy tính để bàn.
AJMansfield

1
Đối với đầu ra đồ họa, nếu bạn không cần hoạt hình, bạn có thể viết mọi thứ bên ngoài setup()draw()sử dụng "chế độ tĩnh". Bạn cũng có thể sử dụng màu lục giác 6 chữ số và trình thông dịch sẽ thay đổi chúng, đôi khi sẽ trả hết ( #FF8000< 255,128,0) và nếu bạn đang sử dụng thang độ xám chỉ cần một số cần được chỉ định ( 255< 255,255,255)
quat

7

Rút ngắn trở lại

Bạn có thể rút ngắn các câu lệnh trả về chuỗi bằng một byte bằng:

return "something";

đến

return"something";

Và, nếu bạn tình cờ bắt đầu tuyên bố trở lại của mình bằng dấu ngoặc đơn, bạn có thể làm điều tương tự với chúng:

return (1+taxRate)*value;

đến

return(1+taxRate)*value;

Tôi đoán trích dẫn được coi như ngoặc đơn? Tôi thực sự đã chọn cái này thông qua AppleScript, đủ vui, và nghĩ rằng nó có thể đáng được đề cập.


1
Áp dụng tương tự cho các dấu hiệu số, như return-n;thay vì return -n;hoặc return~n;thay vì return ~n;. Cũng như độc thân thay vì dấu ngoặc kép:return'A';
Kevin Cruijssen

1
Về cơ bản, hoạt động cho bất kỳ thứ gì không thể là một phần của mã định danh (nghĩa là không phải chữ cái và không chữ số).
Paŭlo Ebermann 17/2/18

7

Đừng ngại sử dụng ký hiệu khoa học

Nếu bạn đang xử lý gấp đôi, hoặc nổi, bạn có thể sử dụng ký hiệu khoa học cho các số. Vì vậy, thay vì viết, double a=1000bạn có thể thay đổi nó double a=1e3để tiết kiệm 1 byte.


7

Hãy thử sử dụng intthay vìboolean

Trong một số trường hợp, tôi thấy rằng việc trả về một giá trị số nguyên từ một phương thức thường trả về giá trị boolean, tương tự như những gì có thể được thực hiện trong các chương trình C.

Phải tắt bat intlà 4 byte ngắn hơn boolean. Mỗi lần bạn viết return 0thay vì return 1<0, bạn lưu thêm 2 byte và tương tự cho return 1 hơn return 1>0.

Điều đáng tiếc ở đây là mỗi lần bạn muốn sử dụng giá trị trả về trực tiếp dưới dạng boolean, nó có giá 2 byte ( if(p(n))v. if(p(n)>0)). Điều này có thể được tạo ra bằng cách sử dụng số học boolean. Đưa ra một kịch bản có sẵn, nơi bạn muốn viết

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

thay vào đó bạn có thể viết

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

để tiết kiệm 2 byte.


6
Tôi làm điều này khá thường xuyên khi chơi golf, nhưng hãy nhớ rằng sự đồng thuận chung là như vậy 01không cấu thành sai / đúng trong Java (và JLS cũng không xem xét chúng theo cách đó). Vì vậy, nếu golf đặc biệt yêu cầu sự thật / giả, bạn cần phải booleanize nó (và thật không may, làm cho nó trở thành một booleanchức năng, ném nhiều byte hơn vào nó).
Geobits

2
t[0]+=p(n):10?0;Điều này thậm chí còn hợp lệ?
dorukayhan

@dorukayhan không, nó có nghĩa là vậy t[0]+=p(n)?10:0;. (Tôi đã chỉnh sửa nó.)
Paŭlo Ebermann

6

Nếu bạn sử dụng enum thay vì lớp , bạn lưu một ký tự.

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

    }
}

Nhưng bạn phải giới thiệu ít nhất một ví dụ enum (F, G, H trong ví dụ này) phải tự trả tiền.


2
Có vẻ như bạn không cần bất kỳ trường hợp nào. Tôi đã làm enum M{;public static void main(String[]a){...}không có vấn đề.
Daniel

3
@Danny Nhưng sau đó nó không lưu bất kỳ ký tự nào. class M{có độ dài chính xác như enum M{;. Trong trường hợp đó, tôi sẽ đi với classvì nó đẹp hơn (IMO)
Justin

1
ít nhất là đối với tôi enum{làm việc mà không có ;sau này; IDE chỉ rên rỉ rằng có lỗi nhưng trình biên dịch chấp nhận nó
masterX244

@ masterX244 Trình biên dịch / phiên bản nào? Của tôi nổi cơn thịnh nộ và sẽ không làm điều đó.
Geobits

đã làm việc trên java 1.7 cho tôi (đã xuất hiện, ned để điều tra thêm nguyên nhân với bản cập nhật .8 nó đã ngừng hoạt động)
masterX244

5

Khi bạn có một phương thức sẽ trả về một booleanhoặc Boolean, tức là:

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

Bạn có thể thay đổi boolean/ Booleanreturn-type thành Objectđể lưu 1 byte:

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

Ngoài ra, như bạn có thể nhận thấy, bạn có thể sử dụng một <1kiểm tra thay vì ==0để lưu một byte. Mặc dù đó là một mẹo chơi gôn mã chung thay vì đặc thù Java.
Điều này chủ yếu được sử dụng khi số nguyên không thể âm, như kiểm tra độ dài:

a.length<1

thay vì

a.length==0

1
Mẹo hay! Bạn có thể muốn thêm một ví dụ khác trong phần "nếu nó không thể phủ định" để minh họa cho nó, vì c(-21)trả về truevới ví dụ hiện tại.
Geobits

Làm rõ. Ngoài ra, bạn không có ý c(-20)thay vì -21? -21 % 5 = 4-20 % 5 = 0.
Kevin Cruijssen

1
Không, ý tôi là vậy -21. -21 % 5 != 4trong Java, đó là quan điểm của tôi. Hàm chia hết cho năm hàm sẽ hoạt động chính xác nếu mô đun luôn trả về không âm, nhưng không. Xem đoạn ví dụ này .
Geobits

@Geobits Ah, cảm ơn vì ví dụ. Tôi gần như không bao giờ sử dụng số âm với %, vì vậy tôi đã quên Java trả lại phần còn lại thay vì mô đun, do đó có sự khác biệt ..
Kevin Cruijssen

5

Cách vẽ trong Java ...

Đây là tấm nồi hơi sơn GUI ngắn nhất có thể:

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

Chơi gôn với 111 byte:

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

5

Tránh StringBuilders

Việc thêm các công cụ vào Stringchiếm ít byte hơn nhiều.

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

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

Nếu bạn phải đảo ngược một chuỗi và in nó ngay lập tức, sử dụng một 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

Nếu bạn phải đảo ngược một chuỗi và sau đó làm một cái gì đó khác hơn là in nó, sử dụng formỗi vòng lặp.

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

3
Một vòng lặp foreach ngắn hơn so StringBuffervới chuỗi đảo ngược. String b="";for(char c:"Hello, World!".toCharArray()){b=c+b;}
Chọc

1
Bạn cũng nên xóa {}vòng lặp foreach đó nếu bạn sẽ sử dụng phương thức đó.
Geobits

1
Lưu 2 byte bằng cách sử dụng String s:"".split("")thay vì char c:"".toCharArray().
charlie

Nếu bạn java.util.stream.Streamđã nhập và nếu bạn cần xâu chuỗi một cuộc gọi khác đến kết quả (như B.chartAt(42)) hoặc nếu bạn chỉ cần chuyển kết quả cho một hàm (như f(B)), thì việc sử dụng for(:)là tương đương Stream.of("Hello, World!".split("")).reduce("",(a,b)->b+a).
charlie

Cả hai dòng trong ví dụ của bạn với for-every đều có thể được đánh gôn. Người đầu tiên có thể trở thành: String b=new StringBuffer("Hello, World!").reverse()+"";(được .toStringthay thế bằng +"") và dòng thứ hai của bạn có thể trở thành: String B="";for(String c:"Hello, World!".split(""))B=c+B;( charđến String.toCharArray()đến .split("")).
Kevin Cruijssen

5

Sử dụng Java 10 var

Nếu bạn xác định một biến duy nhất của một loại cụ thể, hãy sử dụng var.

Ví dụ

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

Không thể sử dụng trong bất kỳ ví dụ nào sau đây

var không thể được sử dụng trong nhiều ví dụ

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)

RE tại sao điều này không hoạt động với các tham chiếu phương thức, lưu ý rằng có các giao diện chức năng tiêu chuẩn chỉ cho một bộ chữ ký nhỏ (và các phương thức có thể đưa ra các ngoại lệ được kiểm tra).
Jakob


4

Trong hầu hết các trường hợp, chương trình của bạn sẽ là một luồng đơn, tức là nó sẽ chỉ có một luồng chạy. Bạn có thể khai thác thực tế này bằng cách returnlấy từ phương thức chính khi bạn phải thoát ngay lập tức.

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

So sánh nó với "đúng" kết thúc chương trình:

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

Hoặc chỉ vào null:

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

Hoặc chia cho 0:

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

4

Đôi khi, một câu lệnh for-loop có thể thay thế được. Hãy xem xét các mã sau đây:

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

Đây là một vòng lặp đơn giản là một giải pháp cho câu hỏi này .

Vì chúng tôi biết rằng isẽ không đủ lớn để gây ra lỗi StackOverflow, nên chúng tôi có thể thay thế vòng lặp for bằng đệ quy thay thế:

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

Chúng ta có thể mô phỏng một vòng lặp bằng cách sử dụng toán tử ternary trong câu lệnh return để gây ra đệ quy.

Việc giảm này khá cụ thể, nhưng tôi có thể tưởng tượng nhiều tình huống hơn sẽ có ích.


4

Sử dụng ...(varags) làm tham số

Trong một số trường hợp, việc sử dụng một varargs Java làm tham số thay vì lỏng lẻo là ngắn hơn.
Ví dụ:

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

Sẽ bị đánh gôn bởi hầu hết điều này:

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

Nhưng có thể được đánh một byte bổ sung cho điều này:

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

Lưu ý rằng cả ba số nguyên chỉ được truy cập một lần trong chính phương thức. Vì intnó khá ngắn nên chỉ có lợi nếu bạn sử dụng chúng mỗi lần một lần trong phương thức và có ba hoặc nhiều trong số chúng làm tham số.

Với các tham số dài hơn, điều này thường hữu ích hơn mặc dù. Ví dụ: đây là câu trả lời ban đầu của tôi cho thử thách này (tính toán các lần xuất hiện của ký tự đầu vào trong chuỗi đầu vào):

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

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

Và tôi đã được đề nghị đánh gôn nó:

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

Nhưng tôi đã kết thúc việc chơi golf bằng cách này ...:

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

LƯU Ý: Nếu câu hỏi / thách thức yêu cầu đầu vào linh hoạt, tất nhiên ...có thể rút ngắn thành câu hỏi []. Nếu câu hỏi / thách thức đặc biệt yêu cầu, giả sử, ba Stringđầu vào và không cho phép một String-array chứa ba giá trị, bạn có thể sử dụng String...thay vì String a,String b,String c.


2
Bạn không thể sử dụng String[]thay vì sử dụng varargs? (tiết kiệm thêm 1 byte)
Kritixi Lithos

@KritixiLithos Hmm .. điểm tốt. Nhưng điều đó chủ yếu phụ thuộc vào mức độ linh hoạt của đầu vào cho thử thách. Nếu bất kỳ định dạng đầu vào nào được cho phép, thì điều đó thực sự sẽ ngắn hơn. Tôi sẽ thêm điều này vào lời khuyên này, cảm ơn.
Kevin Cruijssen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.