Énumération brute

En Java, naïf

     class Ceb {
     
  private static StringBuffer r = new StringBuffer () ;
     
  private static Op [] ops = {new Add (), new Sub (), new Mul (), new Div ()} ;
     

   5 
  private static int dmax = 0 ;
     
  static void debug (int [] t, int nb) {
     
    System.err.print("[") ;
     
    for (int i=0 ; i < nb ; i++) {
     
      System.err.print("_" + t[i]) ;      
  10 
    }
     
    System.err.println("_]") ;
     
  }
     

     
  static boolean cb(int [] t, int nb, int total) {
  15 
    //    debug(t,nb) ;
     
    for (int i = 0 ; i < nb ; i++) {
     
      if (t[i] == total) {
     
        return true;
     
      }
  20 
      for (int j = i+1 ; j < nb ; j++)
     
        for (int k = 0 ; k < ops.length ; k++) {
     
          int res = ops[k].eval(t[i],t[j]) ;
     
          if (res != 0) {
     
            int savei = t[i], savej = t[j];
  25 
            t[i] = res ; t[j] = t[nb-1] ;
     
            if (cb(t, nb-1, total)) {
     
              r.append(Math.max(savei, savej) + "_" + ops[k].symbol() +
     
                       "_" + Math.min(savei,savej) + "_=_" + res + '\n') ;
     
              return true ;
  30 
            }
     
            t[i] = savei ; t[j] = savej ;
     
          }
     
        }
     
    }
  35 
    return false ;
     
  }
     

     
  public static void main (String [] arg) {
     
    int plaque [] = new int [arg.length-1] ;
  40 
    for (int i = 0 ; i < arg.length-1 ; i++)
     
      plaque[i] = Integer.parseInt(arg[i]) ;
     
    int total = Integer.parseInt(arg[arg.length-1]) ;
     

     
    if (cb(plaque, plaque.length, total)) {
  45 
      System.out.println("Le_compte_est_bon") ;
     
      System.out.print(r.toString()) ;
     
    } else {
     
      System.out.println("Le_compte_est_pas_bon") ;
     
    }
  50 
  }
     
}
     

En C, optimisé

     #include <stdlib.h>
     
#include <stdio.h>
     
#include <string.h>
     
#define PMAX 16
   5 

     
/* quelques macros pour les opérations  « à la compte est bon » */
     
#define SUB(a,b) ((a) > (b) ? (a)-(b) : (b)-(a))
     
#define MOD(a,b) ((a) > (b) ? (a)%(b) : (b)%(a))
     
#define DIV(a,b) ((a) > (b) ? (a)/(b) : (b)/(a))
  10 
#define MAX(a,b) ((a) > (b) ? (a) : (b))
     
#define MIN(a,b) ((a) < (b) ? (a) : (b))
     

     
/* type des entiers manipulés, non signé */
     
#ifndef LONG
  15 
typedef unsigned int num ;
     
#define NUMFORM "%u"
     
#else
     
typedef unsigned long num ;
     
#define NUMFORM "%lu"
  20 
#endif
     

     
/* Plaques et nombre effectif de plaques au départ */
     
num plaque[PMAX] ;
     
int pmax ;
  25 

     
/* type des noeuds de l'arbre qui représente les opérations */
     
typedef struct node {
     
  char tag ;
     
  union {
  30 
    num k ;
     
    struct {
     
      struct node *g, *d ;
     
    } n ;
     
  } arg ;
  35 
} node ;
     

     
/* tableau des arbres, parallèle au tableau des plaques */
     
node nodes[PMAX] ;
     

  40 
/* Macro pour affecter les noeuds */
     
#define SETNODE(p,t,fg,fd) (p)->tag = (t), (p)->arg.n.g = (fg), (p)->arg.n.d = (fd)
     

     
#define K '\0'
     

  45 
/* Pour copier un arbre vers l'espace de stockage définitif */
     
node *tcopy(node *to, node *p) {
     
  if (p->tag == K) {
     
    to->tag = K ;
     
    to->arg.k = p->arg.k ;
  50 
    return ++to ;
     
  } else {
     
    to->tag = p->tag ;
     
    to->arg.n.g = to+1 ;
     
    to->arg.n.d = tcopy(to+1,p->arg.n.g) ;
  55 
    return tcopy(to->arg.n.d,p->arg.n.d) ;
     
  }
     
      
     
}
     
/* Affichage des arbres */
  60 
void print(node *p) {
     
  if (p->tag == K)
     
    printf(NUMFORM, p->arg.k) ;
     
  else {
     
    printf("(") ;
  65 
    print(p->arg.n.g) ;
     
    printf("%c", p->tag) ;
     
    print(p->arg.n.d) ;
     
    printf(")") ;
     
  }
  70 
}
     

     
int opt=0; /* opt != 0 => chercher les solutions optimales */
     
/* Chercher les solutions entre BEG et END */
     
#define BEG 1
  75 
#define END 999
     
int found[END-BEG+1] ; /* nombres trouvés */
     
int depth[END-BEG+1] ; /* et leur profondeur */
     
node save[END-BEG+1][2*PMAX-1] ; /* espace de stockage des arbres solution */
     
int remains = END-BEG+1; /* compteur des nombres non encore trouvés */
  80 

     
/* Un nombre de l'intervale [BEG..END] a-t-il déja été trouvé */
     
int was_found(int i) {
     
  if (opt)
     
    return depth[i-BEG] > 0 ;
  85 
  else
     
    return found[i-BEG] ;
     
}
     

     
/*
  90 
 Traitement des résultats de l'énumération.
     
 *  s est le nombre.
     
 *  t est l'arbre des opérations qui y conduit
     
 *  indent est la profondeur de récursion
     
      (pmax-indent+1 majore le nombre de plaques utilisées,
  95 
      majoration atteinte au moins une fois.
     
 pall renvoie vrai quand il est inutile de poursuivre la recherche.
     
  Elle stocke l'arbre dans save[s-BEG] si c'est approprié.
     
*/
     

 100 
int pall(num s, node *t, int indent)
     
{
     
#ifdef DEBUG
     
  if (s == 0)
     
  {
 105 
    int k ;
     

     
    for (k = indent+1 ; k < pmax ; k++)
     
      printf("__") ;
     
    printf(NUMFORM ":_",s) ;
 110 
    print(t) ;
     
    putchar('\n') ;
     
  }
     
#endif
     
  if ((BEG <= s) && (s <= END)) {
 115 
    if (opt) {
     
      if (depth[s-BEG] < indent) {
     
        depth[s-BEG] = indent ;
     
        tcopy(&save[s-BEG][0],t) ;
     
      }
 120 
      return 0 ;
     
    } else {
     
      if (!found[s-BEG]) {
     
        found[s-BEG]=1 ;
     
        tcopy(&save[s-BEG][0],t) ;
 125 
        return --remains <= 0 ;
     
      } else
     
        return 0;
     
    }
     
  } else
 130 
    return 0 ;
     
}
     

     
/* Enumération
     
   * t est le tableau des plaques (à un instant donné).
 135 
   * nb est la dernière plaque valide.
     
   * nodes est le tableau des arbres, nodes[i] correspondant à t[i].
     

     
  all renvoie vrai lorsque poursuivre l'énumération est devenu inutile.
     
*/  
 140 
  
     

     
int all(num *t, num *nb, node *nodes) {
     
  num *i,*j ;
     
  node *in, *jn ;
 145 
  
     
  if (nb-t == 1) { /* cas terminal */
     
    num a=t[0], b=t[1] ;
     
    node *an = nodes, *bn = nodes+1 ;
     
    node w;
 150 

     
    SETNODE(&w,'+',an,bn) ;
     
    if (pall(a+b,&w,1))
     
      return 1;
     

 155 
    SETNODE(&w,'*',an,bn) ;
     
    if (pall(a*b,&w,1))
     
      return 1;
     
    
     
    if (a > b) {
 160 
      SETNODE(&w, '-', an, bn) ;
     
      if (pall(a-b,&w,1))
     
          return 1;
     
      if (a % b == 0) {
     
        SETNODE(&w, '/', an, bn) ;
 165 
        if (pall(a/b,&w,1))
     
          return 1;
     
      }
     
    } else if (a < b) {
     
      SETNODE(&w, '-', bn, an) ;
 170 
      if (pall(b-a,&w,1))
     
          return 1;
     
      if (b % a == 0) {
     
        SETNODE(&w, '/', bn, an) ;
     
        if (pall(b/a,&w,1))
 175 
          return 1;
     
      }
     
    } else {
     
      w.tag = K ;
     
      w.arg.k = 1 ;
 180 
      if (pall(1,&w,1))
     
          return 1;      
     
    }
     
    return 0;
     
  }
 185 

     
  /* Cas général */
     
  for (i=t, in=nodes ; i < nb ; i++, in++) {
     
    num a = *i ;
     
    node an = *in ;
 190 

     
    for (j = i+1, jn=in+1; j <= nb ; j++, jn++) {
     
      num b = *j ;
     
      node bn = *jn ;
     
      if ((an.tag != K) || (bn.tag != K) || (a <= b)) {
 195 

     
        *j = *nb ;
     
        *jn = *(nodes+(nb-t));
     
        if (an.tag != '+') {
     
          /* Inutile de tester (a+b)+c et (a+c)+b, car a+(b+c) l'est */  
 200 
          *i = a+b ;
     
          SETNODE(in,'+',&an,&bn) ;
     
          if (pall(*i,in,nb-t) || all(t, nb-1, nodes))
     
            return 1;
     
        }
 205 
        if (an.tag != '*' && a != 1 && b != 1) { /* idem */
     
          *i = a*b ;
     
          SETNODE(in,'*',&an,&bn) ;
     
          if (pall(*i,in,nb-t) || all (t, nb-1, nodes))
     
            return 1;
 210 
        }
     
        if (a != b) {
     
          *i = SUB(a,b) ;
     
          if (a > b)
     
            SETNODE(in,'-',&an,&bn) ;
 215 
          else
     
            SETNODE(in,'-',&bn,&an) ;
     
          if (pall(*i,in,nb-t) || all(t, nb-1, nodes))
     
            return 1 ;
     
        }
 220 
        if (MOD(a,b) == 0 && a != 1 && b != 1) {
     
          *i = DIV(a,b) ; 
     
          if (a > b)
     
            SETNODE(in,'/',&an,&bn) ;
     
          else
 225 
            SETNODE(in,'/',&bn,&an) ;
     
          if (pall(*i,in,nb-t) || all(t, nb-1, nodes))
     
            return 1;
     
        }
     
      }
 230 
      *j = b ;
     
      *jn = bn ;
     
    }
     
    *i = a ;
     
    *in = an ;
 235 
  }
     
  return 0 ;
     
}
     

     
int main (int argc, char **argv) {
 240 
  int i;
     
  int nb = argc-1 ;
     

     
  if (argc > 1 && (strcmp("-o",argv[1]) == 0)) {
     
    nb--;
 245 
    opt = 1 ;
     
    argv++ ;
     
  }
     
  pmax = nb ;
     
  for (i=0 ; i < nb ; i++) {
 250 
    nodes[i].tag = K ;
     
    nodes[i].arg.k =  plaque[i] = atoi(argv[i+1]) ;
     
    pall(plaque[i],&nodes[i],pmax) ;
     
  }
     

 255 
  all(plaque,plaque+nb-1,nodes) ;
     
  for (i=BEG ; i <= END ; i++) {
     
    printf(NUMFORM ":_",i) ;
     
    if (was_found(i)) {
     
      print(&save[i-BEG][0]) ;
 260 
      putchar('\n') ;
     
    } else
     
      printf("?????\n") ;
     
  }
     
  return 0 ;
 265 
}
     

Programmation « dynamique »

En C

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

     
#define NP 16
   5 
int np;
     
typedef unsigned int val;
     
#define FORMAT "%u"
     
val plaque[NP] ;
     

  10 
typedef unsigned int bset;
     

     
void pbset(bset s) {
     
  int i ;
     

  15 
  for (i = np ; i > 0 ; i--) {
     
    putchar(s % 2 ? '+' : '-') ;
     
    s /= 2 ;
     
  }
     
}
  20 

     
/* Ensembles des entiers resultat */
     
typedef struct iset {
     
  val here;
     
  struct iset *left,*right;
  25 
  unsigned char depth:8 ;
     
} iset ;
     

     
iset* sets[1 << NP];
     

  30 
int icard(iset *p) {
     
  if (!p)
     
    return 0;
     
  else {
     
    int r = icard(p->left) ;
  35 
    r++;
     
    return r + icard(p->right) ;
     
  }
     
}
     

  40 
int prof (iset *p) {
     
  if (!p)
     
    return 0 ;
     
  else {
     
    int pl = prof(p->left) ;
  45 
    int pr = prof(p->right) ;
     
    if (pl < pr)
     
      return 1+pr;
     
    else
     
      return 1+pl;
  50 
  }
     
}
     

     
#define K '\0'
     
typedef struct ival {
  55 
  val me ;
     
  char tag:8 ;
     
  struct ival *g,*d;
     
} ival ;
     

  60 

     
void pival(ival *t) {
     
  if (t->tag == K)
     
    printf(FORMAT,t->me) ;
     
  else {
  65 
    putchar('(') ;
     
    pival(t->g) ;
     
    putchar(t->tag) ;
     
    pival(t->d) ;
     
    putchar(')') ;
  70 
  }
     
}
     

     
#define NALLOC 1024
     
ival *vbuff ;
  75 
int iv ;
     

     

     
ival *alloc_ival(val me, char tag, ival *g, ival *d) {
     
  ival *r ;
  80 

     
 if (iv == 0) {
     
    vbuff =  (ival *)malloc(NALLOC*sizeof(ival)) ;
     
    iv = NALLOC ;
     
    if (vbuff == NULL) {
  85 
      fprintf(stderr,"Plus_de_mémoire\n") ;
     
      exit(2) ;
     
    }
     
  }
     
  r = vbuff ; iv-- ; vbuff++ ;  
  90 
  r->me = me ; r->tag = tag ; r->g = g ; r->d = d ;
     
  return r ;
     
}
     

     

  95 
ival *construct(val k, bset s) ;
     

     
ival *csingle(val k, val a, iset *right, bset bl, bset br) {
     
  if (!right)
     
    return NULL ;
 100 
  else {
     
    val b ;
     
    ival *r ;
     

     
    r = csingle(k, a, right->left, bl, br) ;
 105 
    if (r) return r ;
     

     
    b = right->here ;
     
    if (k == a+b)
     
      return alloc_ival (k, '+', construct(a, bl), construct(b, br)) ;
 110 
    if (k == a*b)
     
      return alloc_ival (k, '*', construct(a, bl), construct(b, br)) ;
     

     
    if (a > b) {
     
      if (k == a-b)
 115 
        return alloc_ival (k, '-', construct(a, bl), construct(b, br)) ;
     
      if (b*k == a)
     
        return alloc_ival (k, '/', construct(a, bl), construct(b, br)) ;
     
    } else {
     
      if (k == b-a)
 120 
        return alloc_ival (k, '-', construct(b, br), construct(a, bl)) ;
     
      if (a*k == b)
     
        return alloc_ival (k, '/', construct(b, br), construct(a, bl)) ;
     
    }
     
    return csingle(k, a, right->right, bl, br) ;
 125 
  }
     
}
     

     
ival *cboth(val k, iset *left, iset *right, bset bl, bset br) {
     
  ival *r ;
 130 

     
  if (!left) return NULL ;
     

     
  r = cboth(k, left->left, right, bl, br) ;
     
  if (r) return r ;
 135 

     
  r = csingle(k, left->here, right, bl, br) ;
     
  if (r) return r ;
     

     
  return cboth(k,left->right, right, bl, br) ;
 140 
}
     

     

     
ival *csubsets(val k, bset s, bset r, bset rr, bset mask) {
     
  if (s == 0) {
 145 
    if (rr) {
     
#ifdef DEBUG
     
      putchar('_') ; pbset(r) ;
     
      putchar('_') ; pbset(rr) ;
     
      fflush(stdout) ;
 150 
#endif
     
      return cboth(k, sets[r], sets[rr], r, rr);
     
    } else
     
      return NULL ;
     
    
 155 
  } else {
     
    ival *res ;
     

     
    while (s % 2 == 0) {
     
      s /= 2 ; mask <<= 1 ;
 160 
    }
     

     
    res = csubsets(k, s/2,r | mask ,rr, mask << 1) ;
     
    if (res) return res ;
     
    return csubsets(k, s/2, r, rr | mask, mask << 1) ;      
 165 
  }
     
}
     

     
ival *construct(val k, bset s) {
     
  bset i=0 ;
 170 
  while (s % 2 == 0) {
     
    s /= 2 ; i++ ;
     
  }
     
  s /= 2 ;
     
  if (s)
 175 
    return csubsets(k, s, 1 << i, 0, 1 << (i+1));
     
  else {
     
    return alloc_ival(plaque[i], K, NULL, NULL) ;
     
  }
     
}
 180 

     
iset *sbuff ;
     
int is ;
     

     
iset *alloc_iset(val here) {
 185 
  iset *r ;
     

     
  if (is == 0) {
     
    sbuff =  (iset *)malloc(NALLOC*sizeof(iset)) ;
     
    is = NALLOC ;
 190 
    if (sbuff == NULL) {
     
      fprintf(stderr,"Plus_de_mémoire\n") ;
     
      exit(2) ;
     
    }
     
  }
 195 
  r = sbuff ; is-- ; sbuff++ ;  
     
  r->left = r->right = NULL ;
     
  r->here = here ;
     
  r->depth = 1 ;
     
  return r ;
 200 
}
     

     

     
unsigned char depth(iset *s) {
     
  return s ? s->depth : 0 ;
 205 
}
     

     
iset *balance(iset *s) {
     
  int hl = depth(s->left) ;
     
  int hr = depth(s->right) ;
 210 
  
     
  if (hl-hr > 1) {
     
    iset *l=s->left ;
     
    iset *ll=l->left ;
     
    iset *lr=l->right ;
 215 
    if (depth(lr) <= depth(ll)) {
     
      unsigned char d = 1+depth(lr) ;
     
      s->left = lr ; s->depth = d ;
     
      l->right = s ; l->depth = 1+d ;
     
      return l ;
 220 
    } else {
     
      unsigned char d = depth(ll) ;
     
      s->left = lr->right ; s->depth = d+1 ;
     
      l->right = lr->left ; l->depth = d+1 ;
     
      lr->left = l ; lr->right = s ; lr->depth = d+2 ;
 225 
      return lr ;
     
    }
     
  } else if (hr-hl > 1) {
     
    iset *r = s->right ;
     
    iset *rl = r->left ;
 230 
    iset *rr = r->right ;
     
    if (depth(rl) <= depth(rr)) {
     
      unsigned char d = 1+depth(rl) ;
     
      s->right = rl ; s->depth = d ;
     
      r->left = s ; r->depth = 1+d ;
 235 
      return r ;
     
    } else {
     
      unsigned char d = depth(rr) ;
     
      s->right = rl->left ; s->depth = d+1 ;
     
      r->left = rl->right ; r->depth = d+1 ;
 240 
      rl->left = s ; rl->right = r ; rl->depth = d+2 ;
     
      return rl ;
     
    }
     
  } else {
     
    s->depth = hl > hr ? hl+1 : hr+1 ;
 245 
    return s ;
     
  }
     
}
     

     
iset *insert(val k, iset *s) {
 250 
  if (!s) {
     
    return alloc_iset(k) ;
     
  } else {
     
    val c = s->here ;
     
    if (k < c) {
 255 
      iset *r = insert(k, s->left) ;
     
      if (r) {
     
        s->left = r ;
     
        return balance(s) ;
     
      } else
 260 
        return NULL ;
     
    } else if (k > c) {
     
      iset *r = insert(k, s->right) ;
     
      if (r) {
     
        s->right = r ;
 265 
        return balance(s) ;
     
      } else
     
        return NULL ;
     
    }
     
    return NULL ;
 270 
  }
     
}
     

     
#define BEG 1
     
#define END 1000
 275 
ival *res[END-BEG+1];
     
int remains=END-BEG+1;
     
bset curset;
     

     

 280 
void print_res(void) {
     
  val i ;
     
  for (i = BEG ; i <= END ; i++) {
     
    printf(FORMAT ":_", i) ;
     
    if (res[i-BEG] == NULL)
 285 
      printf("?????") ;
     
    else
     
      pival(res[i-BEG]) ;
     
    putchar('\n') ;
     
  }
 290 
}
     

     
void record_res(val k) {
     

     
  if (BEG <= k && k <= END) {
 295 
    if (res[k-BEG] == NULL) {
     
      res[k-BEG] = construct(k, curset) ;
     
#ifndef PRINT
     
      if (--remains == 0) {
     
        print_res() ;
 300 
        exit(0) ;
     
      }
     
#endif
     
    }
     
  }
 305 
}
     

     
iset *tinsert(val k, iset *r) {
     
  iset *rr ;
     

 310 
  record_res(k) ;
     
  rr = insert(k, r) ;
     
  return rr ? rr : r ;
     
}
     

 315 
iset *single(val a, iset *right, iset *r) {
     
  if (!right)
     
    return r ;
     
  else {
     
    val b = right->here ;
 320 
    val k ;
     

     
    r = single(a, right->left, r) ;
     

     
    k = a+b ;
 325 
    r = tinsert(k, r) ;
     

     
    k = a*b ;
     
    r = tinsert(k, r) ;
     

 330 
    if (a > b) {
     
      k = a-b ;
     
      r = tinsert(k, r) ;
     

     
      if (a % b == 0) {
 335 
        k = a/b ;
     
        r = tinsert(k, r) ;
     
      }
     
    } else {
     
      k = b-a ;
 340 

     
      if (k != 0) {
     
        r = tinsert(k, r) ;
     
      }
     

 345 
      if (b % a == 0) {
     
        k = b/a ;
     
        r = tinsert(k, r) ;
     
      }
     
    }
 350 
  }
     
  return single(a, right->right, r) ;
     
}
     

     
iset *both(iset *left, iset *right, iset *r) {
 355 
  if (!left)
     
    return r;
     
  r = both(left->left, right, r) ;
     
  r = single(left->here, right, r) ;
     
  return both(left->right, right, r) ;
 360 
}
     

     

     

     
void subsets(bset s, bset r, bset rr, bset mask) {
 365 
  if (s == 0) {
     
    if (rr) {
     
      s = r | rr ;
     
#ifdef DEBUG
     
      putchar('_') ; pbset(r) ;
 370 
      putchar('_') ; pbset(rr) ;
     
      fflush(stdout) ;
     
#endif
     
      curset = s ;
     
      sets[s] = both(sets[r], sets[rr], sets[s]);
 375 
    }
     
  }
     
  else {
     
    while (s % 2 == 0) {
     
      s /= 2 ; mask <<= 1 ;
 380 
    }
     
    subsets(s/2,r | mask ,rr, mask << 1) ;
     
    subsets(s/2,r, rr | mask, mask << 1) ;      
     
  }
     
}
 385 

     
void topsubsets(bset s) {
     
  bset i=0 ;
     
  while (s % 2 == 0) {
     
    s /= 2 ; i++ ;
 390 
  }
     
  s /= 2 ;
     
  if (s)
     
    subsets(s, 1 << i, 0, 1 << (i+1));
     
  else {
 395 
    curset = 1 << i ;
     
    sets[curset] = tinsert(plaque[i],sets[curset]) ;
     
  }
     
}
     

 400 

     

     

     
void piset(iset *p, bset s) {
     
  if (p) {
 405 
    piset(p->left, s) ;
     
    printf(FORMAT ":_", p->here);
     
    pival(construct(p->here, s)) ;
     
    putchar('\n') ;
     
    piset(p->right, s) ;
 410 
  }
     
}
     

     
void cnp(int n, int p, bset r, bset mask) {
     
  if (p == 0) {
 415 
    if (r != 0) {
     
#ifdef PRINT
     
    int ic,in;
     
    pbset(r) ;
     
    fflush(stdout) ;
 420 
#endif
     
    topsubsets(r) ;
     
#ifdef PRINT
     
    ic = icard(sets[r]) ;
     
    in = prof(sets[r]) ;
 425 
    printf(":_%d,_%d\n",in,ic) ;
     
#ifdef DEBUG
     
    piset(sets[r], r) ;
     
    putchar('\n');
     
#endif
 430 
#endif
     
    }
     
  } else if (p <= n) {
     
    cnp(n-1, p-1, r | mask, mask << 1) ;
     
    cnp(n-1, p, r, mask << 1) ;
 435 
  }
     
}
     

     
void cardsubsets(int n, int p) {
     
  cnp(n, p, 0, 1) ;
 440 
}
     

     
int main (int argc, char **argv) {
     
  int i;
     
  bset s, full;
 445 

     
  np = argc-1 ;
     
  full = (1 << np)-1 ;
     
  
     
  for (i=0 ; i < np ; i++) {
 450 
    plaque[i] = atoi(argv[i+1]) ;
     
  }
     

     
  for (i=1 ; i <= np ; i++) {
     
      cardsubsets(np,i) ;
 455 
  }
     
  print_res() ;
     
  return 0;
     
}
     

 460 

     

     

     

     

 465 

     

     

En Caml

     
     
type t = {i : int ; t : term}
     
and term = 
     
  | Const
   5 
  | Op of char * t * t
     

     
let rec taille x = match x.t with
     
| Const -> 1
     
| Op (_,x,y) -> taille x+ taille y
  10 
;;
     

     
let rec rev_append xs ys = match xs with
     
| [] -> ys
     
| x::rem -> rev_append rem (x::ys)
  15 

     
let rev_map f xs =
     
  let rec do_rec f r = function
     
    | [] -> r
     
    | x::xs ->
  20 
        do_rec f (f x::r) xs in
     
  do_rec f [] xs
     

     

     
let rec merge r xs ys = match xs,ys with
  25 
| [],_ -> rev_append r ys
     
| _,[] -> rev_append r xs
     
| x::rxs, y::rys ->
     
    if x.i < y.i then merge (x::r) rxs ys
     
    else if y.i < x.i then merge (y::r) xs rys
  30 
    else
     
      merge (if taille x <= taille y then x::r else y::r)
     
        rxs rys
     

     
let rec step r = function
  35 
  | [] -> r
     
  | [xs] -> xs::r
     
  | xs::ys::rem ->
     
      step (merge [] xs ys::r) rem
     

  40 
let rec merges xss = match step [] xss with
     
| [] -> []
     
| [r] -> r
     
| r   -> merges r
     

  45 

     
  
     
let rec app op r xs ys = match xs with
     
| [] -> merges r
     
| x::rem ->
  50 
    app
     
      op
     
      (List.map (fun y -> op x y) ys::r)
     
      rem ys
     
;;
  55 

     
let sums xs ys = app (fun x y -> {i=x.i+y.i ; t= Op ('+',x, y)}) [] xs ys
     
and mults xs ys = app (fun x y -> {i=x.i*y.i ; t= Op ('*',x, y)})  [] xs ys
     

     
let tdiff x y = {i=x.i-y.i ; t=Op ('-',x,y)}
  60 

     
let diff_end x ys = List.map (fun y -> tdiff y x) ys
     
let rec diff r x = function
     
  | [] -> r
     
  | y::ys ->
  65 
      if y.i < x.i then diff (tdiff x y::r) x ys
     
      else if x.i=y.i then
     
        merge [] r (diff_end x ys)        
     
      else
     
        merge [] r (diff_end x (y::ys))
  70 

     

     
(* x > y *)
     
let tdiv x y r =
     
  if x.i mod y.i = 0 then
  75 
    {i=x.i/y.i ; t = Op ('/',x,y)}::r
     
  else
     
    r
     

     
let div_end x ys = 
  80 
  List.fold_right (fun y r -> tdiv y x r) ys []
     

     
let rec div r x = function
     
  | [] -> r
     
  | y::ys ->
  85 
      if y.i < x.i then div (tdiv x y r) x ys
     
      else
     
        merge [] r (div_end x (y::ys))
     

     
let rec app2 f r xs ys = match xs with
  90 
| [] -> merges r
     
| x::rem ->
     
    app2
     
      f
     
      (f [] x ys::r)
  95 
      rem ys
     

     
let diffs xs ys = app2 diff [] xs ys
     
and divs xs ys = app2 div [] xs ys
     

 100 
let zyva xs ys =
     
  merge []
     
    (merge [] xs ys)
     
    (merge []
     
       (merge [] (sums xs ys) (mults xs ys))
 105 
       (merge [] (diffs xs ys) (divs xs ys)))
     

     
let rec print_item x = match x.t with
     
| Const -> print_int x.i
     
| Op (c,x,y) ->
 110 
    print_char '(' ;
     
    print_item x ;
     
    print_char c ;
     
    print_item y ;
     
    print_char ')'
 115 
;;
     

     
let rec pr_list = function
     
  |  [] -> print_newline ()
     
  | x::rem ->
 120 
      print_int x.i ; print_char '=' ;
     
      print_item x ; print_char '\n' ; pr_list rem
     
;;
     

     

 125 

     

     
let rec partitions xs = match xs with
     
| [] -> []
     
| [_] -> []
 130 
| [x ; y] -> [[x],[y]]
     
| x::rem ->
     
    let p = partitions rem in
     
    List.fold_left
     
      (fun r (l,m) -> (x::l,m)::(l,x::m)::r)
 135 
      [[x],rem] p
     
;;
     

     
let t = Hashtbl.create 107
     

 140 
let rec pr_set = function
     
  |  [] -> print_newline ()
     
  | x::rem ->
     
      print_int x ; print_char ' ' ; pr_set rem
     
;;
 145 

     
let rec ceb l =
     
  try Hashtbl.find t l
     
  with Not_found ->
     
    let r = match l with
 150 
    | [] -> assert false
     
    | [x] -> [{i=x ; t=Const}]
     
    | s ->
     
        let ps = partitions s in
     
        merges
 155 
          (rev_map
     
             (fun (l,m) -> 
     
               let n1 = ceb l and n2 = ceb m in
     
               zyva n1 n2)
     
             ps) in
 160 
    Hashtbl.add t l r ;
     
    r
     
;;
     

     
let plaques = ref []
 165 
;;
     

     
for i=1 to Array.length Sys.argv-1 do
     
  plaques := !plaques @ [int_of_string Sys.argv.(i)]
     
done
 170 
;;
     

     
let rec end_select max = function
     
  | [] -> []
     
  | x::xs ->
 175 
      if x.i > max then []
     
      else
     
        x::end_select max xs
     

     
let rec select min max = function
 180 
  | [] -> []
     
  | x::xs ->
     
      if x.i >= min then end_select max (x::xs)
     
      else
     
        select min max xs
 185 
;;
     

     

     
pr_list ((ceb !plaques))
     
;;
 190 


This document was translated from LATEX by HEVEA.