liste.c

#include <stdlib.h>
#include <stdio.h>

/************************** Question 1 *****************************/
typedef struct s_maillon *p_maillon_t;
typedef p_maillon_t       liste_t;
typedef liste_t          *p_liste_t;

/************************** Question 2 *****************************/
/******* A la C ***********/
/*  typedef struct s_maillon */
/*  { */
/*    int valeur; */
/*    p_maillon_t suivant; */
/*  } maillon_t; */

/******* A la LISP ***********/
typedef struct s_maillon
{
  int valeur;
  liste_t suivant;
} maillon_t;

/*  typedef struct s_maillon */
/*  { */
/*    int valeur; */
/*    liste_t suivant; */
/*  } maillon_t; */

/************************** Question 3 *****************************/
/******* Liste vide ***********/
liste_t nil()
{
  return NULL;
}

/******* Constructeur ***********/
liste_t cons(int val, liste_t liste)
{
  liste_t tete = malloc(sizeof(maillon_t));

  tete->valeur = val;
  tete->suivant = liste;
  return tete;
}

/************************** Question 4 *****************************/
/******* fonction car ou head ***********/
int car(liste_t liste)
{
  if(liste == nil()) {
    printf("Le car d'une liste vide, c'est pas terrible !!\n");
    exit(1);
  }
  return liste->valeur;
}

/******* fonction cdr ou tail ***********/
liste_t cdr(liste_t liste)
{
  if(liste == nil()) {
    printf("Le cdr d'une liste vide... disons vide par convention !\n");
    return(nil());
  }
  return liste->suivant;
}

/******* copie d'une liste *************/
liste_t copie(liste_t liste)
{
  if(liste==(nil())) {
    return (nil());
  } else {
    return (cons(car(liste),copie(cdr(liste))));
  }
}

/************************** Question 5 *****************************/
/******* concatenation ***********/
/* concat([a_1, a_2, ... , a_n],[b_1, b_2, ... , b_p]) ->
       [a_1, a_2, ... , a_n, b_1, b_2, ... , b_p]       */

/*** Version itérative paresseuse ***/
/*** on crée juste un lien entre le dernier élément de fst et
     le premier élément de snd ***/
liste_t iter_lazy_concat(liste_t fst, liste_t snd)
{
  liste_t current=fst;
   
  if(fst==NULL) {
    return snd;
  } else {
    while(current->suivant!=NULL) current=current->suivant;
    current->suivant=snd;
    return fst;
  }
}

/*** Version récursive paresseuse ***/
/*** on peut mieux faire ... c'est bizarrement écrit ***/
liste_t recur_lazy_concat(liste_t fst, liste_t snd)
{
  liste_t current;
  
  if(fst==NULL) {
    return snd;
  } else {
    current=recur_lazy_concat(fst->suivant, snd);
    fst->suivant=current;
    return fst;
  }
}

/* Cette fonction modifiant la liste initiale et partageant des données
   avec la seconde, il peut être plus prudent d'utiliser 
   concat(copie(fst), copie(snd)) */

/*** Version récursive vraiment plus safe ... ***/
liste_t concat(liste_t fst, liste_t snd)
{
  if(fst==NULL) {
    return copie(snd);
  } else {
    return cons(car(fst),concat(cdr(fst),snd));
  }
}

/******* reverse  ***********/
/* reverse([a_1, a_2, ... , a_n]) ->
       [a_n, ... , a_2, a_1]                  */

/* mais ici on retourne litéralement la première liste...
   elle est modifiée... */
/*** Version itérative ***/
liste_t iter_reverse(liste_t liste)
{
  liste_t current=liste, next, renversee=nil();
  
  if(liste!=NULL) {
    while(current->suivant!=NULL) {
      next=current->suivant;
      current->suivant=renversee;
      renversee=current;
      current=next;
    }
    current->suivant=renversee;
    renversee=current;
  }
  return renversee;
}

/* si on ne veut pas la modifier, il vaut mieux faire comme ça... */
/*** Version récursive lente ***/
liste_t slow_reverse(liste_t liste)
{
  if(liste!=NULL) {
    int val = car(liste);
    liste_t queue = cdr(liste);

    return concat(slow_reverse(queue),cons(val,nil()));
  } else return nil();
}

/*** ou mieux !!! ***/
/*** Version récursive plus rapide ***/
liste_t aux_reverse(liste_t liste, liste_t renversee)
{
  if(liste==NULL) return renversee;
  else return(aux_reverse(cdr(liste),cons(car(liste),renversee)));
}

liste_t reverse(liste_t liste)
{
  return aux_reverse(liste,nil());
}

/************************** Question 6 *****************************/
/******* fonction map ***********/
/* concat(f,[a_1, a_2, ... , a_n]) ->   
   f(a_1); f(a_2); ... ; f(a_n);
 */
/*** Version itérative ***/
void iter_map(void f(int), liste_t liste)
{
  liste_t current=liste;
  if(current) {
    while(current->suivant!=NULL) {
      f(current->valeur);
      current=current->suivant;
    }
    f(current->valeur);
  }
}

/*** Version récursive ***/
void map(void f(int), liste_t liste)
{
  if(liste) {
    f(liste->valeur);
    map(f, liste->suivant);
  }
}

/******* fonction apply ***********/
/* concat(f,[a_1, a_2, ... , a_n]) ->   
   [f(a_1), f(a_2), ... , f(a_n)]
 */
/*** Version itérative ***/
liste_t iter_apply(int f(int), liste_t liste)
{
  liste_t prev,current;
  liste_t new_prev,new_current,new_liste;
  if(liste) {
    current=liste;
    new_current=new_liste=cons(f(current->valeur),nil());
    while(current->suivant!=NULL) {
      prev=current;
      new_prev=new_current;
      current=current->suivant;
      new_current=cons(f(current->valeur),nil());
      new_prev->suivant=new_current;
    }
  } else {
    new_liste = nil();
  }
  return new_liste;
}

/*** Version récursive ***/
liste_t apply(int f(int), liste_t liste)
{
  if(liste) {
    return(cons(f(car(liste)), apply(f,cdr(liste))));
  } else return nil();
}

/******* fonction reduce ***********/
/* reduce(op,e,[a_1, a_2, ... , a_n]) ->   
   ((...((e op a_1) op a_2) op ... ) op a_n)
 */
/*** Version itérative ***/
int iter_reduce(int op(int,int), int init,liste_t liste)
{
  liste_t current=liste;
  int accu=init;
  if(current) {
    while(current->suivant!=NULL) {
      accu=op(accu,current->valeur);
      current=current->suivant;
    }
    accu=op(accu,current->valeur);
  }
  return accu;
}

/*** Version récursive ***/
int reduce(int op(int,int), int init,liste_t liste)
{
  if(liste) {
    return(reduce(op, op(init,car(liste)), cdr(liste)));
  } else return init;
}

void print_int(int valeur)
{
  printf("%d\n",valeur);
}

void print_separateur()
{
  printf("****\n");
}

int carre(int valeur)
{
  return(valeur*valeur);
}

int plus(int x, int y)
{
  return(x+y);
}

int main()
{
  liste_t first = cons(1, cons(2, cons(3, nil())));
  liste_t second= cons(4, cons(5, nil()));
  liste_t concatenee = nil();
  liste_t first_carre = apply(carre, first);
  liste_t second_carre = apply(carre, second);
  liste_t concatenee_carre = apply(carre, concatenee);

  map(print_int, first);print_separateur();
  map(print_int, second);print_separateur();
  map(print_int, concatenee);print_separateur();
  map(print_int, first_carre);print_separateur();
  map(print_int, second_carre);print_separateur();
  map(print_int, concatenee_carre);print_separateur();
  concatenee = concat (first,second);

  map(print_int, first);print_separateur();
  map(print_int, second);print_separateur();
  map(print_int, concatenee);print_separateur();
  map(print_int, first_carre);print_separateur();
  map(print_int, second_carre);print_separateur();
  map(print_int, concatenee_carre);print_separateur();
  concatenee_carre = apply(carre, concatenee);
  map(print_int, concatenee_carre);print_separateur();
  print_int(reduce(plus, 0, concatenee_carre));print_separateur();
  map(print_int, reverse(cons(1,cons(2,cons(3,nil())))));print_separateur();
  map(print_int, reverse(cons(2,cons(3,nil()))));print_separateur();
  map(print_int, reverse(cons(2,nil())));print_separateur();
  map(print_int, reverse(nil()));print_separateur();
  return 0;
}


Generated by GNU enscript 1.6.2.