Re: Validate array of numbers in sequence
by matsmats (Monk) on Sep 08, 2003 at 09:17 UTC
|
Since you obviously already has solved the problem, I guess you're mostly after other ways to do it just out of novelty or something. But here's another way, at least:
my @numlist = (1,2,3,4,5);
if (join (",", @numlist ) eq join (",", (1..$#numlist+1))) {
print "correct";
} else {
print "incorrect";
}
Or more onelinerish:
print ( (join (",", @numlist) eq join (",", (1..$#numlist+1))) ? "corr
+ect" : "incorrect" );
Seems like Array::Compare could be a good place to go too.
Mats
| [reply] [d/l] [select] |
Re: Validate array of numbers in sequence
by wirrwarr (Monk) on Sep 08, 2003 at 09:15 UTC
|
Your solution for the problem is fine, I think. But
I have two remarks on the code:
You check twice for the "1" at index 0.
Your loop is somewhat complicated. Try
something like:
my $index = 1;
foreach my $number (@numlist) {
unless ($index == $number) {
print "...";
last;
}
$index ++;
}
daniel. | [reply] [d/l] |
Re: Validate array of numbers in sequence
by Abigail-II (Bishop) on Sep 08, 2003 at 09:44 UTC
|
my @numlist = ....;
my %numbers;
@numbers {@numlist} = ();
die "Not valid\n" unless @numlist == keys %numbers;
exists $numbers {$_} or die "Not valid\n" for 1 .. @numlist;
print "Valid\n";
__END__
Abigail
| [reply] [d/l] |
Re: Validate array of numbers in sequence
by broquaint (Abbot) on Sep 08, 2003 at 09:37 UTC
|
use strict;
## I've lazily pre-sorted these ;)
my @ars = (
[ qw/ 1 2 3 4 5 / ],
[ qw/ 1 2 3 4 6 / ],
[ qw/ 2 3 4 6 7 / ],
);
for(@ars) {
print "broken list: @$_\n" and next
if $_->[0] != 1;
my($i, $n) = 0;
$n = $_->[$i]
while $i <= $#{$_} and $_->[$i] + 1 == $_->[++$i];
print "woo: @$_\n"
if $n == $_->[-1];
print "doh: sequence broke at index ${\($i - 1)} (@$_[$i - 1,$i])\n"
if $n != $_->[-1];
}
__output__
woo: 1 2 3 4 5
doh: sequence broke at index 3 (4 6)
broken list: 2 3 4 6 7
So basically it checks the sequence by iterating through the pre-sorted array until there's a gap in the sequence. Then just checks whether the end value is the same as last value seen in the iteration.
HTH
_________ broquaint | [reply] [d/l] |
Re: Validate array of numbers in sequence
by cLive ;-) (Prior) on Sep 08, 2003 at 09:41 UTC
|
#!/usr/bin/perl
use strict;
use warnings;
my @list = qw( 1 3 5 4 2 6 7 8 9);
my %hash;
@hash{@list}=1;
delete $hash{$_} for (1..@list);
print "is sequence\n" unless %hash;
cLive ;-) | [reply] [d/l] |
|
#!/usr/bin/perl
use strict;
use warnings;
my @list = qw( 1 1 2 );
my %hash;
@hash{@list}=1;
delete $hash{$_} for (1..@list);
print "is sequence\n" unless %hash;
perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The
$d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider
($c = $d->accept())->get_request(); $c->send_response( new #in the
HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
| [reply] [d/l] [select] |
|
Fair point. Just switch things around a little...
my %hash;
@hash{1..@list}=1;
delete $hash{$_} for (@list);
Funny, this was how I did it originally, but I thought the other way round looked prettier :)
cLive ;-)
| [reply] [d/l] |
|
| [reply] [d/l] |
Re: Validate array of numbers in sequence
by DrHyde (Prior) on Sep 08, 2003 at 10:25 UTC
|
Seeing that you're looking for other ways to do it, I offer this, which solves the general case of validating any sequence where the value of Nn depends only on Nn-1:
# first the sequences to test
my @sequences = (
[qw(1 2 3 4 5)], # start at 1, inc by 1
[qw(1 3 5 7 9)], # start at 1, inc by 2
[qw(0 1 0 1 0)], # start at 0, alternate 0/1
[qw(2 1 0 -1 -2)] # start at 2, dec by 1
);
# the functions to test them against - each one should
# match just one of the sequences above
my @functions =(
{ text => 'start at 1, increment by 1',
start => 1,
function => sub { $_[0] + 1 }
},
{ text => 'start at 1, increment by 2',
start => 1,
function => sub { $_[0] + 2 }
},
{ text => 'start at 0, alternate 0/1',
start => 0,
function => sub { ($_[0] == 0) ? 1 : 0 }
},
{ text => 'start at 2, decrement by 1',
start => 2,
function => sub { $_[0] - 1 }
}
);
foreach my $function (@functions) {
print $function->{text}."\n";
foreach my $sequence (@sequences) {
print ' ';
print 'not ' unless(
checksequence(
@{$sequence},
$function->{start},
$function->{function}
)
);
print 'ok ['.join(', ', @{$sequence})."]\n";
}
}
# takes a sequence, the desired start value, and the
# function to generate the next correct value
sub checksequence {
# the sequence is the most important parameter, so
# i pass it first.
my($f, $z, @seq) = reverse(@_);
@seq = reverse(@seq);
# check that the first value is correct
return 0 unless(shift(@seq) == $z);
# now see if any subsequent values are wrong and
# if they are, return immediately
foreach my $value (@seq) {
return 0 unless(($z = $f->($z)) == $value);
}
1;
}
Of course, with some devious and evil trickery the function you pass in to checksequence() could maintain some state information, so it could check more complicated sequences where a value depends on more than just its immediate predecessor. | [reply] [d/l] |
Re: Validate array of numbers in sequence
by Roger (Parson) on Sep 08, 2003 at 12:10 UTC
|
The following is my little implementation:
#!/usr/bin/perl
use strict;
my @list1 = qw/ 1 2 3 4 5 6 /;
my @list2 = qw/ 6 2 1 5 4 3 /;
my @list3 = qw/ 7 1 6 5 4 3 /;
my @list4 = qw/ 4 5 7 6 2 3 /;
my @list5 = qw/ 0 4 5 6 2 3 /;
printf "%s\n", validate_number_list (\@list1) ? "Ok" : "Error";
printf "%s\n", validate_number_list (\@list2) ? "Ok" : "Error";
printf "%s\n", validate_number_list (\@list3) ? "Ok" : "Error";
printf "%s\n", validate_number_list (\@list4) ? "Ok" : "Error";
printf "%s\n", validate_number_list (\@list5) ? "Ok" : "Error";
sub validate_number_list()
{
my ($list) = @_;
my @sorted_list = sort { $a <=> $b } @{$list};
my $prev;
foreach (@sorted_list)
{
$prev + 1 != $_ ? return(0) : {$prev = $_};
}
return 1;
}
The above code will give the following result:
Ok Ok Error Error Error
Which is what we expect.
| [reply] [d/l] |
Re: Validate array of numbers in sequence
by johndageek (Hermit) on Sep 08, 2003 at 20:52 UTC
|
Another way for fun
Dageek
#!/usr/bin/perl -w
use strict;
my @list = ( 1,4,3, 2, 5, 6);
my $index=0;
## set to the number your list should start at
my $list_start=1;
@list = sort {$a<=>$b} @list;
my $msg = "list is ok\n";
for (@list)
{
if ($list[$index] != $index + $list_start)
{
$msg="bad list\n";
last;
}
$index++;
}
print "$msg";
| [reply] [d/l] |
Re: Validate array of numbers in sequence
by dtr (Scribe) on Sep 08, 2003 at 20:00 UTC
|
An even simpler way to do this would be to add all of the numbers up. This also has the performance benefit of avoiding the sort entirely.
For example:-
my $total = 0;
my $expect = 0;
for(int i=0;i<@array;i++) {
$total += $array[$i];
$expect += $i;
Correction: $expect += $i + 1;
}
return 1 if ($total == $expect);
Aaarrrggghhh - sorry, ignore this post. As has been pointed out, it doesn't work.
| [reply] [d/l] |
|
This method does not work!
You can not validate the number sequence by simply adding it up. Consider the following lists:
1, 1, 4, 4 and 1, 2, 3, 4. Both add up to 10, but the first list is certainly not in sequence!
| [reply] |