Conseils pour jouer au golf en JavaScript


133

Quels conseils généraux avez-vous pour jouer au golf en JavaScript? Je recherche des idées pouvant être appliquées aux problèmes de code de golf en général, qui soient au moins quelque peu spécifiques à JavaScript (par exemple, "supprimer les commentaires" n'est pas une réponse).

Remarque: Voir également des astuces pour le golf dans ECMAScript 6 et versions ultérieures.


Je me demandais réellement, est-il autorisé à mettre des variables dans les sauvegardes globales var? Et le code de golf JavaScript doit-il être une fonction ou produire quelque chose directement? Honnêtement, je pense que cela peut faire beaucoup de différence.
pimvdb

1
@primvdb: C'est autorisé, mais vous devez faire attention car cela peut avoir des effets secondaires si une fonction est appelée plusieurs fois et manipule des variables globales, ou s'il s'agit d'une fonction récursive.
Mellamokb

Réponses:


108

Fantaisie pour les boucles

vous pouvez utiliser la norme pour la boucle de manière non standard

for ( a; b; c )

est essentiellement équivalent à:

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

Un bon truc consiste donc à écrire votre code avec une whileboucle, puis à le scinder en plusieurs a,b,cparties for.

Quelques exemples que j'ai écrits :

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

Enchaîner vos setters

Si vous initialisez ou réinitialisez plusieurs valeurs, enchaînez la valeur à toutes les variables qui en ont besoin:

a=b=1;

Casting implicite

Ne vérifiez pas vos types, utilisez-les tels quels. parseInt()coûts de 10caractères. Si vous avez besoin de sortir d'une chaîne, soyez créatif:

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;

Évitez les points-virgules

JavaScript a une insertion automatique de point-virgule. Utilisez-le souvent et bien.

Une ligne

Économisez sur les crochets en plaçant autant que possible en lignes simples ou paramètres:

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

Opérateurs d'incrémentation / décrémentation

a = a - 1;
foo(a);

et

foo(a);
a = a - 1;

peut facilement être réécrit comme

foo(--a);

et

foo(a--);

respectivement.

Utiliser thisou selfau lieu de windowdans un contexte global

Économies explicites de 2 caractères.

Utiliser la notation entre crochets pour l'accès aux propriétés répétées

Il s’agit bien d’un équilibre entre la longueur du nom de la propriété et le nombre d’accès. Au lieu d'appeler a.longFunctionName()deux fois avec la notation par points, il est plus court d'enregistrer le nom et d'appeler la fonction via la notation entre crochets:

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

-contre-

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

Ceci est particulièrement efficace avec des fonctions telles document.getElementByIdque celles pouvant être réduites à d[e].

Remarque:

Avec la notation entre crochets, le coût est 6 + name.lengthla première fois en caractères. Chaque accès ultérieur a un coût de3 caractères.

Pour la notation par points, tous les accès coûtent name.length + 1(+1 pour les .) caractères.

Utilisez cette méthode si 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = longueur du nom de la propriété
i = accès minimum à exploiter

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

Le nombre d'accès peut également couvrir plusieurs objets. Si vous accédez au moins .length4 fois sur des tableaux différents, vous pouvez utiliser la même variable contenant la chaîne 'length'.


5
c = ~~a-~~bdevrait être c = ~~a+~~b. En outre, vous pouvez implicitement transtyper en entier en utilisant |0, par exemple Math.random()*6|0.
Mellamokb

7
Il est moins coûteux de contraindre une chaîne à un numéro avec l'opérateur unaire plus. Si aet bsont des chaînes, vous pouvez faire +a+bpour convertir en nombre et les ajouter.
Peter Olson

8
Je jure que je vais utiliser d- -bun jour mon code ...
John Dvorak

4
+ a + b ne fonctionne pas (au moins sur le mien ...) // a = "1", b = "1", + a + b // donne "11"
imma

2
Pour "Utiliser Array-Access pour les appels de fonction répétés" si vous utilisez la fonction plus de deux fois sur le même objet , la solution un peu plus courte consiste à attribuer la fonction à un nouveau membre commea.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender le


56

Utilisez l'opérateur virgule pour éviter les accolades ( s'applique également à C ):

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

Au lieu de

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

qui est un caractère plus long.


2
Le point-virgule est-il nécessaire à la fin du premier échantillon?
wjl

4
@wjlafrance: Cela ne serait pas nécessaire si c'est à la fin du one-liner.
mellamokb

48

Génération de nombres aléatoires plus courte

Si vous avez besoin d'un booléen aléatoire ( 0ou 1):

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

Si vous avez besoin d'un entier aléatoire 0 <= n < 1337:

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

Cela fonctionne car a Dateest stocké en interne dans JavaScript sous forme de millisecondes depuis une époque. Il new Dateest donc forcé de le faire 123somebignumber456lorsque vous essayez de faire un calcul de nombre entier dessus.

Bien sûr, ces nombres "aléatoires" ne le seront pas vraiment, surtout si vous les appelez plusieurs fois de suite, gardez cela à l'esprit.


1
Je viens juste de me rappeler cette réponse en lisant plus de mensonges que les programmeurs croient au sujet du temps : «21. Si vous créez deux objets de date l'un à côté de l'autre, ils représentent la même heure. (un fantastique générateur de Heisenbug) ” .
Sebastian Simon

39

Vous pouvez utiliser la forme littérale d'objet de get / set pour éviter d'utiliser le mot-clé 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 partie getter / setter était vraiment utile. thx
gion_13

1
En fait, la méthode des objets est encore meilleure si vous ne l'utilisez que <= 2 fois. D'un autre côté, les fonctions fléchées sont bien meilleures pour réduire les caractères, car elles servent presque le même but, et les classes sont rarement utiles dans le code golfé.
Isiah Meadows

Si le support est important, les fonctions de flèche ne sont pas supportées par FX. ie11
Jim Wolff

35

Celui-ci est moins connu et moins utilisé, mais peut être impressionnant s'il est utilisé dans la bonne situation. Considérons une fonction qui ne prend aucun argument et retourne toujours un nombre différent à l'appel, et le nombre retourné sera utilisé dans un calcul:

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

Vous pouvez normalement raccourcir cette fonction en utilisant un nom de variable à une lettre:

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 meilleur moyen de réduire la longueur consiste à abuser valueOf, ce qui vous permet d'économiser 2 caractères par invocation. Utile si vous appelez la fonction plus de 5 fois:

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
Ou, vous pouvez le faire comme suit: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)ou let a=Array(7).map((_,i)=>i*Math.random()|0+5), 36 ou 42 octets enregistrés, respectivement.
Isiah Meadows

Est-il possible de le remplacer r()ou de le raccourcir?
NiCk Newman

3
r={valueOf:Math.random}C'est juste du génie: D
ETHproductions

1
@ Isiah, eh bien oui, vous pouvez le faire maintenant :-D
Andy E

32

Profiter des opérateurs de court-circuit

Plutôt que de longues ifdéclarations ou l'utilisation d'opérateurs ternaires, vous pouvez utiliser &&et ||raccourcir votre code. Par exemple:

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

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

peut devenir

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

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

L’ ||opérateur est souvent utilisé de cette manière pour définir les valeurs par défaut:

evt = evt || window.event;

C'est la même chose que d'écrire

if (!evt)
    evt = window.event;

Création de chaînes répétitives à l'aide de Array

Si vous souhaitez initialiser une longue chaîne d'un caractère particulier, vous pouvez le faire en créant un tableau de n + 1 , où n est le nombre de fois où vous souhaitez répéter le caractère:

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

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

Plus la chaîne est grosse, plus le gain est important.

Numéros d'analyse

Utilisez les opérateurs +et à la ~place de parseFloat()ou parseInt()lors de la fusion d'un type de chaîne qui n'est qu'un nombre à un type de nombre:

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

Méfiez-vous cependant, d'autres types peuvent être fusionnés avec ces opérateurs (par exemple, truedeviendraient 1), une chaîne vide ou une chaîne contenant uniquement des espaces deviendrait 0. Cela pourrait toutefois être utile dans certaines circonstances.


6
+1 pour la création de chaînes répétitives à l'aide de Array - n'y avait pas pensé.
Mellamokb

4
Pour créer des chaînes répétitives, dans ES6, vous pouvez utiliserstr.repeat(count)
Oriol

26

Faufiler l'initialisation d'une variable dans l'appel prompt () pour obtenir une entrée utilisateur

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

à la place d'utiliser

n=prompt();i=5;

En tant qu'effet secondaire, il affiche la valeur d'entrée dans la fenêtre d'invite tout en enregistrant 1 caractère.


12
Ceci peut également être appliqué à toute fonction qui n'accepte pas les arguments.
Casey Chu

3
Même lorsque la fonction accepte les arguments, cela peut être utile, comme [1,2,3].join('',i=5)dans les cas où elle enregistre une paire d'accolades.
DocMax

3
@ DocMax: Vous pouvez utiliser l'opérateur virgule pour cela - i=5,[1,2,3].join().
Konrad Borowski

@GlitchMr: Je pourrais, mais cela n'enregistre aucun personnage. Je conviens que la plupart du temps, ce sera plus propre. Je pense qu'il peut toujours arriver que ma commande sauve un personnage, bien que je ne puisse pas en proposer un pour le moment (et que je peux me tromper).
DocMax

@DocMax Uniquement si vous utilisez ASI.
Isiah Meadows

24

Combinez les boucles imbriquées:

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

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

Exemple avec différentes valeurs pour 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)

(J'ai édité une) faute de frappe mineure, mais très intelligente! Notez que cela ne fonctionnera que sur des boucles imbriquées de même longueur (sauf si je me trompe).
Camilo Martin

1
@ CamiloMartin Non, il n'est pas nécessaire que les boucles aient la même longueur. Le nombre d'itérations qui en résulte est i*jet les opérateurs de division / module récupèrent les valeurs individuelles de iet j.
quietmint

@ user113215 Vous avez raison, génial! :) J'ai modifié la réponse pour inclure un exemple.
Camilo Martin

23

Raccourcis Unicode

Si vous utilisez une propriété intégrée dans un grand défi de golf, vous pouvez aliaser chaque propriété avec un équivalent d'un personnage:

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

Après avoir exécuté le code ci-dessus, vous pouvez l'utiliser comme ceci:
"foo".Č(/.*/,'bar') // replaces foo with bar

Cela coûte 118 octets, donc cela peut ne pas être utile dans certaines situations

Cela peut dépendre du navigateur et je ne sais pas s'il est plus court with(Array){join(foo),...}ou si les variables sont définies comme propriétés utilisées, with(Array){j=join,m=map...}mais ça vaut la peine de le mentionner.

    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         

J'utilise Google Chrome, et ils donnent tous undefined.
SuperJedi224

Il doit alors être très spécifique à Firefox. Désolé pour le dérangement.
bebe

Pourquoi sont-ils tous des caractères spéciaux? Pourquoi ne pas simplement utiliser ASCII imprimable? (plus facile à taper, plus fiable, et seulement 1 octet pour jouer au golf)
Cyoce 10/02/2016

Cela ne fonctionne pas vraiment Mathparce qu'il n'a pas d' .prototypeattribut. En supprimant Math, cependant, j’ai réussi à en faire un extrait de 114 octets qui les assigne tous à des lettres à un octet. Vous pouvez le trouver ici .
ETHproductions

1
Vous pouvez également attribuer 106 octets à ma solution au détriment du déplacement de toutes ces propriétés dans la plage À- ÿ, qui correspond toujours à 1 octet dans le codage ISO-8859-1 (pris en charge par JS). Dans Firefox 50, la .localeCompareméthode est malheureusement activée ×, mais cela ne devrait généralement pas être un problème. source
ETHproductions

22

Convertir une whileboucle en forboucle est souvent équivalent:

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

Mais la seconde forme peut avoir une initialisation variable combinée:

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

Notez que la deuxième forme est un caractère plus court que la première.


6
Ou, mieux encore, utilisez simplement pour les boucles. Il n'y a vraiment pas de cas où l'utilisation d'une boucle for entraîne un code plus volumineux, autant que je sache.
Isiah Meadows

22

Exception abuser

au cas où les littéraux chaîne / caractère sont interdits, vous pouvez utiliser un bloc try catch:

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

maintenant strégale"something"

si plus de chaînes sont nécessaires, vous pouvez les chaîner avec un nombre (par exemple, des zéros)

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

maintenant arrégale["something", "foo", "bar", " is not defined"]


18

Si vous initialisez une variable à 1chaque itération d'une boucle (par exemple, en réinitialisant une variable dans une boucle externe pour une boucle interne), procédez comme suit (tiré de ma réponse à cette question ):

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

Puisque le résultat d'une condition comme j++<=nest 1chaque fois que sa valeur est true, vous pouvez simplement affecter la condition directement à la variable (car lorsqu'elle devient false, la boucle cessera de s'exécuter et n'aura plus d'importance):

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

Vous pouvez généralement enregistrer 2 caractères en utilisant cette méthode. En ce qui @ugorenconcerne l'idée dans les commentaires à cette réponse.


Pour un autre exemple, j’ai également appliqué cette astuce à ma réponse ici avec l’expression figurant w=r=++c<S.lengthdans ma boucle for externe, en sauvegardant au total 4 caractères.


18

Si vous pouvez accepter des scripts spécifiques à Spidermonkey (pour le moment), vous pouvez utiliser les fonctions de flèche ECMAScript 6 . Au lieu d'écrire du code comme suit.

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

Vous pouvez le raccourcir comme ça.

a.map(x=>x*2)

17

Si vous avez besoin de vérifier NaN, n'utilisez pas isNaN(x), mais utilisez x!=xqui est plus court et qui fonctionne aussi.

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

Notez que cela ne fonctionne que si typeof(x) === "number"; si c'est une chaîne par exemple, isNaN("string")retourne true, mais "string" != "string"retourne false. Merci à Cyoce de l'avoir signalé!


2
C'est une utilisation géniale de cette bizarrerie. +1
ETHproductions

Attention: ce ne sont pas toujours équivalents: isNaN("string")retourne true, alors que "string"!="string"retourne false(évidemment)
Cyoce 10/02/16

@ Cyoce Bon point, merci! J'ai édité ma réponse.
ProgramFOX

Dans de nombreux cas, vous pouvez même aller chercher if(!x){, si vous détectez NaNexplicitement.
Hohmannfan

1
La conversion xen nombre, le +x!=+xrend équivalent à isNaN(x)2 caractères plus courts. Ensuite, +"string"!=+"string"retourne vrai.
Tomas Langkaas

15

Tableau somme / produit / quotient

ES5 : 17 octets

eval(a.join('+'))

ES6 : 15 octets

eval(a.join`+`)

Bien sûr, vous pouvez échanger le +pour tout ce que vous voulez, par exemple *pour un produit ou /un quotient.


14

Utilisez une opération au niveau des bits pour arrondir un nombre vers zéro:

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

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

(Source: basculement aléatoire des dés )

La priorité de l'opérateur détermine laquelle sera la plus courte dans votre programme.


2
Ceci peut également être utilisé pour fusionner une entrée de chaîne en un entier, c'est-à-dire n=prompt()|0.
Mellamokb

1
bitwise est aussi super rapide par rapport à math.floor: jsperf.com/floor-vs-bitwise
vsync

@vsync: Bizarre. Math.floor est environ deux fois plus rapide que bitwise sur Chrome 11.0.696.77.
Mellamokb

très étrange. pour moi, ils sont plus ou moins les mêmes vitesses et très rapides sous Chrome, mais en FF, le bitwise est beaucoup plus rapide que Chrome, et il Math.floorest terriblement lent ... la plupart ne devraient pas être utilisés, je dirais.
vsync

Pour garder les commentaires à jour, dans la Fx actuelle, ils sont à la fois rapides et à peu près égaux. Ce n'est pas que cela risque d'être un goulot d'étranglement en premier lieu, comparé au code environnant ...
FireFly

14

Astuce en boucle I

Vous pouvez sauvegarder un 1caractère en boucle en modifiant ile dernier temps utilisé:

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

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

Remarque: fonctionne avec --aussi (mais modifiez la boucle en conséquence pour éviter une boucle infinie)


Looping Tip II

Il existe certains scénarios dans lesquels vous pouvez enregistrer un personnage en jouant avec l'opérateur et les valeurs d'incrémentation:

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

Remarque: vous devez faire attention lorsque, par exemple 0 to -1. et 9 to 10, 99 to 100, alors jouez jusqu'à ce que vous trouviez un moyen de sauver le personnage


13

Utiliser ^au lieu de !=ou ==en comparant à un entier

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

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

Remplacer les appels aux fonctions mathématiques intégrées par des expressions plus courtes

//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
Alternativement, vous pouvez simplement utiliser -au lieu de !=pour les entiers; Par exemple, n!=1?a:bserait équivalent àn-1?a:b
vrugtehagel

10

Il est intéressant de noter que vous pouvez utiliser une chaîne à la place de zéro dans certains cas pour sauvegarder quelques octets ici et là dans des boucles:

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

1
J'ai essayé "" ++ dans la console plus tôt en me demandant si cela fonctionnerait, bien sûr, il doit d'abord être dans une variable. Merci!
Vartan

10

Très simple, même ainsi, personne n'en avait parlé.

Si vous utilisez Math.min()ou Math.max()vous pouvez enregistrer 6 caractères en procédant comme suit:

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

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

10

Arrondi

Je sais que des alternatives à Math.floor() ont été postées, mais qu'en est-il des autres?

Sol:

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

Arrondi:

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

Plafond:

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

1
Notez que 0|x+1simplement ajoute 1 si le nombre dont vous voulez trouver le plafond est déjà un entier. Une alternative (généralement) sûre est 0|x+1-1e9, mais ce n'est que trois octets plus court.
ETHproductions

@ETHproductions tu ne veux pas dire 0|x+1-1e-9?
Mama Fun Roll

Oups, ouais. Merci d'avoir fait remarquer cela. (Pour une raison quelconque, je ne peux pas faire @ (votre nom d'utilisateur) ...)
ETHproductions

Probablement parce que mes caractères de nom d'utilisateur sont à l'envers :)
Mama Fun Roll

1
Pour le plafond, x%1?-~x:x(9 caractères) est une meilleure alternative. Cependant, comme les alternatives de sol 0|xet ~~x, il ne fonctionne que pour les nombres positifs.
Tomas Langkaas

9

Dans les cas où vous utilisez l'opérateur ternaire pour choisir entre deux nombres et que le conditionnel est un booléen ou un nombre 1 or 0 , vous pouvez effectuer des opérations mathématiques à la place:

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

Remarque: En plus de cela, vous devrez supprimer l'inutile 0-, +0, +-etc.

Note 2: il existe un cas isolé où (x) !== (x?1:0), comme xil se doit typeof === "number"pour que cela fonctionne. Cependant, dans le cas de (-x)cela fonctionne très bien.

Note3: Si vous ne trouvez pas d’épargne, utilisez simplement l’ancien(x?y:z)

Auparavant, je pensais que la méthode B ne pourrait jamais battre A, bien que des exceptions existent:

(x?97:100) //original

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

J'ai créé un projet github qui nous simplifie la tâche ( démo jsFiddle )


@ ajax333221 void 0(ce n'est pas une fonction, mais un mot clé) n'est pas une valeur, il retourne simplement undefined.
Camilo Martin

@CamiloMartin vous avez raison, je vois aussi maintenant le sens de cette réponse, mais il adoit être
égal à

@ ajax333221 Oui, ce qui est amusant avec le code de golf, c'est que la plupart des meilleurs tricks ne fonctionnent que pour ce que vous faites, et on se sent si malin de trouver l'un de ces cas d'angle avec des solutions d'angle: D By the ainsi, vous ne devez supprimer des commentaires ...
Camilo Martin

9

tl; dr: Utilisez les fonctionnalités de l'ES6!

Fonctions de flèche

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

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

Les fonctions de flèches ont déjà été mentionnées le 13 octobre 2013 à 15h42 . Mais ça for.. ofc'est cool. Même plus courte que for each.. in.
Manatwork

2
La syntaxe de compréhension du tableau semble être fausse. Selon la documentation devrait être comme en Python: b = [s(x) for (x of a)].
Manatwork

@manatwork Les exemples ci-dessus fonctionnent bien dans la REPL de Traceur
Florent

Aucune idée de Traceur, mais vous avez mentionné ECMAScript et pointé vers la documentation de Mozilla. Et la compréhension du tableau dans aucun d'entre eux ne ressemble à ce que vous avez écrit.
Manatwork

1
Les compréhensions de la matrice ont en fait été tirées à mi-parcours.
Isiah Meadows

9

Abuser des littéraux

Exemple récent: Vérifiez si "c"les lettres sont majuscules ou minuscules, peu importe la lettre

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

3
Comment cela marche-t-il?
Kritixi Lithos

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

8

Comment comparer un nombre avec l'aide de comment les nombres se transforment en booléens:

Si vous voulez vérifier si quelque chose est égal à un nombre positif , vous pouvez soustraire ce montant et inverser ce qui était à l'intérieur des blocs ifet 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();
}

Et au cas où vous voudriez comparer avec un nombre négatif (* différent de -1), il vous suffit simplement d’ ajouter ce nombre au lieu de le soustraire.

* Bien, vous pouvez sûrement utiliser x.indexOf(y) + 1, mais dans le cas particulier de -1vous avez la possibilité d'utiliser à la ~x.indexOf(y)place.


8

Utilisez la fonctionnalité non standard de "fermeture d’expression" de Mozilla pour enregistrer dans un script de nombreux caractères devant uniquement fonctionner dans les moteurs SpiderMonkey / Firefox ou Rhino. Par exemple,

function foo(){return bar}

devient

function foo()bar

Voir la page Dépassement de pile pour plus de telles astuces.


2
Ce n'est pas Javascript. C'est une station spatiale !!!
Thomas Eding

1
ECMAScript 6 à la rescousse! ->bar
Ry-

5
ECMAScript 6:, let foo = () => bar;ironiquement plus court que le code golfé ci-dessus.
Isiah Meadows

1
ECMAScript 6:, foo=_=>barmême plus court.
ETHproductions

ce lien est cassé.
Cyoce



8

Transformation en booléen :

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

Note: Cela change 0, "", false, null, undefinedet NaNà false(tout le reste true)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.