Vous n'êtes pas identifié.
Vous êtes sur le forum du master ESA !
Le site du master ESA - description de la formation, notes de cours, contacts... vient de déménager !!!
Venez visiter notre nouveau site : www.master-esa.fr
Puisque vous aimez les problèmes amusants (tiens, le précédent n'a pas reçu de réponse...), en voici un nouveau :
Mes amis Luc et Albert sont venus me rendre visite et m'ont exposé le problème amusant suivant :
soit un nombre, appelons le abcdefghi, composé des neuf chiffres 1 2 3 4 5 6 7 8 9
chaque chiffre ne peut être utilisé qu'une fois et le nombre est tel que :
abcdefghi est divisible par 9
abcdefgh est divisible par 8
abcdefg est divisible par 7
abcdef est divisible par 6
abcde est divisible par 5
etc.
Normalement, un peu de logique doit vous aider à résoudre le problème. (par exemple, e ne peut être que 5)
Ecrivez le programme SAS qui vous trouvera ce nombre magique...
(je n'ai pas encore écrit le programme mais ce doit être amusant à faire)
cordialement
SR
Hors ligne
Je trouve le résultat même si le code est un peu lourd !
DATA nombre_magique; INPUT a; CARDS; 1 ; RUN; /* Je crée une table avec toutes les possibilités de nombre, 9!=362880 (éviter l'instruction PROC PRINT sur la totalité cette table!). Il ne faut qu'aucun des chiffres soit égal à un autre, d'où l'instruction IF sûrement maladroite. */ DATA nombre_magique; SET nombre_magique; DO a=1 TO 9; DO b=1 TO 9; DO c=1 TO 9; DO d=1 TO 9; DO e=1 TO 9; DO f=1 TO 9; DO g=1 TO 9; DO h=1 TO 9; DO i=1 TO 9; IF a ne b AND a ne c AND a ne d AND a ne e AND a ne f AND a ne g AND a ne h AND a ne i AND b ne c AND b ne d AND b ne e AND b ne f AND b ne g AND b ne h AND b ne i AND c ne d AND c ne e AND c ne f AND c ne g AND c ne h AND c ne i AND d ne e AND d ne f AND d ne g AND d ne h AND d ne i AND e ne f AND e ne g AND e ne h AND e ne i AND f ne g AND f ne h AND f ne i AND g ne h AND g ne i AND h ne i THEN OUTPUT; END; END; END; END; END; END; END; END; END; RUN; /* Maintenant, il faut rassembler les chiffres pour créer nos variables finales. || est l'opérateur de concaténation.*/ DATA nombre_magique (KEEP= a a1 a2 a3 a4 a5 a6 a7 a8); SET nombre_magique; a1=a||STRIP(b); a2=TRIM(a1)||STRIP(c); a3=TRIM(a2)||STRIP(d); a4=TRIM(a3)||STRIP(e); a5=TRIM(a4)||STRIP(f); a6=TRIM(a5)||STRIP(g); a7=TRIM(a6)||STRIP(h); a8=TRIM(a7)||STRIP(i); RUN; /* Malheuresement, les fonctions TRIM et STRIP transforment nos variables numériques en variables caractères. J'utilise ici la fonction INPUT pour retransformer les variables a1-a8 en valeurs numériques. */ DATA nombre_magique (KEEP= a ab abc abcd abcde abcdef abcdefg abcdefgh abcdefghi); SET nombre_magique; ab = INPUT(a1,16.); abc = INPUT(a2,16.); abcd = INPUT(a3,16.); abcde = INPUT(a4,16.); abcdef = INPUT(a5,32.); abcdefg = INPUT(a6,32.); abcdefgh = INPUT(a7,32.); abcdefghi = INPUT(a8,32.); RUN; /* MOD est la fonction de congruence. */ DATA nombre_magique (KEEP= abcdefghi); SET nombre_magique; IF MOD(ab,2)^=0 THEN DELETE; IF MOD(abc,3)^=0 THEN DELETE; IF MOD(abcd,4)^=0 THEN DELETE; IF MOD(abcde,5)^=0 THEN DELETE; IF MOD(abcdef,6)^=0 THEN DELETE; IF MOD(abcdefg,7)^=0 THEN DELETE; IF MOD(abcdefgh,8)^=0 THEN DELETE; IF MOD(abcdefghi,9)^=0 THEN DELETE; RUN; /* Nous obtenons finalement le "nombre magique" : */ TITLE 'Le nombre magique'; FOOTNOTE 'http://master-esa.com/viewtopic.php?id=190'; PROC PRINT data=nombre_magique; RUN;
Hors ligne
voici une version light :
DATA nombre_magique; INPUT a; CARDS; 1 ; RUN; DATA nombre_magique2; SET nombre_magique; DO a=1 TO 9; DO b=1 TO 9; DO c=1 TO 9; DO d=1 TO 9; e=5; DO f=1 TO 9; DO g=1 TO 9; DO h=1 TO 9; i=45-a-b-c-d-e-f-g-h; /*Si chaque chiffre n'apparait qu'une fois alors leur somme vaut 45 */ if a*b*c*d*e*f*g*h*i= 362880 /*Et leur produit vaut 362880 */ and mod(a*10+b,2)=0 /* Puis on verifie les conditions demandées*/ and mod(a*10**2+b*10+c,3)=0 and mod(a*10**3+b*10**2+c*10+d,4)=0 and mod(a*10**5+b*10**4+c*10**3+d*10**2+e*10+f,6)=0 and mod(a*10**6+b*10**5+c*10**4+d*10**3+e*10**2+f*10+g,7)=0 and mod(a*10**7+b*10**6+c*10**5+d*10**4+e*10**3+f*10**2+g*10+h,8)=0 then output; END; END; END; END; END; END; END; RUN; proc print; run;
Dernière modification par Vincent.DEROUET (16-10-2011 11:53:42)
Hors ligne
je viens de remarquer (honte à moi) que vous étiez en train de vous amuser avec ce petit problème...
recevez toutes mes félicitations puisque vous êtes le premier à proposer une solution (et qui offre une solution très rapidement !)
très malin le coup de la somme qui doit être égal à 45 et du produit égal à 362880 (je n'y avais pas pensé...)
Votre première étape data ne sert en fait à rien... (retirez l'instruction SET de la seconde et vous verrez que cela fonctionne aussi bien)
et si cela vous amuse, vous pouvez aussi regarder ce petit problème...
http://www.diophante.fr/problemes-par-t … fraternels
diophante.fr est un site qui propose de très nombreuses énigmes...
certaines sont amusantes à résoudre avec SAS...
Hors ligne
Je me suis amusé à résoudre le problème.
http://www.diophante.fr/problemes-par-t … fraternels
Uniquement les nombres fraternels de quatre chiffres qui sont en même temps des carrés parfaits.
*Je crée une table avec tout les nombres de 1000 à 9999 -> 9000 obs éviter un proc print sur la totalité ^^; data nombre4; do mil=1 to 9; do cent=0 to 9; do diz=0 to 9; do unit=0 to 9; output; end; end; end; end; run; proc contents; run; *Je crée une première table dans laquelle seuls les nombres fraternels de la forme 1112, 3234, 9899 (nombres consécutifs mais avec les 2 premiers plus petits que les deux derniers); data nombre4_2; set nombre4; *pour obtenir les nombres dans la configuration voulue, j'élimine étape par étape tout les autres; if cent=unit then delete; *le chiffre des centaines est forcément différent de celui des unités etc...; if diz>(mil+1) then delete; if unit>(cent+1) and unit^=0 then delete; if (mil+cent)>(diz+unit) and unit^=0 then delete; if unit=0 and diz ne (mil+1) then delete; if unit^=0 and mil ne diz then delete; if unit=0 and cent^=9 then delete; *là par exemple c'est pour gérer les cas 1920, 2930, 3940...; run; proc print data=nombre4_2; run; *à la fin j'ai une table qui contient 89 obs de nombres fraternels à quatre chiffres de la forme 1112, 1213.. il suffira ensuite de permuter pour obtenir les autres (1211 1312...; *Je concatène les variables (elles seront transformées en variables caractères); data nombre4_3 (drop= mil cent diz unit); set nombre4_2; a1=strip(mil)||strip(cent)||strip(diz)!!strip(unit); run; *Je regroupe le chiffre des milliers et des centaines puis celui des dizaines et des unités pour ensuite pouvoir permuter; data nombre4_4 (drop= mil cent diz unit b1 b2); set nombre4_2; b1=strip(mil)!!strip(cent); b2=strip(diz)!!strip(unit); a1=strip(b2)!!strip(b1); *(1112 -> 1211, 6768 -> 6867 etc...); run; *J'utilise la procédure APPEND pour ajouter les observations de la table que je viens d'obtenir. une étape data avec instruction set sur les deux tables aurait pu tout aussi bien faire l'affaire; proc append base=nombre4_3 data=nombre4_4; run; proc print data=nombre4_3; run; *j'ai maintenant tout les nombres à quatre chiffres fraternels; data nombre_fraternel (drop=a1); set nombre4_3; a2=input(a1,8.); *j'utilise INPUT pour transformer la variable caractère en variable numérique; a3=sqrt(a2); if round(a3)^= a3 then delete; *l'arrondi d'un nombre entier est égal à lui même, pour conserver uniquement le/les carrés parfaits, je demande à supprimer toutes les obs qui n’auraient pas un nombre entier pour racine carrée; run; proc print; run;
J'aurais pu faire beaucoup moins d'étapes data, mais par souci de clarté j'ai préféré tout détailler..
Hors ligne
Oui je connais ce site. Il y a plein de problème sympa qui parfois peuvent être résolu avec SAS.
Roger a écrit:
J'aurais pu faire beaucoup moins d'étapes data, mais par souci de clarté j'ai préféré tout détailler..
A vrai dire on peut faire en une seule.
data nf; do mil=1 to 9; do cent=0 to 9; do diz=0 to 9; do unit=0 to 9; N=mil*1000+cent*100+diz*10+unit; X=N**(1/2); if abs(mil*10+cent-diz*10-unit)=1 and int(X)=X then output; end; end; end; end; Keep N X; run; proc print; run;
Hors ligne
Après, on peut aussi avoir tous les carrés parfaits fraternelles à 4, 6, 8, 10 chiffres en une étapa data :
data nf; do a=10 to 99999; l=int(log10(a)); if l^=log10(a) then do; /*on enlève les cas où a=10, 100, 1000 ou 10000*/ b=a-1; N1=a*10**(l+1)+b; /* si a=112, alors b=111 et l+1=3 : N1=112*10^3+111=112111*/ X1=N1**(1/2); /* ainsi les N1 et N2 que l'on crée sont fraternelle*/ N2=b*10**(l+1)+a; X2=N2**(1/2); if int(X1)=X1 then do; /*on vérifie que N1 est un carré parfait*/ N=N1;X=X1; output; end; if int(X2)=X2 then do; N=N2;X=X2; output; end; end; end; Keep N X; run; proc print; run;
Dernière modification par Vincent.DEROUET (28-02-2012 16:29:26)
Hors ligne
solution retrouvée...
une autre façon d'appréhender le problème.... (et moi qui gardais ce problème pour un beau mercredi...)
data toto; do i=10 to 98; X=i*100+i+1; output; end; do i=100 to 998; X=i*1000+i+1; output; end; do i=1000 TO 9998; X=i*10000+i+1; OUTPUT; END; Do i=10000 to 99998; X=i*100000+i+1; OUTPUT; END; run; data toto;set toto; where x**0.5=int(x**.5); Y=x**.5; run; proc print;run;
et on obtient :
Obs i X Y 1 183 183184 428 2 328 328329 573 3 528 528529 727 4 715 715716 846 5 6099 60996100 7810 6 13224 1322413225 36365 7 40495 4049540496 63636
mais je n'ai pas considéré par exemple 8281 comme un nombre fraternel... j'aurai peut être dû (il faut que je retravaille ma définition de "consécutif"...)
Hors ligne
bon allez, on va maintenant faire sérieux :
data toto; do i=1 to 99999; num2=.; num=1*compress(put(i,8.)||put(i+1,8.)); if num**0.5=int(num**.5) then output; num=.; num2=1*compress(put(i,8.)||put(i-1,8.)); if num2**0.5=int(num2**.5) then output; end; run; proc sql; select coalesce(num,num2) as fraternel format=15. , calculated fraternel**.5 as racine from toto ; quit;
et
fraternel racine ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ 8281 91 183184 428 328329 573 528529 727 715716 846 60996100 7810 82428241 9079 98029801 9901 1322413225 36365 4049540496 63636
Hors ligne