Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check a string for alphabetically ordered characters

Tags:

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.

What I want

  • A function that takes a string as input.
  • Checks that string for the number of times it has alphabetical orderded sequences of more than 3 characters:
  • returns true if a sequence of more than 3 has been found.

Example

"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


Possible usecase

  • password strength checker
  • wordgame
  • ...

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 :)

like image 929
Wayfarer Avatar asked Aug 25 '12 19:08

Wayfarer


People also ask

How do you check if a string is in alphabetical order in Python?

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.

How do you check if one string is alphabetically before another?

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.


2 Answers

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); } 
like image 129
ircmaxell Avatar answered Oct 23 '22 23:10

ircmaxell


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;   } 
like image 42
ADev Avatar answered Oct 23 '22 23:10

ADev