boucle for récursive [Résolu] - C++ - Programmation
Marsh Posté le 17-11-2006 à 13:48:49
C++, mais si t'as une idée en C dis toujours...
Marsh Posté le 17-11-2006 à 14:19:45
on a déjà fait 30000 sujets le dessus, fait une recherche, nous aussi on en a marre de répondre en boucle aux mêmes questions.
Marsh Posté le 17-11-2006 à 14:40:49
Taz a écrit : on a déjà fait 30000 sujets le dessus, fait une recherche, nous aussi on en a marre de répondre en boucle aux mêmes questions. |
+1 : le sujet a été plusieurs fois abordé.
Un exemple de topic très proche du tien : [algo] parcourir une matrice de taille (lignes et colonnes) variable
Marsh Posté le 17-11-2006 à 16:43:59
Je dois avoir des problèmes d'expression, ou alors certains gueulent avant de lire...
Le problème n'est pas de faire un algo bidon pour parcourir un arbre ou je ne sais trop quoi, mais d'imbriquer un nombre indéfini de boucles for... Je ne parle pas de permutations mais de combinaisons.
Bon, j'ai trouvé ça sur le net :
Code :
|
C'est astucieux, mais le souci c'est que dans mon cas il s'agit de millions d'appels de la fonction contenant ces lignes, et le tableau comb doit contenir une centaine de 0 pour trois ou quatre 1, ce qui fait beaucoup trop de if(comb[c]) à mon goût...
J'ai aussi trouvé ça :
Code :
|
mais je me demande si ça vaut vraiment le coup de passer par une telle fonction, qui me semble un peu longue et donc peut-être moins efficace que l'appel récursif... non ?
PS : J'avais pas vu qu'il y avait une section algo, désolé...
Marsh Posté le 17-11-2006 à 18:15:28
SkippyleGrandGourou a écrit : Je dois avoir des problèmes d'expression, ou alors certains gueulent avant de lire... |
Je ne sais pas si tu as lu le lien que je t'ai donné, mais il y a de grandes similitudes entre le problème posé dans ce topic et le tien. En particulier, tous deux admettent des solutions récursives presque triviales, qu'on cherche à rendre itératives.
Tu pourras aussi remarquer que la solution que j'ai proposée dans le topic mentionné est basée sur la notion d'incrément permettant de passer d'une combinaison à la suivante, ce qui est exactement le rôle joué par la fonction next_combination que tu as trouvé sur le web. Tant que tu raisonnes en termes de "nombre indéfini de boucles for imbriquées", tu ne débouches que sur des solutions récursives ; c'est la notion d'incrément qui te permet de changer de point de vue et de rendre l'algorithme itératif.
Tu n'as apparemment pas de problème d'expression, mais je ne suis pas sûr que ce soit moi qui gueule avant de lire
Marsh Posté le 18-11-2006 à 13:52:16
SkippyleGrandGourou a écrit : Salut,
où le u varie sur M et le i sur N. Le premier appel est donc recursive(0,0). Le cout est là de manière à afficher le résultat précédent. |
Il faudrait avoir quelques précisions. Il y a peu j'avais besoin d'appliquer une fonction prenant en argument toutes les "combinaisons avec répétitions" de k éléments parmi n ( http://fr.wikipedia.org/wiki/Combi [...] 3%A9tition ). Pas exactement comme toi, mais similaire en ce que je me suis aperçu que j'aurai du mal à écrire une procédure itérative de génération de ces combinaisons. Surtout sans bug... La fonction next_combination() que tu reproduit plus haut me conforte dans mon idée, même si je pense que les combinaisons avec répétitions sont plus simples.
Par contre :
Code :
|
Bon, tout ce 3615 MyLife pour te dire que si tu as les mêmes contraintes que moi, la solution est simple. Notamment, vérifie bien que la récursivité te pose un problème avant de passer à un algo itératif. J'aurais quelques hésitations avant de coller une horreur comme ton "next_combination" dans mon programme.
Imaginons que tu gardes la récursivité. Si tu ne veux pas comme moi stocker en mémoire l'ensemble des combinaisons, mais bien appliquer "grosse_fonction" pendant le parcours, pourquoi ne pas t'inspirer des "functors" de la STL ( http://www.sgi.com/tech/stl/functors.html ) ? Tu passes à ta procédure de parcours un objet qui encapsule ta fonction + tous ses arguments qui n'ont rien à voir avec le parcours. Je l'ai fait ci-dessous pour une fonction qui doit être appliquée à tous les entiers i de 0 à max. Cela oblige à "templater" le parcours mais ce n'est pas horrible.
Code :
|
La fonction à appliquer est un objet, elle doit juste implémenter l'opérateur () appliqué à un entier i. Tu pourrais adapter sans grosse difficulté le principe à une fonction qui implémente l'opérateur () appliqué à une combinaison c, passée en paramètre à ta procédure de parcours.
Les autres arguments de la fonction f sont passés à la construction de l'objet qui l'encapsule. Par exemple pour une fonction qui affiche les entiers i en collant une "étiquette" derrière (paramètre supplémentaire de f qui n'a rien à voir avec le parcours), voici :
Code :
|
Résultat :
Code :
|
Marsh Posté le 18-11-2006 à 14:00:15
SkippyleGrandGourou a écrit : Je dois avoir des problèmes d'expression, ou alors certains gueulent avant de lire... |
Désolé de me répéter, mais cette fonction est infâme. Par contre, si elle est bien codée (je ne veux même pas chercher à comprendre comment elle fonctionne) elle sera normalement plus efficace que la récursion. Par "principe", en C++ au moins, itératif > récursif pour l'efficacité.
Mais 1) si la récursion n'est pas limitante dans le cadre de tes contraintes de temps de calcul et de taille de la pile d'appel, tu ferais mieux de garder la récursion (comme ça peut-être que quelqu'un repassant un jour sur ton code aura une chance de comprendre quelque chose) et 2) le souci que tu exprimais dans ton premier post était de passer des arguments supplémentaires au parcours récursif et il y a au moins 1 solution.
Marsh Posté le 20-11-2006 à 11:55:30
franceso a écrit : Je ne sais pas si tu as lu le lien que je t'ai donné, mais il y a de grandes similitudes entre le problème posé dans ce topic et le tien. En particulier, tous deux admettent des solutions récursives presque triviales, qu'on cherche à rendre itératives. |
Ok, suivant ton conseil j'ai repris ce sur quoi j'étais parti au tout début (avant la méthode récursive) et que je pensais non utilisable, et j'ai réussi à le faire fonctionner :
Code :
|
boulgakov a écrit :
|
Dans mon cas, l'utilisation des combinaisons à la place des permutations qu'il y avait avant va faire qu'il sera possible de l'utiliser pour n>3, justement...
boulgakov a écrit :
|
Ça ne fonctionnera pas (en tout cas pas simplement) pour moi, car le programme ne passe pas forcément par les N combinaisons : si l'utilisateur demande N=5, le programme va d'abord tester N=1, puis 2, jusqu'à 5, et il s'arrête dès qu'il est content.
Je pense que tant pour la lisibilité que pour l'efficacité, dans mon cas, la méthode itérative est préférable à la méthode récursive. Mais merci quand même pour les infos sur les functors, ça peut toujours servir.
Marsh Posté le 21-11-2006 à 13:41:04
SkippyleGrandGourou a écrit : Ok, suivant ton conseil j'ai repris ce sur quoi j'étais parti au tout début (avant la méthode récursive) et que je pensais non utilisable, et j'ai réussi à le faire fonctionner :
|
Ironie du sort : je viens de coder l'algo itératif pour les combinaisons avec répétitions... Mon raisonnement sur le récursif "élégant et qui suffit" n'a pas résisté à la deuxième utilisation que j'en ai eu !
Marsh Posté le 26-11-2006 à 05:05:56
boulgakov a écrit : Ironie du sort : je viens de coder l'algo itératif pour les combinaisons avec répétitions... Mon raisonnement sur le récursif "élégant et qui suffit" n'a pas résisté à la deuxième utilisation que j'en ai eu ! |
Hum...
Si quelqu'un avait une meilleure idée que cette chose. Il faut trouver tous les n-uplets d'entiers positifs tels que somme(n{i}) = k.
Code :
|
Pffff... Je l'ai écrite en observant les motifs qui se répétaient dans ma fonction récursive. Ca marche, mais je ne comprends pas mon code !
Quelqu'un pourrait m'orienter vers qqchose de mieux ?
Marsh Posté le 17-11-2006 à 12:10:34
Salut,
J'ai besoin de parcourir toutes les combinaisons possibles de M valeurs dans un choix de N (le C(M,N) en combinatoire). Par exemple pour M=3 valeurs dans les entiers de 0 à 4 valeurs (donc N=5) je veux les jeux :
La meilleure méthode que j'ai trouvé pour l'instant est une fonction récursive :
où le u varie sur M et le i sur N. Le premier appel est donc recursive(0,0). Le cout est là de manière à afficher le résultat précédent.
Le problème est que la fonction grosse_fonction prend une palanquée d'arguments qui n'ont pas spécialement besoin d'être défini globalement, ce qui fait que je dois fournir tous ces arguments aussi à la fonction récursive... Donc je me demande s'il n'y a pas moyen (mais je ne pense pas... ) de faire dans la fonction qui appelle recursive(0,0) une boucle sur M de boucles for, de manière à ce que tout reste dans cette fonction (plus besoin des fonctions "recursive" et "grosse_fonction" ).
Voilà, je veux pas vous faire réfléchir à ma place, mais si quelqu'un a une idée de génie ou a déjà eu affaire à un truc de ce genre, on sait jamais...
Merci.
Message édité par SkippyleGrandGourou le 20-11-2006 à 11:56:01