Consejos para jugar golf en JavaScript

133

¿Qué consejos generales tienes para jugar al golf en JavaScript? Estoy buscando ideas que puedan aplicarse a los problemas de código de golf en general que sean al menos algo específicos de JavaScript (por ejemplo, "eliminar comentarios" no es una respuesta).

Nota: Consulte también Consejos para jugar golf en ECMAScript 6 y superior

mellamokb
fuente
Realmente me preguntaba, ¿está permitido poner variables en global (guardar var)? ¿Y el código de golf JavaScript debería ser una función o generar algo directamente? Sinceramente, creo que esto puede hacer mucha diferencia.
pimvdb
1
@primvdb: está permitido, pero debes tener cuidado porque puede causar efectos secundarios si una función se llama varias veces y está manipulando variables globales, o si es una función recursiva.
mellamokb

Respuestas:

108

Fantasía para bucles

puede usar el bucle estándar para formas no estándar

for ( a; b; c )

es esencialmente equivalente a:

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

así que un buen truco es escribir su código con un whilebucle y luego dividirlo en a,b,cpartes en un forbucle.

Un par de ejemplos que he escrito :

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);

Encadena a tus acomodadores

Si está inicializando o restableciendo múltiples valores, encadene el valor a todas las variables que lo necesitan:

a=b=1;

Casting implícito

No verifiques tus tipos, solo úsalos como están. parseInt()cuesta 10personajes. Si necesita expulsar de una cadena, sea creativo:

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;

Evitar los punto y coma

JavaScript tiene inserción automática de punto y coma. Úselo a menudo y bien.

One-liners

Ahorre entre paréntesis empujando tanto como sea posible en líneas individuales o parámetros:

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

Operadores de aumento / disminución

a = a - 1;
foo(a);

y

foo(a);
a = a - 1;

puede reescribirse fácilmente como

foo(--a);

y

foo(a--);

respectivamente.

Usar thiso en selflugar de windowen contexto global

Ahorro autoexplicativo de 2 caracteres.

Use la notación de paréntesis para repetir el acceso a la propiedad

Este es definitivamente un acto de equilibrio entre la longitud del nombre de la propiedad y el número de accesos. En lugar de llamar a.longFunctionName()dos veces con notación de punto, es más corto guardar el nombre y llamar a la función mediante notación de paréntesis:

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

-vs-

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

Esto es especialmente efectivo con funciones como las document.getElementByIdque se pueden reducir a d[e].

Nota:

Con la notación de corchetes, el costo son 6 + name.lengthcaracteres la primera vez. Cada acceso posterior tiene un costo de 3caracteres.

Para la notación de puntos, todos los accesos cuestan name.length + 1(+1 para los .) caracteres.

Use este método si 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = longitud del nombre de la propiedad
i = accesos mínimos para aprovechar

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

El número de accesos también puede abarcar múltiples objetos. Si accede .length4 o más veces en diferentes matrices, puede usar la misma variable que contiene la cadena 'length'.

zzzzBov
fuente
55
c = ~~a-~~bdebería ser c = ~~a+~~b. Además, puede convertir implícitamente a entero usando |0, por ejemplo Math.random()*6|0.
mellamokb 01 de
77
Es más barato forzar una cadena a un número con el operador unario más. Si ay bson cadenas, puede hacer +a+bpara convertir a número y agregarlas.
Peter Olson
8
Juro que d- -balgún día usaré mi código ...
John Dvorak
44
+ a + b no funciona (al menos en el mío ...) // a = "1", b = "1", + a + b // da "11"
Imma
2
Para "Usar Array-Access para repetir llamadas de función" si está usando la función más de dos veces en el mismo objeto , lo que es un poco más corto es asignar la función a un nuevo miembro comoa.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender
131

División con números para guardar las comillas:

"alpha,bravo,charlie".split(",") // before
"alpha0bravo0charlie".split(0)   // after
ajax333221
fuente
2
Funciona, y lo he usado para varios dígitos.
Isiah Meadows
12
Lol, esto es realmente bastante creativo
NiCk Newman
99
en ES6 esto ya no importa, solo puedes hacerlo.split`...`
David Archibald
"alpha,bravo,charlie".split`,`
Kamil Kiełczewski
56

Use el operador de coma para evitar llaves (también se aplica a C ):

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

En lugar de

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

que es un personaje más largo.

mellamokb
fuente
2
¿Es necesario el punto y coma al final de la primera muestra?
wjl
44
@wjlafrance: solo no sería necesario si está al final de la línea.
mellamokb
48

Generación de números aleatorios más corta

Si necesita un booleano aleatorio ( 0o 1):

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

Si necesita un entero aleatorio 0 <= n < 1337:

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

Esto funciona porque a Datese almacena internamente en JavaScript como la cantidad de milisegundos desde una época, por lo que new Datese está coaccionando 123somebignumber456cuando intentas hacer matemáticas enteras en él.

Por supuesto, estos números "aleatorios" realmente no serán tan aleatorios, especialmente si los llamas varias veces seguidas, así que tenlo en cuenta.

Pomo de la puerta
fuente
1
Acabo de recordar esta respuesta mientras leía Más falsedades que los programadores creen sobre el tiempo : “21. Si crea dos objetos de fecha uno al lado del otro, representarán la misma hora. (un fantástico generador de Heisenbug) " .
Sebastian Simon
39

Puede usar la forma literal del objeto get / set para evitar usar la palabra clave 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)

fuente
la parte de captador / definidor fue realmente útil. thx
gion_13
1
En realidad, incluso mejor es un método de objeto, si solo lo usa <= 2 veces. Por otro lado, las funciones de flecha son mucho mejores para cortar caracteres, ya que sirven para casi el mismo propósito, y las clases rara vez son útiles en el código de golf.
Isiah Meadows
si el soporte es importante, las funciones de flecha no se admiten en fx. ie11
Jim Wolff
35

Este es menos conocido y menos utilizado, pero puede ser impresionante si se usa en la situación correcta. Considere una función que no toma argumentos y siempre devuelve un número diferente cuando se llama, y ​​el número devuelto se usará en un cálculo:

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

Normalmente puede acortar esta función usando un nombre de variable de una letra:

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];

Una mejor manera de reducir la longitud es abusando valueOf, lo que le permite guardar 2 caracteres por invocación. Útil si llama a la función más de 5 veces:

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];
Andy E
fuente
8
O bien, puede hacerlo de la siguiente manera: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)o let a=Array(7).map((_,i)=>i*Math.random()|0+5), 36 o 42 bytes guardados, respectivamente.
Isiah Meadows
¿Es posible reemplazarlo r()o acortarlo?
NiCk Newman el
3
r={valueOf:Math.random}Eso es genial: D
ETHproductions
1
@Isiah, bueno, sí, puedes hacerlo ahora :-D
Andy E
32

Aprovechando los operadores de cortocircuito

En lugar de largas ifdeclaraciones o el uso de operadores ternarios, puede utilizar &&y ||acortar su código. Por ejemplo:

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

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

puede llegar a ser

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

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

El ||operador se usa a menudo de esta manera para establecer valores predeterminados:

evt = evt || window.event;

Esto es lo mismo que escribir

if (!evt)
    evt = window.event;

Crear cadenas repetitivas usando Array

Si desea inicializar una cadena larga de un carácter en particular, puede hacerlo creando una matriz con una longitud de n + 1 , donde n es el número de veces que desea repetir el carácter:

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

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

Cuanto más grande es la cuerda, mayor es el ahorro.

Analizando números

Use +y ~operadores en lugar de parseFloat()o parseInt()al fusionar un tipo de cadena que es solo un número con un tipo de número:

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()

Sin embargo, tenga cuidado, otros tipos pueden fusionarse con estos operadores (por ejemplo, truese convertirían 1) en una cadena vacía o se convertiría en una cadena que contiene solo un espacio en blanco 0. Sin embargo, esto podría ser útil en ciertas circunstancias.

Andy E
fuente
66
+1 para crear cadenas repetitivas usando Array: no había pensado en eso.
mellamokb
44
Para crear cadenas repetitivas, en ES6 puede usarstr.repeat(count)
Oriol
26

Introducir la inicialización de la variable en la llamada prompt () para obtener la entrada del usuario

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

En lugar de usar

n=prompt();i=5;

Como efecto secundario, muestra el valor de entrada en la ventana de solicitud al guardar 1 carácter.

mellamokb
fuente
12
Esto también se puede aplicar a cualquier función que no acepte argumentos.
Casey Chu
3
Incluso cuando la función acepta argumentos, puede ser útil, como [1,2,3].join('',i=5)en los casos en que guarda un par de llaves.
DocMax
3
@DocMax: Puede usar un operador de coma para eso - i=5,[1,2,3].join().
Konrad Borowski el
@ GlitchMr: Podría, pero no guarda ningún personaje. Estoy de acuerdo en que la mayoría de las veces será más limpio. Creo que todavía puede haber casos en los que mi pedido podría ahorrar un carácter, aunque no puedo encontrar uno en este momento (y es posible que esté equivocado).
DocMax
@DocMax Solo si aprovecha ASI.
Isiah Meadows
24

Combinar anidados para bucles:

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

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

Ejemplo con diferentes valores para 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)
Kae Verens
fuente
(He editado un) error tipográfico menor, ¡pero muy inteligente! Tenga en cuenta que esto solo funcionará en bucles anidados de la misma longitud (a menos que esté equivocado).
Camilo Martin
1
@CamiloMartin No, los bucles no necesitan tener la misma longitud. El número resultante de iteraciones es i*jy los operadores de división / módulo recuperan los valores individuales de iy j.
quietmint
@ user113215 Tienes razón, ¡increíble! :) He editado la respuesta para incluir un ejemplo.
Camilo Martin
23

Atajos Unicode

Si utiliza una gran propiedad incorporada en un gran desafío de golf, puede asignar un alias a cada propiedad con un equivalente de un personaje:

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

Después de ejecutar el código anterior, puede usarlo así:
"foo".Č(/.*/,'bar') // replaces foo with bar

Esto cuesta 118 bytes, por lo que podría no ser útil en ciertas situaciones

Puede depender del navegador y no estoy seguro de si es más corto with(Array){join(foo),...}o define variables como propiedades utilizadas, with(Array){j=join,m=map...}pero vale la pena mencionarlo.

    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         
bebe
fuente
Estoy usando Google Chrome, y todos estos están dando indefinido.
SuperJedi224
Debe ser muy específico de Firefox entonces. Lo siento por los inconvenientes ocasionados.
bebe
¿Por qué son todos estos personajes especiales? ¿Por qué no solo usar ASCII imprimible? (más fácil de escribir, más confiable y solo 1 byte para jugar al golf)
Cyoce
Esto realmente no funciona Mathporque no tiene un .prototypeatributo. Sin Mathembargo, al eliminarlo , logré convertir esto en un fragmento de 114 bytes que los asigna a todos a letras de un solo byte. Lo puedes encontrar aquí .
ETHproductions
1
También puede campo de mi solución a 106 bytes a expensas de mover todas estas propiedades a la gama À- ÿ, que todavía es de 1 byte cada uno en la codificación ISO-8859-1 (que apoya JS). En Firefox 50, desafortunadamente esto activa el .localeComparemétodo ×, pero eso no debería ser un problema. fuente
ETHproductions
22

Convertir un whilebucle en un forbucle suele ser equivalente:

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

Pero la segunda forma puede tener una inicialización variable combinada:

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

Observe que la segunda forma tiene un carácter más corto que la primera forma.

mellamokb
fuente
66
O, mejor aún, solo use para bucles. Realmente no hay ningún caso en el que usar un bucle for dé como resultado un código más grande, por lo que he experimentado.
Isiah Meadows
22

Abuso de excepción

en caso de que se prohíban los literales de cadena / caracteres, puede usar un bloque try catch:

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

ahora stres igual"something"

Si se necesitan más cadenas, puede encadenarlo con un número (por ejemplo, ceros)

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

ahora arres igual["something", "foo", "bar", " is not defined"]

bebe
fuente
18

Si está inicializando una variable 1en cada iteración de un bucle (por ejemplo, restableciendo una variable en un bucle externo para un bucle interno), como el siguiente (de mi respuesta a esta pregunta ):

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

Dado que el resultado de una condición como j++<=nes 1siempre que sea ​​verdadera, solo puede asignar la condición directamente a la variable (porque cuando se vuelve falsa, el ciclo dejará de ejecutarse y ya no importará):

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

Por lo general, puede guardar 2 caracteres con este método. Saludos a @ugorenla idea en los comentarios a esa respuesta.


Para otro ejemplo, también apliqué este truco a mi respuesta aquí con la expresión w=r=++c<S.lengthen mi bucle for externo, guardando un total de 4 caracteres.

mellamokb
fuente
18

Si puede aceptar scripts específicos de Spidermonkey (por ahora), puede usar las funciones de flecha de ECMAScript 6 . En lugar de escribir código como el siguiente.

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

Puedes acortarlo así.

a.map(x=>x*2)
Konrad Borowski
fuente
17

Si necesita verificar NaN, no lo use isNaN(x), pero use x!=x, que es más corto y también funciona.

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

Tenga en cuenta que esto solo funciona si typeof(x) === "number"; si es una cadena, por ejemplo, isNaN("string")devuelve true, pero "string" != "string"devuelve false. ¡Gracias a Cyoce por señalar esto!

ProgramFOX
fuente
2
Ese es un uso genial de este capricho. +1
ETHproductions
Advertencia: estos no siempre son equivalentes: isNaN("string")devoluciones true, mientras que "string"!="string"devoluciones false(obviamente)
Cyoce
@Cyoce Buen punto, gracias! Edité mi respuesta.
ProgramFOX
En muchos casos, incluso puede ir if(!x){, si está detectando NaNexplícitamente.
Hohmannfan
1
Transmitir xal número, lo +x!=+xhace equivalente a isNaN(x), aún así, 2 caracteres más cortos. Entonces, +"string"!=+"string"vuelve verdadero.
Tomas Langkaas
15

Suma de matrices / producto / cociente

ES5 : 17 bytes

eval(a.join('+'))

ES6 : 15 bytes

eval(a.join`+`)

Por supuesto, puede cambiarlo +por lo que desee, por ejemplo, *por producto o /por cociente.

George Reith
fuente
14

Use una operación bit a bit para redondear un número hacia cero:

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

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

(Fuente: propinas al azar )

La precedencia del operador determina cuál será más corto en su programa.

Por favor levantese
fuente
2
Esto también se puede utilizar para coalescer una entrada de cadena en un entero, es decir, n=prompt()|0.
mellamokb
1
bitwise también es súper rápido en comparación con math.floor: jsperf.com/floor-vs-bitwise
vsync
@vsync: raro. Obtengo math.floor para que sea aproximadamente dos veces más rápido que bit a bit en Chrome 11.0.696.77.
mellamokb
muy raro. para mí son más o menos las mismas velocidades y súper rápidas en Chrome, pero en FF el bit a bit es mucho más rápido que Chrome, y Math.floores terriblemente lento ... casi no debería usarse, diría yo.
vsync
Para mantener los comentarios actualizados, en Fx actual ambos son rápidos y casi iguales. No es probable que sea un cuello de botella en primer lugar, en comparación con el código circundante ...
FireFly
14

Sugerencia de bucle I

Puede guardar el 1carácter cuando se repite cambiando ila última vez que se usó:

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

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

Nota: también funciona con --(pero modifique el bucle en consecuencia para evitar bucles infinitos)


Punta de bucle II

Hay ciertos escenarios en los que puedes guardar un personaje jugando con el operador y los valores incrementales:

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

Nota: debe prestar atención cuando, por ejemplo 0 to -1. y 9 to 10, 99 to 100, así que juega hasta que encuentres una manera de salvar al personaje

ajax333221
fuente
13

Usar en ^lugar de !=o ==cuando se compara con un número entero

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

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

Reemplazar llamadas a funciones matemáticas incorporadas con expresiones más cortas

//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
Tomás Langkaas
fuente
2
Alternativamente, puede usar simplemente en -lugar de !=para enteros; Por ejemplo, n!=1?a:bsería equivalente an-1?a:b
vrugtehagel
10

Algo que vale la pena señalar es que puede usar una cadena en lugar de cero en algunos casos para guardar un par de bytes aquí y allá en bucles:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10
Dom Hastings
fuente
1
Intenté "" ++ en la consola antes preguntándome si funcionaría, por supuesto, primero tiene que estar en una variable. ¡Gracias!
Vartan
10

Muy simple, aun así, nadie lo había mencionado.

Si está utilizando Math.min()o Math.max()puede guardar 6 caracteres haciendo esto:

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

Math.max(a,b)
a>b?a:b
António Almeida
fuente
10

Redondeo

Sé que Math.floor()se han publicado alternativas , pero ¿qué pasa con los demás?

Piso:

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

Redondeo:

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

Techo:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas
Mama Fun Roll
fuente
1
Tenga en cuenta que 0|x+1simplemente suma 1 si el número del que desea encontrar el techo ya es un número entero. Una alternativa segura (principalmente) es 0|x+1-1e9, pero esto es solo tres bytes más corto.
ETHproductions
@ETHproductions no quieres decir 0|x+1-1e-9?
Mama Fun Roll
Vaya, si. Gracias por señalar eso. (Por alguna razón, no puedo hacer @ (su nombre de usuario) ...)
ETHproductions
Probablemente porque los caracteres de mi nombre de usuario están al revés :)
Mama Fun Roll
1
Para techo, x%1?-~x:x(9 caracteres) es una mejor alternativa. Sin embargo, al igual que las alternativas de pisos 0|xy ~~x, solo funciona para números positivos.
Tomas Langkaas
9

En los casos en que está utilizando el operador ternario para elegir entre dos números , y el condicional es un booleano o un número 1 or 0 , puede realizar operaciones matemáticas en su lugar:

(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)

Nota: Además de esto, se tendrá que eliminar lo innecesario 0-, +0, +-etc.

Nota 2: hay un caso aislado donde (x) !== (x?1:0), como xdebe ser typeof === "number"para que funcione. Sin embargo, en el caso de (-x)que funcione bien.

Nota 3: en caso de que no encuentre ahorros, simplemente use el primero(x?y:z)

Anteriormente pensé que el método B nunca podría vencer a A, sin embargo, existen excepciones:

(x?97:100) //original

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

Creé un proyecto github que nos simplifica ( demo jsFiddle )

mellamokb
fuente
@ ajax333221 void 0(no es una función, sino una palabra clave) no es un valor, simplemente devuelve undefined.
Camilo Martin
@CamiloMartin tiene razón, también ahora veo el punto en esta respuesta, sin embargo, adebe ser 1 o 0 para que funcione
ajax333221
@ ajax333221 Sí, en realidad lo más divertido del golf de código para mí es que la mayoría de los mejores trucos solo funcionan para esa cosa en particular que estás haciendo, y uno se siente tan inteligente para encontrar uno de estos casos de esquina con soluciones de esquina: D Por el manera, no tienes que eliminar comentarios ...
Camilo Martin
9

tl; dr: ¡ Usa las funciones de ES6!

Funciones de flecha

Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Ejemplo:

s = x => x*x
// s = function (x) {
//   return x * x;
// }
Florent
fuente
Las funciones de flecha ya se mencionaron el 13 de octubre de 13 a las 15:42 . Pero eso for... ofes genial. Incluso más corto que for each.. in.
manatwork
2
La sintaxis de comprensión de matriz parece estar equivocada. De acuerdo con la documentación debe ser como en Python: b = [s(x) for (x of a)].
manatwork
@manatwork Las muestras anteriores funcionan bien en el REPL de Traceur
Florent
No tenía idea de Traceur, pero mencionó ECMAScript y señaló la documentación de Mozilla. Y la comprensión de la matriz en ninguno de ellos parece que la escribiste.
manatwork
1
Las comprensiones de matriz en realidad fueron extraídas a la mitad.
Isiah Meadows
9

Abusar de literales

La muestra reciente: compruebe si "c"es mayúscula o minúscula, no importa si no es letra

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case
l4m2
fuente
3
¿Como funciona esto?
Kritixi Lithos
2
@Cowsquack String({})da "[object Object]".
Dennis
8

Cómo comparar un número con la ayuda de cómo los números se convierten en booleanos:

Si va a verificar si algo es igual a un número positivo , puede restar esa cantidad e invertir lo que estaba dentro de los bloques ify 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();
}

Y en caso de que desee comparar con un número negativo (* diferente a -1), simplemente necesita sumar este número en lugar de restar.

* bueno, seguramente puedes usarlo x.indexOf(y) + 1, pero en el caso especial de -1que tengas la oportunidad de usarlo ~x.indexOf(y).

ajax333221
fuente
8

Utilice la función no estándar de "cierres de expresiones" de Mozilla para guardar muchos caracteres en un script que solo necesita funcionar en los motores SpiderMonkey / Firefox o Rhino. Por ejemplo,

function foo(){return bar}

se convierte

function foo()bar

Ver la página de desbordamiento de pila para más trucos.

Por favor levantese
fuente
2
Eso no es Javascript. Esa es una estación espacial!
Thomas Eding
1
ECMAScript 6 al rescate! ->bar
Ry-
55
ECMAScript 6: let foo = () => bar;irónicamente más corto que el código de golf anterior.
Isiah Meadows
1
ECMAScript 6: foo=_=>barincluso más corto.
ETHproductions
Ese enlace está roto.
Cyoce
8

En lugar de escribir truepuedes usar !0.

Wolle Vanillebär Lutz
fuente
44
Del mismo modo, !1para false.
James M. Lay
10
Mejor aún, use 1for truey 0for false, a menos que realmente necesite los valores literales.
ETHproductions
8

Transformando a un booleano :

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

Nota: Esto cambia 0, "", false, null, undefinedy NaNparafalse (todo lo demás a true)

ajax333221
fuente