|
Publicité ' | ||||||||||||||||||||||||
|
|
#81 | ||
|
Invité(e)
![]() Messages : n/a ![]() |
Allez hop, je suis en forme! Pour rigoler, une version avec mémoization (sale, en impératif, tout ça tout ça !)
Code :
Après la question qui se pose c'est : qu'est ce que veut dire "déterminer" dans le défi de base. Allez, il est 2h du mat par chez moi, je file au lit |
||
00
|
|
|
#82 | ||
|
Membre Expert
![]() Inscription : mars 2007 Messages : 851 ![]() |
Une amélioration de la solution Prolog de Trap D:
les partitions ne sont pas représentées sous forme classique mais sous forme d'un tableau de taille N qui donne le nombre de N, le nombre de N-1, ... jusqu'au nombre de 1 dans la partition. Pas de doublons, donc plus besoin de faire un tri et de les supprimer. L'idée est de résoudre l'équation X1*N + X2*(N-1) + ... +XN*1 = N. Code :
|
||
|
|
00
|
|
|
#83 | ||
|
Membre Expert
![]() Inscription : mars 2007 Messages : 851 ![]() |
Et finalement, l'algorithme "naïf" en Prolog. Je pensais que ça allait être plus compliqué à implémenter que dans les langages fonctionnels, mais il n'en est rien! Je trouve même qu'il est plus simple. Le non-déterminisme de Prolog fait merveille ici pour éviter de se coltiner des opérations sur les listes (concat, map,...).
Code :
edit: N=37, c'est avec un stack de 4MB. En le poussant à 128 MB (le maximum semble-t-il dans SWI-Prolog), je monte à N=57. Cela prend environ 12 secondes pour obtenir la réponse. |
||
|
|
00
|
|
|
#84 | |||
|
Expert Confirmé Sénior
![]() ![]() |
Citation:
Dans ce second message plutôt qu'un véritable arbre, tu fais un DAG (Directed Acyclic Graph), en fait cette compression correspond à ce qui se passe réellement dans les versions mémoizé des codes fonctionnels, sauf que dans leur cas, le sous parcours aussi est mémoizé, pas avec ton système. Ton code a cependant le bénéfice de faire apparaître certaines symétries cachées du modèle, et d'offrir une représentation compressée de la solution. Au fait, on peut en faire une version purement fonctionnelle, et ne souffrant pas des petits défauts de ta variable globale pour la mémoization par exemple : Code :
-- Jedaï |
|||
|
|
00
|
|
|
#85 | |||||
|
Invité(e)
![]() Messages : n/a ![]() |
Citation:
Et si ce qui vous chagrine, c'est que je n'affiche pas le nombre de feuille : Code :
Citation:
Citation:
Dernière modification par alex_pi ; 25/07/2007 à 17h19. |
|||||
00
|
|
|
#86 | |||
|
Expert Confirmé Sénior
![]() ![]() |
Citation:
Je sais que l'ensemble des solutions est compris dans ton arbre, mais une fois dit ça, je peux affirmer que même sans l'exécuter la définition de ma fonction récursive "contient" l'intégralité des possibilités, et son occupation mémoire est encore moindre que ton arbre... L'argument est légèrement spécieux. Par ailleurs tu dis que le printer est naïf ? L'est-il tant que ça ? Comment l'améliorerais-tu ? (personnellement j'utiliserais bien un zipper, mais je pense pas que ça améliore les performances, ça devrait simplement permettre de créer un itérateur sur l'arbre) Ton dernier programme calcule effectivement le nombre de solutions, mais il ne le fait pas de la même façon que les autres programmes, c'est à dire en comptant une par une chacune des possibilités, autrement dit, je suis à peu près sûr, que le code suivant est plus rapide encore : Code :
-- Jedaï |
|||
|
|
00
|
|
|
#87 | ||
|
Invité(e)
![]() Messages : n/a ![]() |
Citation:
Citation:
|
||
00
|
|
|
#88 |
|
Invité régulier
![]() Inscription : juin 2007 Messages : 6 ![]() |
Quelques remarques :
(1) Le problème est suffisamment simple pour qu'il soit possible d'énumérer les solutions plutôt que de les chercher. Concrètement ça veut dire qu'il est possible d'écrire un programme qui ne contient pas de test du type if(somme == n). L'idée est la suivante : on génère les solutions s = s_1..s_i..s_k de longueur k, strictement décroissantes (s_(i+1) <= si). Si on a déjà généré la partie s_1..s_(i-1), on peut déterminer les valeurs minimales et maximales que peut prendre s_i pour obtenir une solution, et chaque de ces valeurs contribue à une solution. Je vous laisse poser les équations. L'algorithme consiste donc tout simplement, pour chaque valeur de k, à parcourir les valeurs entre min et max, puis à avancer à l'élément suivant. Il est optimal dans le sens où le travail effectué est exactement proportionnel au nombre de solutions. (2) Si on veut comparer des performances, il faut comparer des choses comparables. Je serais tenté de rajouter à l'énoncé que le programme doit stocker les solutions sous une forme telle que tableau, liste chaînée ou arbre, avec la contrainte que l'affichage d'une solution doit se faire en temps linéaire par rapport à la taille de la solution (sinon ça veut dire qu'une partie du travail est fait lors de l'affichage, et donc pas compté dans les performances mesurées). (3) Petite remarque sur l'énoncé : les solutions qu'on recherche sont des multiensembles, pas des ensembles (l'ensemble {1, 1, 1} est le même que l'ensemble {1}). |
|
|
00
|
|
|
#89 |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
et bienvenue,et as-tu quelque chose à proposer pour apporter une solution "utilisable" et si possible élégante ? |
|
|
00
|
|
|
#90 | |
|
Membre Expert
![]() Inscription : mars 2007 Messages : 851 ![]() |
Citation:
Je crois qu'il serait plus précis de dire que le travail effectué est proportionnel au nombres de noeuds de l'arbre généré par cette méthode. Seules les feuilles de cet arbre sont des solutions. Je ne sais pas si cela a une influence sur la complexité asymptotique (à confirmer), mais cela permet d'expliquer que les programmes qui mémorisent les sous-arbres déjà générés sont plus rapides parce qu'ils évitent de reparcourir les noeuds internes de ces sous-arbres (ils "remontent" les solutions ou morceaux de solutions dans l'arbre). edit: J'aurais plutôt du dire: Ils fusionnent les sous-arbres menant à des queues de solution communes et remontent les queues de solutions au niveau des racines de ces sous-arbres. |
|
|
|
00
|
|
|
#91 | |
|
Invité régulier
![]() Inscription : juin 2007 Messages : 6 ![]() |
Citation:
Remarque que coté performances, c'est encore le programme en C de type génération et test qui reste numéro 1 |
|
|
|
00
|
|
|
#92 | |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Citation:
ce n'est pas le C++ qui est le meilleur pour le moment ?
|
|
|
|
00
|
|
|
#93 | |
|
Invité(e)
![]() Messages : n/a ![]() |
Citation:
|
|
00
|
|
|
#94 | |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Citation:
quel est le rapport ? la version C++ de millie est la plus rapide pour le moment... c'est tout |
|
|
|
00
|
|
|
#95 | |
|
Invité(e)
![]() Messages : n/a ![]() |
Citation:
|
|
00
|
|
|
#96 | |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Citation:
as-tu vérifié l'algo qu'il a utilisé parce que lui non plus ne stocke pas toutes les solutions... |
|
|
|
00
|
|
|
#97 | |
|
Invité(e)
![]() Messages : n/a ![]() |
Citation:
Donc en creusant un peu, la solution de millie ne marche pas. Pour n = 8, il n'affiche ni [4, 3, 1] ni [3, 3, 1, 1]. Et pour n = 100, il retourne 122072 solution alors qu'il y en a 2300165032574323995027. |
|
00
|
|
|
#98 | |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Citation:
tiens bizarre que ça n'ait pas buggé avant n=8 je vais vérifier... exact, ça plante aussi à n=7 |
|
|
|
00
|
|
|
#99 |
![]() ![]() Inscription : juin 2006 Messages : 6 935 ![]() |
J'ai dû faire une mise à jour foireuse l'autre fois. Je regarderai ça ce soir.
__________________
Je ne répondrai à aucune question technique en privé |
|
|
00
|
|
|
#100 | ||
|
Expert Confirmé Sénior
![]() ![]() ![]() Inscription : novembre 2005 Messages : 4 970 ![]() |
Avant de lire vos propositions, la mienne (en C++)
Code C++ :
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça. |
||
|
|
00
|
Copyright © 2000-2013 - www.developpez.com