6

次のような nxm 要素の行列を表す文字列があります。

§inputmap = "
~~~~~~~~~~~~~~~~~~~~B~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~BBB........BBB~~~~~~~~~~~~~
~~~~~~~~~~BB...............FBB~~~~~~~~~~
~~~~~~~~BB....................BB~~~~~~~~
~~~~~~BB.....F..................BB~~~~~~
~~~~~BB.....................F.....B~~~~~
~~~~B..............................B~~~~
~~~B........F.......................B~~~
~~BB.........F......................BB~~
~~B................F.................BB~
~BF....F....F........................FB~
~B.....................................B
B.....................................FB
B........F......F......................B
B...........................F..........B
B......................................B
B......................................B
B.......F.......................F......B
B......FFF.............................B
B.......F.............................FB
~B..................F.................FB
~BF...........................F.......B~
~~B...F...........F..........FFFFF.F.BB~
~~BB..................F..F....F.....BB~~
~~~B.......................FF.FF....B~~~
~~~~B..............................B~~~~
~~~~~BB...........................B~~~~~
~~~~~~BB........................BB~~~~~~
~~~~~~~~BB..........F..........B~~~~~~~~
~~~~~~~~~~BB................BB~~~~~~~~~~
~~~~~~~~~~~~~BBB.......F.BBB~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~BBBBBB~~~~~~~~~~~~~~~~~
";
$inputmap = trim($inputmap);

文字列を検索するには、正規表現 (またはその他のもの) を作成する必要があります。

$search = "
*F*
FFF
*F*
";
$search = trim($search);

グリッド全体で。一方、マップ上で見つかったパターンの行/列の位置を取得するために、5 つの異なる文字「F」(垂直方向に 3 つ、水平方向に 3 つ) のパターンを見つける必要があります。

入力行列が異なる可能性があることを考慮して (5x5 または 10x10 または 20x25 または ...)、php と正規表現で私の問題を解決する方法はありますか?

4

5 に答える 5

4

$length=strstr($inputmap,"\n")各線の幅を見つけるために使用できます。($length-2)次に、F の後に他の文字が続き、その後に 3 つの F が続き、その後に他の文字が続き、その後に F が続く正規表現を作成できます($length-2)

于 2013-06-10T14:43:46.757 に答える
3

次のようなことができます(正規表現なし):

$map = explode("\n", $inputmap);

for ($vcount = 0; $vcount < sizeof($map); ++$vcount) {  // Loop through the map vertically
    for ($hcount = 0; $hcount < strlen($map[$vcount]); ++$hcount) { // Loop through each character of each line
        if ($map[$vcount][$hcount] == "F") {
            if ($map[$vcount + 1][$hcount - 1] == "F" && $map[$vcount + 1][$hcount] == "F" && 
                $map[$vcount + 1][$hcount + 1] == "F" && $map[$vcount + 2][$hcount] == "F")
                echo "Pattern found, starting at : (v)$vcount x (h)$hcount";
        }
    }
}

$> php test.php
php test.php
Pattern found, starting at : (v)18 x (h)8
Pattern found, starting at : (v)22 x (h)30
$>

ただし、非常に大きなマップの場合は時間がかかることを認めなければなりません.

$vcount + 1/2/!\ 行と char が実際に存在することを確認するコードを追加し$hcount + 1ます。

于 2013-06-10T14:48:56.510 に答える
2

次のコードを使用できます。

$lines = array_filter(preg_split("#\r\n?|\n#", $string)); // Creating array of lines
$matrix = array_map('str_split', $lines); // Creating a matrix

foreach($lines as $line_number => $line_content){ // Looping through the lines
    $pos = strpos($line_content, 'FFF');
    if(!$pos === false){// If FFF found
        while(true){
            if(isset($matrix[$line_number-1][$pos+1],$matrix[$line_number+1][$pos+1]) && $matrix[$line_number-1][$pos+1] == 'F' && $matrix[$line_number+1][$pos+1] == 'F'){ //Checking ...
                echo 'Found at: X:'.$pos.' & Y:'.$line_number.'<br>'; // Ouput
            }
            $pos = strpos($line_content, 'FFF', $pos+1); // Search further
            if(!is_int($pos)){
                break;
            }
        }
    }
}

どうしたの ?

  1. 行の配列を作成します
  2. マトリックスを作成します
  3. をループしてこれを検索すると、FFFパフォーマンスが向上します。したがって、行列全体をループして を検索する代わりにF、直接検索しますFFF
  4. 値が行列に存在するかどうかを確認し (未定義のインデックス エラーを防ぐため)、等しいかどうかを確認しますF
  5. 出力
  6. 同じ行でさらに検索する

オンラインデモ

座標は + の中心であることに注意してください。

于 2013-06-10T15:21:16.270 に答える
1

このパターンで試してください:

行末が次の場合\n:

$pattern = '~F.{'. ($n-2) . '}FFF.{' . ($n-2) . 'F~s';

行末が\r\n次に置き換えられる場合$n-3

または、quinxorin トリックを使用して、\n

于 2013-06-10T14:49:31.503 に答える