Деякі невеликі поради щодо гольфу з кодом
Ці поради були трохи замалі для розділених відповідей, тому я буду використовувати цю відповідь для дуже маленьких порад щодо кодового гольфу, які я знайшов або придумав, і в інших порадах поки не згадується:
Видалення останнього символу рядка:
// 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.nioAPI, а також канонічне ім'я, що використовується в API java.ioта java.langAPI. Ось повний список усіх підтримуваних кодувань на Java. Тому завжди використовуйте найкоротший з двох; другий зазвичай коротший (як UTF-8vs utf8, Windows-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)-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так .tt.
Іноді ви можете додати кілька BigIntegers, щоб створити інший для збереження байтів. Тож скажімо, ви хочете 1,10,12чомусь мати BigIntegers :
// 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
Перекидання символів може бути корисним під час друку або додавання їх до рядка або чогось подібного.
Однак, якщо ви використовуєте тільки символи для деяких розрахунків юнікода-номер, ви можете замінити 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повернеться « Копія цього рядка з передньої і задньої прогалини видаляються, або це рядок , якщо вона не має передньої або задньої білого простору . » Я використав це, після того, як хто - то запропонував мені це, в цьому моя відповідь .
Паліндром:
Щоб перевірити, чи струна є паліндром (маючи на увазі і парні, і непарні довжини струн), це найкоротше ( .containsпрацює тут, тому що ми знаємо, що і сама струна, і її зворотна форма мають однакову довжину):
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нулі, ви можете використовувати побітові АБО або додати їх разом, якщо вони завжди позитивні:
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-нарешті замість try-catch (Виняток e) при поверненні та коли його використовувати
Якщо ви не можете використовувати, throws Exceptionале потрібно catchщось робити з цим перед поверненням, ви можете скористатися ним finally:
try{...}catch(Exception e){return ...;} // 33 bytes
try{...}finally{return ...;} // 22 bytes
Що стосується прикладу, коли потрібно використовувати 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 байти), фактично збільшуючи кількість байтів, а не зменшуючи, якщо я міг би використовувати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, може здатися, що найкоротші можуть використовувати такі розрядні оператори:
(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
Це врятувало байти в цій відповіді шахти , і навіть два байта, комбінуючи -n-1в +~nв цій відповіді шахти .
packageможна пропустити.