2011-07-17 58 views
1

我正在研究(爲了好玩)寫一個腳本來識別迴文。到目前爲止,我在「皮划艇」,「賽車」,「安娜」,「一個男人一條運河巴拿馬計劃」方面取得了成功:但後一個詞組的變體例如「amanaplana canalpan ama」給我帶來了問題。PHP初學者回文腳本

作爲一個方面說明:我也明白,使用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,我認爲,我的眼睛,相對業餘),我會很高興。

在此先感謝。

回答

2

有幾件事情怎麼回事...

首先,我不知道,如果你知道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)]在巴拿馬「M」,而不是「一」指點):

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」在巴拿馬結束...

作爲一個側面說明,因爲你是從一月底開始了每一次,這將是可怕的低效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"; 
3

目前,您正在逐字測試的基礎上,這肯定會導致在迴文中字數不均勻的情況下出現錯誤。

最簡單的方法,如果一個字符串是在PHP palandromic:

$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.'; 
+0

+1這意味着一個討巧。 – Kumar

+0

var name「word_array」具有誤導性...... str_split實際上是返回一個字母數組。 – 2011-07-17 13:51:11

1

僞代碼:

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

認爲可以刪除所有空格並完全忽略單詞。如果字符串長度是奇數,就分成兩部分(或其附近),顛倒任何一部分,然後查看它們是否匹配。

$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"; 
} 

與「獨木舟」測試,「賽車」,「安娜」,「一個人一個有計劃的運河巴拿馬」和「amanaplana canalpan AMA」,這都是正確識別爲迴文。

+0

感謝您的評論。但是我正在尋找一種方法來實現它,而不是訴諸於PHP中內置的這樣的庫。 – arkate

0
<?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

這適用於句子和單詞。嘗試一下。 – Shreesh

+0

自從我想要答案已經有一段時間了,但是謝謝:) – arkate