Souhaitant m’entraîner a l'algorithmie en c++, je me suis donc rendu sur France ioi, mais ayant un peu beaucoup la flemme de me taper tous le niveau 1 et 2, je suis passer au déblocage du niveau 3
J'en suis au problème des grenouille (je vais mettre l’énoncer a la fin) et voici mon code :
#include <iostream>
#include <vector>
#include <string>
struct frog
{
int number = -1;
int time_first = 0;
int distance = 0;
};
bool operator!=(frog const& frog_1, frog const& frog_2)
{
if(frog_1.number == frog_2.number)
{
return false;
}
return true;
}
struct round_report
{
int frog_runner;
int distance;
};
std::vector<frog> create_frog_vector(int nb_frog)
{
std::vector<frog> frogs;
for (int i{ 0 }; i < nb_frog; i++)
{
frogs.push_back( frog{ i+1, 0, 0 } );
}
return frogs;
}
round_report get_round_infos()
{
int frog_runner;
std::cin >> frog_runner;
int distance;
std::cin >> distance;
return round_report{ frog_runner, distance };
}
bool has_equality(std::vector<frog> const& frogs, frog const& best_frog)
{
for (auto const& frog : frogs)
{
if (best_frog != frog)
{
if (frog.distance == best_frog.distance)
{
return true;
}
}
}
return false;
}
void update_first(std::vector<frog> & frogs)
{
frog best_frog;
for (int i{ 0 }; i < frogs.size(); i++)
{
if (frogs[i].distance > best_frog.distance)
{
best_frog = frogs[i];
}
}
if (best_frog.number != -1 && !has_equality(frogs, best_frog) )
{
frogs[best_frog.number - 1].time_first += 1;
}
}
void update_frogs(std::vector<frog> & frogs, round_report const& result)
{
frogs[result.frog_runner - 1].distance += result.distance;
}
int get_first(std::vector<frog> & frogs)
{
frog first;
for (auto const& runner : frogs)
{
if (runner.time_first > first.time_first)
{
first = runner;
}
}
return first.number;
}
int main()
{
int nb_frog;
std::cin >> nb_frog;
int nb_round;
std::cin >> nb_round;
std::vector<frog> frogs{ create_frog_vector(nb_frog) };
for (int i{ 0 }; i < nb_round; i++)
{
update_first(frogs);
round_report result{ get_round_infos() };
update_frogs(frogs, result);
}
std::cout << get_first(frogs) << std::endl;;
}
Mon problème est plutôt simple : le code compile sous VS, pas sur France IoI, les erreurs donner :
source.cc: In function ‘std::vector<frog> create_frog_vector(int)’:
source.cc:33:40: error: no matching function for call to ‘frog::frog(<brace-enclosed initializer list>)’
frogs.push_back( frog{ i+1, 0, 0 } );
^
source.cc:33:40: note: candidates are:
source.cc:5:8: note: constexpr frog::frog()
struct frog
^
source.cc:5:8: note: candidate expects 0 arguments, 3 provided
source.cc:5:8: note: constexpr frog::frog(const frog&)
source.cc:5:8: note: candidate expects 1 argument, 3 provided
source.cc:5:8: note: constexpr frog::frog(frog&&)
source.cc:5:8: note: candidate expects 1 argument, 3 provided
source.cc: In function ‘void update_first(std::vector<frog>&)’:
source.cc:70:23: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int i{ 0 }; i < frogs.size(); i++)
^
source.cc: In function ‘int main()’:
source.cc:117:46: error: cannot convert ‘round_report’ to ‘int’ in initialization
round_report result{ get_round_infos() };
^
Je comprend bien (pour commencer la première erreur), il n'arrive pas a appeller le constructeur de frog avec les arguments donner, pourtant je donne bien les 3 arguments nécessaires (d’ailleurs 1 seul est réellement nécessaire, vu que les autre sont défini par défaut..) J'aimerais un peu d'aide pour m’éclairer la dessus..
Merci d'avance pour votre aide / lecture
HS sujet :
nbGrenouilles numérotées de 1 à nbGrenouilles sont placées sur une ligne de départ. À chaque tour, on vous indique le numéro de la seule grenouille qui va sauter lors de ce tour, et la distance qu'elle va parcourir en direction de la ligne d'arrivée.
Écrivez un programme qui détermine laquelle des grenouilles a été strictement en tête de la course au début du plus grand nombre de tours. Notez que comme on s'intéresse à qui est en tête au début de chaque tour, le bond du dernier tour ne sert à rien car même si la grenouille concernée passe en tête, la course est finie (il est purement honorifique selon la tradition algoréenne).
Cette façon de faire n'est pas correcte (de ce que je crois), j'ai pas les connaissances pour t'expliquer pourquoi, toutefois pour ton erreur, il faut faire comme ça :
std::vector<frog> frogs {};
frog my_frog {};
for (int i {0}; i < nb_frog; i++)
{
my_frog.number = i;
my_frog.time_first = 0;
my_frog.distance = 0;
frogs.push_back(my_frog);
}
return frogs;
Ligne 70 : Tu compares deux entiers différents, frogs.size() renvoi un type size_t et non int.
Le soucis se trouve a la ligne 33 comme l'indique le compilateur. Il faut savoir qu'en c++ une structure et une classe sont identique a un détail près : leur visibilité. Une classe est par defaut privée, tandis qu'une structure est publique.
Tout ça pour en venir a ton problème, tu ne peux pas écrire :
frogs.push_back( frog{ i+1, 0, 0 } );
Pour faire ça, tu dois redéfinir le constructeur de ta structure (comme tu le ferais avec une classe).
Le compilateur semble être configuré pour du C++11, il faudrait ajouter -std=c++14 (ou17) dans les options de compilation. Si ce n'est pas possible, il faut enlever les valeurs par défaut pour rendre le code compatible c++11.
Je sais ce qu'est une structure, je n'en suis pas a ma première fois en C++, mais c'est sympa de me le rappeller
Par contre, il faut savoir que ce code compile sous VS17 a jours, donc je doute que ne puisse pas faire cela, c'est le compilateur de France IOI qui n'est pas content
Je ne savais pas que cette maniere de faire datait du c++14, et vu que ce n'est pas mon compilo, je vais devoir rendre ca compatible c++11
Pour les notes jo_link_noir, ca va en effet etre modifier, merci pour tes remarques
Je ne savais pas que cette maniere de faire datait du c++14, et vu que ce n'est pas mon compilo, je vais devoir rendre ca compatible c++11
Le meilleur moyen est alors sans doute de rajouter un constructeur paramétré (et un constructeur par défaut, tant qu'à faire) à ta structure, sous une forme proche de
struct frog
{
frog():frog{-1,0,0}{
}
frog(int number, int first_time, int distance):
number{number}, first_time{first_time}, distance{distance}{
}
int number = -1;
int time_first = 0;
int distance = 0;
};
De cette manière, la partie de ton code qui pose problème (il y en aura peut-être d'autres ) sera au moins compatible avec C++11 et ultérieure, ce qui devrait satisfaire le compilateur de france IOI
Dans le même ordre d'idée, je vois quelques adaptations possibles:
Tu pars du principe que tu vas utiliser l'entrée standard dans la fonction get_round_info. Mais, l'un dans l'autre, tu pourrais tout aussi bien envisager de créer un fichier texte qui contienne les informations pour "plusieurs dizaines de milliers" de frog, alors que l'introduction manuelle te limitera sans doute à seulement quelques dizaines
Par chance, l'entrée standard et les fichiers standards sont touss les deux dérivés de std::istream, et on peut donc parfaitement fournir les deux à une fonction qui s'attend à recevoir une référence sur un std::istream comme paramètre.
En modifiant ta fonction pour lui donner la forme de
tu pourrait l'utiliser aussi bien sous la forme de
int main(){
std::vector<frog> tab;
/* récupère dix éléments depuis l'entrée standard */
for(size_t i=0; i<10; ++i){
tab.push_back( get_round_infos(std::cin) );
}
}
que sous la forme de
int main(){
std::vector<frog> tab;
/* récupère tous les éléments contenus dans un fichier */
std::ifstream ifs("fichier.txt");
while(ifs){
tab.push_back(get_round_info(ifs));
}
}
Cela change très peu ta logique, finalement, mais cela t'offre beaucoup plus de souplesse quant à la manière de travailler
Enfin, lorsque tu t'attends à ce que l'utilisateur introduise une donnée, tu devrais au minimum:
afficher un message indiquant quelle donnée tu t'attends à ce qu'il introduise (et, le cas échéant, les limites que tu veux lui imposer)
t'assurer que la donnée introduite correspond (en type de donnée et en valeur, s'il y a des limites imposées) à ce que tu attends.
L'idéal étant de boucler sur l'affichage du message et la récupération de la donnée aussi longtemps que l'information n'est pas "correcte".
Il en va de même (à ceci près qu'il n'y a pas de message à afficher) lorsque tu souhaite extraire une donnée d'un fichier texte, l'idéal étant alors de lancer une exception si la donnée ne correspond pas à ce que tu attends, pour éviter que ton application ne se retrouve dans un état "invalide"
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
Tout d'abord, merci a toi pour tous tes conseils, je note ça pour la prochaine fois
C'est vrai que j'ai zapper complètement toutes ces parties (principalement la partie "affichage de ce qui est attendu" et "vérification des entrée") car le programme est destiné a être utilisé par un ordinateur (ce qui n'excuse pas mon oublie), et il me semblais avoir lu que les test de france ioi ne concernait pas une fausse entrée.
Plutôt pour la partie souplesse de mon code (que je garde en note, c'est une manière de voir que je n'ai pas encore), je peux expliquer cela par l'utilisation de ce programme unique, les demandes ne vont pas évoluées, et le programme sera supprimé des que les tests seront passés.
N'y vois aucune mauvaise foi, je tente juste de justifier mes mauvais choix, et je profite de tes conseils pour m’améliorer, encore merci
× 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.
GitHub
GitHub
GitHub