|
Publicité ' | ||||||||||||||||||||||||
|
|
#1 |
![]() ![]() Inscription : juin 2006 Messages : 6 935 ![]() |
Bonjour,
Pour ce quatrième défi, l'équipe de developpez.com a décidé de vous proposer un problème de combinatoire. Challenge Le but du challenge est de résoudre un problème d'énumération de matrices. Soit n, la dimension d'une matrice carrée. Soit k, un entier positif. Le problème est de savoir combien il existe de matrice carré binaire (contenant uniquement des 0 et des 1) de dimension n*n dont la somme de chaque ligne et de chaque colonne est égal à k. Exemple Si n=2 et k=1, il existe uniquement 2 matrices vérifiant la propriété du dessus. |1 0| et |0 1| |0 1| |1 0| Si n=2 et k=2, il n'existe qu'une unique matrice vérifiant la propriété : |1 1| |1 1| Si n = 3 et k = 2, les matrices suivantes vérifient la propriété : |1 1 0| |1 0 1| |0 1 1| |1 1 0| |0 1 1| |1 1 0| |1 1 0| |1 0 1| etc. |1 0 1| |0 1 1| |1 0 1| |0 1 1| Les règles Il n'y a pas de règle particulière (évidemment, il faut que la solution proposée fonctionne). Vous pouvez proposer des solutions aussi bien dans des langages fonctionnels (caml, haskell, scheme, lisp...) qu'impératif. Le public pourra ainsi juger du code suivant divers critères :
Le public pourra également juger les différences entre une solution fonctionnelle et une solution impérative. Il lui sera ainsi plus facile de voir, pour un même problème, les différences entre divers paradigmes. A vos claviers de votre participation.
__________________
Je ne répondrai à aucune question technique en privé |
|
|
00
|
|
|
#2 |
![]() ![]() |
Il s'agit de trouver le nombre de matrices ou d'afficher (retourner) toutes les matrices?
__________________
Un gros problème est la somme de plusieurs petits problèmes. Resolvez chacun des petits problèmes: vous aurez resolu le gros problème! ![]() Mes tutos || Mon blog || Développeurs ivoiriens |
|
00
|
|
|
#3 | |
![]() ![]() ![]() Nicolas ValléeIngénieur d'études Inscription : décembre 2005 Messages : 9 963 ![]() |
Citation:
ben a priori, on veut juste le nombre, mais il faut prévoir un mode debug qui les affiche pour qu'on puisse vérifier
|
|
|
|
00
|
|
|
#4 | ||||||
|
Membre chevronné
![]() Inscription : mai 2005 Messages : 657 ![]() |
Une fois n'est pas coutume, on commence par une solution en Ruby :
Code :
Code :
Code :
Au niveau du temps d'execution c'est ... très moyen. Après je ne sais pas dans quelles proportion c'est la faute de Ruby et dans quelles proportions la faute du problème (le nombre de matrices augmentant très vite). Il faudra voir avec d'autres langages Sur ma machine, grosso modo : n=3 -> 30ms n=4 -> 4s n=5 -> je vous laisse essayer
__________________
Toute la documentation Ruby on Rails : gotapi.com/rubyrails Mes articles : > HAML : langage de template pour Ruby on Rails |
||||||
|
|
00
|
|
|
#5 |
|
Expert Confirmé Sénior
![]() ![]() ![]() Inscription : novembre 2005 Messages : 4 970 ![]() |
N'exclus pas la faut à l'algo... (Générer toutes les matrices puis les filtrer, je n'aurais osé cela que dans un langage à évaluation paresseuse en m'arrangeant pour être sur que l'évaluation paresseuse empéchait bien la génération de toutes les matrices).
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça. |
|
|
00
|
|
|
#6 | ||||
|
Membre confirmé
![]() |
Allez, une fois n'est pas coutume non plus, voici une petite solution de fainéant
Code :
Code :
__________________
I'm the kind of guy that until it happens, I won't worry about it. - R.H. RoY05, MVP06 |
||||
|
|
00
|
|
|
#7 | ||
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
Bonjour
Un petit code OCaml : Code :
Pour générer les tableaux je le fais ligne par ligne en ne prenant à chaque fois que les lignes à k uns et qui ne sont pas en contradiction avec les autres lignes déjà placées. D'ailleurs pour pouvoir faire du récursif joli j'ai tout codé en listes, du coup une liste de tableaux se retrouve être de type int list list list ![]() De plus, modulo échange des colonnes on peut se contenter du cas où la première ligne est 11...100..0 puis de multiplier par k parmi n -> idée à creuser, je pense qu'elle peut grandement s'améliorer si on ne l'applique pas que pour la première ligne mais récursivement, ça résoudrait peut-être des problèmes de mémoire. Je trouve les même résultats que Steki-kun (donc soit nos programmes sont juste, soit ils sont faux au même endroit ) et j'ai tout avec n = 6 et pour n = 7 j'ai k = 1, 2, 5, 6.Fractal |
||
|
|
00
|
|
|
#8 |
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
C'est effectivement méchamment optimisable.
Pour (n,k) = (5,2) : - il y a 2040 matrices - mon premier algorithme (programme ci-dessus) permet d'en garder en mémoire "seulement" 204 - à la main en appliquant mon algorithme optimisé, je l'ai calculé très rapidement, en n'ayant besoin de ne stocker que 10 matrices ainsi qu'un arbre à 14 sommets indexé par des entiers.L'algorithme est par contre un peu plus dur à coder, j'essayerai ça ce week-end, mais je pense qu'il peut permettre d'aller beaucoup plus loin vu le gain de place avec (5,2). Fractal |
|
|
00
|
|
|
#9 | ||
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
C'est encore moi
Ça y est, j'ai codé mon algorithme ! Il arrive à calculer tout jusqu'à n = 8, mais pour n = 9 il bloque pour k = 3 ou 4. Il faut dire que certes ça monte vite au début, mais ça monte encore plus vite après ! Voici les résultats que j'arrive à obtenir, pour ceux qui voudraient tester leur programme ou s'apercevoir qu'aller au delà de n = 10 est à peu près utopique (n, k) = (4, 2) -> 90 (n, k) = (5, 2) -> 2 040 (n, k) = (6, 2) -> 67 956 (n, k) = (6, 3) -> 297 200 (n, k) = (7, 2) -> 3 110 940 (n, k) = (7, 3) -> 68 938 800 (n, k) = (8, 2) -> 187 530 840 (n, k) = (8, 3) -> 24 046 189 440 (n, k) = (8, 4) -> 116 963 802 970 (n, k) = (9, 2) -> 14 398 171 200 (n, k) = (9, 3) -> mon ordi a tourné toute la nuit mais n'a pas réussi à trouver ^^ On comprend tout de suite mieux le "Out of memory error" Voici le code, pour ceux qui voudraient le tester ou voir comment ça marche (ou pour ceux qui aiment les List.filter et les List.map, yen a partout Par contre il est très peu commenté donc n'hésitez pas à me demander à quoi sert ou comment marche tel ou tel truc. NB : j'ai un processeur 64 bits, donc les entiers peuvent aller jusqu'à 4 milliards de milliards, ceux qui ont un processeur 32 bits sont a priori limités à 2 milliards, donc vous ne pourrez pas trouver les résultats les plus grands. Code :
Là j'ai compté les matrices modulo permutation des colonnes, ce qui diminue grandement le nombre de matrices à générer, mais il est peut-être possible de les compter modulo permutation des colonnes et des lignes, à suivre Fractal |
||
|
|
00
|
|
|
#10 |
![]() ![]() Xavier PhilippeauArchitecte système Inscription : décembre 2006 Messages : 9 818 ![]() |
Allez, courage. En Java j'ai réussi a calculer (9,4) en 25 secondes.
Vous n'allez pas laisser un sale langage impératif vous battre sur le terrain de la combinatoire, quand même.
__________________
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple. |
|
00
|
|
|
#11 |
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
Bonjour
Juste pour me donner une idée, tu trouves combien pour (9, 4) (ou (9, 3))? Et tu trouves les mêmes résultats que moi pour les autres? (je suis en train de faire un autre algo qui cette fois marchera Fractal |
|
|
00
|
|
|
#12 | |
![]() ![]() Xavier PhilippeauArchitecte système Inscription : décembre 2006 Messages : 9 818 ![]() |
Citation:
![]() (8,1)=40320 (8,2)=187530840 (8,3)=24046189440 (8,4)=116963796250 (9,1)=362880 (9,2)=14398171200 (9,3)=12025780892160 (9,4)=315031400802720
__________________
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple. |
|
|
00
|
|
|
#13 | ||
|
Expert Confirmé Sénior
![]() ![]() ![]() Inscription : novembre 2005 Messages : 4 970 ![]() |
Code shell :
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça. |
||
|
|
00
|
|
|
#14 |
![]() ![]() Xavier PhilippeauArchitecte système Inscription : décembre 2006 Messages : 9 818 ![]() |
@Jean-Marc.Bourguet:
![]() on peut avoir le code, ou au moins une explication de l'algo ?
__________________
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple. |
|
00
|
|
|
#15 |
|
Expert Confirmé Sénior
![]() ![]() ![]() Inscription : novembre 2005 Messages : 4 970 ![]() |
C'est de la programmation dynamique appliquee par ligne. Pour passer d'une ligne a une autre, on place k jetons. Au debut on a n colonnes qui ont besoin de k jetons. Apres la premiere ligne on a n-k colonnes qui ont besoin de k jetons et k colonnes qui ont besoin de k-1 jetons. Ce passage peut de faire de comb(k, n) maniere differentes. Naturellement, apres deux lignes on a plusieurs possibilites, mais ca se gere assez facilement. On a un DAG et on calcule la somme sur les chemins de la tete a l'unique feuille du DAG du produit des poids associe a chaque arc du chemin. Mais le DAG reste purement virtuel et n'est jamais materialise.
Je compte donner le code quand je l'aurai finalise, j'ai encore des idees que je n'ai pas eu le temps de tester -- sans parler de commencer a essayer d'optimiser l'implementation, mais je crois que je donnerai le code avant cette etape. Ici, ton message m'a donne le courage d'implementer rapidement l'algo auquel j'avais pense depuis le debut sans jamais passer a l'etape suivante. Je trouvais que 27s c'etait long pour ce type d'algo et rapide pour un algo qui genere effectivement toute les combinaisons. Mais bon, ne retenez pas votre souffle, j'ai un boulot et trois gamins.
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça. |
|
|
00
|
|
|
#16 | |
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
Citation:
Fractal |
|
|
|
00
|
|
|
#17 | |
|
Expert Confirmé Sénior
![]() ![]() ![]() Inscription : novembre 2005 Messages : 4 970 ![]() |
Citation:
Je garde juste deux niveaux du DAG en memoire a un moment donne: le niveau deja calcule et le niveau en cours de calcul. Et je ne garde que les noeuds, j'ai pas besoin des arcs que je calcule aussi dynamiquement (j'ai besoin de chaque arc une seule fois, ca sert a rien de s'en souvenir).
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça. |
|
|
|
00
|
|
|
#18 |
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
Ne le regardez pas, il est incompréhensible
![]() En fait je commence avec un noeud estampillé (k parmi n), puis de là je regarde toutes les possibilités pour la deuxième ligne, mais modulo permutation des colonnes qui laisse inchangée la première ligne. Par exemple pour le deuxième étage j'aurai un noeud qui correspond à remettre les uns dans la même colonne, un qui correspond à n'en mettre que k-1 et mettre le dernier avec les zéros, etc. jusqu'à un qui consiste à mettre tous les uns là où on avait mis des zéros (il y aura donc au plus k noeuds au deuxième niveau) chacun étant marqué du nombre de permutations qu'il englobe, et ensuite je recommence. Mais du coup pour pouvoir commencer à calculer quelque chose je suis obligé d'avoir fini le graphe (sauf si, en fait, je viens juste d'en avoir l'idée, je le génère branche par branche). Fractal |
|
|
00
|
|
|
#19 | |
|
Futur Membre du Club
![]() Inscription : février 2008 Messages : 75 ![]() |
Citation:
Bon, mais ça marche que pour k = 2 par contre ![]() Fractal |
|
|
|
00
|
|
|
#20 | |
![]() ![]() Xavier PhilippeauArchitecte système Inscription : décembre 2006 Messages : 9 818 ![]() |
Citation:
) je tombe à 35ms pour le calcul de (9,4) en java.Il faudrait que je regarde en dérécursivant...
__________________
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple. |
|
|
00
|
Copyright © 2000-2013 - www.developpez.com