This seems so obvious , but I cannot find a way to do this.
I think there even is a regular PHP function to do this, but even that one stays well hidden after 1,5 hours of intensive Google searches.
"youlookgreatbcdetoday" => has "bcde" in it ... so has to return true
"youlookgreatklmtoday" => only has "klm" in it ... so that has to return false
"youlookgreattoday" => has no alphabetically ordered sequences in it, so returns false
disclaimer: I wish I already had some code to show you, but I literally have nothing yet.
Only thing I could come up with was to split the string up in an array and do some magic on the array ... but even then I got stuck.
Hope one of you will save me :)
A character (or string) in Python is "less than" another character if it comes before it in alphabetical order, so in order to see if a string is in alphabetical order we just need to compare each pair of adjacent characters.
To determine which of two strings of characters comes first when arranging in alphabetical order, their first letters are compared. If they differ, then the string whose first letter comes earlier in the alphabet comes before the other string.
So, let's start off with a trivial implementation using a loop and a counter (for increasing only):
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; }
So, how does it work? Basically, it loops through, and checks to see if the ord
(ascii number) of the character is one more than the one before it. If so, it increases the count parameter. Otherwise, it sets it to 1 (since we already processed that character). Then, if $count
is ever more or equal to the number requested, we know we found a sequence, and can return...
So, now let's check in both directions:
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; }
Now, it'll return true for abcd
and dcba
...
Now, here's a far simpler solution:
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); }
And there you go. We use the property that if we add a decreasing number to each position, consecutive sequences will appear as the same number. And that's exactly how this works.
And here's the same theory applied to both directions:
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); }
Fewer loop and if condition!
function alphacheck($str, $i=4) { $alpha = 'abcdefghijklmnopqrstuvwxyz'; $len = strlen($str); for($j=0; $j <= $len - $i; $j++){ if(strrpos($alpha, substr($str, $j, $i)) !== false){ return true; } } return false; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With