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; |
Partager