Советы по игре в гольф на JavaScript

133

Какие общие советы у вас есть для игры в гольф на JavaScript? Я ищу идеи, которые могут быть применены к проблемам с гольфом в коде, которые, по крайней мере, несколько специфичны для JavaScript (например, «удалить комментарии» - это не ответ).

Примечание. См. Также Советы по игре в гольф в ECMAScript 6 и выше.

mellamokb
источник
Мне было действительно интересно, разрешено ли помещать переменные в глобальные (сохраняет var)? И должен ли гольф-код JavaScript быть функцией или выводить что-то напрямую? Я искренне думаю, что это может иметь большое значение.
pimvdb
1
@primvdb: Это разрешено, но вы должны быть осторожны, потому что это может вызвать побочные эффекты, если функция вызывается несколько раз и манипулирует глобальными переменными или является рекурсивной функцией.
mellamokb

Ответы:

108

Fancy For Loops

Вы можете использовать стандарт для цикла нестандартными способами

for ( a; b; c )

по существу эквивалентно:

a;
while ( b )
{
  ...
  c;
}

так что хороший трюк - написать код с whileциклом, а затем разбить его на a,b,cчасти в forцикле.

Несколько примеров, которые я написал :

for(x=y=n;!z;x--,y++)z=i(x)?x:i(y)?y:0
for(a=b=1;b<n;c=a+b,a=b,b=c);

Цепи ваши сеттеры

Если вы инициализируете или сбрасываете несколько значений, объедините их во все переменные, которые в нем нуждаются:

a=b=1;

Неявное кастинг

Не проверяйте свои типы, просто используйте их как есть. parseInt()стоит 10персонажей. Если вам нужно изгнать из строки, будьте изобретательны:

a='30';
b='10';
c = a + b; //failure
c = parseInt(a) + parseInt(b) //too long

c = -(-a-b); //try these
c = ~~a+~~b;
c = +a+ +b;
c = a- -b;

Избегайте точек с запятой

JavaScript имеет автоматическую вставку точек с запятой. Используйте это часто и хорошо.

Однострочники

Сохраните в скобках, запихивая как можно больше в отдельные строки или параметры:

a( realParam1, realParam2, fizz='buzz' )

Операторы приращения / убывания

a = a - 1;
foo(a);

а также

foo(a);
a = a - 1;

может быть легко переписан как

foo(--a);

а также

foo(a--);

соответственно.

Использовать thisили selfвместо windowв глобальном контексте

Само собой разумеющееся 2 символа сбережений.

Используйте скобочные обозначения для повторного доступа к свойствам

Это определенно баланс между длиной имени свойства и количеством обращений. Вместо того, чтобы a.longFunctionName()дважды вызывать с точечной нотацией, короче сохранить имя и вызвать функцию через скобочную нотацию:

a.longFunctionName(b)
a.longFunctionName(c)
//42

vs-

a[f='longFunctionName'](b)
a[f](c)
//34

это особенно эффективно с такими функциями, document.getElementByIdкоторые можно уменьшить до d[e].

Примечание:

В скобках обозначены 6 + name.lengthсимволы в первый раз. Каждый последующий доступ имеет стоимость 3символов.

Для точечной нотации все обращения стоят name.length + 1(+1 для .) символов.

Используйте этот метод, если 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = длина имени свойства
i = минимальный доступ для использования

len | i 
========
1   |  
2   |  
3   | 7 
4   | 4 
5   | 3 
6   | 3 
7   | 3 
8+  | 2 

Количество доступов также может охватывать несколько объектов. Если вы используете .length4 или более раз для разных массивов, вы можете использовать одну и ту же переменную, содержащую строку 'length'.

zzzzBov
источник
5
c = ~~a-~~bдолжно быть c = ~~a+~~b. Кроме того, вы можете неявно приводить к целому числу |0, например, используя Math.random()*6|0.
mellamokb
7
Дешевле принудительно привести строку к числу с помощью оператора унарный плюс. Если aи bявляются строками, вы можете сделать, +a+bчтобы преобразовать в число и добавить их.
Питер Олсон
8
Клянусь, я собираюсь использовать d- -bв своем коде когда-нибудь ...
Джон Дворжак
4
+ a + b не работает (по крайней мере, на моем ...) // a = "1", b = "1", + a + b // выдает "11"
imma
2
Для «Использовать доступ к массиву для повторных вызовов функций», если вы используете функцию более двух раз на одном и том же объекте , то, что немного короче, так это назначить функцию новому члену, какa.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender
131

Разделение по номерам для сохранения кавычек:

"alpha,bravo,charlie".split(",") // before
"alpha0bravo0charlie".split(0)   // after
ajax333221
источник
2
Это работает, и я использовал его для нескольких цифр.
Isiah Meadows
12
Lol это на самом деле довольно креативно
NiCk Newman
9
в ES6 это больше не имеет значения, вы можете просто сделать.split`...`
Дэвид Арчибальд
"alpha,bravo,charlie".split`,`
Камиль Келчевски
56

Используйте оператор запятой, чтобы избежать скобок (также относится к C ):

if(i<10)m+=5,n-=3;

Вместо

if(i<10){m+=5;n-=3}

который на один символ длиннее.

mellamokb
источник
2
Нужна ли точка с запятой в конце первого образца?
WJL
4
@wjlafrance: Это не требуется, только если он находится в конце строки.
mellamokb
48

Короче генерация случайных чисел

Если вам нужен случайный логический ( 0или 1):

new Date&1 // equivalent to Math.random()<0.5

Если вам нужно случайное целое число 0 <= n < 1337:

new Date%1337 // equivalent to Math.floor(Math.random()*1337))

Это работает, потому что a Dateхранится внутри JavaScript в виде количества миллисекунд с начала эпохи, поэтому на new Dateнего навязывают, 123somebignumber456когда вы пытаетесь выполнить с ним целочисленную математику.

Конечно, эти «случайные» числа на самом деле не будут такими случайными, особенно если вы вызываете их несколько раз подряд, так что имейте это в виду.

Дверная ручка
источник
1
Просто запомнили этот ответ, читая Больше лжецов, которым программисты верят во время : «21. Если вы создадите два объекта даты рядом друг с другом, они будут представлять одно и то же время. (фантастический генератор Гейзенбаг) » .
Себастьян Симон
39

Вы можете использовать объектную буквальную форму get / set, чтобы избежать использования ключевого слова function.

var obj = {
  get f(){
    console.log("just accessing this variable runs this code");
    return "this is actually a function";
  },
  set f(v){
    console.log("you can do whatever you want in here, passed: " + v);
  }
};

1 && obj.f; // runs obj.[[get f]]
obj.f = Infinity; // runs obj.[[set f]](Infinity)

источник
часть получения / установки была действительно полезна. thx
gion_13
1
На самом деле, даже лучше использовать объектный метод, если вы используете его <= 2 раза. С другой стороны, функции стрелок намного лучше сокращают символы, поскольку они служат почти той же цели, а классы редко используются в коде игры в гольф.
Isiah Meadows
если поддержка важна, функции стрелок не поддерживаются в FX. ie11
Джим Вольф
35

Это менее известный и менее используемый, но может быть впечатляющим, если используется в правильной ситуации. Рассмотрим функцию, которая не принимает аргументов и всегда возвращает другое число при вызове, и возвращенное число будет использовано в вычислении:

var a = [ 
    Math.random()*12|0,
    Math.random()*11|0,
    Math.random()*10|0,
    /* etc... */ 
];

Обычно вы можете сократить эту функцию, используя однобуквенное имя переменной:

var r=Math.random,a=[r()*12|0,r()*11|0,r()*10|0,r()*9|0,r()*8|0,r()*7|0,r()*6|0,r()*5|0];

Лучший способ уменьшить длину - злоупотреблять valueOf, что дает вам экономию 2 символов за вызов. Полезно, если вы вызываете функцию более 5 раз:

var r={valueOf:Math.random},a=[r*12|0,r*11|0,r*10|0,r*9|0r*8|0,r*7|0,r*6|0,r*5|0];
Энди Э
источник
8
Или, вы можете сделать это так: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)или let a=Array(7).map((_,i)=>i*Math.random()|0+5)36 или 42 байта, соответственно.
Исия Медоус
Можно ли заменить r()или сделать его короче?
NiCk Newman
3
r={valueOf:Math.random}Это просто гений: D
ETHproductions
1
@Isiah, ну да, теперь ты можешь это сделать :-D
Энди Э,
32

Использование преимуществ операторов короткого замыкания

Вместо длинных ifоператоров или использования троичных операторов вы можете использовать &&и ||сократить свой код. Например:

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;

может стать

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

||Оператор часто используется таким образом , для установки по умолчанию:

evt = evt || window.event;

Это так же, как написание

if (!evt)
    evt = window.event;

Создание повторяющихся строк с использованием массива

Если вы хотите инициализировать длинную строку определенного символа, вы можете сделать это, создав массив длиной n + 1 , где n - количество повторений символа:

// Create a string with 30 spaces
str = "                              ";

// or
str = Array(31).join(" ");

Чем больше строка, тем больше экономия.

Разбор чисел

Используйте +и ~операторы вместо parseFloat()или parseInt()при объединении строкового типа, который является просто числом, к числовому типу:

var num = "12.6";
parseFloat(num) === +num;  // + is 10 characters shorter than parseFloat()

var num2 = "12"
parseInt(num2) === +num2;   // + is 8 characters shorter than parseInt()

var num3 = "12.6"
parseInt(num3) === ~~num3;  // ~~ is 7 characters shorter than parseInt()

var num4 = "12.6"
parseInt(num4) === num4|0;  // |0 is 7 characters shorter than parseInt()

Будьте осторожны, другие типы могут объединяться с этими операторами (например, trueстать 1) пустой строкой или строкой, содержащей только пробел 0. Это может быть полезно в определенных обстоятельствах, однако.

Энди Э
источник
6
+1 за создание повторяющихся строк с использованием Array - не думал об этом.
mellamokb
4
Для создания повторяющихся строк в ES6 вы можете использоватьstr.repeat(count)
Oriol
26

Вставить инициализацию переменной в вызов prompt () для получения пользовательского ввода

n=prompt(i=5);     // sets i=5 at the same time as getting user input

Вместо того, чтобы использовать

n=prompt();i=5;

Как побочный эффект, он отображает входное значение в окне подсказки, сохраняя при этом 1 символ.

mellamokb
источник
12
Это также может быть применено к любой функции, которая не принимает аргументы.
Кейси Чу
3
Даже когда функция принимает аргументы, это может быть полезно, как [1,2,3].join('',i=5)в случаях, когда она сохраняет пару фигурных скобок.
DocMax
3
@DocMax: Вы можете использовать оператор запятой для этого - i=5,[1,2,3].join().
Конрад Боровски
@GlitchMr: Я мог бы, но это не спасает никаких символов. Я согласен, что большую часть времени это будет чище. Я думаю, что все еще могут быть случаи, когда мой заказ может сохранить символ, хотя я не могу придумать его в данный момент (и я вполне могу ошибаться).
DocMax
@DocMax Только если вы используете ASI.
Исия Медоус
24

Объединить вложенные в петли:

// before:
for(i=5;i--;)for(j=5;j--;)dosomething(i,j)

// after:
for(i=25;i--;)dosomething(0|i/5,i%5)

Пример с разными значениями для i/ j:

// before:
for(i=4;i--;)for(j=7;j--;)dosomething(i,j)

// after:
for(i=28;i--;)dosomething(0|i/7,i%7)
Кае Веренс
источник
(Я отредактировал) незначительную опечатку, но очень умно! Обратите внимание, что это будет работать только на вложенных циклах одинаковой длины (если я не ошибаюсь).
Камило Мартин
1
@CamiloMartin Нет, циклы не обязательно должны быть одинаковой длины. Полученное число итераций равно, i*jи операторы деления / модуля извлекают отдельные значения iи j.
тихая мята
@ user113215 Ты прав, офигенно! :) Я отредактировал ответ, чтобы включить пример.
Камило Мартин
23

Юникод ярлыки

Если вы используете чертовски встроенную собственность на большом соревновании по гольфу, вы можете присвоить псевдониму каждую собственность эквиваленту одного символа:

[Math,Number,S=String,Array].map(b=>
    Object.getOwnPropertyNames(b).map((p,i)=>
        b.prototype[S.fromCharCode(i+248)]=b[p]
    )
)

После выполнения кода выше вы можете использовать его следующим образом:
"foo".Č(/.*/,'bar') // replaces foo with bar

Это стоит 118 байт, поэтому в некоторых ситуациях это может оказаться бесполезным.

Это может зависеть от браузера, и я не уверен, что он короче with(Array){join(foo),...}или определяет переменные как используемые свойства, with(Array){j=join,m=map...}но все же стоит упомянуть.

    Math        Number              String              Array

ø   toSource    prototype           prototype           prototype
ù   abs         NaN                 quote               join
ú   acos        POSITIVE_INFINITY   substring           reverse
û   asin        NEGATIVE_INFINITY   toLowerCase         sort
ü   atan        MAX_VALUE           toUpperCase         push
ý   atan2       MIN_VALUE           charAt              pop
þ   ceil        MAX_SAFE_INTEGER    charCodeAt          shift
ÿ   clz32       MIN_SAFE_INTEGER    contains            unshift
Ā   cos         EPSILON             indexOf             splice
ā   exp         isFinite            lastIndexOf         concat
Ă   floor       isInteger           startsWith          slice
ă   imul        isNaN               endsWith            filter
Ą   fround      toInteger           trim                isArray
ą   log         parseFloat          trimLeft            lastIndexOf
Ć   max         parseInt            trimRight           indexOf
ć   min         length              toLocaleLowerCase   forEach
Ĉ   pow         name                toLocaleUpperCase   map
ĉ   random      arguments           normalize           every
Ċ   round       caller              match               some
ċ   sin                             search              reduce
Č   sqrt                            replace             reduceRight
č   tan                             split   
Ď   log10                           substr  
ď   log2                            concat  
Đ   log1p                           slice   
đ   expm1                           fromCharCode    
Ē   cosh                            fromCodePoint   
ē   sinh                            localeCompare   
Ĕ   tanh                            length  
ĕ   acosh                           name    
Ė   asinh                           arguments   
ė   atanh                           caller  
Ę   hypot           
ę   trunc           
Ě   sign            
ě   cbrt            
Ĝ   E           
ĝ   LOG2E           
Ğ   LOG10E          
ğ   LN2         
Ġ   LN10            
ġ   PI          
Ģ   SQRT2           
ģ   SQRT1_2         
Бебе
источник
Я использую Google Chrome, и все они дают неопределенные.
SuperJedi224
Это должно быть очень специфично для Firefox. Приносим извинения за неудобства.
bebe
Почему это все специальные символы? Почему бы просто не использовать печатный ASCII? (легче набрать, надежнее и всего 1 байт для игры в гольф)
Cyoce
Это на самом деле не работает, Mathпотому что у него нет .prototypeатрибута. Однако, удалив Math, мне удалось воспроизвести это до 114-байтового фрагмента, который назначает их всем однобайтовым буквам. Вы можете найти это здесь .
ETHproductions
1
Вы можете также гольф мое решение до 106 байт за счет перемещения всех этих свойств в диапазоне À- ÿ, который еще один байт каждый в ISO-8859-1 кодирования (который поддерживает JS). В Firefox 50 это, к сожалению, включает .localeCompareметод ×, но обычно это не должно быть проблемой. источник
ETHproductions
22

Преобразование whileцикла в forцикл часто эквивалентно:

while(i--);
for(;i--;);

Но вторая форма может иметь объединенную инициализацию переменной:

i=10;while(i--);
for(i=10;i--;);

Обратите внимание, что вторая форма на один символ короче первой.

mellamokb
источник
6
Или, что еще лучше, просто используйте петли. На самом деле, ни один случай, когда использование цикла for приводит к большему коду, насколько я знаю.
Исия Медоус
22

Исключение злоупотребляет

если строковые / символьные литералы запрещены, вы можете использовать блок try catch:

try{something0}catch(e){str=e.message.split(0)[0]}

теперь strравняется"something"

если нужно больше строк, вы можете связать их числом (например, нулями)

try{something0foo0bar0}catch(e){arr=e.message.split(0)}

теперь arrравняется["something", "foo", "bar", " is not defined"]

Бебе
источник
18

Если вы инициализируете переменную 1в каждой итерации цикла (например, сбрасываете переменную во внешнем цикле для внутреннего цикла), как показано ниже (из моего ответа на этот вопрос ):

for(j=n-2;p=1,j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^

Поскольку результатом условия like j++<=nявляется 1всякий раз, когда оно имеет значение true, вы можете просто назначить условие непосредственно переменной (поскольку, когда оно становится ложным, цикл прекращает выполнение и больше не имеет значения):

for(j=n-2;p=j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^^^^^

Обычно вы можете сохранить 2 символа, используя этот метод. С уважением к @ugorenидее в комментариях к этому ответу.


В качестве другого примера я также применил этот трюк к своему ответу здесь с выражением w=r=++c<S.lengthво внешнем цикле for, сохранив всего 4 символа.

mellamokb
источник
18

Если вы можете принять специальные сценарии Spidermonkey (на данный момент), вы можете использовать функции стрелок ECMAScript 6 . Вместо написания кода, как показано ниже.

a.map(function(x){return x*2}) // function? return?

Вы можете сократить это, как это.

a.map(x=>x*2)
Конрад Боровски
источник
17

Если вам нужно проверить NaN, не используйте isNaN(x), но используйте x!=x, который короче и также работает.

if(isNaN(x)){
if(x!=x){

Обратите внимание, что это работает только если typeof(x) === "number"; если это строка, например, isNaN("string")возвращает true, но "string" != "string"возвращает false. Спасибо Cyoce за указание на это!

ProgramFOX
источник
2
Это гениальное использование этой причуды. +1
ETHпродукция
Предупреждение: они не всегда эквивалентны: isNaN("string")возвращается true, тогда как "string"!="string"возвращается false(очевидно)
Cyoce
@Cyoce Хорошо, спасибо! Я отредактировал свой ответ.
ProgramFOX
Во многих случаях вы можете даже пойти if(!x){, если вы обнаруживаете NaNявно.
Hohmannfan
1
Приведение xк числу, +x!=+xделает его эквивалентным isNaN(x), но все же на 2 символа короче. Затем +"string"!=+"string"возвращает истину.
Томас Лангкаас
15

Сумма массива / продукт / частное

ES5 : 17 байт

eval(a.join('+'))

ES6 : 15 байт

eval(a.join`+`)

Конечно, вы можете поменять их +на что угодно, например, *на продукт или /частное.

Джордж Райт
источник
14

Используйте побитовую операцию, чтобы округлить число до нуля:

// do this
T=Math.random()*6+1|0

// or do this
T=~~(Math.random()*6+1)

(Источник: Случайная игра в кости )

Приоритет оператора определяет, что будет короче в вашей программе.

PleaseStand
источник
2
Это также может быть использовано для коалесценции строки ввода в целое число, то есть n=prompt()|0.
mellamokb
1
побитовое тоже очень быстро по сравнению с math.floor: jsperf.com/floor-vs-bitwise
vsync
@vsync: странно. Я получаю math.floor примерно в два раза быстрее, чем побитовый на Chrome 11.0.696.77.
mellamokb
очень странно. для меня они оба более или менее одинаковые скорости и супер быстрые в Chrome, но в FF побитовая скорость намного быстрее, чем Chrome, и Math.floorужасно медленная .. почти не следует использовать, я бы сказал.
vsync
Чтобы поддерживать актуальность комментариев, в текущем Fx они оба быстрые и примерно одинаковые. Не то чтобы это скорее всего было узкое место, по сравнению с окружающим кодом ...
FireFly
14

Looping Tip I

Вы можете сохранить 1символ при зацикливании, изменив iна последний использованный:

//not so god
for(i=0;i<3;i++){
  alert(i);
}

//best
for(i=0;i<3;){
  alert(i++);
}

Примечание: работает --также (но измените цикл соответственно, чтобы избежать бесконечного цикла)


Looping Tip II

Есть определенные сценарии, в которых вы можете сохранить один символ, играя с инкрементным оператором и значениями:

for(i=0;i++<9;)
for(i=0;++i<10;)

Примечание: нужно обратить внимание, когда, например 0 to -1. и 9 to 10, 99 to 100, так что поиграйте, пока не найдете способ сохранить персонажа

ajax333221
источник
13

Использовать ^вместо !=или ==при сравнении с целым числом

//x!=3?a:b
  x^3?a:b

//x==3?a:b
  x^3?b:a

Замените вызовы встроенных математических функций более короткими выражениями.

//Math.ceil(n)
  n%1?-~n:n

//Math.floor(n)
  ~~n
  0|n

//Math.abs(n)
  n<0?-n:n

//Math.round(n)
  n+.5|0

//Math.min(x,y)
  x<y?x:y

//Math.max(x,y)
  y<x?x:y
Томас Лангкаас
источник
2
Кроме того, вы можете просто использовать -вместо !=целых чисел; Например, n!=1?a:bбудет эквивалентноn-1?a:b
vrugtehagel
10

Стоит отметить, что в некоторых случаях вы можете использовать строку вместо нуля, чтобы сохранить несколько байтов здесь и там в циклах:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10
Дом Гастингс
источник
1
Я пытался "" ++ в консоли ранее, задаваясь вопросом, будет ли он работать, конечно, сначала он должен быть в переменной. Спасибо!
Вартан
10

Очень простой, даже так, никто не упомянул об этом.

Если вы используете Math.min()или Math.max()можете сохранить 6 символов, сделав это:

Math.min(a,b)  // 13 chars
a<b?a:b        //  7 chars

Math.max(a,b)
a>b?a:b
Антонио Алмейда
источник
10

округление

Я знаю, что альтернативы Math.floor()были опубликованы, но как насчет других?

Напольное покрытие:

Math.floor(x) //before
0|x           //after

Округление:

Math.round(x) //before
0|x+.5        //after

Потолок:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas
Mama Fun Roll
источник
1
Обратите внимание, что 0|x+1просто добавляется 1, если число, которое вы хотите найти, уже является целым числом. (В основном) безопасная альтернатива есть 0|x+1-1e9, но она всего на три байта короче.
ETHproductions
@ETHproductions разве ты не имеешь ввиду 0|x+1-1e-9?
Mama Fun Roll
Ой, да. Спасибо что подметил это. (По какой-то причине я не могу сделать @ (ваше имя пользователя) ...)
ETHproductions
Вероятно, потому что мои символы в логине перевернуты вверх ногами
Mama Fun Roll
1
Для потолка x%1?-~x:x(9 символов) - лучшая альтернатива. Однако, как альтернативы настила 0|xи ~~x, это работает только для положительных чисел.
Томас Лангкаас
9

В тех случаях, когда вы используете троичный оператор для выбора между двумя числами , а условным условием является либо логическое значение, либо число 1 or 0 , вы можете вместо этого выполнять математические операции:

(x ? num1 : num2) conclusions:

    1)if num1 equals num2, there ARE savings
    2)if num1 is (+1) or (-1) than num2, there ARE savings
    3)if either num1 or num2 equals to 0, there ARE savings
    4)it is MORE LIKELY to find greater savings on num1>num2 instead of num1<num2
    5)in method (*A) and (*B), savings are NOT GUARANTEED

    a)num1>num2
        i)(num1==(num2+1))
            ex1: (x?5:4) to (x+4)
            ex2: (x?8:7) to (x+7)
        ii)num2==0
            ex1: (x?3:0) to (x*3)
            ex2: (x?7:0) to (x*7)
        iii)
            (*A) or (*B) //one might be shorter

    b)num1<num2
        i)((num1+1)==num2)
            ex1: (x?4:5) to (5-x)
            ex2: (x?7:8) to (8-x)
        ii)num1==0
            ex1: (x?0:3) to (!x*3)
            ex2: (x?0:7) to (!x*7)
        iii)
            (*A) or (*B) //one might be shorter

    c)num1==num2
        i)
            ex1: (x?5:5) to (5)
            ex2: (x?-3:-3) to (-3)

    (*A) use ((x*(num1-num2))+num2)
        ex1: (x?8:4)   to ((x*4)+4)
        ex2: (x?4:8)   to ((x*-4)+8)

        ex3: (x?6:-4)  to ((x*10)-4)
        ex4: (x?-4:6)  to ((x*-10)+6)

        ex5: (x?4:-6)  to ((x*10)-6)
        ex6: (x?-6:4)  to ((x*-10)+4)

        ex7: (x?-5:-9) to ((x*4)-9)
        ex8: (x?-9:-5) to ((x*-4)-5)

    (*B) use ((!x*(num2-num1))+num1)
        ex1: (x?8:4)   to ((!x*-4)+8)
        ex2: (x?4:8)   to ((!x*4)+4)

        ex3: (x?6:-4)  to ((!x*-10)+6)
        ex4: (x?-4:6)  to ((!x*10)-4))

        ex5: (x?4:-6)  to ((!x*-10)+4)
        ex6: (x?-6:4)  to ((!x*10)-6)

        ex7: (x?-5:-9) to ((!x*-4)-5)
        ex8: (x?-9:-5) to ((!x*4)-9)

Примечание: В дополнение к этому, вам нужно будет удалить ненужные 0-, +0, и +-т.д.

Примечание 2: есть единичный случай, когда (x) !== (x?1:0), как это xдолжно быть, typeof === "number"для его работы. Однако в случае с (-x)этим все работает просто отлично.

Примечание 3: Если вы не нашли сбережения, просто используйте первый(x?y:z)

Ранее я думал, что метод B никогда не сможет победить A, однако существуют исключения:

(x?97:100) //original

(-3*x+100)
(3*!x+97)

Я создал проект GitHub, который делает упрощение для нас ( демонстрация jsFiddle )

mellamokb
источник
@ ajax333221 void 0(это не функция, а ключевое слово) не является значением, оно просто возвращает undefined.
Камило Мартин
@CamiloMartin вы правы, и теперь я вижу смысл в этом ответе, однако aдля его работы должно быть либо 1, либо 0
ajax333221
@ ajax333221 Да, на самом деле забавная вещь в игре в гольф кода состоит в том, что большинство лучших трюков работают только для той конкретной вещи, которую вы делаете, и каждый чувствует себя настолько умным, чтобы найти один из этих угловых случаев с угловыми решениями: D Кстати, вам не нужно удалять комментарии ...
Камило Мартин
9

tl; dr: использовать функции ES6!

Функции стрелок

Документ: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Пример:

s = x => x*x
// s = function (x) {
//   return x * x;
// }
Флоран
источник
Функции стрелок уже упоминались 13 октября 13 в 15:42 . Но это for.. ofэто круто. Даже короче for each.. in.
manatwork
2
Синтаксис понимания массива кажется неправильным. Согласно документации , должно быть , как в Python: b = [s(x) for (x of a)].
manatwork
@manatwork Приведенные выше примеры прекрасно работают в REPL Traceur
Флоран
Понятия не имею о Traceur, но вы упомянули ECMAScript и указали на документацию Mozilla. И массив массивов ни в одном из них не выглядит так, как вы написали.
manatwork
1
Массивы были на самом деле вытащены на полпути.
Исия Медоуз
9

Злоупотреблять литералами

Недавний пример: проверьте, "c"есть ли прописные или строчные буквы, не имеет значения, если не буква

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case
l4m2
источник
3
Как это работает?
Kritixi Lithos
2
@ Cowsquack String({})дает "[object Object]".
Деннис
8

Как сравнить число с помощью того, как числа превращаются в логические значения:

Если вы собираетесь проверить , если что - то равно положительное число , вы можете вычесть эту сумму и обратную , что было внутри ifи elseблоков:

//simplified examples:
x==3?"y":"n"; <- 13 Chars
x-3?"n":"y"; <- 12 Chars

//expanded examples:
if(x==3){
    yes();
}else{
    no();
}

if(x-3){
    no();
}else{
    yes();
}

И в случае, если вы хотите сравнить с отрицательным числом (* отличным от -1), вам просто нужно добавить это число вместо вычитания.

* ну, вы, конечно, можете использовать x.indexOf(y) + 1, но в особом случае у -1вас есть возможность использовать ~x.indexOf(y)вместо этого.

ajax333221
источник
8

Используйте нестандартную функцию «закрытия выражений» в Mozilla, чтобы сохранить множество символов в скрипте, который должен работать только в движках SpiderMonkey / Firefox или Rhino. Например,

function foo(){return bar}

становится

function foo()bar

См. Страницу переполнения стека для большего количества таких уловок.

PleaseStand
источник
2
Это не Javascript. Это космическая станция !!!
Томас Эдинг
1
ECMAScript 6 на помощь! ->bar
Ry-
5
ECMAScript 6: let foo = () => bar;иронически короче, чем приведенный выше код для игры в гольф.
Исия Медоус
1
ECMAScript 6: foo=_=>barеще короче.
ETHproductions
эта ссылка не работает.
Cyoce
8

Используйте if(~a.indexOf(b))вместоif(a.indexOf(b)!=-1)

Konijn
источник
Также обратите внимание на Array.prototype.includes, как и в 2017 году
tsh
8

Вместо написания trueвы можете использовать !0.

Wolle Vanillebär Lutz
источник
4
Аналогично !1для false.
Джеймс М. Лэй
10
Еще лучше использовать 1для trueи 0для false, если вам действительно не нужны буквальные значения.
ETHproductions
8

Преобразование в логическое значение :

if(b){b=true}else{b=false}
b=b?true:false;
b=b?!0:!1;
b=!!b;

Примечание: Это изменение 0, "", false, null, undefinedи NaNк false(все остальное true)

ajax333221
источник