在Perl中,如何测试序列的形式是否为n,n+;1,n+;2,…,n+;K
我正在尝试实现一个子程序,该子程序将一个数组作为其参数(或使用多个参数-仍然没有完全消除差异),并根据该数组是否为递增序列返回true或false(每个数字必须比最后一个数字多1个): 这就是我想到的:在Perl中,如何测试序列的形式是否为n,n+;1,n+;2,…,n+;K,perl,Perl,我正在尝试实现一个子程序,该子程序将一个数组作为其参数(或使用多个参数-仍然没有完全消除差异),并根据该数组是否为递增序列返回true或false(每个数字必须比最后一个数字多1个): 这就是我想到的: sub isIncreasingArray { my $last; foreach $n (@_) { return 0 if defined($last) && $last != $n - 1; $last = int($n)
sub isIncreasingArray {
my $last;
foreach $n (@_) {
return 0 if defined($last) && $last != $n - 1;
$last = int($n);
}
return 1;
}
我对Perl非常陌生,我想知道是否有更简单或更简洁的方法来实现这一点?另外,我写的东西是否符合最佳实践?我最终得到的东西比你的要长一点。这意味着,我想,您的解决方案没有问题:)
这是我能找到的最短形式,检查地图中的每个元素是否等于增加的自我,返回一个0和1的集合,计算1并与集合的原始大小匹配
print isIncreasingArray(1,2,3),"\n";
print isIncreasingArray(1,2,1),"\n";
print isIncreasingArray(1,2),"\n";
print isIncreasingArray(1),"\n";
sub isIncreasingArray {
$i = $_[0];
(scalar grep { 1 == $_ } map { $i++ == $_ } @_) == scalar(@_) || 0;
}
有两点:
return 0
将返回一个由单个元素组成的列表,因此为true。当您希望返回false
并在所有上下文中执行该操作时,一个简单的返回就足够了
strict
,并确保使用my
确定循环变量的范围:
#!/usr/bin/env perl
use strict; use warnings;
use Carp qw(croak);
use Test::More;
ok( isSimplyIncreasingSequence( [ 1298 ] ) ); # true
ok( isSimplyIncreasingSequence( [1,2,3,4] ) ); # true
ok( not isSimplyIncreasingSequence( [1,2,3,1] ) ); # false
ok( not isSimplyIncreasingSequence( [0,9,1] ) ); # false
ok( isSimplyIncreasingSequence( [-2,-1,0] ) ); # true
ok( not isSimplyIncreasingSequence( [1,1,1,1] ) ); # false
done_testing();
sub isSimplyIncreasingSequence {
my ($seq) = @_;
unless (defined($seq)
and ('ARRAY' eq ref $seq)) {
croak 'Expecting a reference to an array as first argument';
}
return 1 if @$seq < 2;
my $first = $seq->[0];
for my $n (1 .. $#$seq) {
return unless $seq->[$n] == $first + $n;
}
return 1;
}
#/usr/bin/env perl
严格使用;使用警告;
使用鲤鱼qw(croak);
使用测试::更多;
ok(ISimplyincreasingsequence([1298]);#真的
ok(ISimplyIncreasingSequence([1,2,3,4]);#真的
ok(不是简单的增量序列([1,2,3,1]);#假的
ok(不是简单的增量序列([0,9,1]);#假的
ok(ISimplyincreasingsequence([-2,-1,0]);#真的
ok(不是简单的增量序列([1,1,1,1]);#假的
完成测试();
子序列{
我的($seq)=@;
除非(定义为($seq)
和('阵列'eq参考$seq)){
croak'期望数组引用作为第一个参数';
}
如果@$seq<2,则返回1;
my$first=$seq->[0];
对于我的$n(1..$#$seq){
除非$seq->[$n]==$first+$n,否则返回;
}
返回1;
}
当然,还有一些基准:
#!/usr/bin/env perl
use strict; use warnings;
use Benchmark qw( cmpthese );
use Carp qw( croak );
my %cases = (
ordered_large => [1 .. 1_000_000],
ordered_small => [1 .. 10],
unordered_large_beg => [5, 1 .. 999_000],
unordered_large_mid => [1 .. 500_000, 5, 500_002 .. 1_000_000],
unordered_large_end => [1 .. 999_999, 5],
);
for my $case (keys %cases) {
print "=== Case: $case\n";
my $seq = $cases{$case};
cmpthese -3, {
'ref' => sub { isSimplyIncreasingSequence($seq) },
'flat' => sub {isIncreasingArray(@{ $seq } ) },
};
}
sub isSimplyIncreasingSequence {
my ($seq) = @_;
unless (defined($seq)
and ('ARRAY' eq ref $seq)) {
croak 'Expecting a reference to an array as first argument';
}
return 1 if @$seq < 2;
my $first = $seq->[0];
for my $n (1 .. $#$seq) {
return unless $seq->[$n] == $first + $n;
}
return 1;
}
sub isIncreasingArray {
my $last;
foreach my $n (@_) {
return 0 if defined($last) && $last != $n - 1;
$last = int($n);
}
return 1;
}
#/usr/bin/env perl
严格使用;使用警告;
使用基准qw(CMP准则);
使用鲤鱼qw(croak);
我的%cases=(
有序大=>[1..1\u 000\u 000],
有序_small=>[1..10],
无序\u大\u beg=>[5,1..999\u 000],
无序的(大)(中)=>[1..500(000),5500(002)..1(000)],,
无序\u大\u端=>[1..999\u 999,5],
);
对于我的$case(关键字%cases){
打印“==案例:$Case\n”;
my$seq=$cases{$case};
cmpthese-3{
'ref'=>sub{isSimplyIncreasingSequence($seq)},
'flat'=>sub{isiincreasingarray(@{$seq}}),
};
}
子序列{
我的($seq)=@;
除非(定义为($seq)
和('阵列'eq参考$seq)){
croak'期望数组引用作为第一个参数';
}
如果@$seq<2,则返回1;
my$first=$seq->[0];
对于我的$n(1..$#$seq){
除非$seq->[$n]==$first+$n,否则返回;
}
返回1;
}
子增量阵列{
我的最后一美元;
付我的$n(@){
如果定义了($last)&&$last!=$n-1,则返回0;
$last=int($n);
}
返回1;
}
==案例:无序\u大\u中
速率平坦参考
平4.64/s--18%
参考5.67/s 22%--
==大小写:有序\u小
速率参考平面
参考号154202/s--11%
173063/s单位12%--
==大小写:订购的\u大
速率平坦参考
单位2.41/s--13%
参考2.78/s 15%--
==案例:无序\u大\u
速率平坦参考
单位54.2/s--83%
参考315/s 481%--
==案例:无序\u大\u端
速率平坦参考
单位2.41/s--12%
参考2.74/s 14%--使用6“交叉点”之前的交叉点:
(如果约束是$x[$n+1]-$x[$n]==1,那么减去1也会产生“Perl真值条件”。)
实际上,考虑到“无”连接操作符有点落后于这个概念,所以我将使用all
:
sub is_increasing_list {
use List::MoreUtils qw<all>;
my $a = shift;
return all { [ ( $a, undef ) = ( $_, ( $_ - $a == 1 )) ]->[-1]; } @_;
}
sub正在增加列表{
使用列表::MoreUtils qw;
我的$a=班次;
返回所有{[($a,unde)=($),($-$a==1))]->[-1];}@;
}
为什么没有人想出智能匹配解决方案
虽然这个解决方案不如其他一些解决方案有效,但它还有使用字符串的额外好处
编辑
对于空列表和单个元素列表,Sub现在返回true,因为:
使用严格;
使用警告;
使用5.010;
sub是_简单地_增加{@124;<2 | |@{~[$\[0]..$\[-1]}
比如说(你只是在增加(1,2,3,4);“真的”:“假的”;#真的
比如(你只是在增加(1,2,3,1)吗?“真”:“假”);#假的
比如(你只是在增加(0,9,1)吗?“真”:“假”);#假的
比方说(你只是在增加(-2,-1,0);“真”:“假”);#真的
比如(你只是在增加(1,1,1,1)吗?“真”:“假”);#假的
比如(你只是在增加(1,4,1,-1)吗?“真”:“假”);#假的
比如说(你只是在增加('a','c')?'true':'false');#假的
比如(你只是在增加('love'.'perl')?'true':'false');#真的
比如说(你只是在增加(2)‘真’:‘假’;#真的
比如说(你只是在增加吗?“真的”:“假的”);#真的
我喜欢我的潜艇只有一条线 这里必须有人加入函数式编程解决方案,因为这种数学公式只要求递归 Th
#!/usr/bin/env perl
use strict; use warnings;
use Benchmark qw( cmpthese );
use Carp qw( croak );
my %cases = (
ordered_large => [1 .. 1_000_000],
ordered_small => [1 .. 10],
unordered_large_beg => [5, 1 .. 999_000],
unordered_large_mid => [1 .. 500_000, 5, 500_002 .. 1_000_000],
unordered_large_end => [1 .. 999_999, 5],
);
for my $case (keys %cases) {
print "=== Case: $case\n";
my $seq = $cases{$case};
cmpthese -3, {
'ref' => sub { isSimplyIncreasingSequence($seq) },
'flat' => sub {isIncreasingArray(@{ $seq } ) },
};
}
sub isSimplyIncreasingSequence {
my ($seq) = @_;
unless (defined($seq)
and ('ARRAY' eq ref $seq)) {
croak 'Expecting a reference to an array as first argument';
}
return 1 if @$seq < 2;
my $first = $seq->[0];
for my $n (1 .. $#$seq) {
return unless $seq->[$n] == $first + $n;
}
return 1;
}
sub isIncreasingArray {
my $last;
foreach my $n (@_) {
return 0 if defined($last) && $last != $n - 1;
$last = int($n);
}
return 1;
}
=== Case: unordered_large_mid
Rate flat ref
flat 4.64/s -- -18%
ref 5.67/s 22% --
=== Case: ordered_small
Rate ref flat
ref 154202/s -- -11%
flat 173063/s 12% --
=== Case: ordered_large
Rate flat ref
flat 2.41/s -- -13%
ref 2.78/s 15% --
=== Case: unordered_large_beg
Rate flat ref
flat 54.2/s -- -83%
ref 315/s 481% --
=== Case: unordered_large_end
Rate flat ref
flat 2.41/s -- -12%
ref 2.74/s 14% --
sub is_increasing_list {
use List::MoreUtils qw<none>;
my $a = shift;
return none {
( my $v, $a ) = (( $_ - $a != 1 ), $_ );
$v;
} @_;
}
return none { [ ( $a, undef ) = ( $_, ( $_ - $a - 1 )) ]->[-1]; } @_;
sub is_increasing_list {
use List::MoreUtils qw<all>;
my $a = shift;
return all { [ ( $a, undef ) = ( $_, ( $_ - $a == 1 )) ]->[-1]; } @_;
}
use strict;
use warnings;
use 5.010;
sub is_simply_increasing { @_ < 2 || @_ ~~ [$_[0] .. $_[-1]] }
say ( is_simply_increasing(1,2,3,4) ? 'true' : 'false' ); # true
say ( is_simply_increasing(1,2,3,1) ? 'true' : 'false' ); # false
say ( is_simply_increasing(0,9,1) ? 'true' : 'false' ); # false
say ( is_simply_increasing(-2,-1,0) ? 'true' : 'false' ); # true
say ( is_simply_increasing(1,1,1,1) ? 'true' : 'false' ); # false
say ( is_simply_increasing(1,4,1,-1) ? 'true' : 'false' ); # false
say ( is_simply_increasing('a','c') ? 'true' : 'false' ); # false
say ( is_simply_increasing('love'..'perl') ? 'true' : 'false' ); # true
say ( is_simply_increasing(2) ? 'true' : 'false' ); # true
say ( is_simply_increasing() ? 'true' : 'false' ); # true
sub isIncreasingArray {
return 1 if @_ <= 1;
return (pop(@_) - $_[-1] == 1) && isIncreasingArray(@_);
}
isIncreasingArray(1,2,3,4);
@a = (1,2,3,4);
$answer = isIncreasingArray(@a);
print isIncreasingArray(1..10000), "\n"; # true
sub isSimplyIncreasingSequence {
return 1 if @_ < 2;
return 0 if $_[-1] - $_[0] != $#_;
...
}