私はあなたがコードで何をしているのかを理解し、あなたが望むようにそれを改善しようとしました。免責事項: それほど単純ではありません。たとえば、グループ化したくないが、代わりにグループ44848..
化4492...
したいなどをアルゴリズムが確認する方法はありません。しかし、これはすでにあなたを助けているかもしれません。44.....
4492...
44924..
336
重要な部分は、たとえば のカウントを調べて3368
削除する「スマートフィルター」だと思います336
(336
の自明なスーパーセットをマークします3368
)。state
ここで重要なのは、変数とともに文字列ソートを行うことです$last
:
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw(say state);
use List::Util 'shuffle';
# shuffled phone numbers (don't make it too easy)
my @numbers = shuffle (
4484800 .. 4484899,
3368700 .. 3368799,
4492000 .. 4492999
);
my %count = ();
# import phone numbers
foreach my $number (@numbers) {
# work on all substrings from the beginning
for (my $pos = 1; $pos <= length $number; $pos++) {
my $prefix = substr $number, 0, $pos;
$count{$prefix}++; # increase the number of equal prefixes
}
}
# smart filter
foreach my $prefix (sort {$a cmp $b} keys %count) {
state $last //= 'nothing';
# delete trivial super sets
if ($prefix =~ /^\Q$last/ and $count{$last} == $count{$prefix}) {
delete $count{$last};
}
# delete trivial sets
if ($count{$prefix} == 1) {
delete $count{$prefix};
next;
}
# remember the last prefix
$last = $prefix;
}
# output
say "$_ ($count{$_})" for sort {
$count{$b} <=> $count{$a} or $a cmp $b
} keys %count;
出力は絶対に正しいですが、まだあなたが望むものではありません:
44 (1100)
4492 (1000)
33687 (100)
44848 (100)
44920 (100)
44921 (100)
44922 (100)
44923 (100)
44924 (100)
44925 (100)
44926 (100)
44927 (100)
44928 (100)
44929 (100)
336870 (10)
(large list of 10-groups)
したがって、10 グループを取り除きたい場合は、次のように変更できます。
# delete trivial sets
if ($count{$prefix} == 1) {
delete $count{$prefix};
next;
}
に
# delete trivial sets
if ($count{$prefix} <= 10) {
delete $count{$prefix};
next;
}
出力:
44 (1100)
4492 (1000)
33687 (100)
44848 (100)
44920 (100)
44921 (100)
44922 (100)
44923 (100)
44924 (100)
44925 (100)
44926 (100)
44927 (100)
44928 (100)
44929 (100)
これはとても良さそうです。4492
-100-groups と44
-1100- groupsをどうするかはあなた次第です。4492
長さに応じて 100 個のグループを削除する場合は、大きなグループを優先してグループを削除することもでき44
ます。