[SPOILER] My Solution to Perl 'Hard' Quiz of the Week #2005-03-22
Shlomi Fish <shlomif-ik1l9ssToec+JF/[email protected]> Mon, 28 Mar 2005 20:10:38 +0200
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
Hi all! Attached is: 1. DivideFsm.pm - a file that implements the aforementioned function. 2. Test.t - a fiel that tests it. Enjoy! Regards, Shlomi Fish --------------------------------------------------------------------- Shlomi Fish shlomif-ik1l9ssToec+JF/[email protected] Homepage: http://www.shlomifish.org/ Hacker sees bug. Hacker fixes bug.
DivideFsm.pm
(application/x-perl-module, 525 B)
use strict;
use warnings;
sub gen_is_divisible_fsm
{
my $N = shift;
my @states;
foreach my $i (0 .. ($N-1))
{
my $next_states = [];
for my $bit (0 .. 1)
{
if (($i & 0x1) == $bit)
{
push @$next_states, ($i >> 1);
}
else
{
push @$next_states, (($i+$N)>>1);
}
}
push @states, +{ 'ret' => $i, 'next_states' => $next_states };
}
return (0, \@states);
}
1;
Test.t
(text/x-troff, 1.1 KB)
#!/usr/bin/perl -w
use strict;
use warnings;
use DivideFsm;
sub run_number
{
my $start_state = shift;
my $fsm = shift;
my $number = shift;
my $state;
$state = $start_state;
while ($number)
{
my $bit = ($number & 0x1);
$number = ($number >> 1);
$state = $fsm->[$state]->{'next_states'}->[$bit];
}
return $fsm->[$state]->{'ret'};
}
sub check_range
{
my $number = shift;
my $start_check_num = shift;
my $end_check_num = shift;
my ($start_state, $fsm) = gen_is_divisible_fsm($number);
foreach my $i ($start_check_num .. $end_check_num)
{
my $fsm_ret = run_number($start_state, $fsm, $i);
my $mod_ret = ($i % $number);
my $ok = (($fsm_ret == 0) eq ($mod_ret == 0));
if ($ok)
{
print "$i % $number OK.\n";
}
else
{
die "$i % $number Not OK."
}
}
}
check_range(3, 0, 50);
check_range(5, 0, 50);
check_range(7, 0, 50);
check_range(9, 0, 50);
check_range(15, 0, 70);
check_range(45, 0, 450);
check_range(3*5*7, 0, 3*5*7*3);