慕虎7371278
我对你的问题提出了一个初步的解决方案。请注意:你永远不会得到只有一个字母的序列,因为每两个连续的字母都是具有一定差异的“线性增长”。我的解决方案不是很干净。例如,您可以将$matches和组合$rules到一个数组中。我的解决方案是幼稚和贪婪的。例如,在示例中adeflk,序列def是 3 的序列,但因为我的解决方案是贪婪的,所以它会考虑ad作为 2 的序列,并ef作为另一个 2 的序列。话虽如此,您仍然可以改进我的代码。该代码很难测试。您可能应该使用 OOP 并将代码划分为许多易于单独测试的小方法。<?phpfunction compress($string, $rules, $matches) { if ($string === '') { return getBestMatch($matches); } $currentCharacter = $string[0]; $matchFound = false; foreach ($rules as $index => &$rule) { if ($rule['active']) { $soFarLength = strlen($matches[$index]); if ($soFarLength === 0) { $matchFound = true; $matches[$index] = $currentCharacter; } elseif ($rule['callback']($currentCharacter, $matches[$index])) { $matches[$index] .= $currentCharacter; $matchFound = true; } else { $rule['active'] = false; } } } if ($matchFound) { return compress(substr($string, 1), $rules, $matches); } else { return getBestMatch($matches) . startNewSequence($string); }}function getBestMatch($matches) { $rule = -1; $length = -1; foreach ($matches as $index => $match) { if (strlen($match) > $length) { $length = strlen($match); $rule = $index; } } if ($length <= 0) { return ''; } return ord($matches[$rule][0]) . '.' . $rule . '.' . $length . "\n";}function startNewSequence($string) { $rules = [ // rule number 1 - all characters are the same 1 => [ 'active' => true, 'callback' => function ($a, $b) { return $a === substr($b, -1); } ], // rule number 2 - ASCII code of current letter is one more than the last letter ("linear growth") 2 => [ 'active' => true, 'callback' => function ($a, $b) { return ord($a) === (1 + ord(substr($b, -1))); } ], // rule number 3 - ASCII code is a geometric progression. The ord() of each character increases with each step. 3 => [ 'active' => true, 'callback' => function ($a, $b) { if (strlen($b) == 1) { return ord($a) > ord($b); } $lastCharOrd = ord(substr($b, -1)); $oneBeforeLastCharOrd = ord(substr($b, -2, 1)); $lastDiff = $lastCharOrd - $oneBeforeLastCharOrd; $currentOrd = ord($a); return ($currentOrd - $lastCharOrd) === ($lastDiff + 1); } ], // rule number 4 - ASCII code of current letter is one less than the last letter ("linear decrease") 4 => [ 'active' => true, 'callback' => function ($a, $b) { return ord($a) === (ord(substr($b, -1)) - 1); } ], // rule number 5 - ASCII code is a negative geometric progression. The ord() of each character decreases by one // with each step. 5 => [ 'active' => true, 'callback' => function ($a, $b) { if (strlen($b) == 1) { return ord($a) < ord($b); } $lastCharOrd = ord(substr($b, -1)); $oneBeforeLastCharOrd = ord(substr($b, -2, 1)); $lastDiff = $lastCharOrd - $oneBeforeLastCharOrd; $currentOrd = ord($a); return ($currentOrd - $lastCharOrd) === ($lastDiff - 1); } ], ]; $matches = [ 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', ]; return compress($string, $rules, $matches);}echo startNewSequence('tsrqpozh');