Fibonacci

Fermé
nabil - Modifié par nabil le 9/10/2011 à 06:33
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 - 10 oct. 2011 à 12:59
salut tt le monde , on a F(1)=a , F(2)=ab , F(n)=F(n-2).F(n-1) , on parle içi d'une concatenation , la quésion 'etait de décrire une solution recurssive au probleme ; moi j'ai fait un programme mais j'arrivé pas a rouvé ou est le probleme , est ceque sur mon DevC++ ou bién des fautes dans mon programme , aidez-Moi :


#include <stdio.h>
#include <stdlib.h>
char* fib(int n)
{
char f[100];
if (n==1)
return "a";
else
if(n==2)
return "b";
else{
f[100]=strcat(fib(n-2) , fib(n-1));
return f ;
}
}
main()
{
int n;
char *st;
scanf("%d",&n);
st=fib(n);
printf ("%s",st);
getch();
}

5 réponses

Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 1 011
9 oct. 2011 à 09:00
Bonjour,

Il faudrait déjà que tu nous dises quel est le problèmes !
Ça ne compile pas ? Le résultat est faux ? Tu as un message d'erreur ?

À vue d'oeil, je vois déjà un problème : tu définis fib(2) comme valant 'b' et non pas comme valant 'ab'.

Xavier
0
Mérciii Xavie mais j'avais un probleme au niveau de la locaion , c'est reglé , mércii bp , mércii.. *!!
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
9 oct. 2011 à 10:04
Regarde comment fonctionne strcat!
Il faudrait plutôt faire :
strcat(f,fib(n-2));
strcat(f,fib(n-1));
return f;

Mais attention à l'allocation de f, car tu vas très rapidement dépasser les 100 caractères.

De plus comme tout ce qui concerne les suites de Fibonacci et assimilés, les méthodes récursives sont exponentielles O(1.618^n), alors que les méthodes itératives sont linéaires !
0
le probleme s'es réglé , mais mon probleme c'est que le programme éfféctue au moin (2 a la puissaance n/2 )/2 concatenations , et moi je veux un programme qui n'éffectue q'au plus 'n' concaténations , comment j peux faire , et qué ce que je devrai changé , peut etre la solution itertive ou bién quoi , et merci bién , merci..
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
9 oct. 2011 à 17:27
Oui, la solution itérative serait beaucoup plus efficace, cependant à partir du moment ou tu assembles des chaines de 'A' et de 'B', tu vas très rapidement te retrouver avec une chaine interminable, donc à quoi bon optimiser ?
Es-tu obligé d'appliquer cette méthode ?
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
9 oct. 2011 à 19:08
C'est vrai que la chaîne va être de plus en plus longue, mais ce sera toujours mieux d'en avoir maximum trois (on ne doit pas pouvoir faire beaucoup mieux) qu'en avoir fibo(n).
On sera rapidement limité en n mais l'optimisation a justement pour but de pouvoir augmenter n, même si ce n'est qu'un petit peu.

Sur ma machine j'ai fait quelques tests, et le malloc de concaténation plante à n=35 pour la méthode récursive, et n=44 pour la méthode itérative... Ce n'est pas sensiblement mieux mais c'est déjà ça ;-)
0
ah bon , passe Moi alos comment t'as fait pénétrer le malloc a ton programme , et aussi comment ça marche la méthode itértive stp é mérciii d'avance...
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
Modifié par KX le 9/10/2011 à 19:32
"Passe moi", "Passe moi"...
Ce n'est pas parce que je l'ai fait dans mon coin que ça doit t'empêcher de la trouver par toi même !

Le malloc je m'en sers pour la concaténation, vu que la taille de la chaîne augmente très rapidement, un char[100] est dépassé dès n=12, il faut donc t'arranger pour allouer dynamiquement l'espace nécessaire pour ton char*
Pour la méthode itérative tu en trouveras plein sur le forum, le principe est toujours le même, tu pars de fibo_0 et fibo_1, puis tu calcules fibo_2, fibo_3, ... fibo_n avec une petite boucle.
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 9/10/2011 à 21:26
Je pense qu'il y aurait moyen d'optimiser nettement sans aucune concaténation, en voici la recette :
- On alloue un gros bloc de caractères, dont la taille définira la taille maximale de la chaine,
- On initialise la chaine avec 'ABB'
- à chaque itération, la chaine contient n-1, qui elle-même contient n-2, donc pour obtenir n, il suffit de copier le début de la chaine, qui correspond donc à n-2, à concurrence du nombre de caractères de n-2...

Il faut donc calculer la taille de n-2 à chaque itération et c'est bon.

Exemple sommaire :
var 
  N1, N2, N3 : Integer; 
  Bloc : Array[0..100000] of Char; 
  Count1, Count2 : integer; 

  Bloc:= 'ABB'; 
  N1:= 02; 
  N2:= 03; 
  
  For Count1:= 0 to 20 do 
  begin 
    For Count2:= 0 to N1-01 do Bloc[Count2 + N2]:= Bloc[Count2]; 
    N3:= N1 + N2; 
    N1:= N2; 
    N2:= N3; 
  end; 


Le chêne aussi était un gland, avant d'être un chêne
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
9 oct. 2011 à 21:57
Idée intéressante (en théorie du moins). En pratique on ne gagnera que 2 itérations puisqu'au lieu d'avoir trois chaînes on en aura deux et que l'espace mémoire va quand même être limité, c'est surtout au niveau de la consommation de ressources pour l'allocation mémoire que l'on y gagnerai.

Calculer la taille du bloc final est "facile", il suffit de calculer la valeur du Nè terme de la suite de Fibonacci (donc 100000 sera dépassé pour n>25) et il serait alors préférable de stocker les valeurs de cette suite pour s'en servir comme "indices" lors des copies des blocs (et ainsi savoir quel est le pointeur destination de la copie)

Par contre je n'ai pas compris d'où sors ton 'ABB' dans ton code, de plus tu notes 01, 02, 03, est-ce des valeurs octales ?
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
9 oct. 2011 à 22:32
Une seule chaine en fait, puisqu'on copie n-2 à partir du début de l'unique chaine...
Et pour ABB, c'est que je partais de f(1) = A et f(2) = B donc f(3) = AB et f(4) = ABB, oui, c'est peut-être pas ce qui est demandé !

Et bien sûr les valeurs affichées ne sont pas en octal, qui n'a aucun intérêt pour moi, mais bien en décimal, c'est juste que j'ai toujours tendance à ajouter un zéro devant les décimaux, sans que je m'explique vraiment pourquoi !
Je crois que c'est dû à l'assembleur, où il est important de faire ressortir les nombres, et il n'y a pas de variation de couleur...

Et je ne comprend pas bien ce que tu veux dire sur les indices de copie ?
Car la chaine est constituée pas-à-pas, sans qu'aucun caractère ne soit copié deux fois, je ne vois pas trop comment faire mieux...

Après j'ai bien pensé à un autre principe, qui consisterait à retenir les tailles de chaines et ensuite reconstituer à la demande, mais c'est beaucoup plus compliqué, et pas spécialement à la portée d'un débutant...
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
9 oct. 2011 à 23:21
En fait si f(3)=f(1)+f(2)="A"+"B"="AB", on devrait avoir avoir f(4)=f(2)+f(3)="BAB" et non pas "ABB"

Pour mes indices, ce que je remarque c'est que pour tout k>2, les fibo(k) derniers caractères de fibo_ab(n) sont exactement la chaîne fibo_ab(k). Du coup je peux me servir des indices fibo(k) pour construire par copie les fibo_ab(k+2)... Enfin c'est sur cette idée que je partais ;-)
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
Modifié par KX le 9/10/2011 à 23:46
En C, ça donnerait à peu près ceci (je raccourci ^^)

int* fibo = fibonacci(n); // fibo[0]=fibo[1]=1, fibo[k]=fibo[k-2]+fibo[k-1]
char* str = malloc(fibo[n]+1);

str[fibo[n]-2]='a';
str[fibo[n]-1]='b';
str[fibo[n]-0]='\0';

for (i=3; i<=n; i++)
    strncpy(str+(fibo[n]-fibo[i]),str+(fibo[n]-fibo[i-2]),fibo[i-2]);
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
10 oct. 2011 à 06:43
Ha oui, c'est pour ça que dans ma méthode j'inverse le résultat, ce qui n'est à priori pas très grave, ce qui permet de conserver chaque chaine ajoutée sans jamais recopier, et le tout dans une seule et unique chaine, ainsi on a : f(3) = f(2) + f(1), la chaine f(3) étant calculée en conservant f(2) à la position initiale, et en ajoutant f(1) à la suite de f(2).
Et puisque f(1) correspond au caractères initiaux de f(2), il suffit d'en connaitre la taille, et de copier du début de la chaine vers sa suite...
ABB            
---+AB        -> Ajout des 2 1ers caractères
------+ABB        -> Ajout des 3 1ers caractères
-----------+ABBAB     -> Ajout des 5 1ers caractères
Résultat:
ABBABABBABBAB
ABB+AB+ABB+ABBAB
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
10 oct. 2011 à 06:52
Alors que moi je voyais ça à l'envers, en copiant fibo(k-2) devant fibo(k-1) pour avoir fibo(k)

-------A   
-------B   
------AB   
-----BAB   
---ABBAB   
BABABBAB   
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
10 oct. 2011 à 07:03
Ce qui revient au même effectivement, ta méthode ayant l'avantage de garder l'ordre voulu !
En tous cas dans un sens comme dans l'autre, la méthode est fonctionnelle...
Mais je ne vois pas trop l'intérêt du résultat, difficile à visualiser et pas très pratique non plus pour effectuer des calculs.
De plus on pourrait pousser la méthode dans ses retranchements en passant au binaire, ce qui diviserait par 8 la taille de la chaine (A = 0 et B = 1)...
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
10 oct. 2011 à 07:16
Evidemment en passant binaire cela permettrait de diviser l'espace mémoire alloué, mais on se retrouve à devoir utiliser des opérateurs bit-a-bit et j'avoue ne pas les connaître suffisamment pour pouvoir faire des copies propres, d'autant que les opérateurs de déplacement se contrôlent surement avec des int, or ce sont eux qui vont désormais déborder à cause de la croissance exponentielle.

Le problème est très scolaire, mais son optimisation l'est un peu moins ^^
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 10/10/2011 à 21:49
Hé bien, pour info, en binaire non optimisé ça donnerais ça, sommairement toujours :
var  
  N1, N2, N3 : Integer;  
  Bloc : Array[0..100000] of Byte;  
  Count1, Count2 : integer;  

  Bloc[0]:= $6;
  N1:= 02;  
  N2:= 03;  

  FillChar(Bloc, SizeOf(Bloc), 0); 

  For Count1:= 0 to 20 do  
  begin  
    For Count2:= 0 to N1-01 do  
    If Boolean(((Bloc[Count2 shr  03]) shr (Count2 and 07)) and 01) then 
    Inc(Bloc[(Count2 + N2) shr  03]) , 01 shl ((Count2 + N2) and 07); 

    N3:= N1 + N2;  
    N1:= N2;  
    N2:= N3;  
  end;  

Il serais évidement possible de copier 32 bits d'un seul coup pour dupliquer les chaines, en plus compliqué...
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
10 oct. 2011 à 12:39
Même en mettant 8 bits par byte, tes 100 000 cases ça fait un peu petit. Peut-être que le Pascal ne te permet pas de faire plus ? Il faudrait que je regarde ce que ça donne avec les bits en C.
Pour l'instant avec 1 octets par caractère, j'atteint n=44 (soit 1,13 milliards de caractères) et ça plante à n=45 (1,84 milliards), en divisant par 8 l'espace, ça permettrait d'atteindre n=48 (7,78 milliards)

Après pour faire plus (est-ce vraiment utile ?) il faudrait faire de la manipulation de fichiers, ce sera certes plus long, mais on soulagera la mémoire vive au détriment de la mémoire physique.
Mais il ne faut pas rêver, on n'ira pas beaucoup plus loin :p
0