Как проверить палиндром в Perl? - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь написать палиндромную проверку на 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 голосов
/ 14 ноября 2018

В настоящее время вы печатаете «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.

0 голосов
/ 14 ноября 2018

Ваш код проверяет только первую букву, а затем останавливает цикл, если они совпадают.Вы правильно определили эту проблему.Это из-за 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 выйти из цикла.Вместо этого вам нужно проверять каждую букву.Как только вы достигли середины, ваш результат верен, потому что строка палиндром .Но как только вы видите несоответствие, вы должны потерпеть неудачу и выйти.

Вы делаете это, сохраняя состояние в переменной и проверяя его после.Я добавил strict и warnings и сделал код немного короче.

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 ( 1 != 0 ) {
    # do stuff
}

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

Обратите внимание, что существует более короткая реализация: вы можете сравнить строку с ее reverse.reverse встроенный , когда вызывается в скалярном контексте, переворачивает строку.

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

if ($name eq reverse $name) {
    print "true\n";
} else {
    print "false\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...