IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Sélection dans un tableau non indexé en fonction d'un tableau indexé


Sujet :

Langage Perl

  1. #1
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut Sélection dans un tableau non indexé en fonction d'un tableau indexé
    Bonjour à tous,


    Voici mes données de départ
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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];
    #  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
     
    # ici on doit trouver 12, 6, [7-8-10-11], 3
    Algorithme:
    # 1) On recherche la bactérie ayant le moins de combinaisons
    # 2-3) On regarde dans la liste des mauvaises combinaisons les numéros à supprimer chez les autres bactéries dans %H_Bact
    # 4) On retire ces mauvaises combinaisons de @A_MauvaisesCombinaisons

    dans cet exemple :
    # 1) on sélectionne Bact4
    # 2) mauvaises combinaisons : 5-12 2-12 2-12
    # 3) retirer 5 et 2 ches les bactéries correspondantes dans %H_Bact
    # 4) on retire les mauvaises combianisons de @A_MauvaisesCombinaisons
    # 1) on sélectionne Bact2 chez qui il ne reste que le numéro 6
    # 2) mauvaises combinaisons : aucune
    # 1) on sélectionne le numéro 1 de Bact1 (chez qui il reste 1, 3 et 4)
    # 2) mauvaises combinaisons : 1-9 (1-5 ayant déjàé été enlevée)
    # 3) retirer 9 dans %H_Bact
    # 4) on retire la mauvaise combianison de @A_MauvaisesCombinaisons
    # 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

    Début de mon code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    use strict;
    use warnings;
    use Statistics::Lite qw(:all);
     
     
    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];
     
     
    #while(@A_MauvaisesCombinaisons !=0)
    for(my $i=0; $i<4; $i++)
    {
            # 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{$_}}}=$_;
                    push(@A_Tailles, @{$H_Bact{$_}});
            };
            # recherche de la taille la plus petite
            my $TailleArrayBact = min (@A_Tailles);
            # 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 = grep { $_ =~ /^$NumBact-| $NumBact$/ } @A_MauvaisesCombinaisons;
            # Liste des numéros à garder (pour le cycle suivant)
            @A_MauvaisesCombinaisons = grep { $_ !~ /^$NumBact-| $NumBact$/ } @A_MauvaisesCombinaisons;
     
            print "$Bact\t$NumBact\n";
            map{print $_."\n";}@A_SelectMauvCombi;
    }
    Mon algorithme est-il correct?
    Pourriez-vous m'aider à améliorer ce début de code?

    J'ai aussi un problème avec le grep
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $NumBact = 12;
    my @A_MauvaisesCombinaisons = qw[5-12 1-9 2-12 4-5 1-5];
    my @A_SelectMauvCombi = grep { $_ =~ /[ -]$NumBact[ -]/ } @A_MauvaisesCombinaisons;
    map{print $_."\n";}@A_SelectMauvCombi;
    Je voudrais sélectionner 5 et 2 qui sont associés à 12.


    Merci pour votre aide,


    Jasmine,

  2. #2
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 58

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    A propos du grep.

    Pour les mauvaises combinaisons à gauche (et symétriquement pour à droite) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my @A_SelectMauvCombi = grep { s/-$NumBact// } @A_MauvaisesCombinaisons;
    Pour avoir les deux (à droite et à gauche), tu peux faire un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    my @A_SelectMauvCombi = map { $1 if /(\d+)-$NumBact/ or /$NumBact-(\d+)/ } 
                                grep { /$NumBact/ } @A_MauvaisesCombinaisons;

  3. #3
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Merci pour ta réponse, je vais faire comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    my @A_SelectMauvCombi = map { $1 if /(\d+)-$NumBact/ or /$NumBact-(\d+)/ }
                            grep { /$NumBact/ } @A_MauvaisesCombinaisons;
    @A_MauvaisesCombinaisons = grep  { $_ !~  /-$NumBact/ or  /$NumBact-/ } @A_MauvaisesCombinaisons;
    Jasmine,

  4. #4
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 58

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    De rien.

    Pour la question principale, je vois bien ce que fait l'algorithme mais je n'ai pas bien compris ce que tu veux précisément. Et donc comment améliorer.

    Qu'entends-tu exactement par
    Recherche les numéros par bactérie en évitant les mauvaises combinaisons
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Il faut favoriser les numéros des bactéries les moins représentées

  5. #5
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Merci beaucoup pour ton aide.


    Je vais essayer d'expliquer concrètement.
    Recherche les numéros par bactérie en évitant les mauvaises combinaisons
    J'ai une liste de bactéries. A chaque bactérie est associée une série de fragments d'ADN. Je dois parmi ces fragments en sélectionner un groupe représentant l'ensemble de mes bactéries. Il faut donc au minimum retrouver 1 fragment par bactérie. L'ennui est que certains de ces fragments sont imcompatibles entre eux et je dois donc veiller à ne pas les retrouver associer ensemble dans ma sélection.
    Chacun de mes fragments est associé à un numéro.
    Il faut favoriser les numéros des bactéries les moins représentées
    Je veux dire que je dois garder en priorité les fragments des bactéries n'ayant qu'un seul fragment. Dans mon exemple je ne dois pas supprimer le 12 sinon je perds la bactérie4. Je dois donc commencer par supprimer le 5 et le 2 qui sont imcompatibles avec le 12. Si j'avais commencé par supprimer ce qui est imcompatibles avec le 5, j'aurais perdu le 12 et donc la bactérie4.

    Est-ce plus clair ainsi?



    Voici quelques valeurs
    # 843 mauvaises combinaisons pour 347 numéros au total repartis sur 82 bactéries
    #
    Nbr de fragments par bactérie => Nbr de bactéries ayant ce nombre de fragments
    1 => 37
    2 => 17
    3 => 6
    4 => 3
    5 => 3
    6 => 4
    7 => 1
    8 => 2
    9 => 1
    10 => 2
    11 => 1
    13 => 2
    21 => 1
    25 => 1
    71 => 1
    Donc, j'ai 37 bactéries n'étant représentées que par un seul fragment que je dois favoriser dans ma sélection. Par contre pour la bactérie ayant 71 fragments, je peux en supprimer jusqu'à 70.


    Vu ces chiffres j'aimerais savoir si il est utile de créer un 'hash inversé' %H_Num ou vaut il mieux reparcourir à chaque fois %H_Bact:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    my %H_Bact = (
                    'Bact1' => [1, 2, 3, 4],
                    'Bact2' => [5, 6],
                    'Bact3' => [7, 8, 9, 10, 11],
                    'Bact4' => [12],
                    );
    # 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_Bact => clé : bactérie    valeur : liste des numéros correspondants
    # %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;
            }
    }
    Petit à petit, l'oiseau fait son nid mon script progresse.


    Merci,


    Jasmine,

  6. #6
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 58

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    Personnellement, j'aurais opté spontanément par un hash 'inversé' sur les fragments (comme tu le proposes dans ton dernier post).

    D'un autre côté la question de la minimisation ne me paraît pas triviale.

    (Pas sûr d'avoir vraiment fait avancer le schmilblick)

  7. #7
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Voici mon script actuel.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #!/usr/local/bin/perl
     
    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++)
    {
            # 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{$_}}}=$_;
                    push(@A_Tailles, @{$H_Bact{$_}});
            };
            # recherche de la taille la plus petite
            @A_Tailles = (sort {$a<=>$b} @A_Tailles);
            my $TailleArrayBact = $A_Tailles[0];
            # 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;
            # Liste des numéros à garder (pour le cycle suivant)
            @A_MauvaisesCombinaisons = grep  { $_ !~  /-$NumBact/ or  /$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/ or  /$NumIncompatible-/ } @A_MauvaisesCombinaisons;
     
            }
     
            print "Numéro à analyser\t$Bact\t$NumBact\n";
            print "Numéro incompatibles à supprimer\n";
            map{print $_."\n";}@A_SelectMauvCombi;
            print "\n\n";
    }
    L'ennui est qu'après le premier cycle, quand j'ai remis à jour @A_MauvaisesCombinaisons (retirer les combinaisons déjà traitées et celles qui n'ont plus lieu d'être car elles étaient associées à un numéro/fragment qui a été éliminé du lot), dans mon second cycle, c'est @A_MauvaisesCombinaisons de départ qui est repris.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    i = 0	ANALYSE DE Bact4	12
    Numéro incompatible à supprimer	Bact1	2
    Mauvaises combinaisons restantes après le retrait de 2
    	1-9
    	4-5
    	1-5
    	2-6
    Numéro incompatible à supprimer	Bact2	5
    Mauvaises combinaisons restantes après le retrait de 5
    	1-9
    	2-6
     
    i = 1	ANALYSE DE Bact2	6
    Numéro incompatible à supprimer	Bact1	2
    Mauvaises combinaisons restant après le retrait de 2
    	1-9
    Après le premier cycle, on retire le fragment 2 et le 5, dans @A_MauvaisesCombinaisons il ne reste plus que 1-9
    ...
    car 2-12 5-12 supprimés car ils contiennent 12
    4-5 1-5 supprimés car ils contiennent 5
    2-6 supprimé car il contien 2
    il ne reste plus que 1-9

    Or au second cycle pour i = 1 ANALYSE DE Bact2 6
    On retombe à nouveau sur 'Bact1 2' à supprimer.

    Cela montre donc que les valeurs retirées de @A_MauvaisesCombinaisons, n'ont pas été prises en compte au second cycle.

    Il y a eu il y a peu le même genre de problème posé sur ce forum, il avait fallu faire un sous programme qui remettait à jour les valeurs... mais je ne sais pas comment faire dans mon cas.

    Désolée si ce n'est pas clair pose moi des questions, je fais de mon mieux afin d'expliquer.


    Merci beaucoup,


    Jasmine,

  8. #8
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 58

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    [idée bête]

    Et si tu faisais une copie de @A_MauvaisesCombinaisons à l'entrée de la boucle et travaillait dessus dans le corps de la boucle ?

    Enfin, j'ai peut être mal compris, et juste là je n'ai pas le temps de tester.

    Bon courage.

  9. #9
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Une copie? Que veux-tu dire?
    Je déclare @A_MauvaisesCombinaisons avant de commencer ma boucle
    Puis au début de la boucle ? Comment faire une copie de mon nouveau @A_MauvaisesCombinaisons qui a changé au cours de la boucle?
    J'ai essayé en 1ière ligne dans la boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @A_MauvaisesCombinaisons = @A_MauvaisesCombinaisons;
    mais cela ne fait rien.

    J'ai essayé de réécrire des explications plus clairement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #  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
    Un grand merci,


    Jasmine,

  10. #10
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Je viens de me rendre compte que le problème est avant, c'est peut-être pas @A_MauvaisesCombinaisons.

    i = 0 ANALYSE DE Bact4 12
    Numéro incompatible à supprimer Bact1 2
    Mauvaises combinaisons restantes après le retrait de 2
    1-9
    4-5
    1-5
    2-6
    Numéro incompatible à supprimer Bact2 5
    Mauvaises combinaisons restantes après le retrait de 5
    1-9
    2-6
    Pour 5, 1-5 et 4-5 sont bien enlevés par contre, je ne sais pas pourquoi mais pour 2 2-6 n'est pas enlevé comme il le devrait ... il est donc normal qu'au second cycle, on retombe sur ce numéro 2 à enlever.

    J'ai pourtant bien mis le tiret à gauche ou à droite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @A_MauvaisesCombinaisons = grep  { $_ !~  /-$NumIncompatible/ or  /$NumIncompatible-/ } @A_MauvaisesCombinaisons;
    Je dois peut-être mettre deux fois !~ ou utiliser des parenthèses afin de regrouper les //or//


    Je vais reprendre des forces et m'aérer le cerveau et je m'y remets.


    Merci,

    Jasmine,

  11. #11
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 58

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    Cela montre donc que les valeurs retirées de @A_MauvaisesCombinaisons, n'ont pas été prises en compte au second cycle.
    Je disais juste que si tu veux travailler sur l'ensemble des valeurs à chaque cycle, tu peux faire une copie de @A_MauvaisesCombinaisons à l'entrée de la boucle et travailler dessus ensuite

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for () {
        my @copy = @A_MauvaisesCombinaisons;
        # ...
        my @A_SelectMauvCombi = map { $1 if /(\d+)-$NumBact/ or /$NumBact-(\d+)/ } 
                                grep { /$NumBact/ } @A_MauvaisesCombinaisons;
        # ...
    }
    Mais en même temps, j'ai aussi l'impression que ton algo suppose qu'on ignore ces valeurs une fois pour toute.

    Humm, pas sûr d'être très utile avec ces 2 derniers posts.

  12. #12
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Humm, pas sûr d'être très utile avec ces 2 derniers posts.
    Au moins, je ne me sens pas seule, c'est bien gentil de ta part d'essayer de m'aider.
    Je disais juste que si tu veux travailler sur l'ensemble des valeurs à chaque cycle
    Non, justement, c'est ce que je ne veux pas! Sinon ça serait une boucle sans fin vu que le but est d'arriver à vider complètement @A_MauvaisesCombinaisons et à nettoyer %H_Bact. Quand mon programme sera au point, for(my $i=0; $i<4; $i++) sera d'ailleurs remplacé par while(@A_MauvaisesCombinaisons !=0).

    Le problème est que quand $NumIncompatible est à droite du tiret il est supprimé et dans le cas contraire il ne l'est pas. C'est donc un petit truc qui manque dans le grep.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    my $NumBact = 12;
    my @A_MauvaisesCombinaisons = qw[5-12 1-9 2-12 4-5 1-5 12-8];
     
    my @A_SelectMauvCombi = map { $1 if /(\d+)-$NumBact/ or /$NumBact-(\d+)/ }
                            grep { /$NumBact/ } @A_MauvaisesCombinaisons;
    @A_MauvaisesCombinaisons = grep  { $_ !~  /-$NumBact/ or  /$NumBact-/ } @A_MauvaisesCombinaisons;
     
    map{print $_."\n";}@A_SelectMauvCombi;
     
    map{print $_."\n";}@A_MauvaisesCombinaisons;
    12-8 devrait disparaitre de @A_MauvaisesCombinaisons car il contient 12 or seuls 5-12 et 2-12 sont supprimés.


    En singeant ton premier post il faudrait quelque chose du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @A_MauvaisesCombinaisons = map { $1 unless /(\d+-$NumBact)/ or /($NumBact-\d+)/ }
                                grep { /$NumBact/ } @A_MauvaisesCombinaisons;
    ... mais qui fonctionne.
    De plus $1 n'est pas utile vu que je veux tout récupérer et non une sous partie.

    Merci,


    Jasmine,

  13. #13
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    J'ai trouvé ... je me compliquais trop les choses!
    Un problème de moins
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @A_MauvaisesCombinaisons = grep  { $_!~/$NumBact-/ and $_!~/-$NumBact/ } @A_MauvaisesCombinaisons;
    Jasmine,

  14. #14
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Maintenant, le problème est que ma boucle est infinie.
    Numéro à analyser Bact4 12
    Numéro incompatibles à supprimer
    5
    2
    Mauvaises combinaisons restant pour le cycle suivant
    => 1-9


    Numéro à analyser Bact2 6
    Numéro incompatibles à supprimer
    Mauvaises combinaisons restant pour le cycle suivant
    => 1-9


    Numéro à analyser Bact2 6
    Numéro incompatibles à supprimer
    Mauvaises combinaisons restant pour le cycle suivant
    => 1-9


    Numéro à analyser Bact2 6
    Numéro incompatibles à supprimer
    Mauvaises combinaisons restant pour le cycle suivant
    => 1-9
    Je boucle sur Bact2 6 car elle reste toujours la bactérie pour laquelle j'ai le moins de fragments.

    Il faudrait faire quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
            # 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;
    =h
            # 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";
     
                    }
            }
    =cut
     
            # Liste des numéros à garder (pour le cycle suivant)
            @A_MauvaisesCombinaisons = grep  { $_!~/$NumBact-/ and $_!~/-$NumBact/ } @A_MauvaisesCombinaisons;

    Merci,

    Jasmine,

  15. #15
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Voici la dernière version de mon script si tu as encore un peu le courage de m'aider.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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";
     
    }
    Je bloque sur cette partie ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
            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";
     
                    }
    Il faut peut-être créer une fonction récursive au lieu de faire un copier coller d'une partie de mon script plus haut.
    Le but de ce while(!@A_SelectMauvCombi) est d'éviter un array vide qui génère une boucle infinie dans ma boucle principale.


    Merci beaucoup ,

    Jasmine,

  16. #16
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Ok, voici ma solution, elle trouve toujours une solution si il en existe une, et signale qu'il est impossible d'en trouver une sinon. Elle devrait être plutôt efficace.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #!/usr/bin/perl
    use strict; use warnings;
     
    my %h_bact = (
    	      'Bact1' => [1, 2, 3, 4],
    	      'Bact2' => [5, 6],
    	      'Bact3' => [7, 8, 9, 10, 11],
    	      'Bact4' => [12],
    	     );
     
    my @a_mauvaises_combinaisons = qw[5-12 1-9 2-12 4-5 1-5];
     
    my %bad_combis;
    for my $combi (@a_mauvaises_combinaisons) {
      $combi =~ m/(\d+)-(\d+)/;
      push @{$bad_combis{$1}}, $2;
      push @{$bad_combis{$2}}, $1;
    }
     
    my %finished;
    my @to_handle = grep {@{$h_bact{$_}} == 1} keys %h_bact;
     
    while( @to_handle ) {
      for my $bact (@to_handle) {
        my $adn = $h_bact{$bact}[0];
        delete_uncompatibles($adn);
        delete_combis($adn);
        $finished{$bact} = 1;
      }
      @to_handle = grep {@{$h_bact{$_}} == 1 && not $finished{$_}} keys %h_bact;
    }
     
    my @rest = grep {@{$h_bact{$_}} > 1} keys %h_bact;
     
    for my $bact (@rest) {
      for my $adn (@{$h_bact{$bact}}) {
        my $update = maybe_delete_uncompatibles($adn);
        if( defined $update ) {
          %h_bact = %{$update};
          delete_combis($adn);
        }
        else {
          delete_one($adn);
          delete_combis($adn);
        }
      }
    }
     
    use Data::Dumper;
    print Dumper(\%h_bact);
     
    sub delete_uncompatibles {
      my $adn = shift;
      if( exists $bad_combis{$adn} ) {
        my @uncompatibles = @{$bad_combis{$adn}};
        for my $bact (keys %h_bact) {
          next if $finished{$bact};
          $h_bact{$bact} = [grep {not in($_, @uncompatibles)} @{$h_bact{$bact}}];
          die "Tache impossible, une bacterie a perdu tout ses fragments\n"
    	unless @{$h_bact{$bact}};
        }
      }
    }
     
    use Storable qw/dclone/;
    sub maybe_delete_uncompatibles {
      my $adn = shift;
      if( exists $bad_combis{$adn} ) {
        my %copy = %{dclone(\%h_bact)};
        my @uncompatibles = @{$bad_combis{$adn}};
        for my $bact (keys %copy) {
          next if $finished{$bact};
          $copy{$bact} = [grep {not in($_, @uncompatibles)} @{$copy{$bact}}];
          return unless @{$copy{$bact}};
        }
        return \%copy;
      }
      return \%h_bact;
    }
     
    sub delete_one {
      my $adn = shift;
      for my $bact (keys %h_bact) {
        next if $finished{$bact};
        $h_bact{$bact} = [grep {not $adn == $_} @{$h_bact{$bact}}];
        die "Tache impossible, une bacterie a perdu tout ses fragments\n"
          unless @{$h_bact{$bact}};
      }
    }
     
    sub delete_combis {
      my $adn = shift;
      if( exists $bad_combis{$adn} ) {
        for my $adn2 (@{$bad_combis{$adn}}) {
          $bad_combis{$adn2} = [grep {not $adn == $_} @{$bad_combis{$adn2}}];
        }
        delete $bad_combis{$adn};
      }
    }
     
    # tools
    use List::Util qw/first/;
    sub in {
      my $searched = shift;
      return first {$searched == $_} @_;
    }
    --
    Jedaï

  17. #17
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Merci beaucoup Jedai. Je pars demain matin en Normandie, mais je testerai cela dès mon retour au boulot, lundi matin.

    Jasmine,

  18. #18
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    J'essaie de comprendre ce programme et j'ai quelques questions.

    Je ne comprends pas l'utilité de la fonction dclone
    # module Storable : http://search.cpan.org/~ams/Storable-2.18/Storable.pm
    # The Storable package brings persistence to your Perl data structures containing SCALAR, ARRAY, HASH
    # or REF objects, i.e.anything that can be conveniently stored to disk and retrieved at a later time
    # Storable provides you with a dclone interface which freezes the structure
    # in some internal memory space and then immediately thaws it out.
    A quoi cela sert-il de 'congeler' mes données dans la mémoire du PC pour les 'décongeler' ensuite?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # tools
    # sous-programme in
    # retourne la première valeur de @_ pour laquelle $searched == $_
    # @_  Tableau contenant les paramètres des routines
     
    use List::Util qw/first/;
    sub in
    {
      my $searched = shift;
      return first {$searched == $_} @_;
    }
    Je ne comprends pas à quoi sert ce sous-programme.


    Merci.


    Jasmine,

  19. #19
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Jasmine80 Voir le message
    J'essaie de comprendre ce programme et j'ai quelques questions.

    Je ne comprends pas l'utilité de la fonction dclone
    A quoi cela sert-il de 'congeler' mes données dans la mémoire du PC pour les 'décongeler' ensuite?
    Et bien cela décrit ce que fait dclone() mais pas vraiment l'objectif de la chose... dclone() signifie deep clone et l'objectif est de faire une copie en profondeur, c'est à dire une copie qui copie récursivement le contenu des références contenues dans la structure, une copie qu'on peut modifier sans modifier l'original.

    Citation Envoyé par Jasmine80 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    use List::Util qw/first/;
    sub in
    {
      my $searched = shift;
      return first {$searched == $_} @_;
    }
    Je ne comprends pas à quoi sert ce sous-programme.
    Si tu lui donnes un élément et un tableau, il teste si l'élément est dans le tableau (numériquement).

    Et sinon, tu as essayé ton algorithme et le mien avec des entrées plus importantes ? Ca donne quoi (le mien peut encore être amélioré nettement).

    --
    Jedaï

  20. #20
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Oui mais
    Si tu lui donnes un élément et un tableau, il teste si l'élément est dans le tableau (numériquement).
    @_ Tableau contenant les paramètres des routines
    Cela teste quels paramètres?


    Dans le sous-programme delete_uncompatibles
    pourquoi fait-on
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     my @uncompatibles = @{$bad_combis{$adn}};
    On recopie le tableau sans le cloner mais cela ne modifie pas l'original car c'est un array et non un hash?


    Une de mes bactéries perd tous ses fragments Peut-être est-ce un problème impossible à résoudre.

    Comment puis-je poster mes fichiers textes contenant mes données?

    Merci,

    Jasmine,

Discussions similaires

  1. [WB16] Sélection dans une table non AJAX
    Par basam95 dans le forum WebDev
    Réponses: 0
    Dernier message: 06/02/2011, 16h37
  2. Recherche élément médian dans tableau non trié
    Par chicorico dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 27/05/2009, 18h39
  3. Tableau non contraint dans une structure
    Par chronos dans le forum C
    Réponses: 8
    Dernier message: 07/06/2007, 18h44
  4. Réponses: 13
    Dernier message: 19/03/2007, 17h55
  5. Ecrire dans un tableau html depuis une fonction js ?
    Par botanica dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 05/10/2005, 13h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo