Voila suite à un autre post sur un algo du site algorea, je suis allez faire un tour pour m'exercer. Tout allait bien jusqu'à bloc de quatre;
Il faut savoir que mon but est juste de mettre en pratique ce que j'apprend et non pas de participer au concourt, ducoup, j'ai voulu faire un algo avec "vector", "iterator" et "algorithm"
J'ai appris les "iterator" à la manière moderne sur ZDS, ce qui n'était pas bon pour le site qui compil en gcc 4.9.0.
J'ai donc chercher et trouver pour les "iterator" mais il persiste un dernier probleme : std::equal;
la bonne blague c'est que en testant sur wandbox.org ca compile parfaitement a partir de gcc 4.9.1 en 4.9.0 j'ai exactement la même erreur que sur algorea. La j'avoue que je suis fatigué, je suis toujours novice, je suis fort pour rechercher mais la j'ai pas trouver.
Voici l'erreur && le code en question;
erreur : si je comprend bien il veux pas soit mes iterateur ou les int;
In file included from /usr/include/c++/4.9/bits/char_traits.h:39:0,
from /usr/include/c++/4.9/ios:40,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from 282611098429108769.cpp:1:
/usr/include/c++/4.9/bits/stl_algobase.h: In instantiation of ‘bool std::equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate) [with _IIter1 = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _IIter2 = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _BinaryPredicate = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]’:
282611098429108769.cpp:50:52: required from here
/usr/include/c++/4.9/bits/stl_algobase.h:1088:46: error: no match for call to ‘(__gnu_cxx::__normal_iterator<int*, std::vector<int> >) (int&, int&)’
if (!bool(__binary_pred(*__first1, *__first2)))
^
code :
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
int numberEntry = 0; // nombre d'entrée - 3;
std::cin >> numberEntry;
std::vector<int> integerSuite ;
for (int i=0; i<numberEntry; ++i)
{
integerSuite.push_back(0);
std::cin >> integerSuite[i];
}
std::vector<int>::iterator start = integerSuite.begin();
std::vector<int>::iterator ends = integerSuite.end();
std::vector<int> integerSave ;
std::vector<int>::iterator first = integerSuite.begin();
std::vector<int>::iterator four = integerSuite.begin()+4;
std::vector<int> integerCopy;
std::vector<int>::iterator in = integerSuite.begin();
std::vector<int>::iterator out = integerSuite.begin()+4;
integerCopy.insert(integerCopy.begin(),first, four-1);
int totalOne = 0;
int totalTwo = 0;
for (int i=0; i<numberEntry -3; ++i)
{
++start;
if ( std::search(start, ends, in, out ) != ends )
{
if (integerSave == integerCopy)
{
break;
}
for (int j=0; j<numberEntry -3; ++j)
{
if ( std::equal( first, four, in, out) )
{
++totalOne;
++first;
++four;
}
else
{
++first;
++four;
}
}
}
if (totalOne > totalTwo)
{
integerSave = integerCopy;
totalTwo = totalOne;
totalOne = 0;
}
++in;
++out;
integerCopy.insert(integerCopy.begin(),in, out-1);
first = integerSuite.begin();
four = integerSuite.begin()+4;
}
std::cout << totalTwo;
return 0;
}
Si mais ca n'avais pas marcher la première fois lol, j'avais du mal recopier, en effet maintenant ça marche;
Merci beaucoup
je fait 70% , mais maintenant que ca marche et que j'ai saisit le fonctionnement des itérateurs et algorithmes ça va allez mieux, je ferais ça demain; j'ai une meilleur idée;
Version corrigée mais pas a 100% ( ne me donné pas la réponse ! )
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
int numberEntry = 0;
std::cin >> numberEntry;
std::vector<int> integerSuite ;
for (int i=0; i<numberEntry; ++i)
{
integerSuite.push_back(0);
std::cin >> integerSuite[i];
}
std::vector<int>::iterator start = integerSuite.begin();
std::vector<int>::iterator ends = integerSuite.end(); // pour search
std::vector<int> integerSave ; //std::vector<int> integerSave = integerSuite;
std::vector<int>::iterator first = integerSuite.begin();
std::vector<int>::iterator four = integerSuite.begin()+4;
std::vector<int> integerCopy; //std::vector<int> integerCopy = integerSuite;
std::vector<int>::iterator in = integerSuite.begin();
std::vector<int>::iterator out = integerSuite.begin()+4;
integerCopy.insert(integerCopy.begin(),in, out);
std::vector<int>::iterator it = integerCopy.begin();
int totalOne = 0;
int totalTwo = 0;
for (int i=0; i<numberEntry -3; ++i) // boucle qui décale bloc de quatre && nbentrée - 3
{
++start; // on se décale d'une case sinon c'est forcément true;
if ( std::search(start, ends, in, out ) != ends )
{
if (integerSave == integerCopy)
{
break;
}
for (int j=0; j<numberEntry -3; ++j) // nbentrée - 3 et - 1 car déjŕ avance d'une case && number -1 a chaque bouce bloc de quatre
{
if ( std::equal( in, out, first) ) //std::begin(integerCopy), std::end(integerCopy)
{
++totalOne;
++first;
++four;
}
else
{
++first;
++four;
}
}
}
if (totalOne > totalTwo)
{
integerSave = integerCopy;
totalTwo = totalOne;
totalOne = 0;
}
++in;
++out;
integerCopy.clear();
integerCopy.insert(integerCopy.begin(),in, out);
first = integerSuite.begin();
four = integerSuite.begin()+4;
}// bloc de quatre
std::cout << totalTwo;
return 0;
}
Question pour les experts: ça vaut la peine d'apprendre C++ sur une vieille version du compilateur? N'y a-t-il pas de sites avec une version récente qui donnent des exercices dans le genre?t
Le Tout est souvent plus grand que la somme de ses parties.
Ça y est, ce matin je me suis lever plus tôt car j'étais trop impatient de coder; Alors j'ai refait bloc de quatre à partir de 0 et voila que je valide à 100% =D;
Merci rouloude pour ton aide avec std::equal
Code de la reussite :
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
int numberEntry = 0;
std::cin >> numberEntry;
std::vector<int> integerSuite ;
for (int i=0; i<numberEntry; ++i)
{
integerSuite.push_back(0);
std::cin >> integerSuite[i];
}
std::vector<int> blockOfFour;
std::vector<int>::iterator start = integerSuite.begin();
std::vector<int>::iterator ends = integerSuite.begin()+4;
std::vector<int>::iterator fourBegin = integerSuite.begin();
std::vector<int>::iterator fourEnd = integerSuite.begin()+4;
blockOfFour .insert(blockOfFour.begin(), fourBegin, fourEnd); //premier bloc de 4
int total = 0;
int counter = 0;
for (int i; i<numberEntry-3; ++i)
{
for (int j=0; j<numberEntry-3; ++j) // boucle comparisonBlock
{
if (std::equal(start, ends, fourBegin) )
{
++start; ++ends; ++counter;
}
else
{
++start; ++ends;
}
}
if (counter > total)
{
total = counter;
}
start = integerSuite.begin(); //remise à 0
ends = integerSuite.begin()+4;
counter = 0;
blockOfFour.clear();
++fourBegin; //bloc de 4 suivant
++fourEnd;
blockOfFour.insert(blockOfFour.begin(), fourBegin, fourEnd);
}
std::cout << total;
return 0;
}
il faut croire que dans ce cas ça vaut directement 0. J'ai eu de la chance
Oui c'est toujours intéressant de voir un autre langage, au final c'est assez similaire avec les deux boucle for imbriquée. A par que moi j'utilise un algorithme tout fait, toi tu as ecrit le tien.
J'ai essayé avec algorithme search, ça me semble plus naturel qu'avec equal :
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int count_bloc(std::vector<int> const &suiteNb, size_t n)
{
int cpt = 0;
std::vector<int>::const_iterator it = suiteNb.begin();
while(true)
{
it = std::search(it, suiteNb.end(), suiteNb.begin(), suiteNb.begin()+n);
if(it++!=suiteNb.end())++cpt;
else break;
}
return cpt;
}
int main()
{
int numberEntry;
std::cin >> numberEntry;
std::vector<int> integerSuite;
for (int i=0; i<numberEntry; ++i)
{
int value;
std::cin >> value;
integerSuite.push_back(value);
}
int max = 0;
for(size_t i=0; i<integerSuite.size()-3; ++i)
{
std::vector<int> intSuite(integerSuite.begin()+i, integerSuite.end());
int cpt = count_bloc(intSuite, 4);
if(cpt>max) max=cpt;
}
std::cout << max;
return 0;
}
EDIT :
Pour ceux qui ce demande de quoi on parle :
Énoncé (Concours Algorea . La moulinette ne fonctionne qu'en C++98 ).
On vous donne une liste de nombres. Trouvez le bloc de 4 nombres successifs qui est présent le plus grand nombre de fois dans la liste.
Par exemple dans la liste ci-dessous, le bloc constitué des nombres 5 3 2 1 dans cet ordre, est présent deux fois. C'est le seul bloc présent plusieurs fois, donc c'est la réponse attendue
Dans un deuxième exemple ci-dessous, c'est le bloc constitué des nombres 1 6 3 1 dans cet ordre, qui est présent le plus de fois (trois fois). Le bloc 2 1 6 3 est quant à lui présent deux fois seulement.
Notez que la deuxième copie du bloc 1 6 3 1 recouvre en partie sa première copie.
Entrée
La première ligne de l'entrée contient un entier nbNombres, le nombre d'éléments de la liste, entre 1 et 100.
Les nbNombres lignes suivantes contiennent chacune un entier de la liste, entre 0 et 100.
Sortie
Vous devez afficher un nombre sur la sortie : le nombre de fois où l'on trouve le bloc le plus présent dans la liste.
Exemples
Voici un exemple d'entrée.
10
4
5
3
2
1
6
5
3
2
1
La sortie attendue est la suivante.
2
Limites
Limite de temps : 100 ms. Limite de mémoire : 64000 kb.
Comme quoi il y a plein de façon de faire, j'aime la boucle "whilte(true) ,,, ,,, else break; " j'avais jamais vu ça comme ça, je pense que je vais adopter cette façon de faire.
Pour parcours numéroté 2 je suis à 64% au premier essais que je poste sur algorea, je dépasse la limite de temps de 9 à 13, je vais peaufiner mon algo.
si vraiment je trouve pas( car j'aime quand même chercher) je posterais mon algo.
Edit : 79% ca diminue
EDIT : 100% je suis sur le cul lol, =D, bon maintenant c'est les fameuse couche de peinture;
je pense que je vais adopter cette façon de faire.
Mouais, bof.
Le while a une condition d'arret. C'est celle qui lance le break. C'est a dire quand it==end. En écrivant while(true), on déplace la condition d'arrêt dans le bloc, ce qui réduit la lecture du code.
Donc mauvaise idee.
rouloude a écrit:
Concours Algorea . La moulinette ne fonctionne qu'en C++98
Donc aucun intérêt. Faites le concours dans un autre langage.
c'est vrai que je comprend pas pourquoi non plus la raison pour la quelle la moulinette à 23 ans
Voila le code qui à validé parcours numéroté 2 ( on vois au nom des variables de boucles que j'ai modif un peu, j'ai eu la flemme de tout conventionner cette fois ci)
100% :
#include <iostream>
#include <vector>
int main()
{
int entryNumber = 0;
int caseNumber = 0;
std::cin >> entryNumber;
std::vector <int> number ;
for (int i=0; i<entryNumber; ++i)
{
number.push_back(0);
std::cin >> number[i];
}
int answer = 0;
int startCase = 0;
int entryNumberWhile = entryNumber;
for (int k=0; k<entryNumberWhile; ++k)
{
int p = number[startCase]; //Premičre case du parcour;
int i = 0; //Remise ŕ zéro;
int counter = 0;
caseNumber = number[startCase];
i = caseNumber;
do {
caseNumber = number[i-1];
i = caseNumber;
++counter;++startCase; //++startCase; On saute les cases déjà passée
}while (p != caseNumber); //on s'arręte une fois revenu ŕ la case de départ;
entryNumberWhile = entryNumber; entryNumberWhile -=startCase;
if (counter > answer) { answer = counter;}
}
std::cout << answer << std::endl;
return 0;
}
J'ai envie d'apprend le C plus tard, mais ca va j'arrive à comprendre ton code quand même;
Moi j'arête pour ajd, j'ai déjà mes couche de peinture qui trouve toute les paires des passage de rouleau, reste plus qu'a écrire la partie qui compte les couche max;
On en avait parlé de cet exo il n'y a pas longtemps, et je me souviens avoir ralé (*) que le moteur du site était bloqué au C++98 et que vous devriez contacter les admins pour demander une mise à jour: https://openclassrooms.com/forum/sujet/bloc-de-quatre
(*) Je voulais appeler std::max_element avec une lambda pour comparer les hauteurs dans les histogrammes remplis -- oui c'est un exo de remplissage d'histogramme conclu par une recherche de la clé associée au plus grand nombre recensé.
Une question, si je l'avais écris comme cela la fonction en gardant le while(true) mais sans le break :
int count_bloc(std::vector<int> const &suiteNb, size_t n)
{
int cpt = 0;
std::vector<int>::const_iterator it = suiteNb.begin();
while(true)
{
it = std::search(it, suiteNb.end(), suiteNb.begin(), suiteNb.begin()+n);
if(it++!=suiteNb.end())++cpt;
else return cpt;
}
}
Peut-on dire que c'est mieux ou pas ?
Ou tu préfères :
int count_bloc(std::vector<int> const &suiteNb, size_t n)
{
int cpt = 0;
std::vector<int>::const_iterator it = suiteNb.begin();
it = std::search(it, suiteNb.end(), suiteNb.begin(), suiteNb.begin()+n);
while(it!=suiteNb.end())
{
++it;
++cpt;
it = std::search(it, suiteNb.end(), suiteNb.begin(), suiteNb.begin()+n);
}
return cpt;
}
Mais ça fait écrire deux fois l'appel à la fonction search.
- Edité par rouloude il y a environ 5 heures
Ce ne serait même pas vraiment mieux, car, le fait est que tu as un type be boucle beaucoup plus lisible (en C++98) pour le cas présent: la boucle "pour"
/* un petit alias de type, car ce sera la galère à réécrire */
typedef typename std::vector<int>::const_iterator const_iterator;
int count = 0;
for(const_iterator it = suiteNB.begin();
it!= suiteNB.end(); ++it){
const_iterator recherche = std::search(it, suiteNB.end(), suitNB.begin(); suiteNB.begin()+n);
if(recherche ==suiteNB.end())
return count;
++ count;
}
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Oh, sur ce coup là, je me suis contenté d'adapter le code que j'avais sous la main, sans plus, et sans la tester
Ce qui importe, c'est qu'une boucle "for" n'est qu'une boucle "while" dans laquelle on prévoit déjà l'évolution d'une variable qui servira de compteur, et qu'il est donc "très simple" de convertir une boucle while en boucle "for"
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
NB: je n'ai pas regardé votre algo à double boucle -- je trouve ça compliqué: une même séquence de nombres verra son évaluation autant de fois qu'il y a d'éléments en tout (moins 3) et divisé par 2 en moyenne, alors que l'on pourrait calculer une seule fois son hash/bin vu qu'il n'est pas demandé de positionner le max.
Les avantages du for en ce qui me concerne sont:
- exprimer une itération sur des éléments -- à contrario de recommencer tant qu'une condition le demande
- réunir l'incrément dans la boucle plutôt que de l'éparpiller plus loin juste avant accolade fermante. A mon goût cela réduit les risques de mismatch après un copier-coller ou un renommage
alors que l'on pourrait calculer une seule fois son hash/bin vu qu'il n'est pas demandé de positionner le max.
Effectivement, je n'y avais pas pensé ! J'ai été voir l'autre sujet que tu citais, j'ai repris ton code, je l'ai adapté pour le site d'Algorea et il passe nickel :
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
int hash(int *t4) {
int res = (((t4[0] * 256 + t4[1]) * 256 + t4[2])* 256) + t4[3];
return res;
}
bool search_max(std::pair<int, int> a, std::pair<int, int> b)
{
return a.second < b.second;
}
int main() {
int n;
std::cin >> n;
std::vector<int> v; v.reserve(n);
for (int h, i = 0 ; i < n && std::cin >> h ; ++i) v.push_back(h);
std::map<int, int> map;
for (int i = 0 ; i < n-3 ; ++i) map[hash(&v[i])]++;
std::cout << std::max_element(map.begin(), map.end(),search_max)->second << "\n";
}
Après pour le choix entre le while ou le for, je ne sais pas trop.
A propos de for VS while, j'ai rencontré un 3e argument plus technique et moins humain que les précédents peu après avoir posté mon message. Un code tel que
init;
while (condition)
{
if (pseudo_precond)
{
trop;
de;
lignes;
mais;
vraiment;
trop;
}
itère;
}
ne peut pas se simplifier avec un `continue` parce que l'itération est dans le bloc au lieu d’être au niveau de la boucle.
Alors maintenant, on peut chipoter sur est-ce que "`continue` et `break` sont le mal incarné?" Je suis plus que flexible sur la question. Le mal incarné ici est en premier lieu la rupture de V(g) faible/fonctions courtes (avatars du SRP) (certains le résolvent avec "utilisez les algos standards"). Ensuite, je préfère garder mes niveaux d'indentation sous contrôle, d'où ma préférence pour `continue`.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
Le Tout est souvent plus grand que la somme de ses parties.
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
Discord NaN. Mon site.
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }
for ( size_t nbMembre : membreForum ) { std::cout << "Bonjour ! \n"; }