それでは、ループとカウンター(増加のみ)を使用した簡単な実装から始めましょう。
function hasOrderedCharactersForward($string, $num = 4) {
$len = strlen($string);
$count = 0;
$last = 0;
for ($i = 0; $i < $len; $i++) {
$current = ord($string[$i]);
if ($current == $last + 1) {
$count++;
if ($count >= $num) {
return true;
}
} else {
$count = 1;
}
$last = $current;
}
return false;
}
それで、それはどのように機能しますか?ord
基本的にはループして、文字の(ASCII番号)が前の文字より1つ多いかどうかをチェックします。その場合、カウントパラメータが増加します。それ以外の場合は、1に設定されます(すでにその文字を処理しているため)。次に、$count
が要求された数以上である場合、シーケンスが見つかったことがわかり、...を返すことができます。
それでは、両方向で確認してみましょう。
function hasOrderedCharacters($string, $num = 4) {
$len = strlen($string);
$count = 0;
$dir = 1;
$last = 0;
for ($i = 0; $i < $len; $i++) {
$current = ord($string[$i]);
if ($count == 1 && $current == $last - 1) {
$count++;
$dir = -1;
if ($count >= $num) {
return true;
}
} elseif ($current == $last + $dir) {
$count++;
if ($count >= $num) {
return true;
}
} else {
$count = 1;
$dir = 1;
}
$last = $current;
}
return false;
}
今、それはtrueを返しabcd
ますdcba
...
さて、これがはるかに簡単な解決策です:
function hasOrderedCharactersForward($string, $num = 4) {
$len = strlen($string) + 1;
$array = array_map(
function($m) use (&$len) {
return ord($m[0]) + $len--;
},
str_split($string, 1)
);
$str = implode('_', $array);
$regex = '#(^|_)(\d+)' . str_repeat('_\2', $num - 1) . '(_|$)#';
return (bool) preg_match($regex, $str);
}
そして、あなたは行きます。各位置に減少する番号を追加すると、連続するシーケンスが同じ番号として表示されるというプロパティを使用します。そして、それはまさにこれがどのように機能するかです。
そして、これが両方向に適用される同じ理論です:
function hasOrderedCharacters($string, $num = 4) {
$i = 0;
$j = strlen($string);
$str = implode('', array_map(function($m) use (&$i, &$j) {
return chr((ord($m[0]) + $j--) % 256) . chr((ord($m[0]) + $i++) % 256);
}, str_split($string, 1)));
return preg_match('#(.)(.\1){' . ($num - 1) . '}#', $str);
}