Jean-Jacques BOURDIN

Université Paris 8
Labo IA, Dépt. Informatique
2, rue de la Liberté
93526 Saint-Denis Cedex
FRANCE

Tél : (+33/0) 1 49 40 64 03
Fax : (+33/0) 1 49 40 64 10
E-mail : Jean-Jacques.Bourdin à ai.univ-paris8.fr


Programmation Impérative II
Projets 2019

Les projets encore "libres" :

8
17
18 
19
20
21
29

Conditions

Les projets sont à faire par groupe de deux (2) personnes. La part de chacun devra être auto-évaluée dans le rapport.
Le rapport et le programme seront envoyés en format électronique (mail) avant le lundi 16/12/19 9h.
Le rapport et le programme seront rendus en version papier le lundi 16/12/19 à 15h.

Les étudiants qui choisiront de rendre leur projet en avance, le mardi 10/12/19 avant 18h (version électronique et version papier) auront un bonus de 2 points.

Pour les étudiants qui veulent rendre leur projet en avance, c'est-à-dire le 10/12/19 avant 18h, il est possible que l'accès à l'Université soit très limité, voire impossible (pas de métro...).

Dans ce cas, la version électronique suffira pour l'instant, la version papier devant être rendue avant le lundi 16/12 à 15h.

Il n'est pas sûr que les transports fonctionnent correctement le lundi 16/12, si vous ne voyez pas comment venir ni faire porter votre document par un collègue, vous pouvez l'envoyer par la poste avant l'heure dite. L'adresse serait alors JJ Bourdin Dept Informatique, 2 rue de la Liberté 93526 Saint-Denis.

Le mardi 17/12/19 devrait être une journée de mobilisation, c'est-à-dire que, vraisemblablement, notre université sera fermée toute la journée. Dans ce cas nous devrons renoncer aux présentations des projets.

Le rapport contiendra des explications sur les procédures mises en oeuvre, le mode d'emploi, le listing du programme et des traces d'utilisation.
Le programme devra tourner sur au moins une des machines en libre-service du Bocal et sera écrit en C, avec, si nécessaire, utilisation des librairies OpenGL, Glu, Glut et GL4D, seules librairies non standard autorisées.

La présentation publique des travaux aura lieu le 17/12/19, de 9 à 11h puis en salle de TP de 14 à 18h.

Si certains ont des problèmes avec leur sujet ou leur binôme, qu'ils n'hésitent pas à poser des questions avant le 9/12/2019 !

Il vous est conseillé d'envoyer au moins une version intermédaire de votre travail de façon à éviter, en particulier, les hors sujet.


  1. Images taches.(***)

    Il faut sur, une image, trouver automatiquement toutes les "taches de couleur". L'image est donnée comme un grand tableau avec un octet par couleur par "pixel" (trois couleurs, R, G et B). C'est donc une vaste matrice de (XMAX x YMAX x 3) octets.
    Trouver les taches consiste à trouver et numéroter les zones connexes ayant la même couleur.
    Une bonne méthode consisterait à commencer par trouver tous les pixels connexes ayant une certaine couleur, ils forment une tache.
    Puis à réitérer ce processus pour tous les pixels.
    On a alors toutes les taches, si elles ont été listées, il est maintenant facile de leur appliquer un traitement.
    Un traitement pourrait être de délimiter en noir les taches de couleur.
    Enfin, une tache peut être une zone dont les pixels ont à peu près la même couleur. On définira cette approximation et on fera la délimitation de ces zones comme précédemment.

  2. Images par carrés. (**)

    On considérera qu'une fenêtre est, dans une image, un carré de taille n x n dans lequel on fait des calculs (et, peut-être, des modifications). La fenêtre de travail passe ensuite au carré suivant. Le fenêtrage est donc une partition de l'image (tout pixel appartient à une et une seule fenêtre).
    Il va falloir d'abord commencer par mettre en place un codage HSV de l'image, pixel après pixel.
    Puis traiter l'image par petites fenêtres.

    • Par fenêtre, trouver le pixel le plus lumineux (le plus grand v) et le placer (placer les valeurs de ses couleurs) dans le coin inférieur gauche. Il s'agit donc d'intervertir les valeurs de ses couleurs avec celles du pixel du coin.
    • Par fenêtre, ranger les pixels en fonction de leur luminosité.
      Plusieurs modes de classement sont possibles : de haut en bas et de gauche à droite, du centre à la périférie, selon une courbe de Peano ou de Hilbert...
    • Par fenêtre, déplacer les pixels en fonction des contrastes (plus grands écarts entre la couleur courante et la couleur moyenne).
    • Par fenêtre, trouver la couleur moyenne, la couleur la plus fréquente et la couleur la plus éloignée des autres. Remplir la fenêtre avec ces trois couleurs dans des proportions que vous trouverez correctes.

  3. Images, et formes.(***)

    Les contrastes sont les différences entre la couleur d'un pixel et la couleur de ses voisins.
    Répérer les pixels ayant le plus fort contraste consiste donc à parcourir l'image en mémorisant ces pixels dont la couleur est très éloignée de celles de ses voisins.
    Mettre en place une fonction qui retourne l'ensemble des pixels de fort contraste.
    Ces pixels peuvent être connexes et dans ce cas, composent une forme.
    Mettre en place une fonction qui prend l'ensemble défini ci-dessus et trouve les alignements de pixels dans cette liste.
    Des lignes adjacentes peuvent composer des formes.
    Mettre en place une fonction qui, à partir des lignes trouvées, compose et reconnaît des objets par leur forme.

  4. Images, BD et vitraux.(**)

    En dande dessinée classique, comme dans les vitraux, les taches de couleur sont uniformes et les formes sont séparées par un trait noir bien visible. Il s'agit dans ce projet de répérer ces formes, ces "régions" de couleur. L'image sera représentée comme un ensemble de contours (c'est-à-dire de listes de points) formant une région associée à une couleur.
    Ce format sera utilisé pour sauvegarder l'image.
    Ce format sera alors repris pour afficher une image ainsi sauvegardée.
    On s'intéressera notamment au ratio de compression,
    (taille du fichier obtenu) / (taille du fichier bmp initial).

  5. Images par proximité. (**)

    Un pixel a huit voisins (1 : est, 2 : nord-est, 3 : nord, 4 : nord-ouest, 5 : ouest, 6 : sud-ouest, 7 : sud, 8 : sud-est). Son voisinage est l'ensemble de ces huit voisins plus lui-même.
    Modifiez l'image pour que chaque pixel prenne la valeur de la moyenne, puis de la moyenne pondérée (un grand poids pour lui-même) de son voisinage.
    Modifiez l'image pour accentuer le contraste : pour chaque pixel on cherche, dans son voisinage, le pixel dont les couleurs sont les plus éloignées des siennes. On augmente alors d'un tiers ce contraste.
    Attention, dans tout le programme, à éviter les effets de bord (cas du pixel p1 augmenté à cause de son contraste avec p2 et de p2 diminué à cause de son contraste avec le nouveau p1).
    On pourra enfin chercher et améliorer les contrastes de "teinte" en mode HSV.

  6. Images et contrastes.(**)

    On va parcourir une image "fenêtre" par "fenêtre" (par exemple par groupes disjoints de 3x3 ou 4x4 pixels). Dans ce voisinage, on peut classer les pixels par "contraste" : le "contraste" d'un pixel est le plus grand des écarts de couleurs par rapport à ses voisins.
    Il est alors possible de déplacer les couleurs des pixels de la fenêtre en plaçant, par exemple les pixels les plus contrastés au centre et les autres de façon régulière vers la périphérie de la "fenêtre". Le sens inverse doit être essayé également.
    D'autres dispositions sont possibles et il faudra voir ce qui fonctionne le mieux, ce qui donne les effets les plus intéressants.
    Le contraste peut aussi être basé sur la "chaleur" des couleurs, par exemple, un bleu ou un vert est considéré comme froid, un rouge comme chaud. Faire tourner les mêmes fonctions avec cette nouvelle définition de contraste.

  7. Sudoku.(* à **) ()

    Il s'agit ici de fabriquer des grilles de sudoku. Les règles sont simples :

    • Dans chaque ligne, colonne et carré, il doit y avoir une occurence unique de chaque chiffre utilisé.
    • Le jeu consiste à remplir une grille incomplète.
    • Il y a une solution unique.
    Mettre en place un système automatique de création de grilles auquel on donnera simplement le nombre de cases non vides au départ du jeu. Il devra donc vérifier que la grille proposée a une solution unique.
    Il faudra veiller à ce que votre programme permette de faire de grilles variées et à ce que le nombre de cases remplies au départ puisse réellement être variable.
    On n'acceptera pas un programme incapable de fournir des grilles de moins de 20 cases préremplies.
    De même, produire une grille qui soit la transposée ou le symétrique d'une grille déjà jouée revient à produire la même grille. Il faut pouvoir produire des grilles réellement différentes.

    NB : enlever des valeurs à une grille pleine et vérifier que la grille respecte les règles a déjà été tenté avec insuccès.

  8. File d'attente.(* à ***) ()

    Soit un arbre n-aire.
    1. Mettre en place une structure de file d'attente qui contienne des pointeurs vers des sommets de l'arbre.
    2. Parcours de l'arbre par génération (on affiche la racine, puis ses descendants, puis leurs descendants...).
    3. Se servir de ce travail pour compléter le projet d'un autre groupe, par exemple sur un jeu (Robots ?), pour améliorer l'"IA".
    4. Adaptez votre travail au parcours d'un graphe, puis s'en servir pour améliorer le programme de l'un des autres groupes, comme, par exemple, l'analyse d'un programme ou la recherche du plus court chemin en altitude.

  9. Robots programmables. (**)

    Mettre en place un jeu de robots programmables.
    Sur une aire de jeu avec des obstacles, des butins et des aires de retour, des robots peuvent se déplacer, se combattre, ramasser du butin.

    1. Mettre en place un tel jeu.
    2. Créer un langage de programmation minimal, pour les robots.
    3. Donner, à chaque joueur, la possibilité de télécommander son robot. Il faut donc voir ce que les capteurs du robot perçoivent.
    4. Donner, à chaque joueur, la possibilité de programmer son robot. Le robot à partir de là agit simplement en suivant son programme.
    5. Visualiser le jeu au cours de son déroulement.

  10. Turing(**)

    Une machine de Turing est une machine virtuelle composée
    • d'un ruban infini (dans un seul sens, ici) qui contient des valeurs binaires.
    • d'une tête de lecture écriture, qui placée en un certain point de la bande permet de lire la valeur courante et d'écrire la valeur désirée. Le déplacement de la tête est automatique.
    • un registre d'état qui mémorise l'état courant.
    • une table de décision. Pour chaque état et chaque valeur lue possible, ce qu'il convient d'écrire, quel est le nouvel état et le sens de déplacement de la tête de lecture (d'une case) sernt indiqués.
    Il faut mettre en place une machine de Turing virtuelle.

    Une fois qu'elle est en place, on écrira des programmes comme l'addition de deux entiers, la soustraction, le décalage... et on vérifiera que la machine fait bien le travail.

    L'enseignant donnera une ou des programmes écrits pour une machine de Turing et vérifiera que votre programme les interprète correctement et réalise les opérations.

  11. Go. (de * à ***) ()

    On peut trouver un certain nombre de problèmes de Go en ligne. Il s'agit ici de mettre en place un système de résolution de problèmes. La taille maximale du goban est fixée TMAX et, dans un premier temps, ne pourra pas dépasser 6 x 6.
    Pour résoudre ce problème il convient d'écrire quelques fonctions :
    1. quel est le nombre de libertés de la pierre isolée (x,y) ?
    2. quel est le nombre de libertés de la paire de pierres (x,y), (x', y') ?
    3. quel est le nombre de libertés du triplet de pierres (x,y), (x', y'), (x", y") ?
    4. la pierre (x,y) est-elle isolée ?
    5. quel est le nombre de libertés de la pierre non isolée (x,y) ?
    6. Quelle est la meilleure structure de données pour ce travail ?
    7. Faites aussi une fonction qui permet facilement de saisir un problème.
    8. Écrivez un programme qui résout des problèmes de go. Dans un premier temps ce seront des problèmes très simples, puis plus complexes.

  12. Morpion solitaire. (***)

    Le morpion consiste à aligner 5 points et en faire un segment. Le morpion solitaire se joue à partir d'une figure initiale, il faut, à chaque coup, ajouter un point qui permette de tracer un nouveau segment. Attention, les segments sont indépendants et deux segments ont au plus un point commun.
    Votre but est de fabriquer un programme qui fait une liste des coups possibles et teste ces coups de façon à obtenir le plus grand nombre possibles de coups successifs.
    Votre programme doit atteindre le record actuel de 178 coups. S'il n'atteint pas 100 coups, il pourra être considéré comme vraiment mauvais (note inférieure à 8).

  13. Quadtree. (**)

    Une image est ici encore donnée sous la forme d'un paquet de triplets d'octets (r,g,b). Il s'agit de la réorganiser sous la forme d'un quadtree. C'est un arbre quaternaire dans lequel une surface, représentée par un sommet, peut avoir une couleur uniforme ou, sinon, elle est divisée en quatre sous-surfaces, les quatre fils du sommet.

    Attention, dans la suite, une fois que la structure quadtree est en place, on ne réutilise pas l'image.

    • Faire une fonction qui prend une image et la transforme en quadtree.
    • Faire une fonction qui prend un quadtree et un point et détermine la superficie de la tache (même couleur) de l'image qui entoure ce point.
    • Faire une fonction qui prend un quadtree et un point et détermine le périmètre de la tache (même couleur) de l'image qui entoure ce point.
    • Comment faire évoluer votre programme pour ne plus considérer une couleur mais un ensemble de couleurs très proches ?

  14. Fortress. (*)

    C'est un jeu dans lequel on contrôle des cases et où on contruit des tours sur un damier. À chaque tour de jeu, un joueur construit ou élève une tour.
    Puis le programme vérifie les contrôles et détruit, éventuellement en cascade, les tours incontrôlées.
    Une tour de n étages donne n contrôles sur sa case et sur les 4 cases voisines.
    Si une tour est construite sur une case contrôlée par l'adversaire, elle est détruite. Exemple :

    Tour1 Joueur 1 (+)
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    | +1 |    |    |    |    |
    -----------------------------------------
    |    |    | +1 | T1 | +1 |    |    |    |
    -----------------------------------------
    |    |    |    | +1 |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    Tour1 Joueur 2 (-)
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    | -1 |    |    |    |
    -----------------------------------------
    |    |    |    | 0  | T2 | -1 |    |    |
    -----------------------------------------
    |    |    | +1 | T1 | 0  |    |    |    |
    -----------------------------------------
    |    |    |    | +1 |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    Tour2 Joueur 1 (+)
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    | -1 |    |    |    |
    -----------------------------------------
    |    |    |    | 0  | T2 | -1 |    |    |
    -----------------------------------------
    |    |    | +1 | T1 | T1 | +1 |    |    |
    -----------------------------------------
    |    |    |    | +1 | +1 |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    Tour2 Joueur 2 (-)
    -----------------------------------------
    |    |    |    | -1 |    |    |    |    |
    -----------------------------------------
    |    |    | -1 | T2 | -2 |    |    |    |
    -----------------------------------------
    |    |    |    | -1 | T2 | -1 |    |    |
    -----------------------------------------
    |    |    | +1 | T1 | T1 | +1 |    |    |
    -----------------------------------------
    |    |    |    | +1 | +1 |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    Tour3 Joueur 1 (+)
    -----------------------------------------
    |    |    |    | -1 |    |    |    |    |
    -----------------------------------------
    |    |    | -1 | T2 | -1 | +1 |    |    |
    -----------------------------------------
    |    |    |    | 0  | +2 | T1 |    |    |
    -----------------------------------------
    |    |    | +1 | T1 | T1 | +2 |    |    |
    -----------------------------------------
    |    |    |    | +1 | +1 |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    En effet, la tour a été détruite car son contrôle (-1) sur la case ne
    dominait pas le contrôle (+2) du joueur J1.
    Tour3 Joueur 2 (-)
    -----------------------------------------
    |    |    |    | -1 |    |    |    |    |
    -----------------------------------------
    |    |    | -1 | T2 | -1 | +1 |    |    |
    -----------------------------------------
    |    |    | -1 | T2 | +1 | T1 | +1 |    |
    -----------------------------------------
    |    |    | +1 | T1 | T1 | +2 |    |    |
    -----------------------------------------
    |    |    |    | +1 | +1 |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    Tour4 Joueur 1 (+)
    Il ajoute un étage à une de ses tours :
    -----------------------------------------
    |    |    |    | -1 |    |    |    |    |
    -----------------------------------------
    |    |    | -1 | T2 | -1 | +2 |    |    |
    -----------------------------------------
    |    |    | -1 | T2 | +2 | TT1| +2 |    |
    -----------------------------------------
    |    |    | +1 | T1 | T1 | +3 |    |    |
    -----------------------------------------
    |    |    |    | +1 | +1 |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    |    |    |    |    |    |    |    |    |
    -----------------------------------------
    
    Il s'agit ici de choisir un bon mode de représentaiton du jeu et des systèmes de contrôles, pas de faire un "truc joli". Puis de s'en servir pour que l'ordinateur gère le jeu.
    Le but du projet est que votre programme joue contre un bon joueur humain et gagne.

  15. Échecs. (de * à ***) 

    Il s'agit, ici de pouvoir résoudre des problèmes d'échecs, tels ce que l'on trouve dans certains journaux.
    1. Créer une fonction permettant de saisir de tels problèmes.
      Dans un premier temps on ne considérera pas toutes les pièces, on se limitera à des problèmes à peu de pièces.
    2. Créer une fonction pour résoudre de simples problèmes. Du genre "Blanc joue et fait mat en un coup".
    3. Créer une fonction pour résoudre des problèmes plus complexes du genre "Blanc joue et fait mat en deux coups".
    4. Créer une fonction pour résoudre des problèmes du genre "Blanc joue et fait mat en n coups".
    5. Résolution de problèmes généraux : "Noir joue et gagne".

  16. Analyse de programme, C. (**)

    Soit un programme écrit, par exemple, en C. Il s'agit de lire le(s) fichier(s) et de l'analyser sous la forme d'un graphe. Chaque fonction sera un noeud du graphe et les liens seront les appels de fonction. On pourra ainsi analyser le programme, par exemple savoir si une fonction n'est jamais appelée ou si une fonction n'est pas dans le sous-graphe connexe de la fonction main, savoir si une fonction est récursive, récursive terminale, etc.
    Détaillez la structure de données retenue.
    Faites la lecture d'un fichier et son entrée dans la structure.
    Faites l'analyse du graphe et du programme.
    Comment gérer les pseudo-fonctions ?
    On peut compléter ce programme en travaillant sur le corps de chaque fonction et analysant les boucles et autres actions spéciales.
  17. Analyse de programmes Scheme. (**)

    Soit un programme écrit en Scheme. Il s'agit de lire le fichier et de l'analyser sous la forme d'un graphe. Chaque fonction sera un noeud du graphe et les liens seront les appels de fonction. On pourra ainsi analyser le programme, par exemple savoir si une fonction n'est jamais appelée ou si une fonction n'est pas dans le sous-graphe connexe d'une fonction donnée, si une fonction est récursive, récursive terminale, etc.
    Attention, en Scheme, il n'y a pas de fonction "main" et donc la structure de graphe n'a pas de racine.
    Attention à la gestion de programmes sur plusieurs fichiers !
    Comment gérer les variables globales dans cette analyse ?

  18. Analyse de programmes Prolog.(** à ***)

    Soit un programme écrit en Prolog. Il s'agit de lire le fichier et de l'analyser sous la forme d'un graphe. Chaque prédicat sera un noeud du graphe et les liens seront les appels à d'autres prédicats. On pourra ainsi analyser le programme, par exemple savoir si une partie n'est jamais appelée ou si un prédicat n'est pas dans le sous-graphe connexe d'un prédicat donné, si un prédicat est récursif, récursif terminal, etc.
    Il faudra être en mesure de travailler sur les problèmes de redondance, les détecter, les corriger si nécessaire.
    Comment faire pour que votre programme détecte également les contradictions dans la base de données qu'est le programme ?

  19. Analyse de programme, C++.(**)

    Soit un programme écrit en C++. Il s'agit de lire le(s) fichier(s) et de l'analyser sous la forme d'un graphe. Chaque méthode sera un noeud du graphe et les liens seront les appels de fonctions ou méthodes. On pourra ainsi analyser le programme, par exemple savoir si une fonction n'est jamais appelée ou si une fonction n'est pas dans le sous-graphe connexe de la fonction main, savoir si une fonction est récursive, récursive terminale, etc.
    Détaillez la structure de données retenue.
    Faites la lecture d'un fichier et son entrée dans la structure.
    Faites l'analyse du graphe et du programme.
    Comment gérer les pseudo-fonctions ?
    On peut compléter ce programme en travaillant sur le corps de chaque fonction et analysant les boucles et autres actions spéciales.

  20. Analyse de programme, Python.(**)

    Soit un programme écrit en Python. Il s'agit de lire le(s) fichier(s) et de l'(les) analyser sous la forme d'un graphe. Chaque fonction sera un noeud du graphe et les liens seront les appels de fonctions ou méthodes. On pourra ainsi analyser le programme, par exemple savoir si une fonction n'est jamais appelée. En Python, qu'est-ce qui fait le rôle de la fonction main ? Il faudra aussi déterminer si une fonction est récursive, récursive terminale, etc.
    Détaillez la structure de données retenue.
    Faites la lecture d'un fichier et son entrée dans la structure.
    Faites l'analyse du graphe et du programme.
    On peut compléter ce programme en travaillant sur le corps de chaque fonction et analysant les boucles et autres actions spéciales.

  21. Analyse de programme, Java.(*)

    Soit un programme écrit en Java. Il s'agit de lire le(s) fichier(s) et de l'analyser sous la forme d'un graphe. Chaque méthode sera un noeud du graphe et les liens seront les appels de fonctions ou méthodes. On pourra ainsi analyser le programme, par exemple savoir si une fonction n'est jamais appelée ou si une fonction n'est pas dans le sous-graphe connexe de la fonction main, savoir si une fonction est récursive, récursive terminale, etc.
    Détaillez la structure de données retenue.
    Faites la lecture d'un fichier et son entrée dans la structure.
    Faites l'analyse du graphe et du programme.
    On peut compléter ce programme en travaillant sur le corps de chaque fonction et analysant les boucles et autres actions spéciales.

  22. Plus court chemin en altitude. (*) 

    Soit une carte avec altitude, donnée sous la forme d'une matrice de points avec l'altitude en mètres de chacun des points.
    Il s'agit de trouver le plus court chemin entre deux points de ce terrain, mais en minimisant, surtout, les déplacements ascendants.
    Quelle est la bonne structure ?

    Comment tenir compte du dénivelé ? Vous remarquerez qu'un dénivelé faible ne pose pas de problème alors qu'un dénivelé très important (par exemple une pente supérieure à 30%) n'est en général pas franchissable.
    Faites le programme !

  23. Problèmes de logique. (**)

    Un problème de logique peut être donné sous la forme d'une série de phrases, comme par exemple :
    On considere cinq maisons, toutes de couleurs differentes (rouge, bleu, jaune, blanc, vert), dans lesquelles logent cinq professionnels (peintre, sculpteur, diplomate, docteur et violoniste) de nationalite differente (anglaise, espagnole, japonaise, norvegienne et italienne) ayant chacun une boisson favorite (the, jus de fruits, cafe, lait et vin) et des animaux favoris (chien, escargots, renard, cheval et chat). On dispose des faits suivants :

    1. l'Anglais habite la maison rouge
    2. l'Espagnol possede un chien
    3. le Japonais est peintre
    4. l'Italien boit du thé
    5. le Norvegien habite la premiere maison a gauche
    6. le proprietaire de la maison verte boit du café
    7. la maison verte est a droite de la blanche
    8. le sculpteur eleve des escargots
    9. le diplomate habite la maison jaune
    10. on boit du lait dans la maison du milieu
    11. le Norvegien habite a cote de la maison bleue
    12. le violoniste boit du jus de fruit
    13. le renard est dans une maison voisine de celle du médecin
    14. le cheval est a cote de la maison du diplomate.
    Il s'agit de trouver le possesseur du chat et le buveur de vin.

    Votre travail est d'écrire un programme qui prend en entrée des propositions comme celles-ci et calcule la solution.
    Votre programme devra donc s'adapter à des problèmes différents mais dont la formalisation sera possible.

  24. Optimisation du problème du voyageur par colonie de fourmis.

    Le problème du voyageur de commerce est représenté par un graphe complet dont les n noeuds représentent les villes (n >= 30). Résoudre le problème, c'est trouver le plus court chemin que doit prendre le voyageur pour visiter toutes les villes et revenir à son point de départ.

    Les arcs sont pondérés par les distances dij entre ces villes et par une autre pondération TRij(t) qui représente la trace de phéromone laissée par les fourmis.

    On appelle génération une succession de n-1 étapes où chaque fourmi aura visité les n villes. Initialement, on placera deux fourmis par ville. On initialise TRij(0) de manière aléatoire entre 0 et 1 ou bien par le réel n/L avec L longueur de visite des n villes en prenant toujours le plus proche voisin.

    Chaque fourmi k possède une liste "tabou" TLk des villes déjà visitées et se meut aléatoirement suivant la probabilité qu'il passe du noeud i à j. Cette probabilité est proportionnelle à TRij / dij^7 (plus il y a de phéromones, et plus la distance est courte, et plus la fourmi a de chance de prendre ce chemin).

    Pour chaque ville i et chaque fourmi k présente en i, si TLk(t) n'est pas complète, on choisit la ville j aléatoirement parmi celles de plus forte probabilité, j est empilé dans TLk(t) pour former TLk(t+1), et la fourmi k passe en j.

    Les phéromones sont mises à jour selon :
    TRij(t+1) = TRij(t)/2 + 100 * (nbre de fourmis passant de i à j)

    Après n-1 étapes, (une génération), la meilleure liste Tabou (plus petite distance cumulée) est mémorisée et une autre génération est reconduite.

    On pourra ensuite essayer de changer le nombre de fourmis et les valeurs numériques. Testez différentes configurations pour voir lesquelles sont les plus intéressantes.

  25. HexaGo.

    On peut trouver un certain nombre de problèmes de Go en ligne mais il est plus difficile de trouver des problèmes d'hexago. Hexago est un jeu de go, basé sur exactement les mêmes principes, mais sur un maillage hexagonal (à grille en nid d'abeille). Chaque pierre a donc six voisins potentiels. Il s'agit ici de mettre en place un système de résolution de problèmes. La taille maximale du goban est fixée TMAX et, dans un premier temps, ne pourra pas dépasser 6 x 6.
    Pour résoudre ce problème il convient d'écrire quelques fonctions :

    • quel est le nombre de libertés de la pierre isolée (x,y) ?
    • quel est le nombre de libertés de la paire de pierres (x,y), (x', y') ?
    • quel est le nombre de libertés du triplet de pierres (x,y), (x', y'), (x", y") ?
    • la pierre (x,y) est-elle isolée ?
    • quel est le nombre de libertés de la pierre non isolée (x,y) ?
    • Quelle est la meilleure structure de données pour ce travail ?
    • Faites aussi une fonction qui permet facilement de saisir un problème.
    • Écrivez un programme qui résout des problèmes de go.

  26. Prairie.(*)

    Il s'agit ici d'écrire un programme qui joue correctement à Prairie. Le programme devrait gagner à tous les coups lorsqu'il joue les bisons.
    Votre Structure de données sera importante et la mémorisation des coups suivants et des choix faits déterminante.
    La présentation est secondaire et ne devra utiliser des images que si le programme joue vraiment bien.

  27. Scrabble.(**)

    Il s'agit ici d'écrire un programme qui joue correctement au Scrabble, en français.
    Le programme doit trouver les scrabbles quand il y en a. Il doit, bien sûr tenir compte des valeurs des cases et de la situation du jeu.
    Il faut mettre en place en plus un système de saisie de situation. En effet, de nombreux sites proposent des problèmes de scrabbles, (dans le genre de "dans cette situation, avec ces lettres, comment faire un scrabble ?)")
    Il faut que le programme résolve de tels problèmes.

  28. Perspective. (**)

    Si un individu est placé en face d'une série d'immeubles, il peut voir le plus proche, P. Mais il peut voir aussi un immeuble P' si P' est plus loin que P mais plus haut que P. De même pour P'' et les suivants.
    On veut fabriquer un paté de nxn immeubles. Les immeubles ont une hauteur, donnée par un X ci-dessous. Les valeurs indiquées sur les bords sont les nombres d'immeubles visibles de ce point. Par exemple si vous êtes en bas et le plus à droite possible, que vous regardez vers le haut, vous devez voir 3 immeubles, ce qui veut dire que un seul des immeubles sera caché par les autres.
    Dernières règles, dans chaque ligne et chaque colonne il y a un seul immeuble d'une hauteur donnée et un problème a une solution unique.
    Exemple de problèmes en taille 4x4.
      | 1  2  3  2 |
    ------------------
    1 | X  X  X  X | 4
    4 | X  X  X  X | 1
    2 | X  X  X  X | 2
    2 | X  X  X  X | 2
    ------------------
      | 2  1  2  3 |
    
    Vous devez maintenant trouver la hauteur de chacun des immeubles. Il est assez facile de trouver la solution :
      | 1  2  3  2 |
    ------------------
    1 | 4  3  2  1 | 4
    4 | 1  2  3  4 | 1
    2 | 2  1  4  3 | 2
    2 | 3  4  1  2 | 2
    ------------------
      | 2  1  2  3 |
    
    Il faut écrire un programme qui puisse :
    • résoudre un problème donné. Donc il doit être facile de fournir un problème quelle que soit sa taille.
    • créer des problèmes de la taille donnée en paramètre. Ces problèmes doivent avoir une solution unique.

  29. Récursivité automatique. (de ** à ***)

    Vous avez fait, en L1, une série de programmes récursifs, en différents langages. C'est souvent assez rébartbatif.
    L'objet de ce projet est de prendre une fonction récursive en Scheme et de la transcrire dans un autre langage.

    Les autres langages cibles seront C, Python et Prolog.
    Par exemple, si la fonction en entrée est :
    (define (som n)
      (if (= n 0) 0
         (+ n (som (- n 1)))))
    
    on voudra obtenir, par exemple :
    int som (int n) {
       if (n == 0)
          return 0;
       return n + som (n - 1);
    }
    
    Pour les fonctions les plus simples, c'est assez facile, pour puissance ou les récursivités terminales, votre programme doit être bien conçu.

    Le problème se complique lorsque deux fonctions sont liées (exemple des fonctions chapeau liées aux récursivités terminales).

  30. Grilles de nombres. (**)

    Soit une grille de nombres croisés de taille nxn, exemple (en 3x3) :

        a b c
      ---------
    1 |       |
    2 |     * |
    3 |       |
      ---------
    
    1) suite de chiffres consécutifs
    2) nombre premier
    3) carré
    a) carré et palindrome
    b) le produit des chiffres est 12
    *) case noire

    Écrire un programme qui résout ce genre de problèmes.
    Dans un premier temps on limitera le nombre de définitions (carré, palindrome) et la taille de la grille.
    Dans un second temps on ajoutera des styles de définitions ("le carré de la somme des chiffres est un palindrome") et la taille de la grille sera étendue (5x5 puis 6x6).

  31. Correction automatique d'erreurs. (***)

    Vous utilisez un compilateur qui vous indique des erreurs. Il faut donc les corriger vous-mêmes. Ne serait-il pas plus agréable de lancer votre propre application, qui utilise le compilateur, détecte les erreurs et corrige les plus simples ? Voilà le projet que vous devez faire.

  32. Mahjong solitaire. (*)

    Le principe de ce solitaire est que des cartes sont posées en tas. Il faut retirer les cartes par paires identiques.
    Votre programme doit chercher une solution, avec retour arrière (backtracking), mais sans mémorisation de la disposition.

  33. Interprête LOGO. (**)

    Le langage Logo est un bon et simple langage d'apprentissage de la programmation. la programmation graphique, à l'aide de la "tortue logo" y est particulièrement aisée.
    Mettre en place un interprête LOGO grâce auquel on pourra programmer des fonctions, qui peuvent être récursives, des déplacements de tortue et donc faire faire des images.

Mis à jour le 26/11/2019 (mise à jour des projets libres)