Recherche de doublons dans une séquence [Concours] - C++ - Programmation
Marsh Posté le 25-04-2004 à 23:57:10
Donc, aucune restriction...
Le résultat du concours t'interresse-t-il ? (le code)
Marsh Posté le 25-04-2004 à 23:59:02
christophe_d13 a écrit : Donc, aucune restriction... |
Euh sur quoi ? Sur la mémoire ?
Disons que des solutions "raisonnables" devraient être envisagées, mais les algos intéressants sont tjrs acceptés.
Disons 100 Mo de RAM maxi.
edit : plutôt 128 Mo...
Marsh Posté le 26-04-2004 à 00:00:54
christophe_d13 a écrit : Donc, aucune restriction... |
Bien sûr, si ça vous intéresse d'essayer. Un petit concours d'optimisation est tjrs amusant (m^me si c'est du C, mais là, je risque de m'en prendre plein la tête... ).
Marsh Posté le 26-04-2004 à 00:01:27
Y a pas que la mémoire... Le code également :
- code-morphing
- dynamic-code
- FPU ? MMX ? SSE ? SSE2 ? 3DNow ?
...
Marsh Posté le 26-04-2004 à 00:02:43
christophe_d13 a écrit : Y a pas que la mémoire... Le code également : |
Non, pas d'asm, juste du C/C++ ou autre langage portable.
Edit : Sauf si ça intéresse certains, mais je crains que sur un forum C++...
Marsh Posté le 26-04-2004 à 00:04:23
Faut bien définir les rêgles...
- C/C++ pur sans les fonctions externes (sauf pour l'affichage) ?
Marsh Posté le 26-04-2004 à 00:06:33
christophe_d13 a écrit : Faut bien définir les rêgles... |
Ok : C/C++ pur, on a le droit aux librairies standard, c'est tout.
Marsh Posté le 26-04-2004 à 20:30:01
Ben ce problème n'a pas l'air de soulever l'enthousiasme...
Marsh Posté le 29-04-2004 à 01:15:23
Et zou, histoire que ce problème ne tombe pas tout de suite aux oubliettes.
Allez, à première vue, ça ressemble à du O(N^2), mais il y a clairement une solution simple en O(N*Log(N)), et même une en O(N) pour des petites séquences.
Marsh Posté le 29-04-2004 à 01:19:24
O(N) ? si tu tries que tu parcoures à la recherche de doublon, ça fait du N*Log(N) + N
Marsh Posté le 29-04-2004 à 02:45:19
Citation : Les 5 millions de chiffres de la séquences seront générés 5 par 5 en prenant les 5 premiers chiffres de r à chaque fois, donc seulement si r>9999. |
j'avais pas vu ça ... non mais ces quoi ces conneires ? tu te rends compte que c'est peut être la partie qui prends le plus de temps ? rien que cette fonction elle fait chier
à ce petit jeu là, t'as plus vite fait de distribuer le fichier avec la séquence
Marsh Posté le 29-04-2004 à 02:56:01
ouais donne la liste, parce que là je commence à péter un plomb j'i bite rien à ta fonction de génération de merde, apprends à t'exprimer
Marsh Posté le 29-04-2004 à 03:12:08
moi je laisse tomber, je me suis assez pris la tête sur des bêtises tout ça parce que l'énoncé est pas clair
« seront générés 5 par 5 »
alors la franchement je vois pas. à jamais
Marsh Posté le 29-04-2004 à 04:22:16
Une petite question concernant la génération : tu peux préciser ou se trouve le LSB et le MSB pour 'r' et pour la 'séquence'. Histoire que tout le monde construise la séquence de la même facon.
Moi je trouve cette sequence :
10422197381276214297921856697316293946912835318827........
Marsh Posté le 29-04-2004 à 04:40:16
el muchacho a écrit : |
Si je repete l'opération 1.000.000 de fois, j'obtiens les 2/3 des chiffres demandés. En fait certains résultats de r sont fortement réduits par le modulo (moins de 5 chiffres significatifs).
Compte-t-on alors les zéro en position MSB ? Je pense que non mais c'est pas super clair...
Marsh Posté le 29-04-2004 à 05:14:43
1542871 trouve 0 fois [ ]. |
Ma séquence est pas bonne ! Elle est ennuyante ta formule à coder en C++ !
Marsh Posté le 29-04-2004 à 22:11:20
ATTENTION !!! SOLUTION !!!
Ne lisez pas ce qu'il y a en-dessous si vous voulez chercher encore !
Taz a écrit : O(N) ? si tu tries que tu parcoures à la recherche de doublon, ça fait du N*Log(N) + N |
Oui, c'est ça ma solution en O(N log (N)) (le +O(N) n'a pas besoin d'être précisé, je crois). Mais en commençant à la coder, je me pose une question : le tri a besoin d'une fonction de comparaison, or je me demande si la comparaison des séquences ne va pas tout faire tomber par terre. J'ai bien l'impression que si.
Par ailleurs, ça bouffe quand même pas mal de mémoire : au moins n*N pour des séquences de taille n, plus un buffer en Log(N) supplémentaire pour le quicksort.
Mon autre solution (en fait celle d'un pote) est impraticable pour des séquences de plus de 8 ou 9 chiffres car elle prend 10^n en mémoire. Par contre, je doute qu'on puisse faire plus rapide : il suffit de faire un tableau de tous les nombres possibles avec n chiffres (donc 10^n chiffes), et d'y stocker les listes des index à chaque apparition. Super simple, super rapide mais super dispendieux en RAM.
Marsh Posté le 29-04-2004 à 22:22:20
Taz a écrit :
|
Je sais. Le problème est de remplir le tableau avec des chiffres aléatoires.
Et puis bon, si c'est ça qui t'empêche de dormir :
Code :
|
(ps : je sais, l'utilisation du sprintf n'est pas heureuse, mais c'est encore la fonction dont je me souviens le mieux. Enfin bon, on s'en fout, là n'est pas le plus important)
Marsh Posté le 29-04-2004 à 22:39:59
xterminhate a écrit : Si je repete l'opération 1.000.000 de fois, j'obtiens les 2/3 des chiffres demandés. En fait certains résultats de r sont fortement réduits par le modulo (moins de 5 chiffres significatifs). |
C'est pour cela que j'ai précisé "pour r > 9999" dans l'énoncé, donc pour les nombres à 5 chiffres minimum...
Mais je suis d'accord, cette partie de l'énoncé est la moins intéressante et la plus rebutante. Le plus simple est que tout le monde parte sur le code que je donne (j'espère qu'il n'y a pas de bug).
Pour info, il me donne (N=5000000): (!! FAUX !!)
40 premiers : 1013911964351982868416495267061476227489
40 derniers : 3125048398216972947012249492535033240745
Marsh Posté le 29-04-2004 à 23:02:36
xterminhate a écrit :
|
Ben oui, c'est bien pour ça que je la proposais.
C'est un bon exercice d'utilisation des conteneurs STL (c'est aussi un bon exercice pour les codeurs en C). Si je suis pas trop paresseux, je m'en ferai peut-être une version des algos en Ocaml aussi (à moins que ça intéresse Joelf ou nraynaud). Une petite comparaison des perfs pourrait être intéressante (je n'ai aucune idée de ce que ça peut donner).
Ce problème n'est pas complètement gratuit, il a je pense des connexions (lointaines) avec le problème de séquençage de l'ADN, ou avec l'indexation de grands textes.
Marsh Posté le 30-04-2004 à 01:10:26
char buf[5] = "\0";
en plus t'es un malin toi
pas standard
#include <stdio.h>
const int N = 5000000;
const unsigned long SEED = 17L;
void alea(unsigned long &rand){
static unsigned long r;
rand = r = 1664525L * r + 1013904223L;
}
à mettre dans namespace, à inliner
vector<char> &v
la je comprends pas le prototype, on parle pas d'entier ?
Marsh Posté le 30-04-2004 à 07:11:19
Bon c'est n'importe quoi la
J'ai un code similaire et mon premier nombre est 1042201148. Alors je vois pas comment tu extrais 10139 de ce premier nombre. J'ai vérifié à la main mes premiers nombres ....
Pour info, voila mon code de génération :
Code :
|
Ce qui m'etonne, c'est qu'en C++ la valeur de ton masque ne passe pas. Donc, tu n'appliques pas vraiment la bonne formule (ce qui est mon cas aussi bien sur) donnée dans l'ennoncé ! Je me trompe ?
En fait, on calcule ca :
newseed = ( seed * multiplier ) % 2^32 + ( adder ) % 2^32 |
En C, on aurait accès au __int64 mais pas en C++, d'ou ma remarque precedente.
Marsh Posté le 30-04-2004 à 07:22:36
tu trouve pas ca un peu lourd de specifier a chaque fois std::, tu fais jamais de using... ? surtout que la tu utilise un seul namespace
Marsh Posté le 30-04-2004 à 07:29:25
Oui, je sais... ca rend le code un peu moins lisible, désolé.
Marsh Posté le 30-04-2004 à 07:57:19
Taz a écrit : char buf[5] = "\0"; |
Ah, je sens qu'on est sur les rails, là.
Dans le reste de mon code, j'inline, mais tu as raison.
Pour le printf, si tu peux me rappeler la version strstream, je changerai volontiers ma petite fonction de génération pour la rendre plus C++.
edit : pas la peine, xterminhate me la donne...
En fait, mon problème s'applique plutôt à un tableau de caractères (mais il peut se généraliser à toute collection d'objets finie ordonnée). Le fait que je dise que ces caractères soient des chiffres, c'est que je l'ai imaginé comme ça. Donc pour ce problème, ce sont des chiffres. Tu peux utiliser un vector<int> si tu préfères, tant que tu obtiens les mêmes valeurs dans ton tableau.
Marsh Posté le 30-04-2004 à 08:00:07
xterminhate a écrit : Bon c'est n'importe quoi la
|
Effectivement, tu as corrigé toi-même. J'ai vu le pb quand j'ai compilé. Le plus simple (ce que j'ai fait dans ma fonction), c'est de virer carrément la partie modulo.
Marsh Posté le 30-04-2004 à 08:03:56
cai juste qu'il me semble pas que cette syntax de format de printf soit standard.
char buf[5] = "\0"; t'as réalisé ce que tu as écris là ?
Marsh Posté le 30-04-2004 à 08:11:53
Taz a écrit : cai juste qu'il me semble pas que cette syntax de format de printf soit standard. |
Quel est le pb ?
(bon cassos boulot)
Marsh Posté le 30-04-2004 à 08:30:30
ReplyMarsh Posté le 30-04-2004 à 09:12:05
skelter a écrit :
|
à rien ! j'espère de comprendre ce qu'il a voulu faire..
Marsh Posté le 30-04-2004 à 20:53:24
Bon, revennons à nos moutons !... le concours
El much -> tu as vérifié ton code parce que pour le moment, on a vraiment pas la meme sequence de départ !
Marsh Posté le 30-04-2004 à 21:00:09
el muchacho : distribue un fichier avec la séquence, chaque élément séparé par un espace, le tout compréssé (et pas en zip/rar hein)
Marsh Posté le 30-04-2004 à 22:20:20
JagStang a écrit : char buf[5] ; |
Ouais, la grosse honte...
J'ai vu la bourde quand j'y ai pensé dans le bus.
En fait, je pensais plutôt à une initialisation du genre :
char buf[5] = "";
De toute façon, ça n'a pas d'incidence ici.
Marsh Posté le 30-04-2004 à 22:40:12
xterminhate a écrit : Bon, revennons à nos moutons !... le concours |
Bon je revois mon code...
Marsh Posté le 25-04-2004 à 23:50:13
J'ai vu que certains aimaient bien les petits problèmes.
Alors voilà, je me lance donc en espérant que celui-là ne fera pas un bide complet.
Le problème est simple : on a une séquence de 5 millions de chiffres aléatoires dans un tableau.
1er problème : (facile) trouver toutes les répétitions de n chiffres successifs dans le tableau. Les écrire dans un fichier txt, ainsi que leurs positions. On fera cette recherche pour toutes les séquences où : 7 <= n <= 15
2e problème : (moins facile) trouver la séquence de chiffres la plus longue qui est répétée au moins une fois.
Les meilleures solutions sont les plus rapides.
Ex. de sortie du premier programme :
Séquences à 7 chiffres :
1542871 trouvé 8 fois [8520, 12555, 47520, 255356, 1352255, 1753256, 2751356, 4256752]
0472123 trouvé 6 fois [154321, 788543, 853156, 1108256, 1332560, 1752212]
etc
Séquences à 8 chiffres :
32845769 trouvé 11 fois [...]
etc
Total :
1749 séquences à 7 chiffres
832 séquences à 8 chiffres
...
3 séquences à 15 chiffres
Durée : 74.245 s
NB : pour ceux que le challenge intéresse, il faut avoir tous la même séquence aléatoire. Je propose le générateur congruentiel suivant (Knuth) :
Graine : r = 17
itérations : r = (1664525 * r + 1013904223) modulo 2^32
Les 5 millions de chiffres de la séquences seront générés 5 par 5 en prenant les 5 premiers chiffres de r à chaque fois, donc seulement si r>9999.
L'opération étant itérée un million de fois (partie non chronométrée).
Ouala, bonne cogitation !
Message édité par el muchacho le 26-04-2004 à 23:26:56