59 caractèresCode:
1
2
3
4 function pgcd() { for(a=arguments,r=a[i=0];n=a[i++];)while(b=n%r)r=b;return r }
Version imprimable
59 caractèresCode:
1
2
3
4 function pgcd() { for(a=arguments,r=a[i=0];n=a[i++];)while(b=n%r)r=b;return r }
Outch, la barre est haute ! Joli :ccool:
97 pour moi, pas mieux donc. J'ai tenté par la récursivité
ps : tu peux même virer le dernier ; pour faire 60 ;)Code:
1
2
3
4
5
6
7
8 function pgcd(){ x=function(a,b){return!b?a:x(b,a%b)};return[].reduce.call(arguments,function(a,b){return x(a,b)}) } console.log( pgcd(27,36) === 9 ); console.log( pgcd(128,8,32) === 8 ); console.log( pgcd(7,14,7,35,707) === 7 ); console.log( pgcd(13,17) === 1 ); console.log( pgcd(7,7) === 7 );
c'est fait, je tombe donc à 60. J'essaie encore d'enlever ce que je peux. J'édite mon post au fur et à mesure que j'y arrive.
C'est pas vrai, à l'exercice précédent, je me suis fait exploser par Kaamo alors que j'étais persuadé qu'il était impossible de mieux faire.
Ici, je pensais qu'il était possible de réduire encore le code en écrivant quelque chose dans le genre
Mais il semblerait qu'en Javascript, tous les éléments d'un OU sont joués même si le premier retourne vrai. Ce n'est pas le cas dans d'autre langages.Code:for(a=arguments,(b=n%r)||(r=a[i=0]);n=a[i++];)r=b
il y a quand même un truc qui me chagrine dans ton code : tu ne vérifies pas si a<b avant de faire la division :koi:
Haha il est fort, très fort ce Barsy :mrgreen: (normal pour un Sylvain)
Ben en fait, pas si fort que ça. Auteur vient de mettre le doigt sur un problème. Si on fait pgcd(27,36), ça passe, mais pgcd(36,27) ça retourne 27.
Je vais corriger ça
95 avec la fonction d'Auteur simplifiée simplement.
les modifsCode:
1
2
3 function pgcd(){ for(x=arguments,i=x.length-1;i;i--){r=a=x[i];b=x[i-1];for(;r;){a=b;b=r;r=a%b}x[i-1]=b}return b; }
Je doute que cela tienne face au 59 de Barsy plus la modif :cry:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 function pgcd(){ for(x=arguments, i=x.length-1;i;i--){ r=a=x[i]; b=x[i-1]; // while(r!=0){ for(;r;){ // if(r!=0){ a=b; b=r; // } r=a%b } x[i-1]=b } return b; }
Si ça peut donner des idées à certains :
PGCD des nombres 96 et 36
96-36=60
60-36=24
36-24=12
24-12=12
12-12=0
PGCD(96;36)=12
;)
La correction me ramène à 73 caractèresCode:
1
2
3
4 function pgcd() { for(a=[].sort.call(arguments),r=a[i=0];n=a[i++];)while(b=n%r)r=b;return r }
EDIT : Et ça ne marche pas avec 96 et 36... et crotte :cry:
Cette fois, c'est la bonne, enfin j'espère... j'ai essayé avec beaucoup de nombres différents et je n'ai pas eu d'erreurs.
Ce qui me ramène au final à 65 caractères.Code:
1
2
3
4 function pgcd() { for(a=arguments,r=a[i=0];n=a[++i];)while(b=n%r){n=r;r=b};return r }
J'ai essayé avec la méthode des soustractions:
83 caractères. Mais ça marche pour tous les cas :)Code:
1
2
3 function pgcd(){ for(a=arguments,n=a[i=0];m=a[++i];){do{if(m<n){t=n;n=m;m=t}m-=n}while(m>0)}return n }
Sinon 2 caractères économisés sur le code de Barsy:
63 caractèresCode:
1
2
3 function pgcd(){ for(a=arguments,r=a[i=0];n=a[++i];)while(b=n%r)n=r,r=b;return r }
La méthode de la division euclidienne est plus courte car le tri croissant est réalisé par la même boucle.
Bon je crois qu'on ira pas plus bas pour ce problème-ci :)
Numéro 6 : convertir un nombre quelconque entre 1 et 3999 en chiffres romains
proposé par Barsy
Les unités à intégrer sont :Code:
1
2
3
4
5
6
7 function romain(n){ //votre code ici } console.assert( romain(12) === "XII" ); console.assert( romain(49) === "XLIX" ); console.assert( romain(74) === "LXXIV" ); console.assert( romain(383) === "CCCLXXXIII");
I 1
V 5
X 10
L 50
C 100
D 500
M 1 000
Celui-là n'est pas facile, bon courage :ccool:
Outch, ça m'a l'air chaud :aie:
Une question, après avoir lu quelques articles ici ou là :
- On ne peut aller que jusqu'à 3999. En effet, 4000 === MMMM. Or, quatre caractères identiques est une exception et ça fait un paramètre de plus à gérer. ça risque de faire un peu trop :)
5000 c'est V surmonté d'un trait horizontal, mais 4999 === MMMMCMXCIX.
Faut il gérer cette histoire de quatre "M" donc ?
A la Bovino :mouarf:
Code:
1
2
3
4 var print=function(msg){console.log(msg)}; (function rtoa(A,R,n,p){ // pour n entre 1 et 3999 s="",L=A.length;for(i=0;++i<L;){while(n>=A[i]){n-=A[i];s+=R[i];}if(n==0)p(s)} })([1000,900,500,400,100,90,50,40,10,9,5,4,1],["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"],383,print);
:mrgreen:
Basé sur le même raisonnement que Daniel :
En 126 caractères donc. Mais à mon avis, y'a plus court, la table de correspondance doit pouvoir se simplifier ... mais avant, j'ai besoin de manger :aie:Code:
1
2
3
4
5
6
7
8
9 function romain(n){ a={M:1e3,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1},r='';for(x in a)for(i=a[x];n>=i;n-=i)r+=x;return r } console.log( romain(12) + ' / ' + (romain(12) === "XII") ); console.log( romain(49) + ' / ' + (romain(49) === "XLIX") ); console.log( romain(74) + ' / ' + (romain(74) === "LXXIV") ); console.log( romain(383) + ' / ' + (romain(383) === "CCCLXXXIII")); console.log( romain(1000) + ' / ' + (romain(1000) === "M")); console.log( romain(3888) + ' / ' + (romain(3888) === "MMMDCCCLXXXVIII")); // le plus long possible !
ça ne marche pas pour "0" et pour les nombres plus grands que 4000, les "M" s'affichent par quatre. Pour 5000, par 5 etc, je ne crois pas que ça soit bon
ps : n'essayez pas 1'000'000 :aie:
EDIT : une mini amélioration pour gagner 1 caractère :aie:
125 :
Code:
1
2
3 function romain(n){ a={M:100,CM:90,D:50,CD:40,C:10,XC:9,L:5,XL:4,X:1,IX:.9,V:.5,IV:.4,I:.1},r='';for(x in a)for(i=a[x]*10;n>=i;n-=i)r+=x;return r }
Je précise que la fonction doit marcher pour n entre 1 et 3999 en effet.
Une question me taraude, je ne connais pas très bien la numérotation romaine, mais est-ce qu'on est pas supposés écrire 490 comme "XD" ou 99 comme "IC" ?
49 s'écrit XLIX et non pas IL.
Sinon, j'ai pas encore essayé mais je tenterai de proposer un code d'ici demain.
Il y a pas mal de libertés prises avec l’énoncé :aie:
Citation:
Les unités à intégrer sont :
I 1
V 5
X 10
L 50
C 100
D 500
M 1 000
pile dans les clou sauf qu'elle ne marche pas sur 49 par exemple :cry:Code:
1
2
3 function fct(v){ s='';r='I,V,X,L,C,D,M,1,5,10,50,100,500,1e3'.split(',');for(i=6;v;i--){d=~~(v/r[i+7]);if(d>=1){for(g=0;g<d;g++)s+=r[i]}v%=r[i+7]}return s; }
Dans l'énoncé il y a surtout les 4 assertions à vérifier. Si une ne passe pas, c'est refusé :)
Foi de fabricant d'usines à gaz ;)
Cela dit... je suis admiratif ! 8OCitation:
vous êtes tous des MALADES !!! :fou:
Comme à mon habitude, je fais le rapia en économisant 1 caractère sur la meilleure solution :mrgreen:
124 caractèresCode:
1
2
3
4
5
6
7
8
9 function romain(n){ r='';for(x in(a={M:100,CM:90,D:50,CD:40,C:10,XC:9,L:5,XL:4,X:1,IX:.9,V:.5,IV:.4,I:.1}))for(i=a[x]*10;n>=i;n-=i)r+=x;return r } console.log( romain(12) + ' / ' + (romain(12) === "XII") ); console.log( romain(49) + ' / ' + (romain(49) === "XLIX") ); console.log( romain(74) + ' / ' + (romain(74) === "LXXIV") ); console.log( romain(383) + ' / ' + (romain(383) === "CCCLXXXIII")); console.log( romain(1000) + ' / ' + (romain(1000) === "M")); console.log( romain(3888) + ' / ' + (romain(3888) === "MMMDCCCLXXXVIII")); // le plus long possible !
Mouhéhéhé 98 :mrgreen: (fonctionne si n > 0 et n < 4000)
Explications :Code:
1
2
3
4
5
6
7
8
9 function romain(n){ for(a='',b=0,c=5;n;b++,c^=7)for(d=n%c,n=n/c^0;d--;a='IVXLCDM'[d>2?b+n-(n&=-2)+(d=1):b]+a);return a } console.log( romain(12) + ' / ' + (romain(12) === "XII") ); console.log( romain(49) + ' / ' + (romain(49) === "XLIX") ); console.log( romain(74) + ' / ' + (romain(74) === "LXXIV") ); console.log( romain(383) + ' / ' + (romain(383) === "CCCLXXXIII")); console.log( romain(1000) + ' / ' + (romain(1000) === "M")); console.log( romain(3888) + ' / ' + (romain(3888) === "MMMDCCCLXXXVIII")); // le plus long possible !
Je suis parti de cette base : ça serait cool de pouvoir "piocher" dans la chaine "IVXLCDM" comme ceci : "IVXLCDM"[0] === "I".
Et ça pourrait marcher, car imaginons cet algo :
- On recherche le romain de 5
- On divise par 5. Reste 0, Résultat : 1
- "IVXLCDM"[Résultat] === "V"
Pour 10 ?
- On recherche le romain de 10
- On divise par 5. Reste 0, Résultat : 2
- "IVXLCDM"[Résultat] === "X"
Pour 50 ?
- On recherche le romain de 50
- On divise par 5. Reste 0, Résultat : 10
- "IVXLCDM"[Résultat] === "c'était trop beau pour être vrai :)"
Mais y'a de l'espoir ! Creusons un peu plus :
J'ai remarqué que pour passer de I à V puis de V à X puis de X à L, etc, il faut respectivement multiplier par 5 puis par 2 puis par 5, etc
Il faudrait donc faire une boucle qui divise le nombre à chercher par 5, puis 2, puis 5, puis 2, etc
Parti de ce postulat, c'est "bouclable" en se servant de XOR alias ^.
Exemple :
Cool ! Imaginons que l'on recherche le romain de 1000, cela veut dire que diviser 1000, par 5, puis 2, puis 5, etc jusqu'à 0 se fait en 7 fois !Code:
1
2
3
4
5
6
7
8
9
10
11 for(a=5,i=0;i<5;i++,a^=7) console.log(a); /* Va afficher : 5 2 5 2 5 .... */
Que vaut "IVXLCDM"[6] ? :mrgreen:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 n=1000 for(b=0,c=5;n;b++,c^=7) console.log((n=n/c^0) + ' / indice : ' + b); /* Donne : 200 / 0 100 / 1 20 / 2 10 / 3 2 / 4 1 / 5 0 / 6 */
on a notre algo. Il suffit ensuite de jongler avec les divisions, les modulo pour récupérer les restes et construire ainsi notre chaine romaine.
Une version de dév commentée qui m'a aidé à construire le code :
ps : oui, ça m'a pris la soirée d'hier, et j'ai eu mal au crâne en me relisant aujourd'hui après manger :mrgreen:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 function romain(n){ for(a='', // la chaine finale b=0, // IVXLCDM[b] c=5; // initialisation de c à 5 pour commencer à diviser n par 5 n; // tant que n n'est pas "falsy" (égal à 0 en l'occurrence). Il va subir une division par 5, puis 2, puis 5, etc ... b++, c^=7) { // c^=7 fait 2, puis, au prochain tour de boucle, c^=7 refera 5, puis encore 2 ensuite, etc console.log('d='+(n%c)+'/n='+(n/c^0)); for(d=n%c, // récupération du reste. Il ne peut jamais être > 4 ! n=n/c^0; // division par 5 ou 2 puis arrondi à l'inférieur => équivaut à n=Math.floor(n/c) ou encore n=~~(n/c) d--;) { // tant que le reste de la division n'est pas "falsy" (égal à 0 en l'occurrence) console.log('n='+n+'/m='+(n&-2)+'/a='+a+'/b='+b+'/c='+c+'/d='+d+'/x='+(1+(d>2?b+n-(n&-2)+1:b))); a='IVXLCDM'[d>2? // pour un reste de 4, soit les 4 ou 9. b+ // gestion des "cinquaines", dizaines, cinquantaines, etc n-(n&=-2) // ajoute 1 ou 0 et transforme n au nombre pair inférieur. n-(n&=-2) fait 0 si n pair et 1 si n impair. Car si n = 9 il faut taper dans la "cinquaine" suivante : ex IX. Tandis que si n = 4 on est dans la bonne cinquaine : ex. IV // si n est pair, (n&-2) === n. Par contre, si n est impair (n&-2) === n-1 +(d=1) // il ne faut plus qu'un tour derrière (exemple : IV si 4, IX si 9, XC si 90) :b]+a; // pour tout le reste, répétition de la lettre pendant d } } return a; }
:bravo: :ave: :scarymov:
Grand fou... J'avais tenté de faire la même chose avec la chaîne "IVXLCDM", mais je n'ai pas eu assez de temps pour arriver à une version aussi optimisée que la tienne. Moi j'utilisais deux variables, une pour l'unité et une pour la cinquaine. Mais basculer entre les deux via l'opérateur ^=, c'est du grand art. Bravo et merci d'avoir pris le temps de rédiger toute l'explication :ccool:
Impressionnant !! 8O8O
J'ai pas réussi à faire mieux que toi d'où le fait de ne pas avoir donné de réponse. J'avais aussi tenté de faire un truc avec la chaîne "IVXLCDM" mais mon approche était différente et trop longue en nombre de caractères.
Pour afficher par exemple 4, je me disais il faut d'abord afficher 1 "I" puis ajouter ce 1 à 4 ce qui donne 5 puis afficher 5 "V" ce qui donne au final "IV". J'avais une idée fixe sur cette méthode et j'ai pas trouvé comment la concrétiser. Je la garde cependant en tête, je m'y replongerai à l'occasion même si le résultat doit dépasser le tien en nombre de caractères.
Démonstration ESPOUSTOUFLANTE :hola::ave:
J'avais remarqué cette séquence 5-2-5-2... et prévue de l'exploiter avec un classique k=7-k, mais j'en suis resté là, de plus le c^=7 +1, euh! -1 caractère :lol:
Quoiqu'il en soit encore un grand coup de chapeau pour ce code et les explications qui vont avec :ccool:
Ces 98 caractères méritent de rester dans les annales du javascript.
Remercions également la période estivale sans qui tout ceci n'aurait pu être possible :mrgreen:
La période estivale n'est pas profitable à tous, y'en a qui bossent et qui ont droit à une canicule en prime :mrgreen:
Puisque le sujet des nombres romains vous a plu, et comme je doute qu'on puisse faire mieux que 98 caractères, je vous propose le sujet inverse:
Numéro 7: décoder les chiffres romains de I à MMMCMXCIX (3999)
Code:
1
2
3
4
5
6
7
8
9 function decodeRomain(s){ //votre code ici, retourne un entier de 1 à 3999 } console.log( decodeRomain("XII") + ' / ' + (decodeRomain("XII") === 12) ); console.log( decodeRomain("XLIX") + ' / ' + (decodeRomain("XLIX") === 49) ); console.log( decodeRomain("LXXIV") + ' / ' + (decodeRomain("LXXIV") === 74) ); console.log( decodeRomain("CCCLXXXIII") + ' / ' + (decodeRomain("CCCLXXXIII") === 383) ); console.log( decodeRomain("M") + ' / ' + (decodeRomain("M") === 1000) ); console.log( decodeRomain("MMMDCCCLXXXVIII") + ' / ' + (decodeRomain("MMMDCCCLXXXVIII") === 3888) );
Salut,
je propose ça :
106 caractèresCode:
1
2
3 function decodeRomain(str){ y=0for(s in a={M:1000,D:500,C:100,L:50,X:10,V:5,I:1}){y+=str.match(new RegExp(s,'g')).length*a[s]}return y }
EDIT : Oups, j'avais oublié le V:5
Version plus courte :
94 caractèresCode:
1
2
3 function decodeRomain(str){ y=0for(s in a={M:1000,D:500,C:100,L:50,X:10,V:5,I:1}){y+=(str.split(s).length-1)*a[s]}return y }
si on change le nom de la variable = -2 char :)Citation:
function decodeRomain(str){
y=0for(s in a={M:1000,D:500,C:100,L:50,X:10,V:5,I:1}){y+=(str.split(s).length-1)*a[s]}return y
}
Code:
1
2
3 function decodeRomain(n){ y=0for(s in a={M:1000,D:500,C:100,L:50,X:10,V:5,I:1}){y+=(n.split(s).length-1)*a[s]}return y }
On ne peut pas changer l'énoncé :mrgreen:
Par contre, tu peux enlever les {} et ajouter un ; pour que ça fonctionne :
Par contre, ça ne marche pas. Par exemple, test decodeRomain("IV") et decodeRomain("VI"), cela renverra 6. Alors qu'on attend 4 et 6. Idem pour le reste : XC, IX, etcCode:
1
2
3 function decodeRomain(str){ y=0;for(s in a={M:1000,D:500,C:100,L:50,X:10,V:5,I:1})y+=(str.split(s).length-1)*a[s];return y }
C'est là toute la problématique
Bon,
et bien je me suis vautré :sm:
Oui ce n'est pas aussi simple qu'un remplacement regexp, la règle de la numérotation romaine IV = V - I reste à indiquer.
Pour le nom de la variable vous pouvez la remplacer par s, c'est purement indicatif dans l'énoncé.
52 ! :ptdr:Code:
1
2
3 function decodeRomain(str){ open('http://fr.wikipedia.org/wiki/Nombres_romains') }
:sm:Bovino
Malin le bouc :ptdr: