1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
| # Recherche les numéros par bactérie en évitant les mauvaises combinaisons
# Il faut favoriser les numéros des bactéries les moins représentées
# par exemple, il faut aboslument garder n°12 qui est unique
# GARDER AU MOINS UN NUMERO PAR BACTERIE
# NE PAS OUBLIER LES CAS SANS SOLUTION OU CERTAINES BACTERIES NE PEUVENT PAS AVOIR DE NUMERO A CAUSE DE CONFLITS
=h
my %H_Bact = (
Bact1 => [1, 2, 3, 4],
Bact2 => [5, 6],
Bact3 => [7, 8, 9, 10, 11],
Bact4 => [12],
);
my @A_MauvaisesCombinaisons = qw[5-12 1-9 2-12 4-5 1-5 2-6];
=cut
# ici on doit trouver
# Bact1 => 1, 3, 4,
# Bact2 => 6
# Bact3 7, 8, 10, 11,
# Bact4 12
# 2, 5 et 9 ont été supprimés rendant tout le reste compatible
# 1) On recherche la bactérie ayant le moins de combinaisons et on choisi un numéro à garder
# 2a) On regarde dans @A_MauvaisesCombinaisons les combinaisons incompatibles avec ce numéro à garder
# 2b) On retire les mauvaises combinaisons de @A_MauvaisesCombinaisons qui contiennent ce numéro que l'on garde
# 3) On retire de %H_Bact ces numéros incompatibles
# 4) On retire de @A_MauvaisesCombinaisons les combinaisons qui contenait les numéros qui étaient associcés au numéro gardé et qui maintenant
# ne sont plus dans %H_Bact.
#dans cet exemple :
# 1) on sélectionne le numéro 12 de Bact4
# 2a) mauvaises combinaisons : 5-12 2-12 => à supprimer 5 et 2
# 2b) on retire 5-12 et 2-12 de @A_MauvaisesCombinaisons
# 3) retirer 5 et 2 chez les bactéries correspondantes dans %H_Bact
# 4) on retire de @A_MauvaisesCombinaisons les mauvaises combinaisons contenant 2 ou 5
# => 4-5, 1-5 et 2-6 (il ne reste plus que 1-9 dans @A_MauvaisesCombinaisons)
# 1) on sélectionne Bact2 chez qui il ne reste que le numéro 6
# 2) mauvaises combinaisons : aucune car 2-6 a été supprimé au tour précédent
# 1) on sélectionne le numéro 1 de Bact1 (chez qui il reste 1, 3 et 4)
# 2a) mauvaises combinaisons : 1-9 => à supprimer 9
# 2b) on retire 1-9 de @A_MauvaisesCombinaisons
# 3) retirer 9 chez les bactéries correspondantes dans %H_Bact
# 4) on retire de @A_MauvaisesCombinaisons les mauvaises combinaisons contenant 1 ou 9
# => aucune car @A_MauvaisesCombinaisons est vide
# Pas de tour suivant car @A_MauvaisesCombinaisons =0
#
# 1) ON NE SELECTIONNE PAS 3 DE BACT1 MAIS ON PASSE A BACT3
# - pour augmenter la probabilité d'avoir au moins un numéro par bactérie
# - après avoir faire tous le tour des bactéries, on revient aux numéros qui n'ont pas encore été testés
#...
# jusqu'à ce que @A_MauvaisesCombinaisons soit vide
use strict;
use warnings;
# %H_Bact => clé : bactérie valeur : liste des numéros correspondants
my %H_Bact = (
Bact1 => [1, 2, 3, 4],
Bact2 => [5, 6],
Bact3 => [7, 8, 9, 10, 11],
Bact4 => [12],
);
my @A_MauvaisesCombinaisons = qw[5-12 1-9 2-12 4-5 1-5 2-6];
# création du ' hash inversé' de %H_Bact, les clés deviennent valeurs et les valeurs deviennent des clés
# => permet à partir d'une valeur de %H_Bact de rapidement retrouver sa clé sans devoir reparcourir tout ce hash.
# %H_Num => clé : numéro valeur : bactérie correspondante
my %H_Num;
foreach my $Bact (sort keys %H_Bact)
{
foreach my $Num (@{$H_Bact{$Bact}})
{
$H_Num{$Num}= $Bact;
}
}
#while(@A_MauvaisesCombinaisons !=0)
for(my $i=0; $i<4; $i++)
{
@A_MauvaisesCombinaisons = @A_MauvaisesCombinaisons;
# 1) On recherche la bactérie ayant le moins de combinaisons
#--------------------------------------------------------------
# Creation d'un hash contenant la taille clé : taille array, valeur : bact (peu importe si on écrase une des bactéries)
my %H_Tailles;
# Creation d'un array contenant la liste des différentes tailles
my @A_Tailles;
foreach (keys %H_Bact)
{
$H_Tailles{@{$H_Bact{$_}}}=$_;
my $T = @{$H_Bact{$_}};
push(@A_Tailles, $T);
};
# recherche de la taille la plus petite
@A_Tailles = (sort {$a<=>$b} @A_Tailles);
my $Indice = 0;
my $TailleArrayBact = $A_Tailles[$Indice];
# Bactérie dont le nombre de numéros est le plus petit
my $Bact = $H_Tailles{$TailleArrayBact};
# on prend le premier numéro de l'array
my $NumBact = ${$H_Bact{$Bact }}[0];
# 2) On regarde dans la liste des mauvaises combinaisons les numéros à supprimer chez les autres bactéries dans %H_Bact
#-------------------------------------------------------------------------------------------------------------------------
# Liste des numéros à supprimer
my @A_SelectMauvCombi = map { $1 if /(\d+)-$NumBact/ or /$NumBact-(\d+)/ }
grep { /$NumBact/ } @A_MauvaisesCombinaisons;
# On vérifie que @A_SelectMauvCombi ne soit pas vide et qu'il existe des mauvaises combinaisons à supprimer de @A_MauvaisesCombinaisons
# si elle l'est => cela signifie que nous avons trouver un numéro qui est compatible avec tous les autres numéros restants
# on doit passer à une autre bactérie, même si il reste des numéro à tester pour celle-ci
while(!@A_SelectMauvCombi)
{
# On recherche la seconde bactérie de @A_Tailles
# @A_Tailles contient par ordre croissant les tailles des arrays de %H_Bact
# Il faut prendre celle de l'indice suivant
$Indice++;
if($A_Tailles[$Indice])
{
$TailleArrayBact = $A_Tailles[$Indice];
print $TailleArrayBact."\n";
# Bactérie dont le nombre de numéros est le plus petit
$Bact = $H_Tailles{$TailleArrayBact};
# on prend le indicième numéro de l'array
$NumBact = ${$H_Bact{$Bact }}[$Indice];
# 2) On regarde dans la liste des mauvaises combinaisons les numéros à supprimer chez les autres bactéries dans %H_Bact
#-------------------------------------------------------------------------------------------------------------------------
# Liste des numéros à supprimer
@A_SelectMauvCombi = map { $1 if /(\d+)-$NumBact/ or /$NumBact-(\d+)/ }
grep { /$NumBact/ } @A_MauvaisesCombinaisons;
print "Taille de \@A_SelectMauvCombi=> ".@A_SelectMauvCombi."\n";
}
# PROBLEME IL NE RESTE PLUS AUCUNE BACTERIE A TESTER (elles ont toutes au moins un numéro de sélectionné)
# ON REVIENT CHOISIR UN SECOND NUMERO POUR UNE DES BACTERIE DEJE TESTEE
else
{
print "PROBLEME\n";
}
}
# Liste des numéros à garder (pour le cycle suivant)
@A_MauvaisesCombinaisons = grep { $_!~/$NumBact-/ and $_!~/-$NumBact/ } @A_MauvaisesCombinaisons;
# Suppression des numéros dans %H_Bact
foreach my $NumIncompatible (@A_SelectMauvCombi)
{
my $BactIncompatible = $H_Num{$NumIncompatible};
@{$H_Bact{$BactIncompatible}} = grep { $_ !~ /$NumIncompatible/}@{$H_Bact{$BactIncompatible}};
#On enlève de @A_MauvaisesCombinaisons les combinaisons contenant les numéros que l'on vient de supprimer
@A_MauvaisesCombinaisons = grep { $_!~/$NumIncompatible-/ and $_!~/-$NumIncompatible/ } @A_MauvaisesCombinaisons;
}
# 3) On supprime le @A_MauvaisesCombinaisons les combinaisons contenant les numéros que l'on vient de supprimer
#-------------------------------------------------------------------------------------------------------------------------
print "Numéro à analyser\t$Bact\t$NumBact\n";
print "Numéro incompatibles à supprimer\n";
map{print $_."\n";}@A_SelectMauvCombi;
print "Mauvaises combinaisons restant pour le cycle suivant\n";
map{print "=> ".$_."\n";}@A_MauvaisesCombinaisons;
print "\n\n";
} |
Partager