Alogbox, c'est sympa, c'est convivial, c'est en français. Mais ça manque un peu de souplesse. Alors je me suis dit que j'allais tâcher de faire un pont entre notre cours de Java et notre cours d'algo.

L'oral d'algorithmique, c'est une heure de préparation (30 minutes sur papier + 30 minutes devant l'ordinateur) suivie de 20 minutes de présentation, où on doit élaborer un court programme en réponse à un problème concret, de nature plutôt mathématique.

Du coup, c'est notre professeur de maths qui nous dispense cet enseignement. Il n'est pas programmeur à la base, alors il utilise avec nous un logiciel pédagogique plutôt conçu pour les lycéens : Algobox. C'est une GUI où on structure nos boucles au travers d'une série de dialogues, et qui se charge de générer le code en arrière-plan. Vous pouvez le voir en action ici..

Algobox : sympa mais vite limitant

A l'usage, la courbe d'apprentissage est rapide, mais on plafonne assez vite. Dès qu'on veut s'abstraire d'un déroulement purement séquentiel, en définissant des fonctions, ou qu'on veut réorganiser son code, parce qu'on a fait fausse route, il faut quitter le mode graphique. On se retrouve alors face à un pseudo-langage qu'il faudrait se donner la peine d'apprendre, alors qu'à ma connaissance on n'aura aucune occasion de s'en resservir ailleurs.

(Le prof de maths est parfaitement conscient de ces bémols, et est en train d'organiser sa migration vers Python.)

Toutefois, il paraît que le jury nous laisse libre d'utiliser l'environnement de notre choix. Moi, c'est avec Java que je suis le plus à l'aise. Alors à notre dernier cours d'algo, j'ai délaissé Algobox, et j'ai ouvert Eclipse.

Verdict : pour moi, c'est beaucoup plus rapide. Je procèderai comme ça le jour de l'examen. Ci-dessous le problème que nous avais soumis notre prof, et ma solution.

Enoncé
Un nombre N > 1 est dit parfait s'il est égal à la somme de tous ses diviseurs autres que lui-même. Par exemple :
• Le nombre 6 est parfait car ses diviseurs sont 1, 2, 3 et 6 et on a 1 + 2 + 3 =6.
• Le nombre 10 n'est pas parfait car ses diviseurs sont 1, 2, 5 et 10 et 1 + 2 + 5 = 8 != 10.
• Le nombre 28 est parfait car ses diviseurs sont 1, 2, 4, 7, 14 et 28 et 1 + 2 + 4 + 7 + 14 = 28.
Questions
1. Ecire et implanter un algorithme qui teste si un nombre N est parfait (on renvoie le message VRAI) ou non (on renvoie le message FAUX).
2. Ecrire et implanter un algorithme qui renvoie la somme des inverses des diviseurs d'un nombre entier N non-nul.
3. Ecrire et implanter un algorithme déterminant le seul nombre parfait de trois chiffres puis la somme des inverses des diviseurs de ce nombre.

package parfait;

import java.util.ArrayList;
import java.util.Scanner;

public class Parfait {

    public static boolean testParfait(int entierN) {
        ArrayList<Integer> diviseurs = getDiviseurs(entierN);
        int sommeDiviseurs = sommeEntiers(diviseurs);
        if (sommeDiviseurs - entierN == entierN) {
            return true;
        }
        return false;
    }

    public static ArrayList<Integer> getDiviseurs(int entierN) {
        ArrayList<Integer> diviseurs = new ArrayList<>();
        for (int k = 1; k <= entierN; k++) {
            if (entierN % k == 0) {
                diviseurs.add(k);
            }
        }
        return diviseurs;
    }

    public static ArrayList<Double> getInverses(ArrayList<Integer> entiers) {
        ArrayList<Double> inverses = new ArrayList<>();
        for (int entier : entiers) {
            inverses.add(1.0d / entier);
        }
        return inverses;
    }

    public static int sommeEntiers(ArrayList<Integer> entiers) {
        int somme = 0;
        for (int i = 0; i < entiers.size(); i++) {
            somme += entiers.get(i);
        }
        return somme;
    }

    public static Double sommeDoubles(ArrayList<Double> doubles) {
        Double somme = 0.0d;
        for (int i = 0; i < doubles.size(); i++) {
            somme += doubles.get(i);
        }
        return somme;
    }

    public static void printEntiers(ArrayList<Integer> entiers) {
        int i = 0;
        for (; i < (entiers.size() - 1); i++) {
            System.out.print(entiers.get(i) + ", ");
        }
        System.out.println(entiers.get(i));
    }

    public static void printDoubles(ArrayList<Double> doubles) {
        int i = 0;
        for (; i < (doubles.size() - 1); i++) {
            System.out.print(doubles.get(i) + ", ");
        }
        System.out.println(doubles.get(i));
    }

    public static void main(String[] args) {

        // Acquisition de l'entier n
        Scanner sc = new Scanner(System.in);
        System.out.print("Entrez la valeur de l'entier n > 2 : ");
        int entierN = sc.nextInt();

        // Affichage des diviseurs
        System.out.print("Liste des diviseurs de n : ");
        ArrayList<Integer> diviseurs = Parfait.getDiviseurs(entierN);
        Parfait.printEntiers(diviseurs);

        // Test : parfait ou non ?
        boolean reponse = Parfait.testParfait(entierN);
        if (reponse == true) {
            System.out.println("VRAI (le nombre " + entierN + " est parfait)");
        } else {
            System.out.println("FAUX (le nombre " + entierN + " n'est pas parfait)");
        }

        // Recherche d'un parfait
        System.out.println("## Recherche d'un nombre parfait dans un intervalle...");
        System.out.print("Entrez la valeur de la borne inférieure : ");
        int borneBasse = sc.nextInt();
        System.out.print("Entrez la valeur de la borne haute : ");
        int borneHaute = sc.nextInt();

        ArrayList<Integer> parfaits = new ArrayList<>();
        for (int i = borneBasse; i <= borneHaute; i++) {
            if (Parfait.testParfait(i)) {
                parfaits.add(i);
            }
        }

        // Affichage des résultats
        if (parfaits.isEmpty()) {
            System.out.println("Désolé, cet intervalle ne contient aucun nombre parfait.");
        } else {
            System.out.print("Liste des nombres parfaits : ");
            Parfait.printEntiers(parfaits);
        }

        // Somme des inverses des diviseurs de chacun des parfaits
        System.out.println("## Somme des inverses des diviseurs pour chacun des parfaits trouvés...");
        if (!parfaits.isEmpty()) {
            for (Integer parfait : parfaits) {
                ArrayList<Integer> diviseursBis = Parfait.getDiviseurs(parfait);
                ArrayList<Double> inverses = Parfait.getInverses(diviseursBis);
                System.out.print(parfait + " --> ");
                Parfait.printDoubles(inverses);
                System.out.println("Somme des inverses de " + parfait + " : " + Parfait.sommeDoubles(inverses));
            }
        }

        sc.close();
    }
}

La vraie raison de post, c'est que je voulais tester la fonctionnalité de coloration syntaxique de mon site. Comme c'est beau !

Article suivant Article précédent