in reply to Re^4: checking a set of numbers for consistency mod p
in thread checking a set of numbers for consistency mod p
The basic idea is that the maximal known value in a sequence rules it's neighborhood.
I probably over optimized it: I thought that comparing two arrays should be fastest and I'm caching those static sieves for comparison.
Of course it's also possible to work without a sieve-table and calculate on the entries on the fly. (So maybe premature optimization on my part)
This must be benchmarked and depends a lot on processor's caching of perl data structures.
Please test and tell me if you find a bug.
FWIW: I left a lot of debug code inside which is optimized away based on the constant DBG
OUTPUT:# https://perlmonks.org/?node_id=11142871 use v5.12; use warnings; use Data::Dump qw/pp dd/; my $range = 32; my %sieves; use constant DBG => 0; sub get_sieve { my ( $prime, $range ) = @_; my @sieve = 0; # p^0 = 1 my @pos = (0); while ( @sieve < 2*$range ) { @sieve = (@sieve) x $prime ; $sieve[-1]++; push @pos, @sieve-1; } pop @pos; # forget edge return { prime => $prime, sieve => [ @sieve[0 .. 2*$range-1] ], sieve_pos => \@pos, sieve_max => @pos-1, }; } sub valid_set_lanx { warn "call:",pp \@_ if DBG; my($p, $a_known) = @_; my $h_sieve_cache = $sieves{$p} //= get_sieve($p,$range); my ($a_sieve, $a_sieve_pos, $sieve_max) = @{$h_sieve_cache}{qw/sie +ve sieve_pos sieve_max/}; warn pp $h_sieve_cache if DBG; # --- find max_known my @known = @$a_known; my $max_known = 0; my $max_pos = 0; my $idx = 0; for my $e (@known) { next unless defined $e; if ($e > $max_known) { $max_known = $e; $max_pos = $idx; } } continue { $idx++; } # --- adjust into sieve range if ($max_known > $sieve_max) { $max_known = $sieve_max; $known[$max_pos] = $max_known; } my $idx_sieve = $a_sieve_pos->[$max_known]- $max_pos; if ( DBG ) { #warn pp [\@known,$a_sieve,$max_known,$a_sieve_pos->[$max_know +n],$idx_sieve,$max_pos]; warn (". "x $idx_sieve, join " ", map { $_ // "?" } @known); warn "@$a_sieve"; } my $ok = 1; for my $e (@known) { #warn (($a_sieve->[$idx_sieve] //"?"), " - ", ($e//"?")) if DB +G; next unless defined $e; $ok=0 if $e != $a_sieve->[$idx_sieve] } continue { $idx_sieve++ } return $ok; } # test the examples: expect [yes, yes, no, no] print valid_set_lanx(@$_) ? "yes\n" : "no\n" for ( [ 2, [0, 1, 0, 2, 0]], [ 2, [1, 0, 5, 0, 1]], [ 2, [2, undef, undef, undef, 2]], [ 3, [1, 0, 0, 1, 0, 0, 1]], [ 2, [1, 0, 8, 0, 1]], );
yes yes no no yes
holes are tricky, still need to cover this buggy edge case, which is legit but won't pass now.
[ 3, [0, undef, 0, 0, 1]]
Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^6: checking a set of numbers for consistency mod p
by LanX (Saint) on Apr 11, 2022 at 15:12 UTC |