Partiel POBJ (LI314)
Emmanuel Chailloux
07 novembre 2012 |
1 Conditions générales
A lire complètement avant de commencer l'épreuve !!!
Cet examen est formé d'un unique problème en plusieurs questions
auxquelles vous pouvez répondre dans l'ordre qui vous plait, néanmoins
certaines questions sont dépendantes de réponses précédentes.
Tous
les documents sont autorisés et notamment ceux du cours (
site du cours).
Votre copie de l'examen sera formée de fichiers textuels qui se
trouveront dans votre espace de travail (workspace) Eclipse
PARTIEL dans lequel vous créerez le paquetage
pobj/partiel2012nov, c'est-à-dire le répertoire
$HOME/workspace/PARTIEL/src/pobj/partiel2012nov qui contiendra les
programmes que vous aurez écrits. Des consignes plus précises seront
énoncées pour chaque question.
Si vous utilisez directement les commandes javac et
java, vous ferez particulièrement attention à respecter la
hiérarchie de fichiers demandée, c'est-à-dire de placer tous les
fichiers demandés dans le catalogue
$HOME/workspace/PARTIEL/src/pobj/partiel2012nov.
À l'exception des clés USB en lecture seule, tous les appareils
électroniques sont prohibés (y compris les téléphones portables, les
assistants numériques personnels et les agendas électroniques).
Le partiel sera corrigé automatiquement.
Pour cela nous vous imposons de n'écrire aucune classe dont le nom
débute par Test, ces noms sont réservés aux classes que nous
utiliserons pour tester vos programmes. Pour la même raison, nous vous
imposons de n'écrire aucune méthode dont le nom débute par
test.
Vos classes seront compilées par la commande javac et les
programmes exécutés par la commande java.
L'épreuve dure deux heures.
Le total du barème indicatif de ce partiel est de 24 points.
Souvenez-vous qu'un fichier qui ne peut être compilé vaut zéro! Il
vaut mieux un fichier qui peut se compiler et qui implante une partie
seulement des spécifications qu'un fichier qui implante presque tout
et qui ne peut être compilé! Cela milite pour une résolution
incrémentielle des problèmes.
Il est tout à fait licite et même louable de réutiliser les classes
que vous avez précédemment écrites. Toutefois si vous modifiez une
classe demandée afin qu'elle en fasse plus, assurez-vous qu'elle
répond toujours aux questions précédentes.
Vous devez répondre en Java 1.7, aucune caractéristique en voie
d'obsolescence (deprecated feature) n'est autorisée.
Toutes les classes demandées doivent appartenir au paquetage
pobj.partiel2012nov.
Cela indique que tous les fichiers que vous écrirez seront placés dans
le catalogue $HOME/workspace/PARTIEL/src/pobj/partiel2012nov et
nulle part ailleurs. Le notateur automatique n'étudiera que les
fichiers de ce catalogue.
Vous aurez probablement besoin de la
documentation sur
Java.
2 Enoncé
On cherche à se doter de traitements extensibles sur les expressions
arithmétiques en utilisant le modèle de conception << Visiteur >>. Un
visiteur correspond à un traitement spécifique, ici sur les
expressions arithmétiques. Ce modèle est présenté à la question 2 en
fournissant un exemple d'un visiteur d'affichage d'expressions arithmétiques.
Pour cela on demande d'implanter plusieurs visiteurs de calcul sur les
expressions : un visiteur d'évaluation des expressions sans variable, un
visiteur d'évaluation d'expressions avec variables, si besoin un visiteur de test de constante, un visiteur de simplification d'expressions et un visiteur de dérivation symbolique.
Remarque : toutes les classes données et demandées sont dans le
paquetage suivant : pobj.partiel2012nov.
On se donne tout d'abord les classes suivantes pour la description des
expressions. Chaque classe concrète possèdera une méthode accepte prenant comme argument un visiteur qui visitera l'instance de la classe pour effectuer son calcul qui correspondra au résultat de la méthode accepte. Le type de résultat de la méthode accepte est paramétré par le type T et dépendra donc du type de retour du calcul d'un tel visiteur.
Voici l'interface IVisiteur<T> que devra respecter tout futur visiteur d'expressions arithmétiques :
et voici la hiérarchie de classes des expressions arithmétiques utilisées :
-
Expression.java
package pobj.partiel2012nov;
abstract class Expression {
public abstract <T> T accepte(IVisiteur<T> v);
}
- Constante.java
package pobj.partiel2012nov;
class Constante extends Expression {
private int value;
Constante(){this.value=0;}
Constante(int value){this.value=value;}
int getValue(){return value;}
public <T> T accepte(IVisiteur<T> v){return v.visite(this);}
}
- OpBin.java
package pobj.partiel2012nov;
abstract class OpBin extends Expression {
protected Expression fg, fd;
Expression getFg(){return fg;}
Expression getFd(){return fd;}
}
- Add.java
package pobj.partiel2012nov;
class Add extends OpBin {
Add(Expression e1, Expression e2) { fg=e1; fd=e2; }
public <T> T accepte(IVisiteur<T> v) {return v.visite(this);}
}
Les attributs fg (pour fils gauche) et fd (pour fils droit) correspondent aux deux opérandes d'une opération binaire (comme l'addition ou la multiplicaiton).
- Mul.java
package pobj.partiel2012nov;
class Mul extends OpBin {
Mul(Expression e1, Expression e2) { fg=e1; fd=e2; }
public <T> T accepte(IVisiteur<T> v) {return v.visite(this);}
}
- Var.java
package pobj.partiel2012nov;
class Var extends Expression {
String nom;
Var(String nom){this.nom=nom;}
String getNom(){return nom;}
public <T> T accepte(IVisiteur<T> v){return v.visite(this);}
}
Code source de départ :
L'archive
partiel2012nov-java.jar
contient toutes ces classes. Vous pouvez soit l'importer directement
dans votre projet, soit le décompresser (avec la commande jar -xf partiel2012nov-java.jar) puis copier les classes extraites dans
dans le répertoire de travail :
$HOME/workspace/PARTIEL/src/pobj/partiel2012nov.
Remarque : Vous aurez à
les recompiler, mais il faut savoir que la notation les utilisera
comme elles sont fournies dans l'énoncé et ne tiendra pas compte de
vos modifications sur ces fichiers.
Question 1
Pour se mettre en route dans cette épreuve, il vous est demandé de
construire trois expressions simples :
-
e1 = ( 2 + 3 ) * 4
- e2 = ( x + 3 ) * (x + 4)
- e3 = ( x + 10 ) * ( y + (-8) )
Les constantes entières seront représentées par des instances de
la classe Constante; les opérateurs +, et * correspondront à des
instances des classes Add et Mul; une variable est représentée par
une instance de la classe Var dont un attribut ( variable
d'instance) contient la chaîne de caractère correspondant à son nom.
Pour pouvoir tester vos constructions, écrivez une classe Question1 du paquetage pobj.partiel2012nov dont le squelette suit :
Les méthodes statiques e1, e2 et e3 retournent
respectivement les expressions e1, e2 et e3 décrites ci-dessus.
Ne cherchez pas à simplifier les expressions demandées.
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/Question1.java
Notation sur 2 point(s)
-
1/2 point(s) si votre fichier Java compile et contient la classe et les méthodes demandées;
- 1/2 point(s) pour chaque méthode si elle construit bien la formule demandée
Question 2
Pour vous familiariser avec l'écriture de visiteurs, voici un
exemple d'un visiteur de conversion en chaînes de caractères appelé
VisiteurTS. Le résultat de ce visiteur est une chaîne de
caractères, pour cela la classe visiteurTS implante
l'interface IVisiteur<String>. La méthode visite est
surchargée permettant d'effectuer un travail spécifique pour chaque
classe concrète sous-classe d'Expression. Si nécessaire pour
le calcul, le visiteur peut parcourir les sous-expressions qui
composent l'expression (comme pour Add ou Mul). Dans
ce cas le visiteur doit être accepté par la sous-expression.
package pobj.partiel2012nov;
class VisiteurTS implements IVisiteur<String> {
public String visite(Constante c){return ( ""+c.getValue());}
public String visite(Var v){return v.getNom();}
public String visite(Add a){
String s1 = a.getFg().accepte(this);
String s2 = a.getFd().accepte(this);
return "( "+ s1 + " + " + s2 + " )";
}
public String visite(Mul a){
String s1 = a.getFg().accepte(this);
String s2 = a.getFd().accepte(this);
return "( "+ s1 + " * " + s2 + " )";
}
}
Et voici le programme de test pobj/partiel2012nov/Exemple.java
qui l'utilise :
package pobj.partiel2012nov;
class Exemple {
public static void main(String[] args) {
VisiteurTS v1 = new VisiteurTS();
VisiteurTS v2 = new VisiteurTS();
Expression e1 = Question1.e1();
Expression e2 = Question1.e2();
Expression e3 = Question1.e3();
String s1 = e1.accepte(v1);
String s2 = e2.accepte(v2);
String s3 = e3.accepte(v1);
System.out.println(s1 + "\n" + s2 + "\n" + s3);
}
}
Il vous est demandé d'écrire une classe VisiteurEval
qui implante l'interface IVisiteur<Integer> qui calcule la valeur d'une expression sans variable.
Si un tel visiteur rencontre une
instance de Var il déclenche l'exception
InvalidArgument déclarée de la manière suivante :
package pobj.partiel2012nov;
class InvalidArgument extends RuntimeException {}
N'oubliez pas de tester votre classe au moins sur les exemples de la question 1.
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/VisiteurEval.java
Notation sur 4 point(s)
-
1 point(s) si votre visiteur évalue correctement les exemples de la question 1;
- 3 point(s) sur nos autres tests.
Question 3
Pour les formules contenant des variables, il est nécessaire de pouvoir les calculer dans un certain environnement. Un environnement est formé de couples liant une variable à une valeur booléenne.
On se donne la classe VarNotFound et on réutilise la classe InvalidArguement toutes deux sous-classes de RuntimeException et la classe Env pour les environnements :
package pobj.partiel2012nov;
class VarNotFound extends RuntimeException {}
package pobj.partiel2012nov;
class Env {
String[] vars;
int[] values;
int size;
Env(int size, String[] vars, int[] values){
this.size=size;
this.vars =vars; this.values= values;
if ( (size != 0) && ((size != vars.length) || (size != values.length)))
throw new InvalidArgument();
}
String[] getVars(){return vars;}
int[] getValues(){return values;}
int getSize(){return size;}
int get(String s){
for (int i=0; i<size; i++) {
if (vars[i].equals(s)) return values[i];
}
throw new VarNotFound();
}
public String toString(){
String res = "";
for (int i = 0; i<size; i++) {
res = res + "(" + vars[i] + "," + values[i] + ")";
}
return res;
}
}
Un environnement vide retournera 0 à l'appel de la méthode getSize.
On cherche à construire les environnements suivants :
-
env1 est l'environnement vide;
- env2 est l'environnement qui associe 10 à la variable "x"
et 20 à "y"; l'ordre importe peu;
- env3 est l'environnement qui associe 9 à la variable "z".
Pour cela il vous est demandé d'écrire une classe Question3.java du paquetage pobj.partiel2012nov dont le squelette suit :
package pobj.partiel2010nov;
class Question3 {
static Env env1() { /* A COMPLETER */ }
static Env env2() { /* A COMPLETER */}
static Env env3() { /* A COMPLETER */}
}
Les méthodes statiques env1, env2 et env3 retournent
respectivement les environnements env1, env2 et env3 décrits ci-dessus.
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/Question3.java
Notation sur 2 point(s)
-
1/2 point(s) si votre fichier Java compile et contient la classe et les méthodes demandées;
- 3/2 point(s) si les trois méthodes construisent bien les environnements demandés.
Question 4
Il vous est demandé d'écrire une classe VisiteurEvalVar, sous-classe de VisiteurEval, permettant l'évaluation d'une formule dans un environnement donné. La classe VisiteurEvalVar possède un constructeur prenant un environnement comme paramètre. On pourra ainsi
construire de tels visiteurs de la manière suivante :
VisiteurEvalVar vev1 = new VisiteurEvalVar(Question3.env2());
Integer resultat = Question1.e2().accepte(vev1);
N'oubliez pas de tester votre classe au moins sur les expressions de la
question 1 associés aux environnements de la question 3.
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/VisiteurEvalVar.java.
Notation sur 3 point(s)
-
1 point(s) si votre visiteur évalue correctement les expressions e1, e2, e3 de la question 1, respectivement dans les environnements env1, env2 et env3
- 2 point(s) si nos autres tests sont couronnés de succès.
Question 5
Pour la question suivante on a besoin de pouvoir vérifier si une expression est une constante. De même dans le cas où c'est bien une constante on peut avoir besoin de savoir si la constante vaut 0 ou 1. Pour cela il suffit de l'évaluer pour savoir si elle vaut 0 ou 1.
Pour cela on vous demande de compléter la classe Question5 suivante :
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/Question5.java
Notation sur 2 point(s)
-
1/2 point(s) si votre fichier Java compile et contient la classe et les méthodes demandées;
- 1/2 point(s) pour chaque méthode si nos tests sont couronnés de succès
Question 6
On cherche à simplifier les expressions arithmétiques que l'on construit selon les règles suivantes :
-
évaluation des opérations sur les constantes :
1 + 3 = 4
3 * 10 = 30
- élément neutre pourles opérateurs + et * :
e + 0 = e
0 + e = e
e * 1 = e
1 * e = e
- élément absorbant pour la multiplication
e * 0 = 0
0 * e = 0
Si les deux membres d'une expression d'un opérateur binaire (+ ou *) sont des constantes, on peut alors évaluer l'opérateur avec un visiteur d'évaluation (VisiteurEval) pour construire une nouvelle expression Constante symbolique valant la somme des deux constantes.
Chaque opération (Add et Mul) possède un élément neutre (0 pour l'addition, et 1 pour la multiplication). De plus la multiplication possède un élément absorbant, 0.
Il vous est demandé d'écrire une classe VisiteurSimplifie qui implante l'interface IVisiteur<Expression> permettant de calculer une expression simplifiée en fonction des règles de simplification proposées. Un tel visiteur retourne une nouvelle expression correspondant à la simplification de l'expression qu'il visite.
VisiteurSimplifie vs = new VisiteurSimplifie();
Expression resultat1 = Question1.e1().accepte(vs);
Expression resultat2 = Question1.e2().accepte(vs);
Expression resultat3 = Question1.e3().accepte(vs);
N'oubliez pas de tester votre classe au moins sur les expressions de la
question 1.
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/VisiteurSimplifie.java.
Notation sur 5 point(s)
-
1 point(s) si votre visiteur simplifie correctement les expressions e1, e2, e3,
- 4 point(s) si nos autres tests sont couronnés de succès.
Question 7
On cherche maintenant à effectuer une dérivée symbolique des expressions par rapport à une variable. On rappelle les formules pour les une dérivée par rapport à la variable x en notant (e)' la dérivée de e par rapport à x.
Il vous est demandé d'écrire une classe VisiteurDerive qui implante l'interface IVisiteur<Expression> permettant le calcul symbolique de la dérivée d'une expression par rapport à une variable. Un tel visiteur retourne une nouvelle expression correspond à la dérivée de l'expression qu'il visite. Il est nécessaire à la construction d'indiquer par rapport à quelle variable s'effectue la dérivée comme dans l'exemple suivant :
VisiteurDerive vd = new VisiteurDerive(new Var("x"));
Expression resultat = Question1.e3().accepte(vd);
A cette question, on ne cherche pas à simplifier l'expression ainsi obtenue.
N'oubliez pas de tester votre classe au moins sur les expressions de la
question 1.
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/VisiteurDerive.java.
Notation sur 5 point(s)
-
1 point(s) si votre visiteur dérive correctement les expressions e1, e2, e3 par rapport à x puis à y,
- 4 point(s) si nos autres tests sont couronnés de succès.
Question 8
Comme le calcul de la dérivée symbolique construit de grosses expressions peu lisibles, il est nécessaire de les simplifier. Pour cela on demande de définir une fonction compose qui prend deux visiteurs f et g, et une expression e et qui retourne le résultat de la composition des deux visiteurs en appliquant d'abord g puis f sur le résultat de g.
Pour cela on vous demande de compléter la classe Question8 suivante :
Livraison
Un fichier $HOME/workspace/PARTIEL/src/pobj/partiel2012nov/Question8.java.
Notation sur 1 point(s)
-
1 point(s) si nos tests sont couronnés de succès.
Ce document a été traduit de LATEX par HEVEA