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 :

Changer la numérotation d'un sommaire


Sujet :

Langage Perl

  1. #61
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    J'ai donc modifié toute l'algorithmique, et j'ai normalement limité au maximum le nombre de calcul de regexp (par ailleurs, l'algorithme ne fonctionne plus pas substitutions de valeurs, mais pas décomposition/recomposition de la liste d'indices d'un numéro de sommaire). Seules subsistent des tests de regexp pour les numéros à supprimer (post-fixés avec *).
    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
    # Philou67430_v3.pm
    package Philou67430_v3;
    use strict;
    use warnings;
    use feature qw(:5.10);
     
    sub transformateur {
      my $balaye = shift;
     
      my (@level, @current, @to_remove, %new_sections) = ();
      my %stats;
      my $a_la_volee = sub {
        my $num = shift;
        my $old_num = $num;
     
        my @num = split /-/, $num;
        my $level = @num - 1;
        push @level, [] if    $level > @level-1;
        pop  @level     while $level < @level-1;
     
        if ($num[-1] =~ s/\*$//) {
          push @to_remove, "^".quotemeta(join "-", @num).q{(?:-|\*?$)};
        }
        push @{$level[$level]}, $num[-1];
        if (@to_remove && $num =~ /$to_remove[-1]/) {
    	    $new_sections{ $old_num } = join "-", "0", @num ;
        }
        else {
          pop @to_remove;
    	    splice @current, $level, @current-$level, shift @{$level[$level]};
    	    $new_sections { $old_num } = join "-", @current ;
        }
      };
     
      $balaye->($a_la_volee, @_);
      return wantarray ? (\%new_sections, \@level, \%stats) : \%new_sections;
    }
     
    1;
    L'algo est neuf, donc à retester avec divers jeux de test, mais avec ce programme test.pl, il donne le résultat attendu.
    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
    # test.pl
    use strict;
    use warnings;
    use 5.010;
     
    sub try_load($;$) {
      my ($module, $catch) = @_;
      eval "use $module;";
      say $@ if $@;
      die !defined $catch ? "Please install module $module by calling\ncpan $module\n" :
        $catch if (!defined $catch || $catch) && $@;
      return !$@;
    }
     
    my $module = $ARGV[0] or die "Usage: $0 <module to check>\n";
    say "Loading module $module";
    try_load($module) or die "Failed !\n";
     
    # notre premiere fonction de balayage et modification de sommaire.
    sub balaye_et_modifie_liste {
        my ($renum, $liste) = @_;
        $_ = $renum->($_) for @$liste;
    }
     
    my @sections = qw(Un* Un-Foo Un-Bar Deux Deux-Foo* Deux-Bar Deux-Bar-One Deux-Bar-Two Deux-Bar-Three Trois* Trois-Foo Trois-Bar Quatre Quatre-Foo Quatre-Bar );
    my %new_sections = (
                      'Un*' => '0-Un',
                      'Un-Foo' => '0-Un-Foo',
                      'Un-Bar' => '0-Un-Bar',
                      'Deux' => 'Un',
                      'Deux-Foo*' => '0-Deux-Foo',
                      'Deux-Bar' => 'Un-Foo',
                      'Deux-Bar-One' => 'Un-Foo-One',
                      'Deux-Bar-Two' => 'Un-Foo-Two',
                      'Deux-Bar-Three' => 'Un-Foo-Three',
                      'Trois*' => '0-Trois',
                      'Trois-Foo' => '0-Trois-Foo',
                      'Trois-Bar' => '0-Trois-Bar',
                      'Quatre' => 'Deux',
                      'Quatre-Foo' => 'Deux-Foo',
                      'Quatre-Bar' => 'Deux-Bar'
                    );
    # voilà comment devrait être la liste après modifications
    my @voulu = map $new_sections{$_}, @sections;
     
    say "avant: @sections";
    {
      no strict qw(refs);
      &{$module."::transformateur"}(\&balaye_et_modifie_liste, \@sections);
    }
    say "apres: @sections";
    say "voulu: @voulu";
     
    use Test::More;
    is_deeply(\@sections, \@voulu, "notre première liste (" . scalar(@sections) . " éléments) a bien été modifiée comme attendu");
    done_testing;
    Reste à compléter ce plan de test.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  2. #62
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    @cmcmc : je n'ai pas encore compris (mais j'ai lu tes longs posts en diagonale, ce qui peut expliqué mon incompréhension) l'intérêt de la forme "alambiquée" pour appeler la fonction de transformation qui passe par plusieurs niveaux de callback, là où j'aurais simplement écrit dans test.pl :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @sections = &{$module."::transformateur"}(@sections);
    Quel est l'intérêt notamment de contrôler à l'extérieur du module fonctionnel, la boucle sur les différents éléments de @sections (à l'aide de la fonction "balaye_et_modifie_liste") ?
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #63
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    @cmcmc : je n'ai pas encore compris (mais j'ai lu tes longs posts en diagonale, ce qui peut expliqué mon incompréhension) l'intérêt de la forme "alambiquée" pour appeler la fonction de transformation qui passe par plusieurs niveaux de callback, là où j'aurais simplement écrit dans test.pl :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @sections = &{$module."::transformateur"}(@sections);
    Quel est l'intérêt notamment de contrôler à l'extérieur du module fonctionnel, la boucle sur les différents éléments de @sections (à l'aide de la fonction "balaye_et_modifie_liste") ?
    Le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @sections = &{$module."::transformateur"}(@sections);
    suppose que les sections sont déjà intégralement connues, et que @sections est de taille raisonnable. C'est peut-être le cas sur cet exemple particulier mais la raison d'être de transformateur est en fait de pouvoir traiter des valeurs à la volée pour des listes arbitraires.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    say "avant: @sections";
    CM_v2::transformateur(\&balaye_et_modifie_liste, \@sections);
    say "apres: @sections";
    Ce code fonctionne parce que balaye_et_modifie_liste fait exactement ce que son nom indique, à savoir balayer séquentiellement \@sections et la modifier en place, en remplaçant chaque valeur par le résultat de l'invocation sur cette valeur de la fonction qu'on lui passe en premier paramètre, en substance a_la_volee de transformateur. Il est plus économique que le code que tu suggérais ci-dessus (on économise en particulier la copie finale), mais devrait être réservé à des listes de petite taille.

    Cette approche à la volée est par ailleurs celle qui m'a permis de faire des tests de charge avec une liste (virtuelle) de 960799 entrées (voir test_CM_v2_lvr.pl, et les versions adaptées pour tes modules) : avec ton code ci-dessus j'aurais dû produire effectivement cette liste en mémoire (sans parler de la copie du résultat...), alors que là je ne manipule jamais plus d'un élément à la fois J'ai par ailleurs quelques idées pour une CM_v3 qui serait plus économique que la version courante (surtout si on peut jeter les numéros non renommés).

    On pourrait utiliser d'autres fonction de balayage, sans rien changer à transformateur, et c'est tout l'intérêt de l'approche. Comme je l'écrivais, Djibril pourrait développer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    sub balayage_et_modification_de_fichiers_xml_en_une_traite {
        my ($renum, @autres_parametre) = @_;
        for my $entree (recherche_des_entrees_de_sommaire(@autres_parametres)) {
            my $old = extraire_numero($entree); # ou peut-être $entree->numero()
            my $new = $renum->($old);
    	modifier_numero($entree, $new); # ou peut-être $entree->modifier_numero($new)
        }
    }
    et l'invoquer par un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CM_v2::transformateur(\&balayage_et_modification_de_fichiers_xml_en_une_traite, @autres_parametres)
    ou conserver son approche initiale et développer plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    sub balayage_et_modification_de_fichiers_xml_en_deux_passes {
        my ($renum, @autres_parametre) = @_;
        my @liste = extraire_le_sommaire_sous_forme_de_tableaux(@autres_parametres);
        my %hash = map { $_ => $renum->($_) } @liste;
        relire_les_fichiers_pour_appliquer_la_nouvelle_numerotation(%hash, @autres_parametres);
    }
    en l'invoquant comme suit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CM_v2::transformateur(\&balayage_et_modification_de_fichiers_xml_en_deux_passes, @autres_parametres)
    sans rien avoir d'autre à modifier. Ici c'est la fonction de balayage qui invoque les routines d'analyse et de modification XML, à la volée dans le premier cas, en deux passes analyse/modification séparées dans le second.

    Ceci dit, il y a des lourdeurs et des erreurs de nommage dans test_CM_v2_lvr.pl et les versions adaptées pour tes modules. Je suis en train de remanier le code pour aboutir à -- je l'espère -- quelque chose de plus clair. Mais pas avant demain (au plus tôt...).
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  4. #64
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    L'algo est neuf, donc à retester avec divers jeux de test...
    Reste à compléter ce plan de test.
    tu peux reprendre test_Philou67430_v2.pl donné ici, puis

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # perl -npe 's/Philou67430_v2/Philou67430_v3/' < test_Philou67430_v2.pl > test_Philou67430_v3.pl
    # perl test_Philou67430_v3.pl
    qui appliquera automatiquement les tests suivants :
    • aucun noeud n'est marqué
    • tous les noeuds sont marqués
    • tous les noeuds de profondeur 1 sont marqués sauf le dernier
    • les noeuds de profondeur 1 et d'index impair (1, 3, 5, ...) sont marqués
    • les noeuds de valeur k et parents k à la profondeur k sont marqués
    • marquage aléatoire (pas de vérification possible, sauf que la table produite est bijective)
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  5. #65
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    J'ai modifié le script de test pour qu'il prenne en paramètre le nom du module à tester (obligatoire en premier paramètre):
    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
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    # test2.pl
    use strict;
    use warnings;
    use feature qw(:5.10);
    use Test::More;
     
    sub try_load($;$) {
      my ($module, $catch) = @_;
      eval "use $module;";
      say $@ if $@;
      die !defined $catch ? "Please install module $module by calling\ncpan $module\n" :
        $catch if (!defined $catch || $catch) && $@;
      return !$@;
    }
     
    my $module = shift @ARGV or die "Usage: $0 <module to check> [nb max]\n";
    say "Loading module $module";
    try_load($module) or die "Failed !\n";
     
    # balaye une liste virtuelle régulière de profondeur $p (toplevel = 1, feuilles = p), 
    # avec $k noeuds à chaque niveau. 
    #  1 1-1 ... 1-k-..-k
    #  2 2-1 ... 2-k-..-k
    #  ...
    #  k k-1 ... k-k-..-k
    # cette liste contient k + k**2 + ... + k**p) élements
    #
    # appelle $process->($renum, $k, $p, $current, @rest) pour chacun des numéros $current de la liste. 
     
    sub balaye_lvr {
      my ($renum, $process, $k, $p, @rest) = @_;
      my $balaye;                  # fonction auxiliaire interne récursive
      $balaye = sub {
        my $parent = shift;
        $parent //= q{};
        for (1 .. $k) {
    	    my $current = $parent ? "$parent-$_" : $_;
    	    return if ($current =~ y/-/-/) >= $p;
    	    $process->($renum, $k, $p, $current, @rest);
    	    $balaye->($current);
        }
      };
      $balaye->();
    }
     
    sub taille {
      my ($k, $p) = @_;
      my $t = 0;
      $t = $k + $k*$t for (1 .. $p);
      $t
    }
     
    if (0) {
      sub show_list {
        my ($renum, $k, $p, $current) = @_;
        say +(q{  } x $current =~ y/-/-/), $current;
      }
     
      for my $k (1 .. 3) {
        for my $p (1 .. 3) {
    	    say "-------- show_list k = $k p = $p";
    	    balaye_lvr(undef, \&show_list, $k, $p);
        }
      }
    }
     
    # aucun noeud n'est marqué
    sub process_marque_aucun {
      my ($renum, $k, $p, $cur, $debug, $nb_errs_ref, $last_err_ref) = @_;
     
      # marquage et renumérotation
      my $old = $cur;
      my $new = $renum->($old);
      say +(q{  } x ($cur =~ y/-/-/)), sprintf("%-10s%-10s", $old, $new) if $debug;
     
      # vérification
      my $exp = $old;
     
      ++$$nb_errs_ref, warn "$old gave $new instead of $exp" unless $exp =~ m/^0-/ || $new eq $exp;
    }
     
    # tous les noeuds sont marqués
    sub process_marque_tous {
      my ($renum, $k, $p, $cur, $debug, $nb_errs_ref, $last_err_ref) = @_;
     
      # marquage et renumérotation
      my $old = "$cur*";
      my $new = $renum->($old);
      say +(q{  } x ($cur =~ y/-/-/)), sprintf("%-10s%-10s", $old, $new) if $debug;
     
      # vérification
      my $exp = "0-$cur";
     
      ++$$nb_errs_ref, warn "$old gave $new instead of $exp" unless $exp =~ m/^0-/ || $new eq $exp;
    }
     
    # Tous les noeuds de profondeur 1 sont marqués sauf le dernier : 
    # après modification tous les noeuds doivent être préfixés par 0
    # sauf les p derniers (k k.1 ... k-k..k) qui sont
    # transformés en      (1 1-1 ... 1-k..k)
    sub process_marque_top_sauf_k {
      my ($renum, $k, $p, $cur, $debug, $nb_errs_ref, $last_err_ref) = @_;
     
      # marquage et renumérotation
      my $old = ($cur =~ m/^\d+$/ && $cur != $k) ? "$cur*" : $cur;
      my $new = $renum->($old);
      say +(q{  } x ($cur =~ y/-/-/)), sprintf("%-10s%-10s", $old, $new) if $debug;
     
      # vérification
      my $exp = $cur =~ m/^$k-?/
        ? $cur =~ s/^\d+/1/r
          : "0-$cur";
     
      ++$$nb_errs_ref, warn "$old gave $new instead of $exp" unless $exp =~ m/^0-/ || $new eq $exp;
    }
     
    # les noeuds de profondeur 1 et d'index impaire (1, 3, 5, ...) sont marqués
    # après modification tous les noeuds dont le toplevel est d'index impair doivent être préfixés par 0
    # et les autres (n n-1 ... n-k..k) transformés en (m m-1 ... m-k..k) avec m = n/2
    sub process_marque_top_impair {
      my ($renum, $k, $p, $cur, $debug, $nb_errs_ref, $last_err_ref) = @_;
     
      # marquage et renumérotation
      my $old = (($cur =~ m/^\d+$/) and ($cur % 2)) ? "$cur*" : $cur;
      my $new = $renum->($old);
      say +(q{  } x ($cur =~ y/-/-/)), sprintf("%-10s%-10s", $old, $new) if $debug;
     
      # vérification
      my $exp = do {
        my ($top) = $cur =~ m/^(\d+)/;
        if ($top % 2) {
    	    "0-$cur";
        } else {
    	    $cur =~ s{^$top}{$top/2}e;
    	    $cur
        }
      };
     
      ++$$nb_errs_ref, warn "$old gave $new instead of $exp" unless $exp =~ m/^0-/ || $new eq $exp;
    }
     
    # les noeuds de valeur k et parents k à la profondeur k sont marqués :
    #>  1*  1-1   1-1-1   1-1-2   1-1-3   1-2   1-2-1   1-2-2   1-2-3   1-3   1-3-1   1-3-2   1-3-3
    #<  0-1 0-1-1 0-1-1-1 0-1-1-2 0-1-1-3 0-1-2 0-1-2-1 0-1-2-2 0-1-2-3 0-1-3 0-1-3-1 0-1-3-2 0-1-3-3
    #>  2   2-1   2-1-1   2-1-2   2-1-3   2-2*  2-2-1   2-2-2   2-2-3   2-3   2-3-1   2-3-2   2-3-3
    #<  1   1-1   1-1-1   1-1-2   1-1-3   0-2-2 0-2-2-1 0-2-2-2 0-2-2-3 1-2   1-2-1   1-2-2   1-2-3
    #>  3   3-1   3-1-1   3-1-2   3-1-3   3-2   3-2-1   3-2-2   3-2-3   3-3   3-3-1   3-3-2   3-3-3*
    #<  2   2-1   2-1-1   2-1-2   2-1-3   2-2   2-2-1   2-2-2   2-2-3   2-3   2-3-1   2-3-2   0-3-3-3
    sub process_marque_diagonale_k_k {
      my ($renum, $k, $p, $cur, $debug, $nb_errs_ref, $last_err_ref) = @_;
     
      # marquage et renumérotation
      my $is_marked;
      my $is_marked_or_after_marked = 1;
      {
        my @nums = split q{-}, $cur;
      loop:
        for (1 .. $nums[0]) {
    	    if (@nums < $nums[0]) {
            $is_marked_or_after_marked = 0;
            last loop
    	    }
    	    unless ($nums[$_-1] == $nums[0]) {
            $is_marked_or_after_marked = 0;
            last loop
    	    }
        }
        $is_marked = $is_marked_or_after_marked && ($nums[0] == scalar(@nums));
      }
      my $old = $is_marked ? "$cur*" : $cur;
      my $new = $renum->($old);
      say +(q{  } x ($cur =~ y/-/-/)), sprintf("%-10s%-10s", $old, $new) if $debug;
     
      # vérification
      my $exp = do {
        if ($is_marked_or_after_marked) {
    	    "0-$cur";
        } else {
    	    my @nums = split q{-}, $cur;
    	    my @orig = @nums;
    	    # pour décrémenter le nombre en position x
    	    # il faut que tous ses parents soient == x 
    	    # et que lui même soit >= x
    	  decrement:
    	    for my $depth (0 .. $#nums) { # x - 1 
            for (0 .. $depth-1) {
              next if $_ < 0;
              next decrement unless $orig[$_] == $depth + 1;
            }
            for ($depth) {
              next if $_ < 0;
              next decrement unless $orig[$_] >= $depth + 1;
            }
            --$nums[$depth];
    	    }
    	    join q{-}, @nums;
        }
      };
     
      ++$$nb_errs_ref, warn "$old gave $new instead of $exp" unless $exp =~ m/^0-/ || $new eq $exp;
    }
     
    # marque de manière aléatoire un pourcentage donné de noeuds
    # pas de vérification possible : on renvoie un nombre d'erreurs négatif
    sub process_marque_x_pourcent {
      my ($renum, $k, $p, $cur, $debug, $nb_errs_ref, $last_err_ref, $pourcentage) = @_;
      # marquage et renumérotation
      my $old = (rand(100) <= $pourcentage) ? "$cur*" : $cur;
      my $new = $renum->($old);
      say +(q{  } x ($cur =~ y/-/-/)), sprintf("%-10s%-10s", $old, $new) if $debug;
     
      # pas de vérification possible : on renvoie un nombre d'erreurs négatif
      --$$nb_errs_ref;
    }
     
    my $kmax = (shift @ARGV) // 3;
    for my $marquage (qw(aucun tous top_sauf_k top_impair diagonale_k_k 10 20 30 40 50)) {
      for my $k (2 .. $kmax) {
        my ($p, $debug, $nb_errs, $last_err) = ($k, $k <= 3, 0);
        my $taille_de_la_liste = taille($k,$p);
        my $process = sub {
    	    no strict 'refs';
    	    $marquage =~ m/^\d+$/ 
            ? "process_marque_x_pourcent"->(@_, $marquage)
              : "process_marque_$marquage"->(@_)
            };
        {
          no strict qw(refs);
          my ($new_sections)
            = &{$module."::transformateur"}(\&balaye_lvr, $process, $k, $p, $debug, \$nb_errs, \$last_err);
        }
        my $methode = $marquage =~ m/^\d+$/ ? "${marquage}_pourcent" : $marquage ;
        cmp_ok $nb_errs, "<=", 0, "[$methode k=$k p=$p] " . ($nb_errs == 0 ? "pas d'erreurs de numérotations observées" : "(non significatif : contrôle non effectué)");
        # my $ndkeys = keys %{$new_sections};
        # is $ndkeys, $taille_de_la_liste, "[$methode k=$k p=$p] le nombre de clés (old) est bien égal à taille de la liste";
        # my %new2old= reverse %{$new_sections};
        # my $ndvals = keys %new2old;
        # is $ndvals, $ndkeys, "[$methode k=$k p=$p] le nombre de valeurs (new) est égal au nombre de clés (old)";
      }
    }
     
    done_testing;
    Résultat des courses :
    - des warnings s'affichent concernant le splice (c'est une warning non bloquante, mais je vais tout de même le corriger)
    - des erreurs sont détectées, je me pencherai dessus demain.
    Dans tous les cas, le module de base a été sensiblement "simplifié"... peut-être trop pour certains cas d'usages (à voir).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  6. #66
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonsoir,

    le trafic est bien trop élevé sur ce post pour que je puisse suivre (il est rare que je puisse me connecter dans la journée, et plus rare encore que j'ai le temps de coder un truc digne de ce nom dans la journée), j'ai donc renoncé jusqu'à maintenant à participer à cette discussion animée et passionnante.

    Je voudrais cependant proposer une approche assez différente (me semble-t-il): (re)construire le sommaire à partir des niveaux, sans se préoccuper des numérotations d'origine (la fonction qui fera cela peut d'ailleurs avoir d'autres utilités).

    Pour illustrer cela, je me moque dans le code qui suit des numéros de paragraphes, seul m'intéressent les niveaux d'intertitrage. C'est pourquoi mes numéros de parties ont la forme anonyme "x x-x x x-x" et non "1 1-a 2 2-a", car les numéros eux-mêmes ne m'intéressent pas pour cette méthode, seul le niveau d'indentation compte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    my @master_list = qw / 1 a A/;
    my @level_list = qw /0 0 0/;
    my @sommaire = qw/ x x-x x x-x x-x x-x-x x x-x x-x-x x-x-x x-x-x x-x x-x-x x x-x x-x x-x-x x-x-x /;
    my @new_sommaire;
    for my $inter (@sommaire) {
    	my @fields = split /-/, $inter;
    	my $level = $#fields;
    	$level_list[$level]++ ;
    	$inter = join '-', @level_list[0..$level];
    	push @new_sommaire, $inter;
    	$level_list[$_] = 0  for ($level+1..2);
    }
    print "@new_sommaire \n";
    Ce qui imprime, pour le sommaire proposé:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ perl sommaire.pl
    1 1-1 2 2-1 2-2 2-2-1 3 3-1 3-1-1 3-1-2 3-1-3 3-2 3-2-1 4 4-1 4-2 4-2-1 4-2-2
    Il est trop tard maintenant pour que j'aie le temps de transformer les chiffres en lettres, mais ça doit pouvoir se faire sans trop de difficultés en 2 ou 3 lignes de code à partir de @master_list.

    Pour le lien entre les nouveaux et les anciens numéros, l'équivalence entre les tableaux @sommaire et @new_sommaire devraient suffire.

    Bien sûr, l'utilisation du code ci-dessus pré-suppose d'avoir préalablement viré les parties que l'on ne souhaite pas garder du sommaire d'origine (au lieu de seulement les marquer d'une étoile), mais cette transformation est assez triviale, me semble-t-il.

    NB: avec quelques essais, il doit être possible d'améliorer l'idée. J'ai adopté des valeurs numériques parce que je ne voulais pas me casser la tête à initialiser une numérotation de type (a b c) à 0 (c'est-à-dire a - 1). Mais ça ne doit pas être trop difficile, j'imagine, en initialisant les valeurs au code ASCII juste en-dessous de 'a' ou de 'A'. Je n'ai juste pas le temps de le faire et de le tester maintenant, je bosse tôt demain, je devrais déjà être couché depuis un bon moment.

  7. #67
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Bonsoir,

    le trafic est bien trop élevé sur ce post pour que je puisse suivre (il est rare que je puisse me connecter dans la journée, et plus rare encore que j'ai le temps de coder un truc digne de ce nom dans la journée), j'ai donc renoncé jusqu'à maintenant à participer à cette discussion animée et passionnante.

    Je voudrais cependant proposer une approche assez différente (me semble-t-il): (re)construire le sommaire à partir des niveaux, sans se préoccuper des numérotations d'origine (la fonction qui fera cela peut d'ailleurs avoir d'autres utilités).

    Pour illustrer cela, je me moque dans le code qui suit des numéros de paragraphes, seul m'intéressent les niveaux d'intertitrage. C'est pourquoi mes numéros de parties ont la forme anonyme "x x-x x x-x" et non "1 1-a 2 2-a", car les numéros eux-mêmes ne m'intéressent pas pour cette méthode, seul le niveau d'indentation compte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    my @master_list = qw / 1 a A/;
    my @level_list = qw /0 0 0/;
    my @sommaire = qw/ x x-x x x-x x-x x-x-x x x-x x-x-x x-x-x x-x-x x-x x-x-x x x-x x-x x-x-x x-x-x /;
    my @new_sommaire;
    for my $inter (@sommaire) {
    	my @fields = split /-/, $inter;
    	my $level = $#fields;
    	$level_list[$level]++ ;
    	$inter = join '-', @level_list[0..$level];
    	push @new_sommaire, $inter;
    	$level_list[$_] = 0  for ($level+1..2);
    }
    print "@new_sommaire \n";
    Ce qui imprime, pour le sommaire proposé:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ perl sommaire.pl
    1 1-1 2 2-1 2-2 2-2-1 3 3-1 3-1-1 3-1-2 3-1-3 3-2 3-2-1 4 4-1 4-2 4-2-1 4-2-2
    Il est trop tard maintenant pour que j'aie le temps de transformer les chiffres en lettres, mais ça doit pouvoir se faire sans trop de difficultés en 2 ou 3 lignes de code à partir de @master_list.

    Pour le lien entre les nouveaux et les anciens numéros, l'équivalence entre les tableaux @sommaire et @new_sommaire devraient suffire.

    Bien sûr, l'utilisation du code ci-dessus pré-suppose d'avoir préalablement viré les parties que l'on ne souhaite pas garder du sommaire d'origine (au lieu de seulement les marquer d'une étoile), mais cette transformation est assez triviale, me semble-t-il.

    NB: avec quelques essais, il doit être possible d'améliorer l'idée. J'ai adopté des valeurs numériques parce que je ne voulais pas me casser la tête à initialiser une numérotation de type (a b c) à 0 (c'est-à-dire a - 1). Mais ça ne doit pas être trop difficile, j'imagine, en initialisant les valeurs au code ASCII juste en-dessous de 'a' ou de 'A'. Je n'ai juste pas le temps de le faire et de le tester maintenant, je bosse tôt demain, je devrais déjà être couché depuis un bon moment.
    tu peux remplacer la ligne 11 ci-dessus par la forme (à proscrire )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	$level_list[@fields] = 0;
    ou si tu préfères
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	$level_list[$level+1] = 0;
    Il me semble cependant que c'est exactement le mécanisme utilisé dans toutes les solutions que j'ai proposées, par exemple ici (l'étape critique ligne 5, correspondant à ta ligne 11 ci-dessus, avait malencontreusement disparu des précédentes versions suite à une erreur d'édition sur la première ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        ....
        map {
    	my @n = split q{-};
    	++$d[$#n];
    	$d[@n] = 0;
    	my $x = join q{-}, map { $fmt{$t[$_]}{ntoa}->($d[$_]) } 0 .. $#n;
    	$p{$x} = $_;
    	$x;
        } grep {
    	...
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  8. #68
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Voici une version de mon programme donnant les numérotations sous une forme 1.a.A et non plus 1.1.1:

    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
    my @master_list = qw / 1 a A/;
    my @level_list = qw /0 0 0/;
    my @sommaire = qw/ x x-x x x-x x-x x-x-x x x-x x-x-x x-x-x x-x-x x-x x-x-x x x-x x-x x-x-x x-x-x /;
    my @new_sommaire;
    for my $inter (@sommaire) {
    	my @fields = split /-/, $inter;
    	my $level = $#fields;
    	$level_list[$level]++ ;
    	my @out;
    	for (0..$#master_list) {
    		my $i = $master_list[$_];
    		$i++ for (0..$level_list[$_]-2);
    		push @out, $i;
    	}  
    	$inter = join '-', @out[0..$level];
    	push @new_sommaire, $inter;
    	$level_list[$_] = 0  for ($level+1..$#master_list);
    }
    print "@new_sommaire \n";
    Ce qui imprime:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $perl   sommaire.pl
    1 1-a 2 2-a 2-b 2-b-A 3 3-a 3-a-A 3-a-B 3-a-C 3-b 3-b-A 4 4-a 4-b 4-b-A 4-b-B

  9. #69
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Voici une version de mon programme donnant les numérotations sous une forme 1.a.A et non plus 1.1.1:

    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
    my @master_list = qw / 1 a A/;
    my @level_list = qw /0 0 0/;
    my @sommaire = qw/ x x-x x x-x x-x x-x-x x x-x x-x-x x-x-x x-x-x x-x x-x-x x x-x x-x x-x-x x-x-x /;
    my @new_sommaire;
    for my $inter (@sommaire) {
    	my @fields = split /-/, $inter;
    	my $level = $#fields;
    	$level_list[$level]++ ;
    	my @out;
    	for (0..$#master_list) {
    		my $i = $master_list[$_];
    		$i++ for (0..$level_list[$_]-2);
    		push @out, $i;
    	}  
    	$inter = join '-', @out[0..$level];
    	push @new_sommaire, $inter;
    	$level_list[$_] = 0  for ($level+1..$#master_list);
    }
    print "@new_sommaire \n";
    L'initialisation de @level_list en ligne 2 ne sert à rien, pas plus que la partie ..$#master_list de la ligne 17 (bis repetita, sous une autre forme )

    Je sais que tu n'as pas eu le temps de tout lire dans la discussion, mais tu pourrais être intéressé par CM_v2.pm dans ce message qui montre qu'on peut se passer d'expliciter le type de numérotation utilisé à chaque niveau, le programme pouvant le détecter lui même (et s'adapter à une numérotation quelconque, en serbo-croate ou en klingon si nécessaire ), auquel cas on n'a pas besoin d'initialiser @master_list en ligne 1, et donc pas besoin de connaître a priori la profondeur du sommaire
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  10. #70
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    tu peux remplacer la ligne 11 ci-dessus par la forme (à proscrire )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	$level_list[@fields] = 0;
    ou si tu préfères
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	$level_list[$level+1] = 0;
    Oui, je peux le faire, mais c'est bien moins clair et, surtout, ça ne fait pas la même chose.

    De même, ma variable $level est inutile, mais utiliser des variables intermédiaires avec un nom significatif est à mes yeux une bonne façon d'auto-commenter le code.

  11. #71
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    L'initialisation de @level_list en ligne 2 ne sert à rien,
    Oui, tu sembles penser que la clarté ne sert à rien. Pourtant, un peu plus de clarté dans le code que tu as proposé dans un autre post t'aurait permis de ne pas avoir à l'expliquer en trois pages. Tu aurais gagné pas mal de temps.

    Citation Envoyé par cmcmc Voir le message
    on peut se passer d'expliciter le type de numérotation utilisé à chaque niveau, le programme pouvant le détecter lui même (et s'adapter à une numérotation quelconque, en serbo-croate ou en klingon si nécessaire ), auquel cas on n'a pas besoin d'initialiser @master_list en ligne 1, et donc pas besoin de connaître a priori la profondeur du sommaire
    Mon but était de définir le format de sortie, indépendamment du format en entrée. Mon programme peut servir à transformer automatiquement un sommaire de type A-a-1 et un format du type 1-A-a. Et (sous réserve d'éventuels bugs, je n'ai sans doute pas testé tous les cas de figure), il marche même sur un format tout pourri du type x-x-x.

  12. #72
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    hmmm, c'est dommage que le bouton citer ne reprenne pas l'intégralité des messages...

    Citation Envoyé par Lolo78 Voir le message
    Oui, je peux le faire, mais c'est bien moins clair et, surtout, ça ne fait pas la même chose.
    Cette phrase pourrait avoir un sens si on comprenait à quoi elle s'applique... Reprenons le contexte. Je propose de remplacer la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $level_list[$_] = 0  for ($level+1..2);
    par l'une ou l'autre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $level_list[@fields] = 0;
    $level_list[$level+1] = 0;
    pour deux raisons (non explicitées, car je pense m'adresser à un programmeur confirmé qui saisira l'indice):
    • le code est limité à des sommaires de profondeur 3 car au delà cette instruction critique ne sera pas exécutée. C'est corrigé dans la version suivante mais...
    • l'itération ne sert à rien : les éléments d'index supérieur à $level+1 seront automatiquement remis à zéro lors du passage par leur parent. Pour un sommaire régulier de facteur de branchement k et de profondeur p, cela résulte en k + k**2 + ... + k**(p-2) opérations inutiles lors du balayage des noeuds de niveau 1, plus k + k**2 + ... + k**(p-3) au niveau 2, etc.

    Donc effectivement ça ne fait pas la même chose.

    Quant à la clarté, on pourrait gloser sur les subtilités de précédence nécessaires pour analyser la condition du for en question mais je vais m'abstenir... Je n'ose pas imaginer que tu penses sérieusement que cette itération éclaire le code de quelque façon que ce soit. Je pense donc que tu fais référence à ma mention de @fields en contexte scalaire. C'était peut être inutilement provocateur, en référence amicale à ta prise de position ici, et d'ailleurs assorti d'un smiley. La signification de @fields en contexte scalaire est parfaitement définie, c'est la taille du tableau @fields, ce qui d'un point de vue algorithmique est exactement ce qu'on veut ici. Tu préfères utiliser $level initialisé à $#fields, qui est égal (si on n'a pas joué par ailleurs avec $[ ou arybase) à @fields-1, en lui ajoutant 1. Dans la mesure où tu t'es donné la peine de définir $level, c'est raisonnable et ma critique ne portait pas là dessus.

    De même, ma variable $level est inutile, mais utiliser des variables intermédiaires avec un nom significatif est à mes yeux une bonne façon d'auto-commenter le code.
    Peut-être, pour autant qu'on comprenne de quel level on parle. Mais je ne vois pas le rapport. Et pour ma part, ma première priorité serait de documenter les constantes comme le 2 de la boucle for.

    Citation Envoyé par Lolo78 Voir le message
    Oui, tu sembles penser que la clarté ne sert à rien. Pourtant, un peu plus de clarté dans le code que tu as proposé dans un autre post t'aurait permis de ne pas avoir à l'expliquer en trois pages. Tu aurais gagné pas mal de temps.
    En parlant de clarté, ça ne te coûterait pas bien cher de mettre un lien sur le post en question. En l'état, j'en suis réduit aux conjectures et suppose que parmi mes posts récents il doit s'agir de celui là (n'hésite pas à me corriger si ce n'est pas le cas). Effectivement, je gagnerais pas mal de temps à ne pas chercher à faire ressentir l'expressivité, l'élégance et la puissance de Perl à des débutants peut-être englués dans leurs réflexes C ou Java ou que sais-je encore. Mais il me semble que tu fais un amalgame entre clarté et verbosité, et entre concision et opacité. Pour ton information, la discussion en question est loin d'être terminée pour peu que l'interlocuteur cible se donne un peu de peine. Et je dois dire que je suis un peu interloqué de cette critique de la part d'un auteur de tutoriel, donc quelqu'un qui doit (devrait ?) se poser des problèmes de pédagogie, et qui plus est se permet de citer MJD en introduction (je n'ai pas encore attaqué la suite)... Mais si tu veux poursuivre ces points, aie s'il te plaît l'obligeance de le faire sur le fil en question, un nouveau fil, ou par MP.

    Quoi qu'il en soit tu es encore passé à côté de ma remarque. L'initialisation de @level_list en ligne 2 ne sert à rien parce que ses éléments d'index supérieur à 0 seront remis à zéro (de multiples fois si tu conserves le for en ligne 17) avant d'être lus. Quant à l'élément d'index 0, il est initialisé à 1 au premier passage par la ligne 8
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $level_list[$level]++ ;
    Si l'incrémentation d'un undef (construction pourtant courante et parfaitement respectable en Perl) te pose problème, tu pourrais à la rigueur initialiser la liste avec le scalaire 0.

    Mais par ailleurs, avec l'introduction de @master_list, dont la taille semble maintenant dimensionner celle des sommaires traitables par ton code (si j'en juge par l'introduction de $#master_list en ligne 17), on se retrouve avec deux listes littérales de même taille. Si une initialisation était réellement nécessaire, il serait préférable de l'écrire sous l'une des formes suivantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my @level_list = (0) x @master_list; # OK, je sors :lol:
    my @level_list = (0) x ($#master_list + 1);
    my @level_list = map {0} @master_list;
    my @level_list; $level_list[$_] = 0 for 0 .. $#master_list;
    ou une autre forme pourvu qu'elle prenne en compte automatiquement toute évolution de @master_list afin de ne pas avoir à intervenir en deux endroits si l'on veut modifier la profondeur admissible.

    Mon but était de définir le format de sortie, indépendamment du format en entrée. Mon programme peut servir à transformer automatiquement un sommaire de type A-a-1 et un format du type 1-A-a. Et (sous réserve d'éventuels bugs, je n'ai sans doute pas testé tous les cas de figure), il marche même sur un format tout pourri du type x-x-x.
    Il me semble que ce potentiel a déjà été évoqué dans la discussion que tu ne t'es pas donné la peine de lire mais merci pour cette contribution.
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  13. #73
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Cette phrase pourrait avoir un sens si on comprenait à quoi elle s'applique... Reprenons le contexte. Je propose de remplacer la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $level_list[$_] = 0  for ($level+1..2);
    par l'une ou l'autre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $level_list[@fields] = 0;
    $level_list[$level+1] = 0;
    pour deux raisons (non explicitées, car je pense m'adresser à un programmeur confirmé qui saisira l'indice):
    • le code est limité à des sommaires de profondeur 3 car au delà cette instruction critique ne sera pas exécutée. C'est corrigé dans la version suivante mais...
    • l'itération ne sert à rien : les éléments d'index supérieur à $level+1 seront automatiquement remis à zéro lors du passage par leur parent. Pour un sommaire régulier de facteur de branchement k et de profondeur p, cela résulte en k + k**2 + ... + k**(p-2) opérations inutiles lors du balayage des noeuds de niveau 1, plus k + k**2 + ... + k**(p-3) au niveau 2, etc.

    Donc effectivement ça ne fait pas la même chose.
    Je n'ai pas dit que ça ne marcherait pas quand même, j'ai dit que ça ne fait pas la même chose, et c'est une affirmation correcte. Sur le premier point, j'avais codé en dur la profondeur de 3 pour terminer rapidement l'exemple à une heure tardive de la nuit, il est clair que l'objectif de l'algo était de pouvoir traiter une profondeur arbitraire, comme je l'ai fait quand j'ai eu un peu de temps le lendemain. Sur le second point, la variable @level_list est le centre névralgique de l'algorithme, je préfère qu'elle soit propre à tout moment; la laisser à quelque chose comme 3-0-5 à un moment donné n'est pas satisfaisant intellectuellement à mes yeux, même si ça ne prête pas à conséquence.
    Citation Envoyé par cmcmc Voir le message
    Quant à la clarté, on pourrait gloser sur les subtilités de précédence nécessaires pour analyser la condition du for en question mais je vais m'abstenir...
    Bah, je ne pense pas ce ce soit si subtil que cela en l'occurrence, il y a une bonne dizaine de niveaux de précédence (et une trentaine d'opérateurs) entre le + et le ..) et, même si on peut avoir un doute sur la question, on comprend assez facilement l'intention.
    Citation Envoyé par cmcmc Voir le message
    Je n'ose pas imaginer que tu penses sérieusement que cette itération éclaire le code de quelque façon que ce soit. Je pense donc que tu fais référence à ma mention de @fields en contexte scalaire. C'était peut être inutilement provocateur, en référence amicale à ta prise de position ici, et d'ailleurs assorti d'un smiley.
    J'avais bien compris que tu provoquais gentiment. Je maintiens que la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $level_list[@fields] = 0;
    est à mes yeux moins clair, mais ce n'est évidemment que mon avis personnel, libre à toi d'avoir un avis divergent sur la question.
    Citation Envoyé par cmcmc Voir le message
    Peut-être, pour autant qu'on comprenne de quel level on parle. Mais je ne vois pas le rapport.
    Je voulais juste dire que je préfère ajouter une ligne de code fonctionnellement inutile si ça me permet de mieux comprendre le sens d ela donnée que je manipule.
    Citation Envoyé par cmcmc Voir le message
    Et pour ma part, ma première priorité serait de documenter les constantes comme le 2 de la boucle for.
    Là, tu as bien raison, il faudrait documenter, j'aurais dû le faire.
    Citation Envoyé par cmcmc Voir le message
    En parlant de clarté, ça ne te coûterait pas bien cher de mettre un lien sur le post en question. En l'état, j'en suis réduit aux conjectures et suppose que parmi mes posts récents il doit s'agir de celui là (n'hésite pas à me corriger si ce n'est pas le cas). Effectivement, je gagnerais pas mal de temps à ne pas chercher à faire ressentir l'expressivité, l'élégance et la puissance de Perl à des débutants peut-être englués dans leurs réflexes C ou Java ou que sais-je encore. Mais il me semble que tu fais un amalgame entre clarté et verbosité, et entre concision et opacité. Pour ton information, la discussion en question est loin d'être terminée pour peu que l'interlocuteur cible se donne un peu de peine. Et je dois dire que je suis un peu interloqué de cette critique de la part d'un auteur de tutoriel, donc quelqu'un qui doit (devrait ?) se poser des problèmes de pédagogie, et qui plus est se permet de citer MJD en introduction (je n'ai pas encore attaqué la suite)... Mais si tu veux poursuivre ces points, aie s'il te plaît l'obligeance de le faire sur le fil en question, un nouveau fil, ou par MP.
    Désolé si je t'ai heurté, ce n'était pas dans mes intentions.

    Citation Envoyé par cmcmc Voir le message
    Mais par ailleurs, avec l'introduction de @master_list, dont la taille semble maintenant dimensionner celle des sommaires traitables par ton code (si j'en juge par l'introduction de $#master_list en ligne 17), on se retrouve avec deux listes littérales de même taille. Si une initialisation était réellement nécessaire, il serait préférable de l'écrire sous l'une des formes suivantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my @level_list = (0) x @master_list; # OK, je sors :lol:
    my @level_list = (0) x ($#master_list + 1);
    my @level_list = map {0} @master_list;
    my @level_list; $level_list[$_] = 0 for 0 .. $#master_list;
    ou une autre forme pourvu qu'elle prenne en compte automatiquement toute évolution de @master_list afin de ne pas avoir à intervenir en deux endroits si l'on veut modifier la profondeur admissible.
    Oui, tu as bien sûr raison, il y a certainement plein d'autres améliorations possibles et souhaitables. Je me répète peut-être un peu, mais c'est du code que j'ai écrit à la va-vite vers une heure du matin. Initialiser ce tableau n'est pas nécessaire (ou peut être fait de meilleure façon), mais le faire m'a permis de bien visualiser ce qu'il allait contenir au moment où j'ai commencé à rédiger la solution.

  14. #74
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    ...
    la variable @level_list est le centre névralgique de l'algorithme, je préfère qu'elle soit propre à tout moment; la laisser à quelque chose comme 3-0-5 à un moment donné n'est pas satisfaisant intellectuellement à mes yeux, même si ça ne prête pas à conséquence.
    ...
    Initialiser ce tableau n'est pas nécessaire (ou peut être fait de meilleure façon), mais le faire m'a permis de bien visualiser ce qu'il allait contenir au moment où j'ai commencé à rédiger la solution.
    OK. Peace
    Et +1 pour le soin et la précision apportés à ces éclaircissements
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  15. #75
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Et je dois dire que je suis un peu interloqué de cette critique de la part d'un auteur de tutoriel, donc quelqu'un qui doit (devrait ?) se poser des problèmes de pédagogie, et qui plus est se permet de citer MJD en introduction (je n'ai pas encore attaqué la suite)...
    J'ai fini mon post précédent précipitamment et ai oublié de dire que je serais naturellement intéressé par ton avis et tes éventuelles suggestions d'améliorations.



    Edit: je viens d'ouvrir une discussion sur ce tutoriel dans ce post.

Discussions similaires

  1. [Débutant] Changer la numérotation sc. de l'axe x dans un plot
    Par nels81 dans le forum MATLAB
    Réponses: 2
    Dernier message: 13/04/2013, 15h35
  2. Changer les numérotations des \subsubsection{} par une lettre
    Par amad206 dans le forum Mise en forme
    Réponses: 2
    Dernier message: 09/11/2009, 17h40
  3. changer la numérotation des sections
    Par Infotic dans le forum Mise en forme
    Réponses: 2
    Dernier message: 16/07/2009, 13h27
  4. Changer la numérotation chapitre et sections
    Par timesmoney dans le forum Mise en forme
    Réponses: 5
    Dernier message: 12/05/2008, 23h00
  5. Changer la numérotation des sections
    Par Doniphon dans le forum Mise en forme
    Réponses: 5
    Dernier message: 09/11/2006, 12h35

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