Algorithme de combinatoire et permutation

Bon je vous explique mon problème: je dois faire un algorithme qui organise des rencontres en tête a tête entre plusieurs personnes, disons A B C D E F.

Chaque personne doit rencontrer une autre personne une fois. Il ne peut y avoir qu’une rencontre par personne par jour.

Jusque la, j’arrive (en faisant 2 boucles imbriquées):

  1. A et B
  2. A et C
  3. A et D
  4. A et E
  5. A et F
  6. B et C
  7. B et D
  8. B et E
  9. B et F
  10. C et D
  11. C et E
  12. C et F
  13. D et E
  14. D et F
  15. E et F

Si l’on fait ca dans cet ordre, ca prends 15 jours. Seulement voila, en optimisant, on se rend bien compte que le premier jour on peut faire:

  1. A et B, C et D, E et F
  2. A et C
  3. A et D
  4. A et E
  5. A et F
  6. B et C
  7. B et D
  8. B et E
  9. B et F
  10. C et E
  11. C et F
  12. D et E
  13. D et F

Et ainsi de suite…

Ma question:
Est ce qu’il existe un algorithme qui permet d’optimiser ca pour un nombre n de personnes? parce que pour l’instant ma technique se limite a de la récursivité:

je découpe le paquet de personnes en deux, je fais la rencontre entre chaque membre des 2 groupes, je recoupes en 2 je refais la rencontre et ainsi de suite.

Cet algorithme ne fonctionne malheureusement bien que pour un nombre de personne égal a une puissance de 2 (2, 4, 8, 16 etc…) mais des qu’on tombe dans un nombre différent ca ne marche plus tellement bien (il y a des trous, par exemple avec 6 personnes, mon algo trouve 7 jours et a la main, j’arrive a faire les rencontres en 5 jours).

Des idées?

(et qu’on vienne pas me dire que je suis pas explicite dans ma demande :P).

[quote name=’[PERE]Cil’ date=’ 1 Mar 2005, 10:56’]Cet algorithme ne fonctionne malheureusement bien que pour un nombre de personne égal a une puissance de 2 (2, 4, 8, 16 etc…) mais des qu’on tombe dans un nombre différent ca ne marche plus tellement bien (il y a des trous, par exemple avec 6 personnes, mon algo trouve 7 jours et a la main, j’arrive a faire les rencontres en 5 jours).
(et qu’on vienne pas me dire que je suis pas explicite dans ma demande :P).
[right][post=“337273”]<{POST_SNAPBACK}>[/post][/right][/quote]
J’y réfléchis, mais comment tu arrives a 5 jours pour 6 personnes ?

[quote name=’[PERE]Cil’ date=’ 1 Mar 2005, 10:56’]Si l’on fait ca dans cet ordre, ca prends 15 jours. Seulement voila, en optimisant, on se rend bien compte que le premier jour on peut faire:

  1. A et B, C et D, E et F
  2. A et C
  3. A et D
    (…)
    Et ainsi de suite…[/quote]

Déjà je trouve ça bizarre, parce qu’en optimisant encore on obtient :

  1. A:B & C:D & E:F
  2. A:C & B:E & D:F
  3. B:C & D:E & F:A

Non très franchement ça me semble etre un listing des combinaisons possible et ensuite un réarrangement pour éviter les doublons dans chaque « jour ».
Je dirais tout d’abord, en un algo peut être pas mais avec quelques fonctions certainement. :stuck_out_tongue:

Enfin je dis ça sans vraiment poser le tête dessus…

« En informatique, la première idée est souvent la mauvaise. »
On me l’a toujours dit :stuck_out_tongue:

Edit ce soir si j’ai eu le temps d’y reflechir. :stuck_out_tongue:

  1. A et B, C et D, E et F
  2. A et C, B et E, D et F
  3. A et D, B et F, C et E
  4. A et E, B et D, C et F
  5. A et F, B et C, D et E

Voila :stuck_out_tongue:

[quote name=’[PERE]Cil’ date=’ 1 Mar 2005, 11:39’]1. A et B, C et D, E et F
2. A et C, B et E, D et F
3. A et D, B et F, C et E
4. A et E, B et D, C et F 
5. A et F, B et C, D et E

Voila :stuck_out_tongue:
[right][post=« 337292 »]<{POST_SNAPBACK}>[/post][/right][/quote]
Putain, je suis con comme un algo moi … pff… Bon je m’y met vite fait.

Salut

Primo, concernant le nombre de binomes de personne que l’on peut faire parmi un ensemble, c’est des maths…Il s’agit de combinatoires. Plutot que de décrire ici les formules et tout le reste, voici un lien intéressant: ICI

Secondo, pour trouver le nombre de jours que ça va prendre; il suffira simplement de faire une division euclidienne du nombre de personnes par le nombre de combinaisons possibles…

Finalement avec ces 2 données, tu as les limites de tes boucles qui vont concrètement créer les tableaux de binomes de personnes.

J’espère que j’étaiS clair… :stuck_out_tongue:

C’était effectivement clair, seulement ca ne me dit toujours pas comment ordonnancer ces rencontres :P.

Bon plein de réflexions après, ca marche toujours pas :/. Ca commences a me casser les koÿs il faut croire que le problème n’était pas aussi trivial que ca.

Allez on fait un concours! Le premier qui me trouve un algo potable, il gagne… mmm une édition Collector (cad tenu en main par moi) de Warcraft 2 Battle.net edition :P. A vos cerveaux :P.

[quote name=’[PERE]Cil’ date=’ 2 Mar 2005, 08:41’]Bon plein de réflexions après, ca marche toujours pas :/. Ca commences a me casser les koÿs il faut croire que le problème n’était pas aussi trivial que ca.

Allez on fait un concours! Le premier qui me trouve un algo potable, il gagne… mmm une édition Collector (cad tenu en main par moi) de Warcraft 2 Battle.net edition :P. A vos cerveaux :P.
[right][post=“337679”]<{POST_SNAPBACK}>[/post][/right][/quote]

J’ai la flemme de reflechir niveau performance, mais si tu veux kkch qui marche:

  1. tu generes la liste de toutes les rencontres possibles.
  2. tu crees un nouveau ‘jour’, en lui associe autant de rencontres possibles (seule limitation, une personne par jour). Tu vire ces rencontres de ta liste.
  3. tant que ta liste est pas vide, tu crees un nouveau jour et applique #2. Bouclation.

Non?

Ouais mais c’est pas optimum.

Cet technique me donne une solution pour 6 personnes de 7 jours. Parce que tout dépend dans quel ordre on prend les rencontres: dans le cas énoncé plus haut, les rencontres sont dans l’ordre optimal (qui n’est pas la séquence de base A B C etc…)

exemple: dans le cas précédent, si on fait

  1. AB CD EF
  2. AF CB ED
  3. AD CF EB

Il n’y a plus moyen de sortir une solution sur 5 jours. C’est forcément une solution sur 7 jours. (ou alors prouvez moi le contraire svp ca veut dire que je me suis plantouillé).

Ah ouais, exact, je viens de saisir le vrai probleme :stuck_out_tongue:
Je le note d’ailleurs, ca va me servir de question d’entretiens…

Je file en reunion dans pas longtemps, je vais prendre mon laptop pour bidouiller un truc :stuck_out_tongue:

Edit:
Bon, j ai rien suivi a la reunion, c’est mal.
Cela dit, voila un truc qui marche: class1.cs
Je sais pas pourquoi, mais ca marche pas avec 8 personnes :stuck_out_tongue:
Enfin, peut etre, ca mouline en tout cas.

Un pote m’a soumis une url :P:

http://www.devenezia.com/downloads/round-r…ule-source.html

Ps: KiniK c’est dégueulasse de poser cette question en entretien d’embauche :P.

Bon j’ai trouvé l’algorithme quivabien, merci a tous les participants. Merci aussi a KiniK pour son algorithme et a GuiHome qui m’a fourni l’algorithme ‘pas en code’ (mais d’une logique implacable, j’en reste impressionné). Voila l’algo qui va ben sortie de ma classe (c’est du PHP, c’était le langage le plus rapide pour développer pour moi):

(désolé pour la tabulation pourrie)

[code]  // check if meetings has to be done
 private function isDone($pMeetings)
 {
   if(count($pMeetings)==0)
  return(true);

return(false);

 }
 
 // delete all meetings that have been assigned to results meetings found for a day
 private function updateMeetings(&$pMeetings,$pRemovalList)
 {
   foreach($pMeetings as $sKey => $pValues)
  foreach($pRemovalList as $sRemovalKey => $pRemovalValues)
 if($pMeetings[$sKey][0]==$pRemovalList[$sRemovalKey][0] && $pMeetings[$sKey][1]==$pRemovalList[$sRemovalKey][1])
   unset($pMeetings[$sKey]);
 }
 
 // delete all meeting that can’t be done this day
 private function deleteTeamFromMeetingList(&$pMeetings)
 {
   reset($pMeetings);
$pData = current($pMeetings);

   $sHomeTeam = $pData[0];
   $sForeignTeam = $pData[1];

foreach($pMeetings as $sKey => $sValue)

  if($pMeetings[$sKey][0]==$sHomeTeam || $pMeetings[$sKey][1]==$sHomeTeam || $pMeetings[$sKey][0]==$sForeignTeam ||$pMeetings[$sKey][1]==$sForeignTeam)
    unset($pMeetings[$sKey]);
 }
 
 // get recursively the next available meeting
 private function getNextMeetingDay(&$pMeetings,$iRecursion)
 {
// no result found, so return false
   if(count($pMeetings)===0)
  return(false);

// get first result
reset($pMeetings);
$pFirstResult[$iRecursion] = current($pMeetings);

// recursion == 1 so only one result should be available
if($iRecursion==1)

  return($pFirstResult);

$this->deleteTeamFromMeetingList($pMeetings);

$bFound = false;

// loop all meetings, to find a good result
while($bFound==false)
{

  // create a working copy to find available meetings
  $pWorkingCopy = $pMeetings;
 
  // ask another time a meeting. In this recursion, we should find n - found meetings
  $pSubResult = $this->getNextMeetingDay($pWorkingCopy,$iRecursion-1);
 
  // no result found
  if($pSubResult===false)
  {
    // if nothing found, delete current item, so we can test with the next one
    array_shift($pMeetings);

 // no results found, this solution isn’t good
 if(count($pMeetings)==0)
   return(false);
  }
  else
 $bFound = true;
}
   
return($pFirstResult + $pSubResult);
 }
 
 private function createMatchesForSeason($pTeams, $iSeason, $iDeadLine)
 {
   $pMeetings = array();
$pMeetingResults = array();

$iNumberTeams = count($pTeams);

// the meeting function work only for pairs number of people
if(($iNumberTeams%2)==1)
{

  $iNumberTeams++;
  $pTeams[] = array(“sName” => “Nobody”);
}

// build the list of meetings
for($iCnt=0;$iCnt<count($pTeams);$iCnt++)

  for($iCnt2=$iCnt+1;$iCnt2<count($pTeams);$iCnt2++)
       $pMeetings[] = array($pTeams[$iCnt][“sName”],$pTeams[$iCnt2][“sName”]);

$iCnt = 0;

               // build the results meeting
while(!$this->isDone($pMeetings))
{
  $pWorkingCopy = $pMeetings;
  $pMeetingResults[$iCnt] = $this->getNextMeetingDay($pWorkingCopy,$iNumberTeams/2);
 
  // delete matches that have been planned
  $this->updateMeetings($pMeetings,$pMeetingResults[$iCnt]);
     
  $iCnt++;
}

   print_r($pMeetingResults);
 }[/code]

Au fait c’est GuiHome qui a gagné l’édition de Warcraft 2 Battle.net :P. Son algo marche pour 8 (et pour 9 je viens de tester, donc 10 ca devrait pas créer de problèmes).

Heu il est ou l’algo de GuiHome?

Genial comme question d’entretien d’embauche cela dit, il a raison kinik :stuck_out_tongue:

Bah il me l’a dit par ICQ, c’est pas un membre de cafzone.

En gros:

  1. tu établis la liste des rencontres a faire. S’il ya un nombre impair de personnes, tu ajoutes une personne “Nobody” qui est un marqueur pour indiquer que la personne qui doit rencontrer “Nobody” rencontre personne.

début de la récursivité, on s’attends a n/2 rencontres

  1. tu parcoures ta liste tu prends la premiere rencontre.

  2. tu fais une copie de la liste, tu supprimes toutes les rencontres contenant les personnes participant a la première rencontre.

  3. on relances une recherche dans la copie de la liste, une nouvelle rencontre qui permet de trouver une série de rencontres suffisantes (n/2): la est la récursivité; par exemple

le premier jour, on trouve AB CD EF.
le second jour, le programme trouve AC, puis le prochain est “normalement” BD. Seulement, BD donne comme résultat EF, qui est déjà pris, DONC BD n’est pas bon. il prend le prochain: BE, il reste DF donc poru le dernier. Ca fait n/2 (3) rencontres, c’est OK, on a trouvé un nouveau jour de rencontre. Et ainsi de suite.

  1. on boucle tant qu’on a des rencontres a faire.

Y a un peu plus elegant en full recursif avec du backtrack la ou il faut mais je te laisse le soin de chercher si tu veux, la solution un peu hybride marche aussi :stuck_out_tongue: