如何在Perl中检查回文?

时间:2018-11-14 11:56:04

标签: perl

我正在尝试在Perl中编写回文检查器。如果输入的向前和向后相同,则应该返回"true"

示例:

./determine kayak
True
./determine "Do geese see God?"
True
./determine "Do ducks see God?"
False

我的代码:

#!/usr/bin/perl -w 

$name = $ARGV[0];
$name = lc $name;
$name =~ s/[^a-z]//g;
@all = split //,$name;
$half = $#all/2;

foreach $i (0..$half){
    my $count = 0;
    if($all[$i] eq $all[-($i+1)]){
        #print"$all[$i]\n";
        #print"$all[-($i+1)]\n";
        print "true\n";
        last;       
    }else{
        print "flase\n";
    }

}

全部读取后无法确定是非。

例如: 读为"Do ducks see God?"时,前两个字母相同,因此将显示为true,但这应该为false。

2 个答案:

答案 0 :(得分:2)

您的代码仅检查第一个字母,然后如果相同则停止循环。您已正确识别出该问题。这是因为last

foreach $i (0..$half){
    my $count = 0;
    if($all[$i] eq $all[-($i+1)]){
        print "true\n";
        last;                       # <-- here
    }else{
        print "flase\n";
    }
}

这将使Perl退出循环。您要做的是继续检查每个字母。到达中间位置后,结果将为true,因为字符串为palindrome。但是一旦发现不匹配,就必须失败并退出。

您可以通过将状态保留在变量中,然后进行检查来做到这一点。我添加了strictwarnings,并使代码更短。

my $name = lc 'Do ducks see God?';
$name =~ s/[^a-z]//g;
my @all = split //, $name;
my $half = $#all / 2;

my $is_palindrome = 1;
foreach my $i ( 0 .. $half ) {
    my $count = 0;
    if ( $all[$i] ne $all[ -( $i + 1 ) ] ) {
        $is_palindrome = 0;
        last;
    }
}

if ($is_palindrome) {
    print "true\n";
} else {
    print "false\n";
}

使用ne check会更容易,因为在if之后有一个空白的空格会造成混淆。

if ( 1 == 0 ) {
} else {
    # do stuff
}

更容易解决条件并摆脱障碍,或使用unless,这与Perl中的 if 相同。

if ( 1 != 0 ) {
    # do stuff
}

unless ( 1 == 0 ) {
    # do stuff
} 

请注意,有一种更短的实现方式:您可以将字符串与其reverse进行比较。 reverse built-in在标量环境中调用时,将字符串转过来。

my $name = lc '12321';
$name =~ s/[^a-z]//g;

if ($name eq reverse $name) {
    print "true\n";
} else {
    print "false\n";
}

答案 1 :(得分:2)

当前,您为字符数组的每次迭代打印“ true”或“ false”。您真的想检查每个字母,只在最后打印结果。

my $is_palindrome = 1;

foreach $i (0..$half){
    if ($all[$i] ne $all[-($i+1)]){
        $is_palindrome = 0;
        last;
    }
}

say $is_palindrome ? 'true' : 'false';

但是,就我个人而言,我认为检查您的$name变量是否与它的倒数相同会更容易。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my $name = $ARGV[0];
$name = lc $name;
$name =~ s/[^a-z]//g;

say $name eq reverse($name) ? 'true' : 'false';

注意:请使用use warnings代替-w,也要使用use strict