Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1428 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2  3
Auteur Sujet :

[Concours] Recherche de doublons dans une séquence

n°713256
el muchach​o
Comfortably Numb
Posté le 30-04-2004 à 22:40:12  profilanswer
 

Reprise du message précédent :

xterminhate a écrit :

Bon, revennons à nos moutons !... le concours :p
 
El much -> tu as vérifié ton code parce que pour le moment, on a vraiment pas la meme sequence de départ !


 
Bon je revois mon code...


Message édité par el muchacho le 30-04-2004 à 22:49:41
mood
Publicité
Posté le 30-04-2004 à 22:40:12  profilanswer
 

n°713264
el muchach​o
Comfortably Numb
Posté le 30-04-2004 à 22:44:51  profilanswer
 

Taz a écrit :

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)


 
C'est inutile. Les chiffres de début et de fin sont bien suffisants.

n°713302
xterminhat​e
Si vis pacem, para bellum.
Posté le 30-04-2004 à 23:41:28  profilanswer
 

L'idée de taz me parait bonne au passage, ca evite de trop se prendre la tête sur la génération de la séquence qui n'a rien a voir avec de la programmation C++ ! Au contraire ca pourrait être du pur C pour correctement coder ta formule (__int64).  
 
Soit tu nous file le fichier de 5.000.000 octets qui va bien (sans espace si possible, mais bon je m'en fou).


---------------
Cordialement, Xterm-in'Hate...
n°713303
xterminhat​e
Si vis pacem, para bellum.
Posté le 30-04-2004 à 23:42:04  profilanswer
 

Soit on prend mon code :) Il est pas si mauvais non en terme de C++ (taz?)


---------------
Cordialement, Xterm-in'Hate...
n°713315
Taz
bisounours-codeur
Posté le 01-05-2004 à 00:28:18  profilanswer
 

xterminhate a écrit :

L'idée de taz me parait bonne au passage, ca evite de trop se prendre la tête sur la génération de la séquence qui n'a rien a voir avec de la programmation C++ ! Au contraire ca pourrait être du pur C pour correctement coder ta formule (__int64).  
 
Soit tu nous file le fichier de 5.000.000 octets qui va bien (sans espace si possible, mais bon je m'en fou).

ben si j'avais la séquence ... j'ai tenté avec une hashmap< int, vector<position> >

n°713353
el muchach​o
Comfortably Numb
Posté le 01-05-2004 à 06:45:42  profilanswer
 

xterminhate a écrit :

L'idée de taz me parait bonne au passage, ca evite de trop se prendre la tête sur la génération de la séquence qui n'a rien a voir avec de la programmation C++ ! Au contraire ca pourrait être du pur C pour correctement coder ta formule (__int64).  
 
Soit tu nous file le fichier de 5.000.000 octets qui va bien (sans espace si possible, mais bon je m'en fou).


 
Bon, c'est tout con, je viens de piger ce matin en me réveillant (c'est grâve, là, de rêver de C++). J'ai pas initialisé ma variablez statique.
 
il suffit donc de mettre : static unsigned long r = SEED.
 
Le code correct est donc :  
 

Code :
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. const int              N = 5000000;
  5. const unsigned long SEED = 17UL;
  6. inline void alea(unsigned long &rand){
  7.   static unsigned long r = SEED;
  8.   rand = r = 1664525UL * r + 1013904223UL;
  9. }
  10. int remplit_v(vector<char> &v, const int n)
  11. {
  12.   unsigned long r;
  13.   char buf[20] = "";
  14.   vector<char> tmp;
  15.  
  16.   v.reserve(n);
  17.   for (int i = 0; i < n; i+= 5)
  18.     {
  19.       do alea(r); while (r < 10000UL);
  20.       sprintf(buf, "%u", r);
  21.       tmp.assign(buf, &buf[sizeof(buf)]);  // faute de mieux
  22.       copy(tmp.begin(), tmp.end(), back_inserter(v));
  23.     }
  24.   return v.size();
  25. }


 
Si j'ajoute une fonction main comme :

Code :
  1. int main(int argc, string argv[])
  2. {
  3.   vector<char>  vect;
  4.   remplit_v(vect, N); // genere un vecteur aleatoire
  5.  
  6.   /////////////// VERIFICATION MANUELLE ////////////////////
  7.   unsigned long  nn =   1664525UL * 17UL + 1013904223UL;
  8.   for (int i = 0; i < 8; i++){
  9.     cout << nn << "\n";
  10.     nn =  1664525UL * nn + 1013904223UL;
  11.   }
  12.   //////////////////////////////////////////////////////////
  13.   cout << "Genere un vecteur de " << vect.size() << " chiffres." << endl; 
  14.   for (int i = 0; i < 40; ++i) cout << vect[i] ;
  15.   cout << endl;
  16.   for (int i = N-40; i < N; ++i) cout << vect[i] ;
  17.   cout << endl;
  18. }


 
J'obtiens :

Citation :


1042201148
3524153451
1973856974
1276228565
3066622768
1429761231
2883449826
921854425
669737316
2398403955
Genere un vecteur de 5000000 chiffres.
1042235241197381276230666142972883492185
1675913308512872428215612116421983834693


 
Bon, sur ce, on va enfin pouvoir passer au morceau intéressant ! :na:


Message édité par el muchacho le 07-05-2004 à 21:09:46
n°713358
el muchach​o
Comfortably Numb
Posté le 01-05-2004 à 07:56:45  profilanswer
 

xterminhate a écrit :

Soit on prend mon code :) Il est pas si mauvais non en terme de C++ (taz?)


 
Ben il a un ch'ti problème.
 

Code :
  1. std::string generation()
  2.   {
  3.     std::string alea;
  4.     std::string::size_type taille_sequence( alea.size() );
  5.     const unsigned long multiplier( 1664525UL );
  6.     const unsigned long addend( 1013904223UL );
  7.     unsigned long valeur( 17UL );
  8.     while( taille_sequence < 10 )
  9.     {                         
  10.       if( ( valeur =  ( multiplier * valeur + addend ) ) > 9999UL )
  11.       {/*
  12.         std::ostringstream str;
  13.         str << valeur;     
  14.         alea += str.str().substr(0,5);*/
  15.         cout << valeur << "\n";
  16.         taille_sequence++; 
  17.       }
  18.     }
  19.     return alea;
  20.   }

 
 
donne la bonne séquence. La séquence que tu as donnée "saute" des valeurs.


Message édité par el muchacho le 01-05-2004 à 08:11:04
n°713362
xterminhat​e
Si vis pacem, para bellum.
Posté le 01-05-2004 à 09:24:07  profilanswer
 

Bon c'est cool, je viens de compiler ton code et on trouve exactement la même séquence au final ! Enfin :) :) :)
 
On peut commencer, mais je garde mon code (il fait moins de warning dans gcc) par contre le mien tourne 5 fois moins vite (et m......).


Message édité par xterminhate le 01-05-2004 à 10:07:29

---------------
Cordialement, Xterm-in'Hate...
n°713375
el muchach​o
Comfortably Numb
Posté le 01-05-2004 à 10:51:45  profilanswer
 

Taz a écrit :

ben si j'avais la séquence ... j'ai tenté avec une hashmap< int, vector<position> >


 
Tiens oui, pas con, la hashmap. Probablement la meilleure solution.

n°713391
xterminhat​e
Si vis pacem, para bellum.
Posté le 01-05-2004 à 11:40:31  profilanswer
 

Voila, le calcul est simple : j'aurai ma solution dans 28 jours a peu pres..... j'ai interet d'acheter un onduleur ! :p


---------------
Cordialement, Xterm-in'Hate...
mood
Publicité
Posté le 01-05-2004 à 11:40:31  profilanswer
 

n°713406
souk
Tourist
Posté le 01-05-2004 à 12:26:55  profilanswer
 

avec un petit arbre de suffixes a la Ukkonen ca se fait pas bien ? :)

n°714693
xterminhat​e
Si vis pacem, para bellum.
Posté le 03-05-2004 à 21:39:41  profilanswer
 

Suite au crash de ce WE, mon post a viré. Je le remets.
 
Avez vous trouvé un nombre de plus de 12 chiffres dans la séquence d'aléa qui se répete au moins une fois ?


---------------
Cordialement, Xterm-in'Hate...
n°714696
el muchach​o
Comfortably Numb
Posté le 03-05-2004 à 21:47:36  profilanswer
 

Pas eu le temps de continuer ce we. Mariage, tout ça. C'est bien les mariages, ça rappelle qu'il y a une vie à coté du pécé.
Question : les string sont-ils illimités en taille ? (est-ce tjrs le cas ?)


Message édité par el muchacho le 03-05-2004 à 21:49:48
n°714710
xterminhat​e
Si vis pacem, para bellum.
Posté le 03-05-2004 à 22:03:07  profilanswer
 

Réponse normande : aussi limités que les vector ?!


Message édité par xterminhate le 03-05-2004 à 22:03:16

---------------
Cordialement, Xterm-in'Hate...
n°717972
el muchach​o
Comfortably Numb
Posté le 06-05-2004 à 22:22:35  profilanswer
 

xterminhate a écrit :

Suite au crash de ce WE, mon post a viré. Je le remets.
 
Avez vous trouvé un nombre de plus de 12 chiffres dans la séquence d'aléa qui se répete au moins une fois ?


 
Non. Voici la liste des nombres de 12 chiffres que j'ai trouvés :

Citation :


Séquences à 12 chiffres :
251171222386 est repete 2 fois [4014523 4178258 ]
493337816967 est repete 2 fois [315458 3344903 ]
617314402174 est repete 2 fois [1491421 3665914 ]
238736143232 est repete 2 fois [96106 3681379 ]
182428036637 est repete 2 fois [533908 2812393 ]
528333149232 est repete 2 fois [1631619 3485164 ]
923295163412 est repete 2 fois [494142 4702474 ]
911107194538 est repete 2 fois [2255209 4050609 ]
227113708026 est repete 2 fois [581265 3523865 ]
340737154117 est repete 2 fois [505659 2702371 ]
407719582282 est repete 2 fois [76221 4165646 ]
570420451489 est repete 2 fois [483946 4716727 ]
532531180082 est repete 2 fois [638204 4322849 ]
020197153311 est repete 2 fois [42784 3330204 ]
574228782149 est repete 2 fois [123951 1714636 ]
071199204248 est repete 2 fois [127217 2690946 ]
632266371121 est repete 2 fois [894934 4846064 ]
198413477935 est repete 2 fois [3473960 4620965 ]
921633115889 est repete 2 fois [2825419 4904334 ]


 
Mon code prend 6mn 30s de temps CPU sur un P4 à 2.4 GHz (commande : doublons 5000000 7 15) et s'arroge jusqu'à 500 Mo de RAM, donc dépasse très largement la limite des 128 Mo de RAM que je m'étais fixée...
 

Code :
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <deque>
  5. #include <ext/hash_map>
  6. #include <map>
  7. using namespace std;
  8. unsigned int N;
  9. const unsigned long SEED = 17L;
  10. typedef deque<char> Chaine;
  11. inline void alea(unsigned long &rand){
  12.   static unsigned long r = SEED;
  13.   rand = r = 1664525UL * r + 1013904223UL;
  14. }
  15. int remplit_v(vector<char> &v, const int N)
  16. {
  17. // Pour un vecteur de 5000000 chiffres avec seed = 17 :
  18. // 40 premiers chiffres : 1042235241197381276230666142972883492185
  19. // 40 derniers chiffres : 1675913308512872428215612116421983834693
  20.  
  21.   unsigned long r;
  22.   char buf[20] = "";
  23.   vector<char> tmp;
  24.  
  25.   v.reserve(N);
  26.   for (int i = 0; i < N; i+= 5)
  27.     {
  28.       do alea(r); while (r < 10000UL);
  29.       sprintf(buf, "%u", r);
  30.       tmp.assign(buf, &buf[5]);  // faute de mieux
  31.       copy(tmp.begin(), tmp.end(), back_inserter(v));
  32.     }
  33.    
  34.   int num = 40;
  35.   cout << num << " premiers chiffres : ";
  36.   for (int k = 0; k < num; ++k) cout << v[k]; cout << endl;
  37.   cout << num << " derniers chiffres : ";
  38.   for (int j = N-num; j < N; ++j) cout << v[j]; cout << endl;
  39.  
  40.   return v.size();
  41. }
  42. // Fonction de hachage (cf Taz)
  43. struct FNV_hash{
  44.     inline unsigned operator()(const string& x) const                                         
  45.     {                                                       
  46.       register unsigned hash = 2166136261u;
  47.       const string::size_type x_size(x.size());
  48.    
  49.       for(register string::size_type i = 0; i < x_size;
  50.           hash = (hash * 16777619u)^x[i++]);
  51.    
  52.       return hash;
  53.    }
  54. };
  55. typedef hash_map<const string, vector<int>, FNV_hash> HachageChaine;
  56. int hache(HachageChaine &table_H, const vector<char> &vect, const int n)
  57. {
  58.   string str;
  59.   HachageChaine::iterator it;
  60.   str.reserve(100);
  61.   table_H.resize(N-n+1);
  62.  
  63.   for (unsigned int i = 0; i < N-n; ++i)
  64.     {
  65.       for(unsigned int j = i; j <= i+n; j++) str += vect[j]; //grossièrement répétitif
  66.      
  67.       it = table_H.find(str);
  68.       if(it == table_H.end())
  69.         {
  70.           vector<int> v;
  71.           v.push_back(i);
  72.           table_H.insert(HachageChaine::value_type(str, v));
  73.         }
  74.       else
  75.         {
  76.           it->second.push_back(i);
  77.         }
  78.        
  79.       str.erase();
  80.     }
  81.   return table_H.size();
  82. }
  83. int hache(map<const string, vector<int> > &table_M, const vector<char> &v, const int n)
  84. {
  85.   string str;
  86.   map<const string, vector<int> >::iterator it;
  87.   str.reserve(100);
  88.  
  89.   for (unsigned int i = 0; i < N-n; ++i)
  90.     {
  91.       for(unsigned int j = i; j <= i+n; j++) str += v[j];
  92.      
  93.       it = table_M.find(str);
  94.       if(it == table_M.end())
  95.         {
  96.           vector<int> v;
  97.           v.push_back(i);
  98.           table_M.insert(pair<string, vector<int> >(str, v));
  99.         }
  100.       else
  101.         {
  102.           it->second.push_back(i);
  103.         }
  104.       str.erase();
  105.     }
  106.   return table_M.size();
  107. }
  108. void affiche_doublons(const vector<char>& vect , const int lmin, const int lmax)
  109. {
  110.   HachageChaine table;
  111.   typedef HachageChaine::iterator H_iter;
  112.   for (int l = lmin; l <= lmax; ++l)
  113.     {
  114.       cout << "\nSéquences à " << l << " chiffres :\n";
  115.       cout << "Hachage : " << N - hache(table, vect, l) - l
  116.            << " séquences trouvées\n";
  117.      
  118.       for(H_iter it = table.begin(); it != table.end(); ++it)
  119.         {
  120.           string clef = it->first;
  121.           int card = it->second.size();
  122.           if(card > 1)
  123.             {
  124.               cout << clef << " est repete " << card << " fois [ ";
  125.               copy(it->second.begin(), it->second.end(),
  126.                    ostream_iterator<int>(cout, " " ));
  127.               cout << "]" << endl;
  128.             }
  129.         }
  130.       table.clear();
  131.     }
  132. }
  133. void affiche_doublons_m(const vector<char>& vect , const int lmin, const int lmax)
  134. {
  135.   map<const string, vector<int> > table;
  136.   typedef map<const string, vector<int> >::iterator M_iter;
  137.   for (int l = lmin; l <= lmax; ++l)
  138.     {
  139.       cout << "\nSéquences à " << l << " chiffres :\n";
  140.       cout << "Hachage : " << N - hache_m(table, vect, l) - l
  141.            << " séquences trouvées\n";
  142.       for(M_iter it = table.begin(); it != table.end(); ++it)
  143.         {
  144.           string clef = it->first;
  145.           int card = it->second.size();
  146.           if(card > 1)
  147.             {
  148.               cout << clef << " est repete " << card << " fois [ ";
  149.               copy(it->second.begin(), it->second.end(),
  150.                    ostream_iterator<int>(cout, " " ));
  151.               cout << "]" << endl;
  152.             }
  153.         }
  154.       table.clear();
  155.     }
  156. }
  157. int main(int argc, char* argv[])
  158. {
  159.   vector<char>  vect;
  160.   int lmin, lmax;
  161.  
  162.   if (argc != 4 ) {
  163.     cout << "Usage : doublons N lmin lmax" << endl;
  164.     return -1;
  165.   }
  166.  
  167.   N    =  atoi(argv[1]);
  168.   lmin =  atoi(argv[2]);
  169.   lmax =  atoi(argv[3]);
  170.   cout << "Genere un vecteur de " << N << " chiffres." << endl;
  171.   remplit_v(vect, N);
  172.   //affiche_doublons_m(vect, lmin, lmax);
  173.   affiche_doublons_h(vect, lmin, lmax);
  174.   return 0;
  175. }


 
En prime, il y a la version avec map.


Message édité par el muchacho le 07-05-2004 à 21:18:47
n°718027
Taz
bisounours-codeur
Posté le 06-05-2004 à 23:16:08  profilanswer
 

je vois pas le besoin d'utiliser des string

n°718040
Kristoph
Posté le 06-05-2004 à 23:39:19  profilanswer
 

Le problème est assez pipo en fait. Si il est resolu pour n = 7 par exemple, et bien tout le reste en découle très très facilement et consomme forcement beaucoup moins de mémoire à traiter avec le résultat pour n = 7 disponible.
 
De plus la 2eme question n'a alors plus aucun sens car la réponse sera très vite donnée par la première question : il suffit de trouver le premier n pour lequel il n'y a pas de répétition :)

n°718049
xterminhat​e
Si vis pacem, para bellum.
Posté le 06-05-2004 à 23:51:40  profilanswer
 

Je me permets de reposer ma question une fois de plus (elle n'a semble-t-il pas été comprise). Avez vous trouvé un nombre de plus de 12 chiffres ? C'est à dire 13 ou plus encore !! Person j'ai que des sequences de 12 chiffres au maximum.


---------------
Cordialement, Xterm-in'Hate...
n°718053
el muchach​o
Comfortably Numb
Posté le 06-05-2004 à 23:58:39  profilanswer
 

Taz a écrit :

je vois pas le besoin d'utiliser des string


 
Y'en a pas. J'avais commencé avec des deque<char> en fait (uniquement pour pouvoir faire un pop_front(); push_back() sur la fenetre...). C'est juste que l'implémentation de hash_map de STLPort accepte des char * ou des string. Mais il s'avère que le temps est passé en grande majorité dans les fonctions de la hashmap. J'ai pas mesuré mais je me demande si la fonction de hachage n'est pas un peu compliquée, ou si le fait d'utiliser des string ne ralentit pas grandement l'implémentation. Je n'en sais rien mais je compte essayer avec des char * ou au moins un vector<char> si possible.
Les quelques tests que j'ai faits donnaient la version avec hashmap seulement 50% plus rapide que la version avec map, ce qui est un peu décevant (sur des tableaux de l'ordre de ~50 000 caractères, sans doute pas assez grands).
 
Enfin, dans la fonction "hache()", je voulais faire un truc du genre :

Code :
  1. pair<string, bool> res;
  2. res = table_H.insert(HachageChaine::value_type(str, v));
  3. if(res.second == false)
  4. {
  5.   récupérer it d'une manière ou d'une autre
  6.   it->second.push_back(i);
  7. }


 
ce qui m'aurait évité d'appeler la méthode find.
Y'aurait-il une manière de faire cela ?


Message édité par el muchacho le 07-05-2004 à 00:16:15
n°718061
el muchach​o
Comfortably Numb
Posté le 07-05-2004 à 00:11:36  profilanswer
 

Kristoph a écrit :

Le problème est assez pipo en fait. Si il est resolu pour n = 7 par exemple, et bien tout le reste en découle très très facilement et consomme forcement beaucoup moins de mémoire à traiter avec le résultat pour n = 7 disponible.
 
De plus la 2eme question n'a alors plus aucun sens car la réponse sera très vite donnée par la première question : il suffit de trouver le premier n pour lequel il n'y a pas de répétition :)


 
Euh, j'ai pas tout compris... à part le fait que on peut prendre les chaines de longueur n comme base pour trouver celles de longueur n+1 (j'y ai pensé, optimisation intéressante).
Pour la 2e question, c'est sûr que la méthode brutale marche, mais je voulais savoir s'il n'y avait pas une procédure plus directe. Ceci dit, avec l'optimisation proposée, c'est pas mal.

n°718062
el muchach​o
Comfortably Numb
Posté le 07-05-2004 à 00:12:39  profilanswer
 

xterminhate a écrit :

Je me permets de reposer ma question une fois de plus (elle n'a semble-t-il pas été comprise). Avez vous trouvé un nombre de plus de 12 chiffres ? C'est à dire 13 ou plus encore !! Person j'ai que des sequences de 12 chiffres au maximum.


 
J'ai répondu. Tu n'as pas vu ?
 
Au fait, on peut voir ton code ? :bounce:


Message édité par el muchacho le 07-05-2004 à 00:21:15
n°718069
Kristoph
Posté le 07-05-2004 à 00:27:43  profilanswer
 

Code :
  1. $ time python sequence2.py > result.txt
  2. 137.34user 4.20system 5:42.74elapsed 41%CPU (0avgtext+0avgdata 0maxresident)k
  3. 0inputs+0outputs (25945major+163035minor)pagefaults 0swaps
  4. $ ll result.txt
  5. -rw-r--r--    1 kristoph kristoph 46702592 mai  7 00:24 result.txt
  6. $ cat sequence2.py
  7. import psyco
  8. psyco.full()
  9. import os
  10. f = file("data.txt","rb" )
  11. data = f.read()
  12. def recherche(data,size):
  13.         result = {}
  14.         for i in xrange(len(data)-size+1):
  15.                 chunck = data[i:i+size]
  16.                 val = result.get(chunck,None)
  17.                 if val is None:
  18.                         result[chunck] = [i]
  19.                 else:
  20.                         val.append(i)
  21.         return result
  22. d = recherche(data,7)
  23. for seq,posList in d.iteritems():
  24.         if len(posList) > 1:
  25.                 print "Found %s at pos : %s" % (seq,posList)
  26. os._exit(0)


 
Qui a dis que le python c'est lent  :whistle:
 
Au fait, la config c'est un Athlon XP 1800+


Message édité par Kristoph le 07-05-2004 à 00:30:36
n°718070
xterminhat​e
Si vis pacem, para bellum.
Posté le 07-05-2004 à 00:30:12  profilanswer
 

Donc le max est bien 12 ;)


---------------
Cordialement, Xterm-in'Hate...
n°718071
xterminhat​e
Si vis pacem, para bellum.
Posté le 07-05-2004 à 00:39:47  profilanswer
 

Mon code n'est vraiment pas terrible, il tourne tellement lentement! Si je trouve le moyen de l'optimiser et si j'atteins des perfs acceptables, je le posterai.
 
Dans le principe, j'applique une fonction de traitement du signal : autocorrelation. Cela répond à la fois aux deux problèmes posés initialement. Ainsi, je compare l'aléa avec lui même sur toute sa longueur et pour tous les décalages possibles compris entre 1 (pas 0 evidemment) et 5.000.000.
 
Mon code est en fait une double boucle for imbriquée avec au milieu un test : alea[t]==alea[delta_t+t). Ainsi, je mesure le taux de corrélation, et lorsque j'obtiens un pic de correlation, je suis en présence d'une séquence qui se répete. Je relève donc toutes les séquences qui ont générées un pic de correlation supérieur ou égale à 7.
 
Mais bon, j'ai lancé mon code sur une machine d'appoint (Celeron300) et dans la version complète (relevé des séquences de 7 à 15), il prend son temps (28jours j'avais calculé)! :)


Message édité par xterminhate le 07-05-2004 à 00:41:13

---------------
Cordialement, Xterm-in'Hate...
n°718074
Taz
bisounours-codeur
Posté le 07-05-2004 à 00:53:47  profilanswer
 

f = file("data.txt","rb" )
  data = f.read()
 
laid
 
 
                  val = result.get(chunck,None)
                  if val is None:  
 
laid, mauvais, utilise setdefault
 
 
 
os._exit(0)
...

n°718076
Kristoph
Posté le 07-05-2004 à 01:05:36  profilanswer
 

Taz a écrit :

f = file("data.txt","rb" )
  data = f.read()
 
laid


Peut être mais tu mettrais quoi à la place ?

Taz a écrit :


                  val = result.get(chunck,None)
                  if val is None:  
 
laid, mauvais, utilise setdefault


Alors là pas d'accord. Je ne vois vraiment pas ce que setdefault viens faire ici.
 

Taz a écrit :


os._exit(0)
...


 
C'est pour ne pas faire desallouer la mémoire à la fin du script. Je prendrais sinon la moitié en quittant le programme  :whistle:


Message édité par Kristoph le 07-05-2004 à 01:05:59
n°718081
Taz
bisounours-codeur
Posté le 07-05-2004 à 01:24:28  profilanswer
 

data = file("data.txt","rb" ).read()
 
result.setdefault(chunck, []).append(i)

n°718083
Kristoph
Posté le 07-05-2004 à 01:33:11  profilanswer
 

Taz a écrit :

data = file("data.txt","rb" ).read()
 
result.setdefault(chunck, []).append(i)


 
Mouais, ce n'est pas evident au premier abord que la methode setdefault renvoie le resultat de get apres affectation. En tout cas, je ne pense pas que ce soit plus clair que ce que j'ai ecris
 
Et pour le file, j'essaye d'eviter ce genre de syntaxe car on ne peux pas faire explicitement appel à close() de cette façon. ( appel que j'ai oublié dans le code ... )
 

n°718084
Taz
bisounours-codeur
Posté le 07-05-2004 à 01:56:03  profilanswer
 

au si ça l'est. et c'est bien plus rapide
 
 
« Et pour le file, j'essaye d'eviter ce genre de syntaxe car on ne peux pas faire explicitement appel à close() de cette façon. ( appel que j'ai oublié dans le code ... ) »
 
et les __del__ de python c'est du vent ? python __a__ des destructeurs et il les __appelle__ systématiquement (sauf cyle)
 
alors re pose toi dessus et oubli le C

n°718100
el muchach​o
Comfortably Numb
Posté le 07-05-2004 à 08:03:31  profilanswer
 

xterminhate a écrit :

Mon code n'est vraiment pas terrible, il tourne tellement lentement! Si je trouve le moyen de l'optimiser et si j'atteins des perfs acceptables, je le posterai.
 
Dans le principe, j'applique une fonction de traitement du signal : autocorrelation. Cela répond à la fois aux deux problèmes posés initialement. Ainsi, je compare l'aléa avec lui même sur toute sa longueur et pour tous les décalages possibles compris entre 1 (pas 0 evidemment) et 5.000.000.
 
Mon code est en fait une double boucle for imbriquée avec au milieu un test : alea[t]==alea[delta_t+t). Ainsi, je mesure le taux de corrélation, et lorsque j'obtiens un pic de correlation, je suis en présence d'une séquence qui se répete. Je relève donc toutes les séquences qui ont générées un pic de correlation supérieur ou égale à 7.
 
Mais bon, j'ai lancé mon code sur une machine d'appoint (Celeron300) et dans la version complète (relevé des séquences de 7 à 15), il prend son temps (28jours j'avais calculé)! :)


 
Ah oui, effectivement, c'est un peu "bourrin" ! :D  
La méthode rapide pour l'autocorrélation est d'utiliser des FFT -> n Log (n).
 
Avec l'optimisation proposée plus haut, je devrais pouvoir faire tomber ma méthode à moins de 2 minutes sur un gros P4.

n°719179
el muchach​o
Comfortably Numb
Posté le 07-05-2004 à 20:43:13  profilanswer
 

el muchacho a écrit :


 
Enfin, dans la fonction "hache()", je voulais faire un truc du genre :

Code :
  1. pair<string, bool> res;
  2. res = table_H.insert(HachageChaine::value_type(str, v));
  3. if(res.second == false)
  4. {
  5.   récupérer it d'une manière ou d'une autre
  6.   it->second.push_back(i);
  7. }


 
ce qui m'aurait évité d'appeler la méthode find.
Y'aurait-il une manière de faire cela ?


 
Je me disais bien que ça existait. Il suffisait de lire le fuckin' manual :  
 

Code :
  1. pair <HachageChaine::iterator, bool
  2.       res = table_H.insert(hash_map<string,
  3.                            vector<int>,
  4.                            FNV_hash>::value_type(str, v));
  5.       if(res.second == false) res.first->second.push_back(i);


Message édité par el muchacho le 10-05-2004 à 09:24:06
n°719427
assyrium
Posté le 08-05-2004 à 13:27:46  profilanswer
 

Kristoph a écrit :

Code :
  1. $ time python sequence2.py > result.txt
  2. 137.34user 4.20system 5:42.74elapsed 41%CPU (0avgtext+0avgdata 0maxresident)k
  3. 0inputs+0outputs (25945major+163035minor)pagefaults 0swaps
  4. $ ll result.txt
  5. -rw-r--r--    1 kristoph kristoph 46702592 mai  7 00:24 result.txt
  6. $ cat sequence2.py
  7. import psyco
  8. psyco.full()
  9. import os
  10. f = file("data.txt","rb" )
  11. data = f.read()
  12. def recherche(data,size):
  13.         result = {}
  14.         for i in xrange(len(data)-size+1):
  15.                 chunck = data[i:i+size]
  16.                 val = result.get(chunck,None)
  17.                 if val is None:
  18.                         result[chunck] = [i]
  19.                 else:
  20.                         val.append(i)
  21.         return result
  22. d = recherche(data,7)
  23. for seq,posList in d.iteritems():
  24.         if len(posList) > 1:
  25.                 print "Found %s at pos : %s" % (seq,posList)
  26. os._exit(0)


 
Qui a dis que le python c'est lent  :whistle:
 
Au fait, la config c'est un Athlon XP 1800+


 
 
 
J'ai essayé ce programme sur ma machine (je ne suis absolument pas un connaisseur en python), mais le programme a tourné plus de 10 minutes, l'ordi s'est mis à swaper comme un fou (mes pauvres 512Mo ne suffisaient pas). Y a t'il une explication (peut être mon fichier data qui n'était pas correct syntaxiquement) ? Autrement, j'aurai une version c++ qui mettrait 3 mn sur un athlon 2000+ (mais il faut que je vérifie le résultat) qui fonctionne avec des arbres avl (et qui n'est pas du tout optimisée : c'est très moche). Je posterai le code dès que ça sera vérifié.

n°719437
Kristoph
Posté le 08-05-2004 à 13:45:32  profilanswer
 

assyrium a écrit :

J'ai essayé ce programme sur ma machine (je ne suis absolument pas un connaisseur en python), mais le programme a tourné plus de 10 minutes, l'ordi s'est mis à swaper comme un fou (mes pauvres 512Mo ne suffisaient pas). Y a t'il une explication (peut être mon fichier data qui n'était pas correct syntaxiquement) ? Autrement, j'aurai une version c++ qui mettrait 3 mn sur un athlon 2000+ (mais il faut que je vérifie le résultat) qui fonctionne avec des arbres avl (et qui n'est pas du tout optimisée : c'est très moche). Je posterai le code dès que ça sera vérifié.


 
Moi aussi j'ai seulement 512Mo et ça suffisait tout juste à faire marcher cette version. J'en ai une autre qui prend un peu moins de place pour n=7 mais pour réduire encore la consomation mémoire, il va falloir passer à du C ou du C++

n°719443
assyrium
Posté le 08-05-2004 à 13:58:07  profilanswer
 

Kristoph a écrit :

Moi aussi j'ai seulement 512Mo et ça suffisait tout juste à faire marcher cette version. J'en ai une autre qui prend un peu moins de place pour n=7 mais pour réduire encore la consomation mémoire, il va falloir passer à du C ou du C++


 
Ah oui, en + je n'avais pas fait attention que c'était pour n=7(j'ai recopié bêtement le code).ma version fait pour n=7 à n= 15... à priori ça prend à peu près 100 Mo (je suis en train de mesuree). Mais je le fais en plusieurs passes, c'est pas très propre... et si je fais en une passe, avec des arbres dans les arbres (ça accélère de 2 ou 3 fois), ça prend 500 Mo à 20% de tous les calculs... va faloir trouver un moyen de changer ça.

n°719447
el muchach​o
Comfortably Numb
Posté le 08-05-2004 à 14:02:35  profilanswer
 

Kristoph a écrit :

Moi aussi j'ai seulement 512Mo et ça suffisait tout juste à faire marcher cette version. J'en ai une autre qui prend un peu moins de place pour n=7 mais pour réduire encore la consomation mémoire, il va falloir passer à du C ou du C++


 
Personne n'a encore essayé en Ocaml ?
Je pars en vacances 15 jours et au retour, je m'y colle.


Message édité par el muchacho le 08-05-2004 à 14:08:02
n°719678
assyrium
Posté le 08-05-2004 à 23:01:14  profilanswer
 

J'ai un peu optimisé, mnt ça met 45 secondes sur un amd 2000+, et ça utilise environ 250 mo de ram. Par contre, le code fait 400 lignes environ, je ne sais pas si ça ne gêne pas (ou se fait) de poster un message de cette taille.

n°719684
Taz
bisounours-codeur
Posté le 08-05-2004 à 23:47:49  profilanswer
 

bah cai psyco qui te fait tout péter je pense là

n°719783
el muchach​o
Comfortably Numb
Posté le 09-05-2004 à 13:02:19  profilanswer
 

assyrium a écrit :

J'ai un peu optimisé, mnt ça met 45 secondes sur un amd 2000+, et ça utilise environ 250 mo de ram. Par contre, le code fait 400 lignes environ, je ne sais pas si ça ne gêne pas (ou se fait) de poster un message de cette taille.


 
Si si, ça devrait être intéressant. Vas-y, envoie. :)

n°719853
assyrium
Posté le 09-05-2004 à 16:02:15  profilanswer
 

Code :
  1. #include <iostream.h>
  2. #include <cstdlib>
  3. unsigned int N = 5000000;
  4. const unsigned long SEED = 17L;
  5. class Position **PositionsRedondantesG;
  6. int NbPositionsG;
  7. template <class T> class noeud
  8. {
  9. private:
  10.  noeud *fg;
  11.  noeud *fd;
  12.  int dq;//desequilibre du noeud
  13.  int Nb;//compteur du nombre d'occurence de l'element ajoute
  14.  T Info;
  15. public:
  16.  T &RInfo(){return Info;}
  17.  noeud<T> *Ajouter(T &Info, noeud *&Lien, int &G);
  18.  //noeud<T> *Ajouter(noeud<T> &Info, noeud *&Lien, int &G);
  19.  void RotationDroite(noeud *&N);
  20.  void RotationGauche(noeud *&N);
  21.  void RotationGaucheDroite(noeud *&N);
  22.  void RotationDroiteGauche(noeud *&N);
  23.  void Reequilibrer(noeud *&Lien, int des);
  24.  void Vider();
  25.  noeud(T &Info)
  26.  {
  27.   fg = NULL;
  28.   fd = NULL;
  29.   noeud::Info = Info;
  30.   Info.SetParent(this);
  31.   Nb = 1;
  32.   dq = 0;
  33.  };
  34. };
  35. template <class T> class arbre
  36. {
  37. private:
  38. int Haut;
  39. int NbElmt;
  40. public:
  41. noeud<T> *Racine;
  42. noeud<T> *Ajouter(T &Info);
  43. arbre();
  44. ~arbre();
  45. };
  46. class Position
  47. {
  48. private:
  49.  unsigned long long n;
  50.  int Nb;
  51.  unsigned int Positions[10];
  52.  void *Contenant;
  53. public:
  54.  void SetPos(int Pos){Positions[0] = Pos;};
  55.  void SetN(unsigned long long N){n = N;};
  56.  unsigned long long GetN(){return n;};
  57.  int GetNb(){return Nb;};
  58.  int GetPos(int i){return Positions[i];};
  59.  void SetParent(void *C) {Contenant = C;};
  60.  void *GetParent(){return Contenant;};
  61.  Position()
  62.  {
  63.   Nb = 0;
  64.   n = 0;
  65.  }
  66.  void Afficher()
  67.  {
  68.   cout << "Nb "<<n<<" -> "<< Nb <<" fois ";
  69.   for (int i = 0; i < Nb; i++)
  70.    cout <<"["<<Positions[i]<<"] ";
  71.   cout <<endl;
  72.  }
  73.  Position &operator = (Position &p)
  74.  {
  75.   Positions[Nb++] = p.Positions[0];
  76.   n = p.n;
  77.  }
  78.  bool operator == (Position &p)
  79.  {
  80.   if (p.n == n)
  81.   {
  82.    if (Nb == 1) PositionsRedondantesG[NbPositionsG++] = this;
  83.    Positions[Nb++] = p.Positions[0];
  84.    return true;
  85.   }
  86.   return false;
  87.  }
  88.  bool operator < (Position &p)
  89.  {
  90.   if (n < p.n) return true;
  91.   return false;
  92.  }
  93.  bool operator > (Position &p)
  94.  {
  95.   if (n > p.n) return true;
  96.   return false;
  97.  }
  98. };
  99. template <class T> void noeud<T>::Vider()
  100. {
  101. if (fd) fd->Vider();
  102. if (fg) fg->Vider();
  103. if (Nb <= 1) delete this;
  104. else Info.Afficher();
  105. }
  106. template <class T> void noeud<T>::Reequilibrer(noeud *&Lien, int des)
  107. {
  108. noeud *FG=NULL, *FD = NULL;
  109. bool DoubleRotation = false;
  110. if (des > 0)
  111. {
  112.  if (fg->dq >= 0)
  113.  {
  114.   RotationDroite(Lien);
  115.   if (Lien->dq == 1) Lien->fd->dq = Lien->dq = 0;
  116.   else Lien->dq = -1, Lien->fd->dq = 1;
  117.  }
  118.  else
  119.  {
  120.   RotationGaucheDroite(Lien);
  121.   DoubleRotation = true;
  122.   FG = Lien->fg;
  123.   FD = Lien->fd;
  124.  }
  125. }
  126. else
  127. {
  128.  if (fd->dq <= 0)
  129.  {
  130.   RotationGauche(Lien);
  131.   if (Lien->dq == -1) Lien->fg->dq = Lien->dq = 0;
  132.   else Lien->fg->dq = -1, Lien->dq = 1;
  133.  }
  134.  else
  135.  {
  136.   RotationDroiteGauche(Lien);
  137.   DoubleRotation = true;
  138.   FG = Lien->fd;
  139.   FD = Lien->fg;
  140.  }
  141. }
  142. if (DoubleRotation)
  143. {
  144.  switch(Lien->dq)
  145.  {
  146.   case 1: FG->dq = 0;
  147.       FD->dq = -1;
  148.   break;
  149.   case -1:FG->dq = 1;
  150.       FD->dq = 0;
  151.   break;
  152.   case 0: FG->dq = FD->dq = 0;
  153.  }
  154.  Lien->dq = 0;
  155. }
  156. }
  157. template <class T> noeud<T> *noeud<T>::Ajouter(T &Info, noeud *&Lien, int &G)
  158. {
  159. noeud<T> *R;
  160. if (Info > noeud::Info)
  161. {
  162.  if (fd) R = fd->Ajouter(Info, fd, G);
  163.  else  R = fd = new noeud(Info), G = 1;
  164.  if (G) dq--;
  165.  if (dq >= 0) G = 0;
  166.  if (dq == -2) Reequilibrer(Lien, dq), G=0;
  167. }
  168. else if (Info < noeud::Info)
  169. {
  170.  if (fg) R = fg->Ajouter(Info, fg, G);
  171.  else  R = fg = new noeud(Info), G = 1;
  172.  if (G) dq++;
  173.  if (dq <= 0) G = 0;
  174.  if (dq == 2) Reequilibrer(Lien, dq), G=0;
  175. }
  176. else
  177. {
  178.  noeud::Info==Info;
  179.  Nb++;
  180.  return NULL;
  181. }
  182. return R;
  183. }
  184. template <class T> void noeud<T>::RotationDroite(noeud *&Q)
  185. {
  186. noeud *P = Q->fg;
  187. Q->fg = P->fd;
  188. P->fd = Q;
  189. Q = P;
  190. }
  191. template <class T> void noeud<T>::RotationGauche(noeud *&P)
  192. {
  193. noeud *Q = P->fd;
  194. P->fd = Q->fg;
  195. Q->fg = P;
  196. P = Q;
  197. }
  198. template <class T> void noeud<T>::RotationGaucheDroite(noeud *&R)
  199. {
  200. RotationGauche(R->fg);
  201. RotationDroite(R);
  202. }
  203. template <class T> void noeud<T>::RotationDroiteGauche(noeud *&R)
  204. {
  205. RotationDroite(R->fd);
  206. RotationGauche(R);
  207. }
  208. template <class T> noeud<T> *arbre<T>::Ajouter(T &Info)
  209. {
  210. int G = 0;
  211. noeud<T> *N;
  212. if (Racine == NULL)
  213. {
  214.  Racine = new noeud<T>(Info);
  215.  NbElmt++;
  216.  return Racine;
  217. }
  218. else
  219. {
  220.  N = Racine->Ajouter(Info, Racine, G);
  221.  if (N) NbElmt++;
  222.  return N;
  223. }
  224. }
  225. template <class T> arbre<T>::arbre()
  226. {
  227. NbElmt = 0;
  228. Racine = NULL;
  229. Haut = 0;
  230. }
  231. template <class T> arbre<T>::~arbre()
  232. {
  233. if (Racine) Racine->Vider();
  234. }
  235.  
  236.   inline void alea(unsigned long &rand){
  237.       static unsigned long r = SEED;
  238.       rand = r = 1664525UL * r + 1013904223UL;
  239.   }
  240.  
  241.   int remplit_t(char *Tampon, const int N)
  242.   {
  243.  
  244.       unsigned long r;
  245.       char buf[20] = "";
  246.    
  247.       for (int i = 0; i < N; i+= 5)
  248.         {
  249.             do alea(r); while (r < 10000UL);
  250.             sprintf(&Tampon[i], "%u", r);
  251.         }
  252.   }
  253.  
  254. int lmin = 7, lmax = 15;
  255.  
  256. int main(int argc, char *argv[])
  257. {
  258. char *Tampon;
  259. unsigned long long f;
  260. char Tmp;
  261. unsigned int i, j, k, t, v;
  262. int Nb;
  263. int PosTmp;
  264. int NbPositionsTmp;
  265. Position ** PositionsTmp;
  266. PositionsRedondantesG = new Position *[N];
  267. NbPositionsG = 0;
  268. Tampon = new char[N];
  269. remplit_t(Tampon, N);
  270. arbre<Position> *Arbre = new arbre<Position>;
  271. Position Temp;
  272. j = 7;
  273. for (i = 0; i < N-j; i++)
  274. {
  275.  Tmp = Tampon[i+j];
  276.  Tampon[i+j] = 0;
  277.  f = atoll(&Tampon[i]);
  278.  Tampon[i+j] = Tmp;
  279.  Temp.SetN(f);
  280.  Temp.SetPos(i);
  281.  Arbre->Ajouter(Temp);
  282. }
  283. for (t = 8; t <= 15; t++)
  284. {
  285.  cout <<"nombres de "<<t-1<<"  chiffres --------------" <<endl;
  286.  delete Arbre;
  287.  Arbre = new arbre<Position>;
  288.  NbPositionsTmp = NbPositionsG;
  289.  PositionsTmp = PositionsRedondantesG;
  290.  if (NbPositionsTmp)
  291.  {
  292.   PositionsRedondantesG = new Position *[NbPositionsTmp];
  293.   NbPositionsG = 0;
  294.   for (i = 0; i < NbPositionsTmp; i++)
  295.   {
  296.    Nb = PositionsTmp[i]->GetNb();
  297.    for (j = 0; j < Nb; j++)
  298.    {
  299.     PosTmp = PositionsTmp[i]->GetPos(j);
  300.     if (N - PosTmp > t)
  301.     {
  302.     Tmp = Tampon[PosTmp+t];
  303.     Tampon[PosTmp+t] = 0;
  304.     f = atoll(&Tampon[PosTmp]);
  305.     Tampon[PosTmp+t] = Tmp;
  306.     Temp.SetN(f);
  307.     Temp.SetPos(PosTmp);
  308.     Arbre->Ajouter(Temp);
  309.     }
  310.    }
  311.   }
  312.   for (i = 0; i < NbPositionsTmp; i++)
  313.    delete (noeud<Position> *) PositionsTmp[i]->GetParent();
  314.   delete PositionsTmp;
  315.  }
  316. }
  317. cout <<"nombres de "<<t-1<<"  chiffres --------------" <<endl;
  318. delete Arbre;
  319. if (NbPositionsTmp)
  320. {
  321.  for (i = 0; i < NbPositionsTmp; i++)
  322.   delete (noeud<Position> *) PositionsTmp[i]->GetParent();
  323.  delete PositionsTmp;
  324. }
  325. delete [] Tampon;
  326. return EXIT_SUCCESS;
  327. }


 
Voilà... Y'a beaucoup de choses en dur (notamment le nb max de positions dans la classe Position). Ensuite, le programme perd finalement beaucoup de temps à générer le fichier résultat (en redirection avec > ). D'autres choses sont moches, mais ça a été fait à l'arrache. Soyez indulgents, merci.
 
 
lecouteux@zorglub:~$ time ./rdoublon >result
 
real    0m35.759s
user    0m32.150s
sys     0m3.520s
 
Là c'est sur un ordi de mon université, un xeon à 2,4 Ghz.
Ensuite, je pense qu'on peut encore pas mal optimiser le code pour accélérer de deux fois... mais j'pense que je vais m'arrêter là.


Message édité par assyrium le 11-05-2004 à 14:30:08
n°719863
Taz
bisounours-codeur
Posté le 09-05-2004 à 16:23:04  profilanswer
 

adieu, c'est trop pour moi

n°719876
el muchach​o
Comfortably Numb
Posté le 09-05-2004 à 16:46:13  profilanswer
 

assyrium, mets ton code entre les balises "[ c p p ]" et "[/ c p p ]" (enlève les espaces que j'ai rajoutés pour éviter qu'elles ne soient inerprétées).
 
Ensuite, quelques commentaires ne seraient pas de trop, surtout que ton algo est costaud, et que tout le monde ne sait pas ce qu'est un arbre AVL (ce qui est mon cas... :sweat: ).
 
Enfin, petite remarque :

Code :
  1. bool operator > (Position &p)
  2.   {
  3.    if (n > p.n) return true;
  4.    return false;
  5.   }


 
Peut être écrit  

Code :
  1. inline  bool operator > (Position &p){ return (n > p.n); }


 
En tout cas, chapeau bas, parce que ton algo tient la corde, et de loin, et même en l'optimisant, je ne pense pas que ma solution puisse atteindre cette performance.


Message édité par el muchacho le 09-05-2004 à 17:02:00
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3

Aller à :
Ajouter une réponse
 

Sujets relatifs
Recherche de chaineRecherche d'imprimantes réseau en PHP
Recherche cours et didacticiels: JSP/Servlet/JavaBeans - Struts - MVC2[Java WebStart]Recherche d'un tutorial
[C++] recherche tutorial COMPLET et SERIEUX sur DLL win32Comment passer d'une séquence d'images BMP à une video ?
Recherche APIfonction de recherche de fichier en C [LINUX]
éviter les doublons[Access97] Recherche avec l'option "tous" (zone de liste modifiable)
Plus de sujets relatifs à : [Concours] Recherche de doublons dans une séquence


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR