Correction 4:
Types avancés


Exercice 1: Manipulation d'un tableau (-, Niveau 0)

Cet exercice ne nécessite pas de corrigé.


Exercice 2: Quiz du MOOC (MOOC, Niveau 1)

Cet exercice ne nécessite pas de corrigé

Exercice 3: Norme Unicode (type char, Niveau 1)

Pour résoudre cet exercice, il suffit de savoir que le passage d'un char à son codage Unicode (et vice-versa) se fait par une opération de conversion (transtypage) explicite.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Codes {

    public static void main(String[] args) {
        char[] chars = {'*', '9', 'W'};
        for (int i = 0; i < chars.length; i++) {
            System.out.println("Unicode de " + chars [i]
                        + " : " + (int) chars [i]);
        }

        int [] codes = {34, 65, 123};
        for (int i = 0; i < codes.length; i++) {
            System.out.println("Caractere correspondant a l'Unicode " 
                        + codes [i] + " : " 
                        + (char) codes [i]);
        }
    }
}

Affichage du programme:
Unicode de * : 42
Unicode de 9 : 57
Unicode de W : 87
Caractère correspondant à l'Unicode 34 : "
Caractère correspondant à l'Unicode 65 : A
Caractère correspondant à l'Unicode 123 : {

Exercice 4: Conversion majuscules/minuscules (type char, Niveau 1)

Deux versions du programme vous sont données. La première, plutôt brute, exige de connaître le codage Unicode des caractères, c'est-à-dire de savoir exactement où sont situés les caractères alphabétiques dans cette norme). La seconde, beaucoup plus élégante, utilise simplement le fait que les caractères se suivent selon l'ordre alphabétique dans la norme et que les majuscules sont placées avant les minuscules.

Solution brute :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import java.util.Scanner;

class Conversion1 {

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        System.out.print("Entrez une seule lettre A..Z ou a..z : ");
        char c = scanner.next().charAt(0);
        if (((int) c > 122) || ((int) c < 65)
                    || (((int) c > 90) && ((int) c < 97))) {
            System.out.println("Caractere non valable");
        } else if ((int) c < 91) {
            System.out.println("Version minuscule : " + (char) (c + 32));
        } else {
            System.out.println("Version majuscule : " + (char) (c - 32));
        }
    }
}


"Jolie" solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;

class Conversion2 {

    private static Scanner scanner = new Scanner(System.in);

    public static void main (String[] args) {
        System.out.print("Entrez une seule lettre A..Z ou a..z : ");
        char c = scanner.next().charAt(0);

        if (( c <= 'z' ) && ( c >='a')) {
            c = (char) ((int)c + (int)'Z' - (int)'z');
            System.out.println("Version majuscule : " + c);
        } else if (( c <= 'Z' )&& ( c >= 'A')) {
            c=(char)((int)c - (int)'Z' + (int)'z');
            System.out.println("Version minuscule : " + c);
        } else {
            System.out.println("Caractere non valable");
        }
    }
}


Exercice 5: Produit scalaire (Tableaux, Niveau 1)

Les tableaux, ici à une dimension, sont typiquement parcourus au moyen de boucles for. Ces boucles sont utilisées pour remplir les vecteurs (par lecture de doubles) et pour effectuer le calcul du produit scalaire. La principale chose à remarquer ici est qu'avec les moyens à disposition au moment de la série, on ne sait pas réutiliser des portions de code lorsqu'elles sont requises à plusieurs endroits du programme (exemple: la lecture des vecteurs). Ceci implique que le code concerné est tout simplement dupliqué. Nous verrons à partir du cours prochain comment améliorer cet état des choses.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.Scanner;

class Scalaire {

    public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        
        int nMax = 10;
        int n = 0;

        // On exige l'introduction d'un entier entre 0 et 10
        while (n < 1 || n > nMax) {
            System.out.print("Quelle taille pour vos vecteurs [entre 1 et " 
                        + nMax + "] ? ");
            n = scanner.nextInt();
        }

        // Déclaration-construction des deux vecteurs
        double [] v1 = new double [n];
        double [] v2 = new double [n];

        System.out.println("Saisie du premier vecteur :");
        for (int i = 0; i < n; i++) {
            System.out.print(" v1[" + i + "] = ");
            v1[i] = scanner.nextDouble();
        }

        System.out.println("Saisie du second vecteur :");
        for (int i = 0; i < n; i++) {
            System.out.print(" v2[" + i + "] = ");
            v2[i] = scanner.nextDouble();
        }

        // Calcul du produit scalaire
        double somme = 0.0;
        for (int i = 0; i < v1.length; i++) {
            somme += v1[i] * v2[i];
        }

        System.out.println("Le produit scalaire de v1 par v2 vaut " + somme);

        scanner.close();
    }
}


Exercice 6: Triangle de Pascal (Tableaux, Niveau 2)

On a encore affaire à un tableau en deux dimensions, mais cette fois avec un nombre variable de colonnes sur chaque ligne. Ceci permet d'optimiser l'espace de stockage requis en tenant compte du fait que, pour un triangle de Pascal, certains éléments ne sont pas définis (exemple l'élément d'indices [0][2] n'existe pas). La matrice calculée a ici une forme triangulaire.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.Scanner;

class Pascal {

    public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        
        int size = 0;

        // On demande la taille
        System.out.println("Taille du triangle de Pascal : ");
        size = scanner.nextInt();

        // Ici on déclare le tableau, mais on ne construit que la première
        // dimension
        int[][] triangle = new int[size][];

        // On construit et initialise la 1ère ligne
        triangle[0] = new int[1];
        triangle[0][0] = 1;

        for (int row = 1; row < size; row++) {

            // Chaque ligne du triangle est un tableau à une dimension
            // dont la taille est celle de la ligne precedente + 1:
            // on construit ces lignes (new) au fur et à mesure que l'on
            // progresse dans le tableau
            triangle[row] = new int [triangle[row - 1].length + 1];

            // Remplissage du tableau:
            // les deux éléments aux deux extrémités des lignes valent 1.
            // Les autres sont liés par la relation:
            // triangle[row][j]= triangle[row-1][j-1] + triangle[row-1][j]

            for (int col = 0; col <= row; col++) {
                if ((col == 0) || (col == row)) {
                    triangle[row][col] = 1;
                } else {
                    triangle[row][col] = triangle[row - 1][col - 1]
                            + triangle[row - 1][col];
                }
            }
        }

        // Affichage du tableau
        for (int row = 0; row < size; row++) {
            for (int col = 0; col <= row; col++) {
                System.out.print(triangle[row][col] + " ");
            }
            System.out.println();
        }

        scanner.close();
    }
}


Exercice 7: Comment s'appelait Napoléon? (String, Niveau 1)

L'algorithme simple (qui présuppose que l'utilisateur introduit toujours correctement un prénom) est le suivant: on cherche l'indice du 1er caractère blanc ('') après le prénom concerné et du 1er caractère blanc suivant ce blanc (méthode indexOf). On extrait alors la chaîne située entre ces deux indices (méthode substring).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Scanner;

class NapoleonSimple {

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        String noms = "Napoleon Bonaparte Bill Gates Claudia Schiffer Martina Hingis ";
        System.out.print("Entrez le prenom de la personne a rechercher: ");
        String prenom = scanner.nextLine();

        int prenomStart = 0;
        prenomStart = noms.indexOf(prenom);

        if (prenomStart < 0) {
            System.out.println("Inconnu au bataillon!");
        } else {
            int nomStart = noms.indexOf(' ', prenomStart) + 1;
            int nomEnd = noms.indexOf(' ', nomStart);
            String nom = noms.substring(nomStart, nomEnd);
            System.out.println("Le nom complet est: " + prenom + " " + nom);
        }
    }
}

Critique : Cet algorithme a le mérite de la simplicité mais n'est pas très robuste. L'utilisateur peut très bien introduire par mégarde un nom au lieu d'un prénom. Ce qui produira alors un résultat fantaisiste. Le fichier fourni Napoleon.java vous détaille une solution améliorée, parant à ce problème.


Exercice 8: Palindrôme (String, Niveau 2)

Nous utilisons ici le fait que si une chaine s est un palindrôme, la relation suivante est vérifiée pour tout i: s[i] = s[longeur de s - i]. L'algorithme procède alors comme suit: on parcourt la chaine dans les deux sens en même temps: l'indice p1 sert à parcourir la chaine du début à la fin et l'indice p2 sert à parcourir la chaine de la fin au début. On compare à chaque étape la chaine à l'indice p1 et l'indice p2.
Si c'est le même caractère on progresse, sinon le mot n'est pas un palindrôme. On prend soin, en cours de parcours, de sauter les séparateurs. On s'arrête autrement quand p1 et p2 se rejoignent. Le mot est alors un palindrôme.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.util.Scanner;

class Palindrome {

    private static Scanner scanner = new Scanner(System.in);

    public static void main (String[] args) {
        System.out.print("Entrez un original ou une phrase : ");
        String original = scanner.nextLine();

        // On ne garde que les caractères alphabétiques
        String temp = "";
        for (int i = 0; i < original.length(); i++) {
            char c = original.charAt(i);
            if (Character.isLetter(c)) {
                temp += c;
            }
        }

        // On convertit en minuscules pour éviter
        // les problèmes de casse:
        String test = temp.toLowerCase();

        // On teste si mot2 est un palindrome
        int leftPos = 0;
        int rightPos = test.length() - 1;
        boolean palindrome=true;

        while ((leftPos < rightPos) && palindrome) {
            palindrome = test.charAt(leftPos) == test.charAt(rightPos);
            leftPos++;
            rightPos--;
        }

        if (palindrome) {
            System.out.println("C'est un palindrôme !");
        } else {
            System.out.println("Non, ce n'est pas un palindrôme.");
        }
    }
}


Exercice 9: Échauffement avec les tableaux dynamique (Tableaux dynamiques, Niveau 1)

A)

Le code fourni remplit le tableau tab (de taille 10) d'éléments allant de 0 à 9.

En effet, add ajoute un élément à la fin du tableau. Au moment de l'ajout tab.size() vaut la taille du tableau avant l'ajout (puisque l'élément n'est pas encore ajouté).

Vérification : Le code suivant :

for(Integer i : tab){
   System.out.println(i);
}

placé à la fin du programme, affichera :
0
1
2
3
4
5
6
7
8
9

B)

Ajoute à la fin de tab2 un tableau de même taille que tab1 et contenant que des éléments de même valeur : la valeur du premier élément de tab1 à savoir 99. L'affichage du contenu de tab2 selon le même procédé que précédemment donnerait l'affichage suivant :

99
99
99

Exercice 10: Nombres premiers (Tableaux dynamiques, Niveau 2)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.ArrayList;

class Premiers {
    public static void main(String[] args) {
        // un tableau dynamique d'entiers pour stocker les nombres premiers
        ArrayList<Integer> premiers = new ArrayList<Integer>();

        for (int n = 2; n <= 100; ++n) {
            // résultat du test de primalité
            boolean premier = true;
            int diviseur = 1;

            if (n % 2 == 0) {
                // le nombre est pair
                if (n != 2) {
                    premier  = false;
                    diviseur = 2;
                }
            } else {
                double borneMax = Math.sqrt(n);
                for (int i = 3; (premier) && (i <= borneMax); i += 2) {
                    if (n % i == 0) {
                        premier  = false;
                        diviseur = i;
                    }
                }
            } 
            if (premier) {
                premiers.add(n);
            }
        }

        System.out.println("Les nombres premiers compris entre 2 et 100 sont les suivants : ");
        for (Integer i : premiers) {
            System.out.println(i);
        }
    }
}


Exercice 11: Devoir du MOOC (MOOC, Niveau 2)

Cet exercice ne nécessite pas de corrigé

Exercice 12: Tutorial IntelliJ 6 : Modification du modèle de fichiers (IntelliJ, Niveau 0)

Cet exercice ne nécessite pas de corrigé

Exercice 13: Tutorial Eclipse 7 (inutile si vous travaillez avec IntelliJ) : Modification du modèle de fichiers (Eclipse, Niveau 0)

Cet exercice ne nécessite pas de corrigé

Dernière mise à jour: 13/10/2023  (Revision: 1.2)