Jean-Jacques Lévy

16 décembre 1998






Ensembles et relations en Java

Question 1
On représente une partie par la liste de ses éléments.
class Partie {

  int    elt;
  Partie suivant;

  Partie (int n, Partie x) {elt = n; suivant = x; }

  static boolean estEnOrdre (Partie x) {
    return x == null || x.suivant == null ||
          (x.elt <= x.suivant.elt &&
           estEnOrdre (x.suivant));
  }
Question 2
Les deux fonctions suivantes calculent en temps O(1 + Card X + Card Y).

  static Partie union (Partie x, Partie y) {    
    if (x == null)
        return y;
    if (y == null)
        return x;
    if (x.elt < y.elt)
        return new Partie (x.elt, union (x.suivant, y));
    if (x.elt > y.elt)
        return new Partie (y.elt, union (x, y.suivant));
    else
        return new Partie (x.elt, union (x.suivant, y.suivant));
  }
    
  static Partie inter (Partie x, Partie y) {
    if (x == null || y == null)
        return null;
    if (x.elt == y.elt)
        return new Partie (x.elt, inter (x.suivant, y.suivant));
    else
    if (x.elt < y.elt)
        return inter (x.suivant, y);
    else
        return inter (x, y.suivant);
  }
Question 3
On doit trouver les listes Rj-1 = { i | (i, j) Î R } pour 0 £ j < n. Il faut commencer par les i grands pour avoir les listes Rj-1 en ordre croissant. On parcourt donc tout le tableau s et tous les éléments de R. Donc le temps est en O(1 + n + Card R), qui est dans le pire cas en O(n2).

  final static int N = 100;  // taille max de E

  static Partie[] reverse (Partie[] r) {
    Partie[] s = new Partie [N];
    for (int i = s.length - 1; i >= 0; --i)
        for (Partie p = r[i]; p != null; p = p.suivant)
            s[p.elt] = new Partie (i, s[p.elt]);
     return s;
  }
Question 4
Soit T=RS. On doit trouver les listes Ti = { k | (i, j)Î R, (j, k)Î S } pour 0 £ i < n. Donc Ti = È { Sj | (i, j)Î R } où Sj = { k | (j, k)Î S }. On parcourt tout le tableau R et pour chaque paire dans R, on fait une union entre deux classes de longueur n dans le pire cas. Le tout est donc en O(n3).

  static Partie[] comp (Partie[] r, Partie[] s) {
    Partie[] t = new Partie [r.length];
    for (int i = 0; i < r.length; ++i) {
        t[i] = null;
        for (Partie p = r[i]; p != null; p = p.suivant)
            t[i] = union (t[i], s[p.elt]);
    }
    return t;
  }
}

Ensembles et relations en Ocaml

let rec est_en_ordre x = match x with
          [] -> true
        | [v] -> true
        | v1 :: (v2 :: x2  as x1) -> (v1 <= v2) && est_en_ordre x1;;

let rec union x y =  match x, y with
    [], y -> y
  | x, [] -> x
  | v::x1, w::y1 -> 
      if v < w then
        v:: union x1 y
      else if v > w then
        w :: union x y1
      else
        v :: union x1 y1 ;;
    
let rec inter x y = match x, y with
    [], y -> []
  | x, [] -> []
  | v::x1, w::y1 -> 
      if v < w then
        inter x1 y
      else if v > w then
        inter x y1
      else
        v :: inter x1 y1 ;;

let reverse r = 
  let s = Array.make n [] in
  for i = Array.length r - 1 downto 0 do
    List.iter 
      (function j -> s.(j) <- i :: s.(j) )
      r.(i);
    done;
  s;;

let comp r s = 
  let t = Array.make (Array.length r) [] in
  for i = 0 to Array.length r - 1 do
    List.iter 
        (function k -> t.(i) <- union t.(i) s.(k) )
        r.(i);
  done;
  t;;

Fonctions récursives primitives

Question 5
x× y est en O(xy), x! en O(x!), x-1 en O(x), x-y en O(x), ë x/2 û en O(x).

// multiplication x y
  z = 0;
  for x do
    for y do
      z = z+1;

//  predecesseur x
   z = 0;
   for x do { 
     t = z;
     t = t + 1;
     if (t < x) 
       z = z+1;
     else
       z = z;
   }

// moins x y
  z = 0;
  for x do 
    if (x > y) {
      z = z + 1;
      y = y + 1;
    } else
      z = z;

// div2 x
  z = 0;
  y = 1;
  for x do {
    if (y < x)  
      z = z+1;
    else
      z = z;
    y = y+1; y = y+1;
  }

// fact x 
  z = 0;
  n = 0;
  z = z+1;
  n = n+1;
  for x do {
    // z = mult z n
    z' = 0;
    for z do
      for n do
        z' = z' + 1;
    z = z';
    n = n+1;
  }
Question 6
L'instruction for termine toujours. Donc il en est de même pour tout programme Stupa. Mais en Borobudur, le programme suivant boucle.
x = 0;
y = x + 1;
while (x < y)
  x = x;
Question 7
Par exemple, f(0) = 0, f (x+1) = f(x+1). Un autre exemple est la définition récursive classique de fibonacci, ou d'Ackermann.

Question 8
Les cas 1-4 sont triviaux. Pour le cas 5, supposons que par récurrence, on ait trouvé les programmes Stupa représentant h et g. Alors le programme pour f est:

y1 = x1; y2 = x2; ... yn = xn;
h;
x1 = 0;
for y1 do {
  y1 = x1;
  x2 = y2; ... xn = yn;
  xn+1 = x0;
  g;
  x1 = y1 + 1;
}

This document was translated from LATEX by HEVEA.