PHP начинающий палиндром сценарий - PullRequest
1 голос
/ 17 июля 2011

Я работал (для шутки) над сценарием, распознающим палиндромы. До сих пор я успешен с «Kayak», «Racecar», «Anna», «Man a plan a the Panama», но вариации в последней фразе, такой как «amanaplana canalpan ama», доставляют мне проблемы.

В качестве примечания: Я понимаю, что использование PCRE значительно облегчит мне задачу, но я не очень хорошо разбираюсь в этом, и одна из моих главных целей состояла в том, чтобы понять алгоритм проверки для палиндромов.

 <?php
$word = "amanaplana canalpan ama";

$space = " ";
$word_smallcase = strtolower($word);        

$word_array = str_split($word_smallcase);   

if(in_array($space, $word_array)){      

    for($m = 0; $m<count($word_array); $m = $m + 1){
        if($word_array[$m] == $space)
            unset($word_array[$m]);
    }
}
$count = 0;
$scan_count = -1;
for($i = 0; $i < (count($word_array)/2); $i = $i + 1){

    for($j = count($word_array); $j > (count($word_array)/2); $j = $j - 1){

        if($word_array[$i]==$word_array[$j]){
            $count = $count + 1;
            break;
            }
        }
    $scan_count = $scan_count + 1;

        }
if ($count == $scan_count){
    echo $word." is a palindrome";
}
else{

    echo $word ." is NOT a palindrome";
}


?>

Буду признателен за ответ относительно:

  • Идентификация ошибки, которую я имею.
  • Рекомендации по как я мог бы улучшить код (я был бы счастлив, если бы я мог сделать все работает без обращения к $ count или $ scan_count, которые кажутся мой глаз относительно дилетантский).

Заранее спасибо.

Ответы [ 5 ]

3 голосов
/ 17 июля 2011

В настоящее время вы тестируете дословно, и это определенно вызовет ошибки в случаях, когда слова неравномерны по всему палиндрому.

Простой способ проверить, является ли строка пандандромнойв PHP:

$test = str_replace( array(',', '.', ' '
                     //, and any other punctuation you aren't using
                     ), '', $input );

$test = strtolower( $test );
echo $input . ' is ' . 
             ( ( strrev( $test ) == $test )? "": "not " )
             ' palandromic.';

Что касается вашего кода: перебор массива и одновременное удаление объектов - это приглашение к неприятностям.Вам лучше просто использовать str_replace.Если это не вариант, я бы использовал:

// this takes more space, but it is easier to understand.
$tmp = array();
for($m = 0; $m<count($word_array); $m++){ // ++ is the same as $m = $m + 1
    if($word_array[$m] != $space)
        $tmp[] = $word_array[$m];
}
$word_array = $tmp;

Если strrev (инвертирует строку) недоступен:

$l = count( $word_array ) / 2; // cache this, no sense in recounting
$is_palindromic = TRUE;
for( $i = 0; $i < $l; $i++ )
{
    if( $word_array[ $i ] != $word_array[ ( -1 - $i ) ] )
    {
        $is_palindromic = FALSE;
        break;
    }
}

echo $input . ' is ' . 
         ( $is_palindromic )? "": "not " )
         ' palandromic.';
2 голосов
/ 17 июля 2011

Здесь происходит несколько вещей ...

Во-первых, я не уверен, знаете ли вы, что unset использование массива фактически не удаляет индексы:

$array = array(0, 1, 2, 3);
unset($array[2]);
var_dump($array);
/* array(3) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [3]=>
  int(3)
} */

Таким образом, вы будете иметь некоторые неопределенные смещения при переборе элементов массива. Чтобы перейти один за другим, вы должны использовать цикл foreach.

Другая проблема заключается во вложенном цикле for:

for($i = 0; $i < (count($word_array)/2); $i = $i + 1){

    for($j = count($word_array); $j > (count($word_array)/2); $j = $j - 1){

Учитывая "amanaplanacanalpanama", посмотрите, что вы делаете:

Сравнение, шаг за шагом (кстати, вы на 1 на инициализаторе отключены на $ j ... $word_array[count($word_array)] указывает на «м» в Панаме, а не на «а».):

a eq to a?              j is 22          i is 0
                scan_count: -1   count: 1
m eq to a?              j is 22          i is 1
m eq to m?              j is 21          i is 1
                scan_count: 0    count: 2
a eq to a?              j is 22          i is 2
                scan_count: 1    count: 3

a eq to a в порядке и соответствует ... m находится на следующей итерации, но когда вы переходите к следующему «a», вы находите оригинальное «a» в конце панамы ...

В качестве примечания: поскольку вы каждый раз начинаете с самого конца, это будет ужасно неэффективно O(n^2) с учетом достаточно большой строки ...

Обязательное решение:

$word = "amanaplana canalpan ama";

$j = strlen ($word)-1;
$pal = true;

for ($i = 0; $i < strlen($word)/2; ++$i, --$j) {

    // skip spaces
    while ($word[$i] === " ") {$i++;}
    while ($word[$j] === " ") {$j--;}

    echo "$word[$i] eq $word[$j]?\n";
    if ($word[$i] !== $word[$j])    {
        $pal = false;
        break;
        }
}

if ($pal) print "yes"; else print "no";
1 голос
/ 17 июля 2011

псевдокод:

string phrase = "my phrase here"

int i = 0
int j = phrase.length - 1

while i < j:
  if phrase[i] is not alphanumeric:
    i++;
    continue;
  if phrase[j] is not alphanumeric:
    j--;
    continue;
  if phrase[i] != phrase[j]
    return false;
  i++;
  j--;

return true
0 голосов
/ 17 марта 2014
<?php
$a="amanaplana canalpan ama";
echo "String entered: " . $a;
$b= preg_replace('/\s+/', '', $a);
$org= strtolower($b);
$chk= strrev($org);
echo "<br/>";
if ($org==$chk)
{ echo "Palindrome"; }
else
{ echo "Not Palindrome"; }
?>
0 голосов
/ 17 июля 2011

I думаю можно просто удалить все пробелы и полностью игнорировать слова . Просто разделите на две части (или около того, если длина строки нечетное число), переверните любую половину и посмотрите, совпадают ли они.

$word = "amanaplana canalpan ama";

$sanitizedWord = preg_replace("'\s+'", '', strtolower($word));
$halfway = strlen($sanitizedWord)/2;
$roundedDownMidPoint = floor($halfway);

$firstHalf = substr($sanitizedWord, 0, $roundedDownMidPoint);
$secondHalf = substr($sanitizedWord, is_float($halfway) ? $roundedDownMidPoint+1 : $halfway);

if ($firstHalf === strrev($secondHalf)) {
    echo $sanitizedWord." is a palindrome";
}

Протестировано с "Kayak", "Racecar", "Anna", "Man a plan a cana Panama" и "amanaplana canalpan ama", которые все правильно определены как палиндромы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...