计算在方括号外部包含 3 字母回文且在方括号内部具有相应倒置回文的文件行数

问题描述 投票:0回答:1

我正在尝试解决一个人为的 PHP 任务/挑战,其中需要逐行遍历文本文件,并且如果方括号外部的回文在方括号内部具有倒置版本,则需要累积计算 3 个字母的回文。 回文的第二个字母必须与回文的第一个和第三个字母不同。 挑战/作业是指包含符合条件的回文作为“CrazyID”的行。

输入文件仅包含小写字母和方括号。 打开的大括号总是在同一行中关闭,并且没有嵌套的大括号表达式。 完整文件可以在此处查看:输入文件链接

方括号外部的限定回文可能出现在方括号内部的倒回文之前或之后。

以下是一些简化的输入行,可帮助解释逻辑:

示例行 原因
ede[ded]bab
1
ede
(外部)&
ded
(内部)
abc[ooo]ooo
0
ooo
的第二个字母与第一个和第三个字母没有不同
lmnop[phph]abcphp
1
php
(外部)&
hph
(内部)
abc[de]ghijk[lmno]pq
0 没有符合条件的 3 字母回文
lolofoo[barolol]barfoo[xyz]
1
lol
(外部)&
olo
内部
AND
olo
(外部)&
lol
(内部)
momdad[omoson]mom
1
mom
(外侧两次)和
omo
(内侧)
jab[weave]bob[uppercut]hook[oboxer]ko
1
bob
(外部)和
obo
(内部,不在紧邻的大括号中)

PHP 程序应仅输出一个整数值,表示在 .txt 文件中找到的有效 CrazyID(包含至少一个合格回文的行)的总数。

经过不断的努力,我最新的编码尝试从2000行的txt文件中正确输出了231,但我会理解是否有更简洁或更有效的方法。

// Function to check if a inside_parts contains a HPH ( or BAB, or UVU) pattern
function containsHPH($inside_parts, $phpPatterns) {
    foreach ($phpPatterns as $pattern) { //looping on each collected sequence code/pattern
        $hph = $pattern[1] . $pattern[0] . $pattern[1]; //creating vice versa sequence code/pattern
        if (strpos($inside_parts, $hph) !== false) { //check if it is exist in brackets
            return true; //if found return true
        }
    }
    return false; //patter not found in bracket
}

// Read the Puzzle Input file
$inputFile = 'puzzle_input.txt';
$file_lines = file($inputFile);

$validCrazyIDCount = 0;

foreach ($file_lines as $each_line) { //looping on file to fetch each line
    preg_match_all('/\[([^\]]+)\]/', $each_line, $inside_brackets); //all string inside square bracket
    preg_match_all('/([^\[\]]+)/', preg_replace('/\[[^\]]+\]/', ' ', $each_line), $outside_brackets); //all string outside square bracket separated by space

    // Flatten the arrays
    $inside_parts = implode(' ', $inside_brackets[1]); //0th array having square bracket and 1st array having plain text. so taking 1st array value

    $outside_parts = implode(' ', $outside_brackets[0]); //all arrays are same, so taking 0th means first array value and convert into string

    // Find PHP patterns outside the brackets
    $phpPatterns = [];
    $words = explode(' ', trim($outside_parts)); //outside string to each line array
    
    //to check if a string contains a PHP (or ABA, or VUV) pattern
    foreach ($words as $word) { //fetch each word from each lines all words
        $len = strlen($word); //calculate length of word
        for ($i = 0; $i < $len - 2; $i++) {
            if ($word[$i] === $word[$i + 2] && $word[$i] !== $word[$i + 1]) { //match first and third letter && first letter does not match with second (to avoid AAA)
                $phpPatterns[] = $word[$i] . $word[$i + 1] . $word[$i + 2]; //collect sequence code/pattern in array
            }
        }
    }

    // Check for corresponding HPH patterns inside the brackets
    if (!empty($phpPatterns) && containsHPH($inside_parts, $phpPatterns)) { //if array contains data && check its vice versa string exists
        $validCrazyIDCount++; //if found, increment the count
    }
}

// Output the total number of validated CrazyIDs
echo $validCrazyIDCount; //output is 231
php validation counting palindrome
1个回答
0
投票

因为只需 1 个合格的回文就可以将一行视为有效(计数器),因此无需使用前瞻来在单行中进行多个匹配。

捕获第一个字母,捕获下一个字母并确保它与前一个字母不同,然后捕获下一个字母并确保它与第一个字母相同 - 这将验证第一个出现的回文。

然后捕获下一个出现的方括号(左大括号或右大括号,无论是哪个)。 然后在同一捕获的大括号之前的行中消耗零个或多个字符。 这确保了倒置回文出现在与原始回文相反的“支撑”段中(内部大括号 -> 外部大括号或外部大括号 -> 内部大括号)。

最后匹配所需段内的倒回文。

下面的模式中的几个捕获组不是必需的,但已包含在内是为了使行为更加清晰。 最低限度的捕获组将是第一个字母、第二个字母和“下一个出现的大括号”,

\K
也可以省略。

代码:(演示

$pattern = '/
([a-z])    #capture group 1, a letter
(?!\1)     #second letter cannot be the same as capture group 1
((?1))     #capture group 2, a different letter
(\1)       #capture group 3, the repeated first letter
[^[\]\n]*  #match any trailing non-braces and non-newlines
([[\]])    #capture group 4, the next occurring brace
(?:.*\4)*  #match a subsequent captured brace
[^[\]\n]*  #match zero or more non-braces and non-newlines
(\2)       #capture (for sake of observability) group 2 letter
(\1)       #capture (for sake of observability) group 1 letter
(\2)       #capture (for sake of observability) group 2 letter
.*         #consume the rest of the line for efficiency
\K         #forget the fullstring match to keep output clean
/x';       #x means ignore whitespaces to allow for pattern comments

echo preg_match_all(
         $pattern,
         file_get_contents('puzzle_input.txt'),
         $m,                // only needed if calling var_export() below
         PREG_SET_ORDER     // only needed if calling var_export() below
     );

// var_export($m); // if you want to see the captured characters

使用 2000 行示例输入,我的脚本仅通过调用

file_get_contents()
preg_match_all()
即可找到 231 行合格行。 (PHPize 演示)

© www.soinside.com 2019 - 2024. All rights reserved.