Outil pour la nouvelle notation algorithmique

D’Algobox à Python et au pseudocode, une transition en douceur
dimanche 1er octobre 2017
par  Alain BUSSER

Ci-dessous il y a deux outils :

  • le premier permet de produire du pseudocode similaire à celui du bac 2018, à partir d’un script Python (langage). Il est toujours possible, après cela, de modifier le pseudocode, avant de le copier-coller vers un traitement de texte ;
  • le second outil fait quelque chose de similaire, mais à partir d’« algorithmes » comme ceux du bac 2017, voire de scripts algobox.

Pour les opérations inverses, voir plurialgo pour engendrer de l’algobox, et SofusPy pour passer de l’algorithme en langage naturel, vers le script Python « auto-engendré » .

Voici les outils pour les étudier :

Voici les outils de conversion :

Utilitaires de conversion

Depuis Python

Coller ci-dessous le script Python, puis cliquer ci-dessous... et corriger ci-dessous
Ensuite copier le texte ci-dessus et le coller dans le traitement de texte

Depuis Algobox

Coller ci-dessous l'algobox, puis cliquer ci-dessous ... et corriger le résultat ci-dessous

Scripts

Pour tester l’outil, voici quelques scripts Python, donnés en exemples, dans les onglets suivants :

pgcd

Pour calculer les diviseurs d’un entier :

  1. def diviseurs(unEntier):
  2.         S = set([])
  3.         for d in range(1,unEntier+1):
  4.                 if unEntier%d == 0:
  5.                         S.add(d)
  6.         return S

Télécharger

Maintenant, les diviseurs communs à deux entiers :

  1. def divComm(a,b):
  2.         dA = diviseurs(a)
  3.         dB = diviseurs(b)
  4.         return dA.intersection(dB)

Télécharger

Enfin, le pgcd de deux entiers est le plus grand élément de cet ensemble :

  1. def pgcd(a,b):
  2.         return max(divComm(a,b))

Télécharger

Bien entendu on peut aussi calculer un pgcd par l’algorithme d’Euclide :

  1. def euclide(a,b):
  2.     while b!=0:
  3.         a,b = b,a%b
  4.     return a

Télécharger

Collatz

Version classique, avec des affectations :

  1. u = 65
  2. while u >= 2:
  3.         if u%2==0:
  4.                 u=u/2
  5.         else:
  6.                 u=3*u+1
  7.         print(u)

Télécharger

Et la version Sofus :

  1. u = 65
  2. while u >= 2:
  3.         if u%2==0:
  4.                 u /= 2
  5.         else:
  6.                 u *= 3
  7.                 u += 1
  8.         print(u)

Télécharger

Suites

Extrait du sujet STI2D Polynésie 2017 :

Dans un parc régional, on étudie une espèce de renards. Cette population était de 1 240 renards à la fin de l’année 2016.
On modélise par un le nombre de renards dans le parc régional à la fin de l’année 2016+ n. On a donc u0 = 1240.
On estime à 15 % par an la baisse du nombre un.
On suppose que cette évolution restera identique pour les années à venir.

Déterminer une estimation du nombre de renards présents dans le parc régional à la fin de l’année 2020.

  1. u = 1240
  2. for n in range(5):
  3.         print(n,u)
  4.         u = u-0.15*u

Télécharger

Déterminer la limite de la suite (un). Comment interpréter ce résultat ?

Tout d’abord on vérifie la formule explicite de la suite géométrique :

  1. u = 1240
  2. for n in range(5):
  3.         print(n,1240*0.85**n)

Télécharger

Puis on va, comme dirait Buzz, « vers l’infini et au-delà » :

  1. u = 1240
  2. for n in [0,1,4,10,100,float('inf')]:
  3.         print(n,1240*0.85**n)

Télécharger

Des scientifiques considèrent que l’espèce des renards présents dans le parc sera en situation d’extinction à partir du moment où le nombre de renards deviendra strictement inférieur à 100.
À partir de quelle année l’espèce de renards présents dans le parc sera-t-elle en situation d’extinction ?

  1. u = 1240
  2. n = 0
  3. while u >= 100:
  4.         n = n+1
  5.         u = u-0.15*u
  6.  
  7. print(n)

Télécharger

Afin de préserver l’espèce, on décide d’introduire à chaque année 30 renards à partir de la fin de l’année 2017.
On note vn le nombre de renards présents dans le parc à la fin de l’année 2016+n.
On estime à 15 % par an la baisse du nombre vn.
On a v0 = 1240.

  1. v = 1240
  2. n = 0
  3. for n in range(100):
  4.         print(v)
  5.         v = v-0.15*v + 30

Télécharger

Équations

Dans le cas général on peut résoudre une équation du type f(x)=0 (« chercher un zéro de f ») par dichotomie :

  1. def f(x):
  2.     return x**2-5
  3.  
  4. def zero(f,a,b):
  5.     if f(a)*f(b)>0:
  6.         return None
  7.     while(abs(a-b)>1e-14):
  8.         m=(a+b)/2.
  9.         if f(m)*f(a)>0:
  10.             a=m
  11.         else:
  12.             b=m
  13.     return m
  14.    
  15. print(zero(f,0,6))

Télécharger

Pour résoudre l’équation ax²+bx+c=0, on peut faire ainsi :

  1. from math import *
  2. def solutions(a,b,c):
  3.         S = set([])
  4.         Delta = b**2-4*a*c
  5.         if Delta >= 0:
  6.                 r = sqrt(Delta)
  7.                 x1 = (-b-r)/(2*a)
  8.                 x2 = (-b+r)/(2*a)
  9.                 S.add(x1)
  10.                 S.add(x2)
  11.         return S

Télécharger

Hasard

Pour lancer un dé 600 fois puis voir la répartition de chaque face obtenue, on peut utiliser ce script :

  1. from random import *
  2.  
  3. liste = []
  4. for indice in range(600):
  5.         result = randint(1,6)
  6.         liste.append(result)
  7.  
  8. for face in range(1,7):
  9.         print(face,liste.count(face))

Télécharger

Pour choisir un nombre premier au hasard, on peut faire

  1. from random import *
  2.  
  3. print(choice([2,3,5,7,11]))

Télécharger

Pour simuler une variable aléatoire binomiale de paramètres 8 et 0,4 on peut passer par une approximation hypergéométrique, basée sur un tirage sans remise (comme 8 est petit par rapport à la taille 100 de l’urne, ça revient presque au même). On commence donc par remplir une urne, avec 40 boules rouges et 60 boules bleues, puis on y effectue des tirages de 8 boules, et à chaque fois, on compte le nombre de boules rouges :

  1. from random import *
  2.  
  3. urne = ['rouge']*40+['bleu']*60
  4.  
  5. liste = []
  6. for tirage in range(1000):
  7.         echantillon = sample(urne,8)
  8.         rouges = echantillon.count('rouge')
  9.         liste.append(rouges)
  10.  
  11. for nsucces in range(9):
  12.         print(nsucces,liste.count(nsucces))

Télécharger

Pour simuler une variable aléatoire exponentielle de paramètre 0,5 on fait

  1. from random import *
  2.  
  3. print(expovariate(0.5))

Télécharger

Et pour simuler une variable aléatoire normale de paramètres 25 et 3,5 on fait

  1. from random import *
  2.  
  3. print(gauss(25,3.5))

Télécharger

Tortue

Pour dessiner un coquillage à motif hexagonal :

  1. from turtle import *
  2.  
  3. def hexagone(cote):
  4.         for etape in range(6):
  5.                 forward(cote)
  6.                 left(60)
  7. for longueur in range(20):
  8.         hexagone(10*longueur)
  9.         left(18)

Télécharger

La recette du mouvement brownien est assez simple :

  1. from turtle import *
  2. from random import *
  3. speed(0)
  4. for pas in range(100):
  5.         left(uniform(0,360))
  6.         forward(5)

Télécharger

Utilitaire

D’autres utilitaires sont présentés ici :

Le script suivant affiche dans la console, l’état des variables, à chaque fois qu’on invoque la fonction voir() :

  1. def voir():
  2.     v = {k:v for k,v in globals().iteritems() if k[:2]!="__" and k!="voir"}
  3.     print(v)
  4.  

Télécharger

On peut l’utiliser par exemple de cette manière :

  1. S = 0
  2. for n in range(8):
  3.     S = S+n
  4.     voir()

Télécharger

Certes on pouvait avoir le même effet avec

  1. S = 0
  2. for n in range(8):
  3.     S = S+n
  4.     print(n,S)

Télécharger

et les variables sont automatiquement affichées dans l’onglet variables de Spyder. Mais cette variante dessine vraiment les boîtes avec les étiquettes collées dessus :

  1. #! /usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. from graphviz import Digraph
  4.  
  5. def voir(nom="boite1",afficher=True):
  6.         g = Digraph(format='png')
  7.         v = {k:v for k,v in globals().iteritems() if k[:2]!="__" and k!="voir" and k!="Digraph"}
  8.         for k in v:
  9.                 g.node(k,k,shape="note",style="filled",fillcolor="lightyellow")
  10.                 g.node(str(v[k]),str(v[k]),shape='box3d',style="filled",fillcolor="orange")
  11.                 g.edge(k,str(v[k]))
  12.         g.render(nom,view=afficher)

Télécharger

Ce script engendre des dessins :

  1. S = 0
  2. for n in range(8):
  3.         S = S+n
  4.         voir("somme"+str(n),False)

Télécharger

Les dessins portent les noms somme0, somme1 etc et peuvent ensuite être assemblés pour faire un dessin animé.

Que faire du résultat ?

Le plus simple est de copier-coller le pseudocode ainsi obtenu, vers un traitement de texte. Par exemple avec Libre Office Writer, on peut

  • coller le script dans le sujet qu’on est en train de rédiger ;
  • le sélectionner à la souris ;
  • choisir pour la sélection la police Courier new qui évoque une vieille imprimante ou un écran d’ordinateur ;
  • insérer un cadre, lui donner un bord et pourquoi pas une couleur de fond.

Avec LaTeX les choses sont un peu plus compliquées : Il faut demander à LaTeX de remplacer les « ← » par des « \leftarrow » et désactiver les fonctions de mise en forme de LaTeX (ne serait-ce que pour garder l’indentation). Sur ce dernier point, c’est l’environnement verbatim qui est salvateur. Pour le premier point je rajoute dans le préambule du document les deux lignes suivantes :

  1. \usepackage{newunicodechar}
  2. \newunicodechar{}{$\leftarrow$}

Télécharger

Pour que ça marche il faut aussi choisir l’option « utf8 » pour la paquet inputenc et rédiger le document LaTeX en utf-8.

Pour faire joli je mets le code dans du verbatim qui est dans un cadre framed qui est dans une minipage de largeur 5cm.

Finalement voici le préambule qui convient :

  1. \usepackage[utf8]{inputenc}
  2. \usepackage{amsmath}
  3. \usepackage{amssymb}
  4. \usepackage{framed}
  5.  
  6. \usepackage{newunicodechar}
  7. \newunicodechar{}{$\leftarrow$}

Télécharger

Et pour le script :

  1. \begin{center}
  2. \begin{minipage}{5cm}
  3. \begin{framed}
  4. \begin{verbatim}
  5. ... Coller ici le code ...
  6. \end{verbatim}
  7. \end{framed}
  8. \end{minipage}
  9. \end{center}

Télécharger

Des outils similaires existent aussi ailleurs :

  • passage de CoffeeScript au pseudocode avec alcoffeethmique [1]
  • passage de JavaScript au pseudocode dans le logiciel CaRMetal avec la fonction getZZ()
  • Ne pas oublier aussi Plurialgo dans lequel on colle un script du langage qu’on veut (dans « éditeur 1 ») puis, après choix d’un langage destination (menu en haut à droite), le bouton « reformuler » fabrique l’équivalent dans un autre langage. Le pseudocode est obtenu avec Larp comme langage de destination, mais on peut aussi envisager de passer automatiquement de Python à Algobox, ou vice-versa.

[1cet article contient des compte-rendus de TP utilisant cette fonctionnalité.


Commentaires