Zut, je pars en week-end ... j'aurai pas le temps de chercher avant lundi ! :mrgreen:
SpaceFrog : C'est marrant, j'ai justement commencé un truc de ce genre y'a deux jours. Une sorte de Flappy Bird en 140bytes
Version imprimable
Zut, je pars en week-end ... j'aurai pas le temps de chercher avant lundi ! :mrgreen:
SpaceFrog : C'est marrant, j'ai justement commencé un truc de ce genre y'a deux jours. Une sorte de Flappy Bird en 140bytes
Bon allez, ma première intervention sur ce topic :)
J'ai pris ces cas de test, je préfère préciser :
J'ai mis un moment à comprendre qu'on a bien un fonctionnement en pile mais que les opérandes sont prises « à rebrousse-poil » par rapport au sens de la pile :aie:Code:
1
2
3 console.assert(npi("1 2 + 4 * 3 +") === 15); console.assert(npi("99 27 - 4 /") === 18); console.assert(npi("23 7 4 - -") === 20);
Donc voilà, 116 caractères à gros coups d'arrow functions !
Avec un peu d'aération ça donne ça :Code:p=[],o=_=>p.pop(),u=x=>p.push(x);s.split(/\s+/).forEach(t=>/\d+/.test(t)?u(t):(z=o(),u(eval(o()+t+z))));return p[0];
J'ai un peu mal à mon honneur d'avoir utilisé eval mais il faut avouer que ça simplifie beaucoup le travail ;)Code:
1
2
3
4
5
6
7
8
9
10
11 function npi(s){ p = [], // la pile o = _ => p.pop(), u = x => p.push(x); s.split(/\s+/).forEach( // découpe la chaîne en tokens t => /\d+/.test(t) ? // si c'est un nombre u(t) : (z = o(), u( eval(o() + t + z) )) // dépile deux fois, inverse, calcule et rempile ); return p[0]; }
Hmm je ne sais pas si on peut autoriser ES6, dans les règles il est précisé qu'il faut que ça tourne sur Chrome et Firefox et sans aller bricoler dans les réglages expérimentaux pour un support anticipé des arrow functions :)
Ceci dit mon code est très semblable au tien mais n'utilise pas les arrow functions tout en étant plus court. Une boucle for fait souvent plus court qu'un forEach, et la déclaration des pop et push ne fait pas économiser de caractères ici.
Ce topic a l'avantage de m'apprendre beaucoup de chose :P premièrement j'ai pas le niveau :) deuxièmement beaucoup de méthode, notation qui m'était inconnues.
Je vais me pencher sur les arrow function aujourd'hui :)
Par contre juste une question... peux tu donner une solution sans eval( ) ?
ça m'intéresse fortement ce genre de code :)
:koi:Citation:
Ceci dit mon code est très semblable
Le dernier que tu aies posté, c'est
Alors je veux bien admettre qu'il soit plus court, mais son efficacité me semble douteuse... :?Code:
1
2
3 function npi(s){ //votre code ici }
:pastaper:
Ok alors si j'enlève mes déclarations de pop et push, ainsi que… le point-virgule final (sans blague, je l'avais oublié celui-là) j'arrive à 105, et si je retire la fonction arrow qui reste et que je remplace mon forEach par une boucle for, je remonte à 109.
Et j'ai réussi à gratter un caractère sur mon expression régulière, ce qui fait 108 :P
Code:p=[];for(i=0;t=s.split(/\s+/)[i++];)/\D/.test(t)?(z=p.pop(),p.push(eval(p.pop()+t+z))):p.push(t);return p[0]
Je réfléchis encore pour une solution sans eval.Code:
1
2
3
4
5
6
7
8 function npi(s){ p = []; for (i = 0; t = s.split(/\s+/)[i++];) /\D/.test(t) ? (z = p.pop(), p.push( eval(p.pop() + t + z) )) : p.push(t); return p[0]; }
watilin => avec window ?
@Bovino : je n'ai pas dit que je l'avais posté. Il est sur mon autre poste, je le posterais ce soir. De mémoire il fait 89 caractères et c'est quasiment le même que Watilin, à part que les deux p.push sont combinés en un et que mon test d'entier est plus court
Sans eval, le code explose vite en taille. Il n'y a pas vraiment 36 solutions pour passer de caractères à opérateurs mathématiques.
131 sans eval !
Code:p=[];s.replace(/(\d+)|(\+)|(-)|(\*)|\//g,function(_,n,a,b,c){p.push(n*1||(y=p.pop(),x=p.pop(),a?x+y:b?x-y:c?x*y:x/y))});return p[0]
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 function npi(s){ p = []; s.replace(/(\d+)|(\+)|(-)|(\*)|\//g, function( _, n, a, b, c ){ p.push(n * 1 || ( y = p.pop(), x = p.pop(), a ? x + y : b ? x - y : c ? x * y : x / y)) }); return p[0] }
Voici ma réponse :
107 caractères.Code:for(i=n=[];x=s.split(" ")[i++];)if(isNaN(+x)){a=n.pop();n.push(r=eval(n.pop()+x+a))}else n.push(x);return r
Bon, je retourne déchiffrer les solutions de Watilin, c'est un joli cours de Javascript, grâce à ces défis j'en apprends de plus en plus. Merci !!
Attention Watlin ton test n*1|| ne marche pas pour les valeurs zéro. Mais bien joué pour la version sans eval en moins de 140 ;)
Salut les fous furieux des neurones en folie!
et pour quelques caractères de moins
à partir de l'offre de Watilin en 108
remplacement de z=p.pop() par t+=p.pop() d'où eval(p.pop()+t).Code:for(i=0,p=[];t=s.split(/\s+/)[i++];)/\D/.test(t)?(z=p.pop(),p.push(eval(p.pop()+t+z))):p.push(t);return p[0]
puis si l'on considère un espace unique consécutifCode:for(i=0,p=[];t=s.split(/\s+/)[i++];)/\D/.test(t)?(t+=p.pop(),p.push(eval(p.pop()+t))):p.push(t);return p[0]
et l'utilisation de Barsy concernant l'affectation du résultat de evalCode:for(i=0,p=[];t=s.split(' ')[i++];)/\D/.test(t)?(t+=p.pop(),p.push(eval(p.pop()+t))):p.push(t);return p[0]
on peut gagner encore 2 en utilisant l’initialisation de Barsy, je dois admettre que je ne l'aurait pas tentéCode:for(i=0,p=[];t=s.split(' ')[i++];)/\D/.test(t)?(t+=p.pop(),p.push(r=eval(p.pop()+t))):p.push(t);return r
on arrive à 101Code:for(i=p=[];t=s.split(' ')[i++];)/\D/.test(t)?(t+=p.pop(),p.push(r=eval(p.pop()+t))):p.push(t);return r
à partir de l'offre de Barsy en 107, le isNan est bien vu
on peut remplacer le if{}else.Code:for(i=n=[];x=s.split(" ")[i++];)if(isNaN(+x)){a=n.pop();n.push(r=eval(n.pop()+x+a))}else n.push(x);return r
remplacement de a=p.pop() par x+=p.pop() d'où eval(p.pop()+x).Code:for(i=n=[];x=s.split(" ")[i++];)isNaN(+x)?(a=n.pop(),n.push(r=eval(n.pop()+x+a))):n.push(x);return r
là on arrive à 99.Code:for(i=n=[];x=s.split(" ")[i++];)isNaN(+x)?(x+=n.pop(),n.push(r=eval(n.pop()+x))):n.push(x);return r
Mais c'est avec eval :oops:
Ma solution à 89 caractères :
Code:
1
2
3
4
5
6
7 function npi(s){ for(n=i=[];e=s.split(' ')[i++];)n.push(+e==e?e:(x=n.pop(),eval(n.pop()+e+x)));return n[0] } console.assert(npi("1 2 + 4 * 3 +") === 15); console.assert(npi("99 27 - 4 /") === 18); console.assert(npi("23 7 4 - -") === 20);
:applo: bien vu l'optimisation autour du push, tu peux même encore en gagner 2.
Je continue avec ma proposition sans eval. J'ai corrigé ce problème de zéro que m'a fait remarquer Sylvain et j'ai piqué le coup du return r de Barsy.
Résultat : 130 caractères. -1 bug, -1 octet :mrgreen:
Code:p=[];s.replace(/(\d+)|(\+)|(-)|(\*)|\//g,function(_,n,a,b,c){p.push(r=n?+n:(y=p.pop(),x=p.pop(),a?x+y:b?x-y:c?x*y:x/y))});return r
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 function npi(s){ p = []; s.replace(/(\d+)|(\+)|(-)|(\*)|\//g, function( _, n, a, b, c ){ p.push(r = n ? +n : ( y = p.pop(), x = p.pop(), a ? x + y : b ? x - y : c ? x * y : x / y)) }); return r }
[HS mais je peux pas m'en empêcher et j'assume]Citation:
Je donne ma langue au chat
Ah... toi tu ne sais pas (encore) pourquoi les chats n'utilisent pas de papier toilette... :mouarf:
[/HS mais je peux pas m'en empêcher et j'assume]
M'est avis que ça tourne encore autour du trou de balle cette histoire :lol:
Non sérieusement j'ai essayé plusieurs pistes, je ne vois pas comment descendre sous les 89.
En optimisant ta solution SylvainPV, je suis tombé à 85 :
Code:for(n=i=[];e=s.split(' ')[i++];)n.push(+e?e:(x=n.pop(),r=eval(n.pop()+e+x)));return r
Mince pas vu celle là, mais on peut encore en gagner 1 pour arriver à 84
Code:for(n=i=[];e=s.split(' ')[i++];)n.push(+e?e:(e+=n.pop(),r=eval(n.pop()+e)));return r
Barsy, même remarque que pour Watilin, avec ce test les valeurs zéro ne sont pas prises en compte
La meilleure solution fonctionnelle est donc :Code:console.assert(npi("1 2 3 0 + + +") === 6);
87Code:for(n=i=[];e=s.split(' ')[i++];)n.push(+e==e?e:(e+=n.pop(),r=eval(n.pop()+e)));return r
J'ai réussi à enlever un caractère au code de Watilin pour arriver à 129 caractères. En déplaçant un pop dans les paramètres de l'autre pop, on peut enlèver une virgule :
Quand une méthode ne prend pas de paramètres, on peut placer du code à la place des paramètres. Le code étant protégé par les parenthèses, il n'est pas nécessaire de mettre une virgule ou un point-virgule. On économise donc un caractère.Code:p=[];s.replace(/(\d+)|(\+)|(-)|(\*)|\//g,function(_,n,a,b,c){p.push(r=n?+n:(x=p.pop(y=p.pop()),a?x+y:b?x-y:c?x*y:x/y))});return r
Alors ça, c'est une belle astuce. Bien vu !
J'arrive après la bataille, donc j'ai seulement re-golfé la soluce de Sylvain :mrgreen:
Je vois pas d'autres solutions
-4, donc 83
Code:
1
2
3
4
5
6
7
8 function npi(s,n,i,e){ for(n=i=[];e=s.split(' ')[i++];)n.push(+e==e?e:eval(n.pop(e+=n.pop())+e));return +n } console.assert(npi("1 2 + 4 * 3 +") === 15); console.assert(npi("99 27 - 4 /") === 18); console.assert(npi("23 7 4 - -") === 20); console.assert(npi("1 2 3 0 + + +") === 6);
Du code comme faux arguments de fonctions. Tellement crade et tellement génial à la fois :mrgreen:
deux caractères de moins en reduisant le nom de fonction ...
:mouarf:Code:
1
2
3 function C(s,n,i,e){ for(n=i=[];e=s.split(' ')[i++];)n.push(+e==e?e:eval(n.pop(e+=n.pop())+e));return +n }
@regseb : bien joué, qui va faire du rétro-actif sur ce qui a été posté ?
@SpaceFrog : :koi: si tu comptes tout, tu es à 104 non :mrgreen:
Au fait, j'ai parlé de nous à la dernière @chtijs (j'ai fait un préz sur le JS Golf).
J'espère que ça va attirer des curieux :mrgreen:
Hé, mais je suis chti aussi moi :) S'il y a un prochain meet-up à Lille, j'y participerai volontiers.
Ben c'est toujours moins que 106 ( de Starsbourg ) ...Citation:
@SpaceFrog : si tu comptes tout, tu es à 104 non
Sylvain, prochain meetup jeudi soir au Mutualab à Lille. C'est pas vraiment une ChtiJS cette fois, c'est un meetup WelshDesign (ça ne se limite plus à JS, mais ça ouvre la porte à CSS, HTML et donc au responsive etc).
Plus d'info.
Sinon pour rester dans le sujet. Vous n'êtes sûrement pas passé à côté de 2048. Décliné sur pas mal de forme depuis que c'est sorti.
Voici la version min jouable :
Ça ne tient pas dans 140 mais dans 400 et des brouettes :aie: c'est du high level cette fois. Voici le gist où ça en parle.Code:<body id=P onload="function M(c,d){for(i=H=16;i--;)for(p=B[m=V(j=i%4+1)],G|=p>>11;--j?(q=B[n=V(j)])?!p|p==q&&(h=c?0:B[p?S+=B[m]*=2:B[i++,m]=q,n]=d):1:0;L=localStorage)R=Math.random}function V(x){if(x)return(D>1?4-x:x-1)<<D%2*2|i-i%4>>D%2*2;for(i=H|R(D=4)*H;B[--i%H];);for(B[i%H]=h=2<<R()+.1;D--;)M(1);G|=h}(onkeyup=function(e){D=e?e.keyCode-37:B=[];D>>2|G||M()|V(e?h:V());t=(G?S+' / '+(L.S>S?L.S:L.S=S):S)+'<pre>';for(i=h=H;i--;P.innerHTML=t)t+=(' '+[B[i]]).slice(-4)+(i%4?'|':'|\n')})(S=G=0)">
Excellent le 2048 en javascript !! C'est du haut niveau.
Maintenant, il faut développer en moins de 140 caractère l'IA qui résout le jeu.
Merci Cyril, je viendrais avec plaisir. Petite déception, j'ai cru qu'il y aurait du welsh au menu :mrgreen:
Pour l'IA du 2048, je ne m'y risquerai pas. Je n'ai toujours pas compris comment gagner à coup sûr à ce jeu :)
Cool ! Et non, pas de welsh au menu mais rien ne t'empêche d'en amener un :D
Pour 2048, j'ai pourtant testé pas mal de pattern différent mais je coince toujours à un moment. Je pense que le hasard joue pas mal à haut lvl.
Ma petite soeur a même fait un meilleur score que le mien :aie:
Le plus fort que j'ai vu en JS c'est le TinyChess de js1k : http://js1k.com/2010-first/demo/435
Du tout, il existe déjà des IA qui y arrivent à tous les coups. Il n'y a pas de chance en fait. Je me demande même s'il n'est pas possible de faire un 4096.
Pour ma part, j'ai trouvé une technique qui me permet de faire un 2048 environ une fois sur 2. Elle consiste à coincer le chiffre le plus fort que l'on possède dans un coin en jouant au maximum sur 2 mouvements et en s'autorisant un 3ème mouvement avec parcimonie.
Plus précisément : Je m'impose comme mouvements autorisées que haut vers bas et gauche vers droite ce qui coince le chiffre le plus fort dans le coin en bas à droite. Et je ne fais des mouvements droite vers gauche que si la ligne du bas est complètement remplie (c'est à dire que le chiffre le plus fort ne pourra pas sortir de son coin). Et il est absolument interdit de faire un mouvement bas vers haut. Au final, les nombres les plus forts seront sur la ligne du bas et, normalement, iront en croissants vers la droite et ceux qui sont au dessus sont ceux avec lesquels on joue pour compléter la ligne du bas.
Voilà, maintenant il ne me reste plus qu'à coder tout ça en Javascript :aie:
wow, t'as plus creusé l'idée que moi :D
:yaisse2: UP
Je viens de tomber sur cet article : http://davidwalsh.name/javascript-debounce-function ; qui propose la fonction debounce (équivalente à celle d'underscore.js) en 160 bytes. 160 c'est bien, mais sous les 140 c'est mieux ! Qui se sent d'attaque ?