Erreur:
---- Au niveau des paramètres du main.
---- De syntaxe dans le code:
-------- Pas de code (Pseudo-erreur).
-------- '[' ou ']' manquant(s).
-------- Un ']' avant son '['.
---- Au niveau des entrées/sorties.
Voilà j'en vois pas d'autres.
Edit suite au post de Nanoc: Fallait pas que je le dise ?
encore une question: dans ton exemple vu que dans (2*3)*(10+1)*10 les parenthèses de 2*3 ne sont pas nécessaires :
Peut-on mettre autant de parenthèses que l'on veut dans la solution? même si non nécessaires?
à oui et aussi : si la réponse demandée est 100 et que l'on a un 100 dans nos 6 nombres peut on considérer ce 100 lui-même comme une reponse où faut il faire une opération genre 100/1 pour que la réponse soit validable?
Solution du deuxième exercice du mois de juillet 2008
Bonjour tout le monde ! Il est temps que je dévoile une solution pour le2ème exercice du mois de juillet . Vous avez été 25 (!) à m'envoyer une solution. Ce qui montre que l'exercice a eu beaucoup de succès.
La plus part des solutions étaient correctes. Certaines avaient un problème avec les parenthèses imbriquées, le point difficile de l'exercice. D'autres étaient tellement complètes qu'elle ne pouvaient pas entrer dans ce post ! (Surtout qu'il existe un compilateur BF qui "pèse" moins de 200 octets, vous êtes loin du compte.)
Lecture du fichier
La première étape du programme consistait à lire le fichier BrainFuck et à stocker son contenu dans une chaîne de caractère.
Pourquoi ne pas laisser tout dans le fichier ?
La raison est simple. Avec les [], le programme peut très bien sauter "en arrière", ce qui n'est pas pratique si l'on navique dans un fichier.
Rien de très compliqué, on copie simplement ligne par ligne dans une std::string.
std::ifstream fichier("source.b") //On ouvre le fichier
std::string ligne;
std::string codeSource;
while(getline(fichier,ligne)) //On recupere la ligne
{
codeSource+=ligne; //Et on l'ajoute au code source
}
On ne lit pas tant qu'on a pas atteint EOF. La méthode avec le getline est la seule méthode correcte.
Mise en place de l'interpréteur
A partir de là, il fallait mettre en place les élément importants de l'interpéteur, sa "mémoire vive" et son pointeur. Plusieurs choix sont possibles, personellement, j'ai choisi d'utiliser un std::vector<char> avec comme "pointeur" l'indice de la case. On pouvait tout aussi bien utiliser un tableau standard puisque la taille ne varie pas ou encore une string.
Idem pour le "pointeur", on pouvait aussi utiliser un vrai pointeur ou un itérateur de la STL.
Dans notre cas, nous avons:
std::vector<char> memoire(30000,0);
unsigned int pointeur(0);
Interprétaion du code
Les choses intéressantes commencent ici. Pour interpreter le BF, il fallait parcourir la chaine de caractère d'un bout à l'autre en effectuant l'action associée. Pour ce faire, un switch est sans doute le plus approprié
for(unsigned int i(0); i< codeSource.size();++i) //On parcourt la chaine
{
switch(codeSource[i]]) //switch selon le symbole
{
case '>':
{
//On avance le pointeur
++pointeur;
if (pointeur == 30000) //Si on est au bout
pointeur = 0; //On revient au debut
break;
}
case '<':
{
//Si on est au debut on va a la fin
if (pointeur == 0)
pointeur = 30000;
//Et on recule le pointeur
--pointeur;
break;
}
case '+':
{
//On incremente l'octet pointe
++memoire[pointeur];
break;
}
case '-':
{
//On decremente l'octet pointe
--memoire[pointeur];
break;
}
case '.':
{
std::cout << memoire[pointeur]; //On affiche le caractere
break;
}
case ',':
{
memoire[pointeur] = std::getchar(); //On recupere la saisie de l'utilisateur
break;
}
//Pour les parentheses, voir plus bas
default: //Si c'est un autre caractere
break;
}
}
Les parenthèses
C'est sans doute le point le plus difficile de l'exercice. La première chose à faire était certainement de vérifier que l'expression est bien parenthésée. Compter le nombre de parenthèses ouvrantes et fermantes n'était pas suffisant. En effet, on peut écrire des expressions qui ont le bon nombre de paranthèses mais qui ne sont pas correctes. Par exemple: <math>\() 3+4 (\)</math>
Le problème ensuite était qu'une parenthèse ne renvoit pas forcément à la parenthèse suivante du code source, des parenthèses peuvent êtres imbriquées, comme dans l'expression mathématique <math>\((3*(1+4)-2)+1\)</math>
Il fallait donc trouver un moyen de repérer à quelle parenthèse sauter. Il y a deux grandes techniques pour faire cela.
La première consiste à lire une fois tout le code source et de repérer les couples de parenthèses qui vont ensemble puis stocker les positions des couples dans un tableau. Cette solution n'est viable que si le code source n'est pas trop long.
La deuxième est plus complexe mais fonctionnera toujours. Il s'agit d'utiliser une pile. Chaque fois qu'on rencontre une parenthèse ouvrante, on ajoute sa position au sommet de la pile. Lorsqu'on rencontre une parenthèse fermante, on saute à la position se trouvant sur le sommet de la pile et on supprime le sommet de la pile.
Ce qui est bien c'est que la STL propose une structure de type pile dans l'entête "stack".
Un code complet
Pour le code source complet, je vous propose ce mois le code de MatteX qui a réalisé un programme très complet et utilisant beaucoup la STL. Il a également gérer pas mal d'excpetions et il indique le temps d'exécution du programme.
Ce n'est pas forcément très facile quand on débute, mais il y a beaucoup de commentaires et n'hésitez pas à poser des questions si nécessaire.
BrainFuck.h
// BrainFuck.h
// par : MatteX
// 16 juillet 2008
/** Historique
* 22 juillet 2008 :
* - AJOUT : Une constante globale TAILLE contenant la taille du tableau d'exécution.
* - AJOUT : Une méthode valider_code() permettant de vérifier que le code fournis est un code BrainFuck valide.
* - MODIFICATION : Déplacement de tableau respecte la norme de warping au début
* et à la fin du tableau d'exécution. Pour éviter les dépassement de tableau.
* - MODIFICATION : La méthode Préparer se nomme maintenant Initialisation
* - MODIFICATION : Les méthodes Interpréter et Initialisation prennent
* un paramètre supplémentaire : const std::string & code
* - MODIFICATION : Intitialisation() ne lance plus d'exception si le code n'est pas valide.
* Les caractère non valides seront simplement ignorés à l'exécution
* - RETRAIT : La méthode AddCode a été remplacée par un paramètre de la méthode Interpréter
* - RETRAIT : La variable membre m_code n'existe plus.
* - RETRAIT : L'opérateur >> n'est plus viable.
*/
#ifndef __EXERCICEMIJUILLET2008_MATTEX_BRAINFUCK_H__
#define __EXERCICEMIJUILLET2008_MATTEX_BRAINFUCK_H__
#include <istream>
#include <ostream>
#include <map>
#include <string>
// Interprète un code BrainFuck
class BrainFuck
{
typedef std::string::const_iterator iterateur;
typedef unsigned char octet_t;
// Contient la position de début et de fin d'une paire d'opérateur de boucle.
// Sera initialisé au début de la méthode Interpréter()
std::map<iterateur,iterateur> m_blocs;
// Valide le code et les boucles.
void Initialisation( const std::string & code );
// Interprete les boucles avec leur condition d'arrêt
void Boucle( iterateur & it, const octet_t * const p ) const;
public:
// Execute le code fournis et gère les entrée/sortie lorsque nécessaire
void Interpreter( std::ostream & ostr, const std::string & code );
};
#endif // #ifndef __EXERCICEMIJUILLET2008_MATTEX_BRAINFUCK_H__
BrainFuck.cpp
// BrainFuck.cpp
// par : MatteX
// 16 juillet 2008
#include <algorithm>
#include <iostream>
#include <limits>
#include <stack>
#include <string>
#include <stdexcept>
#undef max
#include "BrainFuck.h"
// ----------------------------------------------------------------------------------------------
// Liste des caractères de début et fin de boucles.
const std::string BOUCLES = "[]";
// Taille du tableau d'exécution
const int TAILLE = 30000;
// ----------------------------------------------------------------------------------------------
void BrainFuck::Interpreter( std::ostream & ostr, const std::string & code )
{
// Préparation de l'interpréteur
Initialisation( code );
// Création du buffer de 30 000 octets requis par la norme BrainFuck
// Le Tableau d'exécution
octet_t buffer[ TAILLE ] = { 0 };
octet_t * p = buffer;
// Interprétation des opérateurs
for ( iterateur it_code = code.begin(); it_code != code.end(); ++it_code )
{
switch (*it_code)
{
case '+':
++(*p);
break;
case '-':
--(*p);
break;
case '>':
if ( ++p >= buffer + TAILLE )
p = buffer;
break;
case'<':
if ( --p <= buffer - 1 )
p = buffer + (TAILLE - 1);
break;
case'.':
ostr << static_cast<std::ostream::char_type>( *p );
break;
case',' :
*p = static_cast<octet_t>( std::cin.get() );
std::cin.clear();
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), std::cin.widen( '\n' ) );
break;
case '[':
case ']':
Boucle( it_code, p );
break;
default: // Si le caractère n'est pas un opérateur BrainFuck, il est tout simplement ignoré.
break;
}
}
}
// ----------------------------------------------------------------------------------------------
// Valide le code et prépare l'interpréteur.
void BrainFuck::Initialisation( const std::string & code )
{
std::stack<iterateur> pile;
iterateur it = std::find_first_of( code.begin(), code.end(), BOUCLES.begin(), BOUCLES.end() );
m_blocs.clear();
while( it != code.end() )
{
if(pile.empty() && *it != *BOUCLES.begin())
{
throw std::runtime_error( "Il manque un ou plusieurs debuts de boucles." );
}
else if( (pile.empty()&& *it == *BOUCLES.begin()) || *pile.top() == *it )
{
pile.push( it );
}
else
{
m_blocs[ pile.top() ] = it;
pile.pop();
}
it = std::find_first_of( it + 1, code.end(), BOUCLES.begin(), BOUCLES.end() );
}
if( !pile.empty() )
throw std::runtime_error( "Il manque une ou plusieurs fins de boucles." );
}
// ----------------------------------------------------------------------------------------------
// Effectue les opérations de début et fin de boucles.
void BrainFuck::Boucle( iterateur & it, const octet_t * const p ) const
{
typedef std::map<iterateur, iterateur>::const_iterator map_iterator;
map_iterator bit;
bit = m_blocs.find( it );
// Si l'opérateur en cours est un début de boucle, nous devons tester la condition.
if( bit != m_blocs.end() )
{
// Teste la condition de fin de boucle;
if( ((*bit->first) == '[' && *p == 0) || (((*bit->first) == ']' && *p != 0)) )
it = bit->second;
}
else
{
// L'opérateur est une fin de boucle ! Nous devons trouver le début de boucle associé et y retourner.
for( map_iterator finder = m_blocs.begin(); finder != m_blocs.end(); ++finder )
{
if( finder->second == it )
{
it = finder->first - 1;
break;
}
}
}
}
main.cpp
/** main.cpp
*
* PROJET : ExerciceMiJuillet2008
* Dans le cadre du sujet Exerices en C++ sur le Site du Zéro
* -> http://www.siteduzero.com
* -> http://www.siteduzero.com/forum-83-257993-2746925-exercices-venez-vous-entrainer.html#r2746925
*
* Merci à Nanoc pour l'idée originale de l'Exercice
*
* Par MatteX
* Fait le 16 juillet 2008 (Une grosse heure)
*/
#include <ctime>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
#include "BrainFuck.h"
// ----------------------------------------------------------------------------------------------
struct timespan
{
time_t m_t;
timespan( time_t t ) : m_t( t ) {}
friend std::ostream & operator<< ( std::ostream & ostr, const timespan & ts )
{
std::tm * temps = std::localtime( &ts.m_t );
if( ts.m_t >= 3600 )
ostr << temps->tm_hour << "h ";
if( ts.m_t >= 60 )
ostr << temps->tm_min << "m ";
if( ts.m_t >= 1 )
ostr << temps->tm_sec << "s.";
if( ts.m_t == 0 )
ostr << "Moins d'une seconde.";
return ostr;
}
};
// ----------------------------------------------------------------------------------------------
void LireFichier( const std::string & chemin, std::string & cpntenu );
// ----------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
BrainFuck bf;
std::string code;
std::time_t temps = 0;
std::cout << "=========== Interpréteur BrainFuck ===========\n Par : MatteX version : 1.0 16.07.2008\n\n------------- Sortie du programme ------------\n";
try
{
if( argc <= 1 )
throw std::runtime_error( "Vous devez passer un fichier de code source BrainFuck en argument." );
LireFichier( argv[ 1 ], code );
temps = std::time( 0 );
bf.Interpreter( std::cout, code );
}
catch( const std::exception & ex )
{
std::cerr << "ERREUR : " << ex.what() << std::endl;
}
if( temps != 0 )
temps = std::time( 0 ) - temps;
std::cout << "----------- Interprétation terminée ----------\nTemps d'exécution : " << timespan( temps ) << std::endl;
return 0;
}
// ----------------------------------------------------------------------------------------------
void LireFichier( const std::string & chemin, std::string & contenu )
{
std::ostringstream oss;
std::ifstream ifstr( chemin.c_str() );
if( !ifstr )
throw std::runtime_error( ("Impossible d'ouvrir : " + chemin).c_str() );
if( !(oss << ifstr.rdbuf()) )
throw std::runtime_error( "Impossible de lire l'intégralité du fichier." );
contenu = oss.str();
}
Une solution plus simple
Voici une solution plus simple, dans le sens où elle fait moins appel à la STL. C'est le code de Masthiks.
#include <sstream>
#include <iostream>
#include <stdexcept>
#include "brainfuck.h"
#define BRAINFUCK nsBrainfuck::Brainfuck
using namespace std;
/**
* Constructeur.
* Permet d'initialiser le fichier brainfuck à analyser et la mémoire brainfuck
* @param Flux représente le fichier à analyser
*/
BRAINFUCK::Brainfuck(istream & Flux, unsigned Taille /* = 30000 */)
: m_Zero(0), m_Taille(Taille)
{
// On récupère le contenu du fichier afin de l'insérer dans un string (il est plus simple
// de procéder de cette manière, plutôt que d'effectuer une interprétation
// directe)
ostringstream Buffer;
Buffer << Flux.rdbuf();
m_Code = Buffer.str();
// On créé un tableau de taille m_Taille
m_Current = m_Memoire = new Octet[m_Taille];
}
/**
* Constructeur.
* Detruit la mémoire brainfuck
*/
BRAINFUCK::~Brainfuck()
{
delete [] m_Memoire;
}
/**
* Analyse le code brainfuck, et affiche le résultat à l'écran
*/
void BRAINFUCK::Exec()
{
for(unsigned i(0); i < m_Taille; ++i) m_Memoire[i] = 0;
for(m_Car = m_Code.begin(); m_Car != m_Code.end(); ++m_Car)
{
// Cette condition permet de gérer le cas où on aurait rencontré un '[' avec la valeur pointée valant 0:
// elle passe toutes les instructions contenues dans la boucle, ainsi que les autres boucles qu'elle pourrait contenir.
if(m_Zero)
{
if(*m_Car == '[') ++m_Zero;
else if(*m_Car == ']') --m_Zero;
}
else
{
// Ii on traite les différentes instructions possibles.
switch(*m_Car)
{
case '+': FonctionIncrementer(); break;
case '-': FonctionDecrementer(); break;
case '.': FonctionSortie(); break;
case '>': FonctionDeplacerDroite(); break;
case '<': FonctionDeplacerGauche(); break;
case ',': FonctionEntree(); break;
case '[': FonctionDebut(); break;
case ']': FonctionFin(); break;
}
}
}
if(m_QWhile.size()) throw runtime_error("Erreur lors de l'execution du programme:\ncaractere ']' manquant");
cout << flush;
}
/**
* Incrémente de 1 la valeur pointée
*/
void BRAINFUCK::FonctionIncrementer()
{
++(*m_Current);
}
/**
* Décrémente de 1 la valeur pointée
*/
void BRAINFUCK::FonctionDecrementer()
{
--(*m_Current);
}
/**
* Permet de gérer la début d'une boucle, lorsqu'on rencontre le caractère '['
*/
void BRAINFUCK::FonctionDebut()
{
// On regarde si la valeur pointée vaut 0, si c'est le cas il faut sauter cette boucle: la valeur
// de m_Zero est incrémentée, ce qui permettra de sauter toutes les instructions que contient la boucle.
if(*m_Current == 0) ++m_Zero;
// Si elle ne vaut pas 0, alors on ajoute la position du début de la boucle à la pile, ce qui permettra de pouvoir y revenir
// plus tard si nécessaire.
else m_QWhile.push(m_Car);
}
/**
* Permet de gérer la fin de la boucle, lorsqu'on rencontre le caractère ']'
*/
void BRAINFUCK::FonctionFin()
{
if(m_QWhile.empty()) throw runtime_error("Erreur lors de l'execution du programme:\ncaractere '[' manquant");
// On regarde si la valeur courrante vaut 0, si c'est le cas, on enlève la position du début de la boucle afin
// de ne pas pouvoir y revenir.
if(*m_Current == 0) m_QWhile.pop();
// SI elle ne vaut pas 0, alors on revient au début de la boucle grace à la valeur contenue dans la pile.
// On prend la dernière position insérée afin de gérer les cas où il y aurait plusieurs boucles dans une seule.
else m_Car = m_QWhile.top();
}
/**
* Demande un caractère à l'utilisateur
*/
void BRAINFUCK::FonctionEntree()
{
cout << flush;
*m_Current = cin.get();
}
/**
* Affiche le caractère courrant à l'écran
*/
void BRAINFUCK::FonctionSortie()
{
cout << *m_Current;
}
/**
* Déplace le pointeur mémoire vers la gauche
*/
void BRAINFUCK::FonctionDeplacerGauche()
{
if(m_Current != m_Memoire) --m_Current;
else m_Current = m_Memoire + m_Taille - 1;
}
/**
* Déplace le pointeur mémoire vers la droite
*/
void BRAINFUCK::FonctionDeplacerDroite()
{
if(m_Current != m_Memoire + m_Taille - 1) ++m_Current;
else m_Current = m_Memoire;
}
#undef BRAINFUCK
Le code inconnu
Pour ceux qui n'y serait pas parvenu, le code mystère affichait la suite de Fibonacci.
Remarques
Quelques remarques sur les codes reçus :
Pas de lecture sur EOF. Utiliser la méthode présentée en haut (ou celle de MatteX)
Pas de #define pour les constantes. Utilisez le mot-clé const.
Pas de macros, ce n'est pas débugguable, pas profilable et on ne sait jamais ce qui peut se passer à la compilation
Il est inutile de rattraper une exception si c'est juste pour la relancer. Laissez la simplement passer
Je trouve le code de Mattex extremement long, 300 lignes c'est beaucoup !! Sinon je préfère utiliser un switch comme tu le montre Nanoc qu'un gros if/else if qui n'ameliore pas la lisibilité. Et le code de Mattex tel quel compile pas chez moi, les lignes du genre " trow std::exeption("chaine"); " le compilo aime pas.
D'autres étaient tellement complètes qu'elle ne pouvaient pas entrer dans ce post ! (Surtout qu'il existe un compilateur BF qui "pèse" moins de 200 octets, vous êtes loin du compte.)
fallait mentionner une taille a ne pas depasser + un temps d'execution max
C'est vrai que le code est long. Mais il est mieux structurer que le mien (je n'ai absolument pas mis d'effort comme la date de remise était dépassé )
Sinon, j'ai utilisé exactement le code que Nanoc "suggère" dans son "pas-a-pas", à la différence que j'ai utilisé un tableau de char* et un pointeur.
C'était un exercice très intéressant! (Encore un!).
Sinon, je viens de finir celui des statistiques. Très simple, en effet.
Par contre, pour moi (et je suis, à temps perdu, écrivain), un paragraphe = un caractère quelconque, suivit d'un ou plusieurs \n suivit d'un autre caractère.
Par exemple : "Allo\n\n \n\nGa!" est pour moi, trois paragraphe.
"Allo!\nÇa va?" équivaut à deux paragraphes.
De plus, dans les outils que j'utilise normalement, le nombre de caractère total ne compte pas les retour à la ligne.
Mais bref, ce sont des détails.
@Freedom: Pour le switch, je suis entièrement d'accord. Pour le reste, oui il fait 300 lignes, mais elles sont toutes utiles. Le code est documenté, commenté, correct et utilise bien la STL, ce que je voulais mettre en avant ici.
Pour ce qui est des exceptions, j'ai corrigé de sorte que ça compile partout.
C'est pas tellement un problème mais j'ai remarqué une "anomalie" dans le code de MatteX.
Le code suivant (qui ne doit pas fonctionner) passe très bien avec le programme de MatteX :
++++[>+++++++++<-]
].[
Si on observe le fonctionnement en détail, on voit que le programme se comporte comme si les deuxième ']' et '[' était inversé (il fait la boucle).
Mon problème est que je n'arrive pas à modifier correctement la fonction de vérification pour que le programme renvoie une erreur dans ce cas-là.
EDIT : Autant pour moi, je n'avais pas compris que lorsque on met "][" il doit se passe quelque chose (la condition d'entrée dans la boucle est inversé).
EDIT : Autant pour moi, je n'avais pas compris que lorsque on met "][" il doit se passe quelque chose (la condition d'entrée dans la boucle est inversé).
Moi j'ai gérer cela comme une erreur...
<édit>
Pour le dernier exo :
Citation : Règle du jeu (Wikipédia)
les nombres de 1 à 10 présents en double exemplaires et les nombres 25, 50, 75 et 100 présents en un seul exemplaire.
EDIT : Autant pour moi, je n'avais pas compris que lorsque on met "][" il doit se passe quelque chose (la condition d'entrée dans la boucle est inversé).
D'après les régles données par Nanoc (et par Wikipedia) ce code n'est pas viable. Quand l'interpréteur arrive sur le 2° ] il doit pouvoir retourner au [ correspondant, or ici il n'y en as pas, idem pour le 2° [. D'ailleur l'interpréteur de Mattex ne marche pas sur ce code (le programme plante).
Bonjour, pour l'exercice sur les chiffre sur les chiffre, j'arrive à quelque chose pour le premier niveau avec une brute force, mais j'ai l'impression qu'elle se répète beaucoup : je m'explique : elle me trouve toujours la solutions, quand il y en a une, en moins de 4 seconde, mais si il y en a pas, il faut au moins 40s pour qu'elle fasse toute les possibilités...
Sinon, j'ai une question : mon programme gère les parenthèse, mais que su 1 "niveau"... Je m'explique :
Il peut facilement faire
(a+b*c)-d/(e+f)
mais pas
((a+b)*(d-c)+e)*f
Et sinon, mon programme ne fonctionne que si tous les chiffres sont utilisés, et ne gère pas la priorité des opérateurs (à part avec les parenthèse...). Est ce grave par rapport à l'énoncé?
(Il faut savoir qu'il donne une solution valable dans 70% des cas...)
@ Freedom: En effet. Je n'ai pas été assez sélectif dans mes tests. Je vais corriger le code de MatteX en conséquence quand je rentre chez moi.
@Mikechaos: Non, ca date de l'époque où l'informatique n'existait pas. Et puis ça ne fait que peu de différence.
@Zebra: On doit pouvoir faire plus court en brute-force. Pour ce qui est des parenthèses, c'est dommage parce que certains calculs nécessitent une profondeur de 2 (3 ?) parenthèses. C'est peut-être ça qui cause le 70%. Pour ce qui est de la priorité des opérateurs, oui c'est grave, si par exemple ton premier calcul ne donne pas le bon résultat (a+b*c).
Me disait bien pourquoi je l'avais pas réussi.....Plein de notions que j'ai jamais vu -___- et qui ne sont pas présente sur le site.....
Il y avait moyen de le faire sans ces notions. La seule chose que j'ai utilisé que tu n'as peut-être jamais vu, c'est les stack. Mais il y avait moyen de s'arranger avec les vector, qui sont présents sur le site.
Du côté des itérateurs, je ne sais plus s'ils sont présents, mais ils étaient tous remplaçable (par un simple indice, dans le cas de la boucle, et par un pointeur dans le cas des [] imbriqués).
Bref, il était très faisable avec les les éléments présents sur le site .
Il y a encore quelque chose à enlever (oui, je suis chiant, je sais). Dans le fichier BrainFuck.cpp : la variable globale OPERATEURS ne sert à rien, elle n'est pas (ou plus) utilisé dans le code
bijour !
juste une petite idée comme ça ....
pourquoi ne pas afficher la difficulté de l'exercice dans le tableau d'affichage de la page1 ? ça pourrait être utile ! peut-être est il dur de juger combien un exercice est difficile mais je pense que ce serait bien, on pourrait organiser un soudage sur une trentaine de personne pour mettre une note sur 10 .....
voila, c'était l'idée à la c** du jour (de leopard)
je poste dans la boite à idées !
@++
La notion de difficulté varie trop selon chaque personne.
Même si on prend deux personnes qui n'ont comme base que le tuto de M@téo, ils peuvent trouver un même exercice très facile ou très difficile selon ce que l'un ou l'autre a/n'a pas compris.
Par exemple ceux qui ont crée un os et qu'on leur demande de faire un IDE, ils disent que c'est facile. Un zéro par contre pourra dire que c'est difficile
bah ouai mais en attendant que tu trouves 30 mecs qui ont chacun codé 1 OS et que tu les fasses voter sur le sdz pour un exercice de nanoc, je vais sur la lune en brasse et je reviens ok ?
ok il y aura des différence au niveau des votes mais globalement, les zéros qui participent aux exercices de nanoc on le même niveau .... (ou tentent de l'avoir comme moi )