Suggerimenti per giocare a golf in JavaScript


133

Quali consigli generali hai per giocare a golf in JavaScript? Sto cercando idee che possano essere applicate ai problemi del codice golf in generale che siano almeno in qualche modo specifiche per JavaScript (ad esempio "rimuovere i commenti" non è una risposta).

Nota: vedere anche Suggerimenti per giocare a golf in ECMAScript 6 e versioni successive


In realtà mi stavo chiedendo, è permesso mettere variabili nel globale (salvataggi var)? E il codice golf di JavaScript dovrebbe essere una funzione o produrre qualcosa direttamente? Sinceramente penso che questo possa fare molta differenza.
pimvdb,

1
@primvdb: è consentito, ma devi fare attenzione perché può causare effetti collaterali se una funzione viene chiamata più volte e sta manipolando variabili globali o se è una funzione ricorsiva.
mellamokb,

Risposte:


108

Fantasia per loop

puoi usare lo standard per loop in modi non standard

for ( a; b; c )

è sostanzialmente equivalente a:

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

quindi un buon trucco è scrivere il codice con un whileciclo e quindi dividerlo nelle a,b,cparti in un forciclo.

Un paio di esempi che ho scritto :

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

Incatena i tuoi setter

Se stai inizializzando o reimpostando più valori, concatenalo su tutte le variabili che ne hanno bisogno:

a=b=1;

Casting implicito

Non controllare i tuoi tipi, basta usarli così come sono. parseInt()costa 10personaggi. Se devi eseguire il cast di una stringa, sii 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;

Evita punti e virgola

JavaScript ha l'inserimento automatico di punti e virgola. Usalo spesso e bene.

One-liner

Risparmia tra parentesi spostando il più possibile in singole righe o parametri:

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

Operatori di incremento / decremento

a = a - 1;
foo(a);

e

foo(a);
a = a - 1;

può essere facilmente riscritto come

foo(--a);

e

foo(a--);

rispettivamente.

Utilizzare thiso selfanziché windownel contesto globale

autoesplicativo risparmio di 2 caratteri.

Utilizzare la notazione parentesi per ripetere l'accesso alle proprietà

Questo è sicuramente un atto di bilanciamento tra lunghezza del nome della proprietà e numero di accessi. Invece di chiamare a.longFunctionName()due volte con la notazione a punti, è più breve salvare il nome e chiamare la funzione tramite la notazione a parentesi:

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

-confrontarli-

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

questo è particolarmente efficace con funzioni come quelle document.getElementByIdche possono essere ridotte a d[e].

Nota:

Con la notazione parentesi, il costo è in 6 + name.lengthcaratteri la prima volta. Ogni accesso successivo ha un costo di 3caratteri.

Per la notazione punto, tutti gli accessi costano name.length + 1(+1 per i .) caratteri.

Utilizzare questo metodo se 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = lunghezza del nome della proprietà
i = accessi minimi per trarne vantaggio

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

Il numero di accessi può anche comprendere più oggetti. Se si accede .length4 o più volte su array diversi, è possibile utilizzare la stessa variabile che contiene la stringa 'length'.


5
c = ~~a-~~bdovrebbe essere c = ~~a+~~b. Inoltre, puoi implicitamente eseguire il cast in numero intero usando |0, ad esempio Math.random()*6|0.
mellamokb,

7
È più economico forzare una stringa in un numero con l'operatore unario positivo. Se ae bsono stringhe, puoi eseguire la +a+bconversione in numero e aggiungerle.
Peter Olson,

8
Giuro che d- -bun giorno userò il mio codice ...
John Dvorak il

4
+ a + b non funziona (almeno sul mio ...) // a = "1", b = "1", + a + b // dà "11"
imma

2
Per "Usa Array-Access per ripetute chiamate di funzione" se stai usando la funzione più di due volte sullo stesso oggetto , ciò che è un po 'più breve è assegnare la funzione a un nuovo membro comea.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender,


56

Utilizzare l'operatore virgola per evitare le parentesi graffe ( vale anche per C ):

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

Invece di

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

che è un personaggio più lungo.


2
Il punto e virgola è necessario alla fine del primo campione?
wjl

4
@wjlafrance: non sarebbe necessario solo se si trovasse alla fine del one-liner.
mellamokb,

48

Generazione di numeri casuali più breve

Se hai bisogno di un booleano casuale ( 0o 1):

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

Se hai bisogno di un numero intero casuale 0 <= n < 1337:

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

Ciò funziona perché a Dateviene memorizzato internamente in JavaScript come la quantità di millisecondi trascorsi da un'epoca, quindi new Dateviene forzato 123somebignumber456quando si tenta di eseguire la matematica intera su di esso.

Naturalmente, questi numeri "casuali" non saranno così casuali, specialmente se li chiami più volte in rapida successione, quindi tienilo a mente.


1
Ho appena ricordato questa risposta durante la lettura di più falsità che i programmatori credono sul tempo : “21. Se crei due oggetti data uno accanto all'altro, rappresenteranno la stessa ora. (un fantastico generatore di Heisenbug) ” .
Sebastian Simon

39

È possibile utilizzare la forma letterale dell'oggetto get / set per evitare di usare la parola chiave 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)

la parte getter / setter è stata davvero utile. thx
gion_13

1
In realtà, anche meglio è un metodo oggetto, se lo usi solo <= 2 volte. D'altra parte, le funzioni delle frecce sono molto più efficaci nel ridurre i caratteri, poiché servono quasi allo stesso scopo e le classi raramente sono utili nel codice golf.
Isiah Meadows,

se il supporto è importante, le funzioni freccia non sono supportate in fx. ie11
Jim Wolff,

35

Questo è meno conosciuto e meno usato, ma può essere impressionante se usato nella giusta situazione. Considera una funzione che non accetta argomenti e restituisce sempre un numero diverso quando viene chiamata e il numero restituito verrà utilizzato in un calcolo:

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

Normalmente è possibile abbreviare questa funzione utilizzando un nome variabile a lettera singola:

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

Un modo migliore per ridurre la lunghezza è l'abuso valueOf, che consente di risparmiare 2 caratteri per invocazione. Utile se si chiama la funzione più di 5 volte:

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
Oppure, potresti farlo come uno di questi: 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), rispettivamente, 36 o 42 byte salvati.
Isiah Meadows,

È possibile sostituire r()o abbreviare?
NiCk Newman,

3
r={valueOf:Math.random}Questo è solo geniale: D
ETHproductions

1
@Isiah, beh sì, puoi farlo ora :-D
Andy E

32

Approfittando degli operatori di corto circuito

Piuttosto che ifdichiarazioni lunghe o l'utilizzo di operatori ternari, è possibile utilizzare &&e ||abbreviare il codice. Per esempio:

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

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

può diventare

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

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

L' ||operatore viene spesso utilizzato in questo modo per impostare i valori predefiniti:

evt = evt || window.event;

È lo stesso della scrittura

if (!evt)
    evt = window.event;

Creazione di stringhe ripetitive utilizzando Array

Se vuoi inizializzare una lunga stringa di un particolare carattere, puoi farlo creando un array con una lunghezza di n + 1 , dove n è il numero di volte in cui desideri ripetere il carattere:

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

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

Maggiore è la stringa, maggiore è il risparmio.

Analisi dei numeri

Utilizzare +e ~operatori invece di parseFloat()o parseInt()quando si unisce un tipo di stringa che è solo un numero a un tipo di numero:

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

Diffidare però, altri tipi possono essere coalizzati con questi operatori (ad esempio, truediventerebbe 1) una stringa vuota o una stringa contenente solo uno spazio bianco diventerebbe 0. Ciò potrebbe essere utile in determinate circostanze, tuttavia.


6
+1 per la creazione di stringhe ripetitive utilizzando Array - non ci avevo pensato.
mellamokb,

4
Per creare stringhe ripetitive, in ES6 è possibile utilizzarestr.repeat(count)
Oriol

26

Inizializza di nascosto la variabile nella richiesta () per ottenere l'input dell'utente

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

invece di usare

n=prompt();i=5;

Come effetto collaterale, visualizza il valore di input nella finestra del prompt mentre si salva 1 carattere.


12
Questo può essere applicato anche a qualsiasi funzione che non accetta argomenti.
Casey Chu,

3
Anche quando la funzione accetta argomenti, può essere utile, come [1,2,3].join('',i=5)nei casi in cui salva un paio di parentesi graffe.
DocMax,

3
@DocMax: potresti usare l'operatore virgola per quello - i=5,[1,2,3].join().
Konrad Borowski il

@GlitchMr: Potrei, ma non salva alcun personaggio. Sono d'accordo che il più delle volte sarà più pulito. Penso che potrebbero esserci ancora casi in cui il mio ordine potrebbe salvare un carattere, anche se al momento non riesco a trovarne uno (e potrei anche sbagliarmi).
DocMax,

@DocMax Solo se stai sfruttando l'ASI.
Isiah Meadows,

24

Combina nidificato per loop:

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

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

Esempio con valori diversi per 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)

(Ho modificato un) piccolo errore di battitura, ma molto intelligente! Nota che funzionerà solo su loop nidificati della stessa lunghezza (a meno che non mi sbagli).
Camilo Martin,

1
@CamiloMartin No, i loop non devono avere la stessa lunghezza. Il numero risultante di iterazioni è i*je gli operatori di divisione / modulo recuperano i singoli valori di ie j.
quietmint

@ user113215 Hai ragione, fantastico! :) Ho modificato la risposta per includere un esempio.
Camilo Martin,

23

Scorciatoie Unicode

Se usi un inferno di una proprietà incorporata in una grande sfida di golf puoi alias ogni proprietà con un equivalente di un personaggio:

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

Dopo aver eseguito il codice sopra puoi usarlo in questo modo:
"foo".Č(/.*/,'bar') // replaces foo with bar

Questo costa 118 byte, quindi potrebbe non essere utile in determinate situazioni

Potrebbe dipendere dal browser e non sono sicuro che sia più breve with(Array){join(foo),...}o che definisca le variabili come proprietà usate, with(Array){j=join,m=map...}ma vale comunque la pena menzionarle.

    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         

Sto usando Google Chrome, e questi stanno dando indefiniti.
SuperJedi224,

Quindi deve essere specifico per Firefox. Ci dispiace per l'inconvenienza.
Bebe,

Perché sono tutti personaggi speciali? Perché non usare solo ASCII stampabile? (più facile da digitare, più affidabile e solo 1 byte per il golf)
Cyoce,

Questo non funziona davvero Mathperché non ha un .prototypeattributo. Rimuovendo Math, però, sono riuscito a golfare questo fino a uno snippet di 114 byte che li assegna tutti a lettere a byte singolo. Puoi trovarlo qui .
ETHproductions

1
Si può anche golf la mia soluzione a 106 byte a spese di spostamento di tutte queste proprietà per la gamma À- ÿ, che è ancora 1 byte ciascuno nella codifica ISO-8859-1 (che supporta JS). In Firefox 50, questo purtroppo mette il .localeComparemetodo su ×, ma di solito non dovrebbe essere un problema. fonte
ETHproductions

22

La conversione di un whileloop in un forloop è spesso equivalente:

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

Ma il secondo modulo può avere un'inizializzazione variabile combinata:

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

Si noti che il secondo modulo è più corto di un carattere rispetto al primo modulo.


6
O, ancora meglio, basta usare per i loop. Non c'è davvero nessun caso in cui l'utilizzo di un ciclo for si traduca in un codice più grande, per quanto ne ho sperimentato.
Isiah Meadows,

22

Abuso di eccezione

nel caso in cui i letterali stringa / carattere siano vietati, è possibile utilizzare un blocco catch catch:

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

ora è struguale"something"

se sono necessarie più stringhe, è possibile concatenarle con un numero (ad es. zeri)

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

ora è arruguale["something", "foo", "bar", " is not defined"]


18

Se stai inizializzando una variabile 1in ogni iterazione di un ciclo (ad esempio, reimpostando una variabile in un ciclo esterno per un ciclo interno), come il seguente (dalla mia risposta a questa domanda ):

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

Poiché il risultato di una condizione come j++<=nè 1ogni volta che è vero, puoi semplicemente assegnare la condizione direttamente alla variabile (perché quando diventa falso, il ciclo smetterà di essere eseguito e non avrà più importanza):

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

Di solito puoi salvare 2 caratteri usando questo metodo. Saluti @ugorenper l'idea nei commenti a quella risposta.


Per un altro esempio, ho anche applicato questo trucco alla mia risposta qui con l'espressione w=r=++c<S.lengthnel mio ciclo esterno, salvando un totale di 4 caratteri.


18

Se è possibile accettare script specifici di Spidermonkey (per ora), è possibile utilizzare le funzioni freccia ECMAScript 6 . Invece di scrivere codice come il seguente.

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

Puoi accorciarlo in questo modo.

a.map(x=>x*2)

17

Se è necessario verificare la presenza di NaN, non utilizzare isNaN(x), ma utilizzare x!=x, che è più breve e funziona anche.

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

Nota che funziona solo se typeof(x) === "number"; se ad esempio è una stringa, isNaN("string")restituisce true, ma "string" != "string"restituisce false. Grazie a Cyoce per averlo segnalato!


2
Questo è un uso geniale di questa stranezza. +1
ETHproductions

Attenzione: questi non sono sempre equivalenti: isNaN("string")ritorni true, mentre "string"!="string"ritorni false(ovviamente)
Cyoce

@Cyoce Ottimo punto, grazie! Ho modificato la mia risposta.
ProgramFOX,

In molti casi, puoi persino cercare if(!x){, se stai rilevando NaNesplicitamente.
Hohmannfan,

1
Casting xin numero, +x!=+xlo rende equivalente a isNaN(x), ma ancora di 2 caratteri più corto. Quindi, +"string"!=+"string"restituisce true.
Tomas Langkaas,

15

Somma matrice / prodotto / quoziente

ES5 : 17 byte

eval(a.join('+'))

ES6 : 15 byte

eval(a.join`+`)

Ovviamente puoi scambiarlo +con tutto quello che vuoi, ad es. *Per prodotto o /per quoziente.


14

Utilizzare un'operazione bit a bit per arrotondare un numero verso zero:

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

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

(Fonte: ribaltamento casuale dei dadi )

La precedenza dell'operatore determina quale sarà più breve nel programma.


2
Questo può anche essere usato per fondere un input di stringa in un numero intero, cioè n=prompt()|0.
mellamokb,

1
bitwise è anche super veloce rispetto a math.floor: jsperf.com/floor-vs-bitwise
vsync

@vsync: Weird. Ottengo math.floor per essere circa due volte più veloce di bit su Chrome 11.0.696.77.
mellamokb,

molto strano. per me sono entrambe più o meno le stesse velocità e super veloci in Chrome, ma in FF il bit a bit è molto più veloce di Chrome, ed Math.floorè terribilmente lento ... quasi non dovrei usare, direi.
vsync,

Per mantenere aggiornati i commenti, nell'attuale Fx sono entrambi veloci e quasi uguali. Non che sia probabilmente un collo di bottiglia in primo luogo, rispetto al codice circostante ...
FireFly

14

Consiglio ad anello I

Puoi salvare il 1personaggio durante il loop modificando il'ultima volta utilizzata:

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

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

Nota: funziona --anche con (ma modifica il loop di conseguenza per evitare loop infiniti)


Punta ad anello II

Esistono alcuni scenari in cui è possibile salvare un personaggio giocando con l'operatore e i valori incrementali:

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

Nota: è necessario prestare attenzione, ad esempio 0 to -1. e 9 to 10, 99 to 100, quindi, gioca fino a trovare un modo per salvare il personaggio


13

Utilizzare ^invece di !=o ==quando si confronta con un numero intero

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

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

Sostituisci le chiamate alle funzioni matematiche integrate con espressioni più brevi

//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
In alternativa, puoi semplicemente usare -invece di !=interi; Ad esempio, n!=1?a:bsarebbe equivalente an-1?a:b
vrugtehagel

10

Una cosa degna di nota è che in alcuni casi è possibile utilizzare una stringa al posto di zero per salvare un paio di byte qua e là nei loop:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10

1
Ho provato "" ++ nella console prima chiedendomi se avrebbe funzionato, ovviamente prima doveva essere in una variabile. Grazie!
Vartan,

10

Molto semplice, anche così, nessuno l'aveva menzionato.

Se stai usando Math.min()o Math.max()puoi salvare 6 caratteri in questo modo:

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

Math.max(a,b)
a>b?a:b

10

Arrotondamento

So che Math.floor()sono state pubblicate delle alternative , ma per quanto riguarda le altre?

Pavimentazione:

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

Arrotondamento:

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

Soffitto:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas

1
Si noti che 0|x+1aggiunge semplicemente 1 se il numero di cui si desidera trovare il limite è già un numero intero. Un'alternativa (principalmente) sicura è 0|x+1-1e9, ma questo è solo tre byte più breve.
ETHproductions

@ETHproductions non intendi 0|x+1-1e-9?
Mama Fun Roll

Oops, si. Grazie per la segnalazione. (Per qualche motivo, non posso fare @ (il tuo nome utente) ...)
ETHproductions

Probabilmente perché i miei caratteri nome utente sono capovolti :)
Mama Fun Roll

1
Per il soffitto, x%1?-~x:x(9 caratteri) è un'alternativa migliore. Tuttavia, come le alternative di pavimentazione 0|xe ~~x, funziona solo per numeri positivi.
Tomas Langkaas,

9

Nei casi in cui stai utilizzando l'operatore ternario per scegliere tra due numeri e il condizionale è un valore booleano o un numero 1 or 0 , puoi invece eseguire operazioni matematiche:

(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: In aggiunta a questo, è necessario rimuovere il superfluo 0-, +0, +-etc.

Nota2: esiste un caso isolato in cui (x) !== (x?1:0), come xdeve essere typeof === "number"perché funzioni. Tuttavia, nel caso in cui (-x)funzioni bene.

Nota 3: Nel caso in cui non trovi risparmi, utilizza semplicemente il primo(x?y:z)

In precedenza pensavo che il metodo B non potesse mai battere A, tuttavia esistono eccezioni:

(x?97:100) //original

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

Ho creato un progetto github che ci semplifica ( demo jsFiddle )


@ ajax333221 void 0(non è una funzione, ma una parola chiave) non è un valore, semplicemente restituisce undefined.
Camilo Martin,

@CamiloMartin hai ragione, anche ora vedo il punto in questa risposta, tuttavia adeve essere 1 o 0 affinché funzioni
ajax333221

@ ajax333221 Sì, in realtà la cosa divertente del golf del codice per me è che la maggior parte dei migliori trucchi funziona solo per quella particolare cosa che stai facendo, e ci si sente così intelligenti a trovare uno di questi casi d'angolo con soluzioni d'angolo: D modo, non è necessario eliminare i commenti ...
Camilo Martin

9

tl; dr: usa le funzionalità ES6!

Funzioni freccia

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

s = x => x*x
// s = function (x) {
//   return x * x;
// }

Le funzioni freccia erano già menzionate il 13 ottobre 13 alle 15:42 . Ma quello for.. ofè bello. Anche più breve di for each.. in.
arte

2
La sintassi di comprensione dell'array sembra essere errata. In base alla documentazione dovrebbe essere come in Python: b = [s(x) for (x of a)].
arte

@manatwork I campioni sopra riportati vanno bene nel REPL di Traceur
Florent

Nessuna idea di Traceur, ma hai menzionato ECMAScript e indicato la documentazione di Mozilla. E la comprensione di array in nessuno di essi sembra che tu l'abbia scritto.
arte

1
Le comprensioni dell'array sono state effettivamente tirate a metà strada.
Isiah Meadows,

9

Abuso letterale

Il campione recente: controlla se "c"è maiuscolo o minuscolo, non importa se non lettera

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case

3
Come funziona?
Kritixi Lithos,

2
@Cowsquack String({})"[object Object]".
Dennis,

8

Come confrontare un numero con l'aiuto di come i numeri si trasformano in booleani:

Se hai intenzione di verificare se qualcosa è uguale a un numero positivo , puoi sottrarre tale importo e invertire ciò che era all'interno dei blocchi ife 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();
}

E nel caso in cui si desideri confrontare un numero negativo (* diverso da -1), è sufficiente aggiungere questo numero invece di sottrarre.

* bene, puoi sicuramente usarlo x.indexOf(y) + 1, ma nel caso speciale -1hai la possibilità di usarlo ~x.indexOf(y)invece.


8

Usa la funzione "chiusure" non standard di Mozilla per salvare molti personaggi in uno script che deve funzionare solo nei motori SpiderMonkey / Firefox o Rhino. Per esempio,

function foo(){return bar}

diventa

function foo()bar

Vedi la pagina Stack Overflow per ulteriori trucchi.


2
Questo non è Javascript. Questa è una STAZIONE SPAZIALE !!!
Thomas Eding,

1
ECMAScript 6 in soccorso! ->bar
Ry,

5
ECMAScript 6:, let foo = () => bar;ironicamente più breve del codice golf sopra.
Isiah Meadows,

1
ECMAScript 6:, foo=_=>barancora più breve.
ETHproductions

quel collegamento è rotto.
Cyoce,



8

Trasformarsi in un booleano :

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

Nota: Questo cambia 0, "", false, null, undefinede NaNper false(tutto il resto a true)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.