4

Need to write a code block which check is one string is a rotation of another.

Looked at loads of posts on here and it is all in Java or C++ but I need to do it in PHP.

I have tried a few different things, trying to work from the C++ and Java examples but I am not having any luck, here is my current code:

<?php

function isSubstring($s1, $s2) {


    if(strlen($s1) != strlen($s2)) {
        return false;
    }

    if(WHAT TO PUT HERE) {
        echo "it is!";
    } else {
        echo "nope";
    }
}


isSubstring("hello", "helol");

?>
  • Just check if all symbols of one string are in another. Or sort symbols and check if they are the same. – u_mulder Mar 17 '16 at 17:54
  • I would sort both strings (alphabetically) and then compare. http://stackoverflow.com/questions/9912469/php-how-to-sort-the-characters-in-a-string – Anees Saban Mar 17 '16 at 17:55
  • Use strrev it will do exactly what you want – Bram Gerritsen Mar 17 '16 at 18:01
  • 1
    @BramGerritsen strrev is a good idea, but it would only work if the strings are exactly reversed. It isn't clear what is meant by "rotation", but from the example in the question it looks like it should return true for strings that contain the same letters in any order. – Don't Panic Mar 17 '16 at 18:04
  • @don't panic, yes you are right, I missed the last line when reading the question – Bram Gerritsen Mar 17 '16 at 18:06

7 Answers7

4

Many ways available. Here one more using built-in function count_chars on both strings, and then comparing both resulting arrays :

function isSubstring($s1, $s2) {
    if (strlen($s1) != strlen($s2)) {
        echo "nope";
        return;
    }

    $s1cnt = count_chars($s1, 1);
    $s2cnt = count_chars($s2, 1);

    if($s1cnt === $s2cnt) {
        echo "it is!";
    } else {
        echo "nope";
    }
}

Edit : as MonkeyZeus pointed out, beware of comparison with multibyte characters. It may bite a little bit :

isSubstring('crढap', 'paࢤrc');

will give true as answer. ढ is UTF-8 indian devanagari three byte char : E0 A2 A4 and ࢤ is also three byte chars (arabic) : E0 A4 A2, and the count_chars function counts the individual bytes. So it would be safe to use if chars are from only one language, else get some headache pills...

It seems to me that to manage this kind of things we need to have chars that are made of 3 bytes.

Zimmi
  • 1,599
  • 1
  • 10
  • 14
  • 1
    This is impressive, I like it :) – MonkeyZeus Mar 17 '16 at 18:38
  • 1
    I wonder if this will exhibit weird behavior when using using stuff like `count_chars('Ýô', 1);` – MonkeyZeus Mar 17 '16 at 18:42
  • @MonkeyZeus Good point you asked. From the manual, it is the individual bytes that are counted, and multibyte chars are not counted as such but it is their composing bytes that are counted. The returned array with mode `0` instead of `1` will be an array of 256 values indexed from 0 to 255. So I'm quite positive it shouldn't break with multibyte chars. But who knows ! Quick short and dirty tests made with french words with accents were successfull. – Zimmi Mar 17 '16 at 19:01
  • I've spent the past 10 minutes trying to break it as well lol. I imagine that one feasible way to break it is if you feed it a quad-byte char in `$s1` and 2 dual-byte chars in `$s2` which use the same four individual byte points. My standard US-qwerty keyboard only ranges from the 35-125 range but multi-bytes go into the high 100s - low 200's so it could take a while to find a combination that breaks it :/ – MonkeyZeus Mar 17 '16 at 19:05
  • @MonkeyZeus Broken! :-) See updated answer. Thanks. But your proposed function gets cheated too by the same case ;-) – Zimmi Mar 17 '16 at 20:56
  • Wow, that is an impressive find. I hadn't considered triple-byte chars which simply had bytes in a different order. Out of curiosity, does it break my algorithm as well? I would try it myself but it appears as though my web browser could not handle displaying your Arabic character. – MonkeyZeus Mar 17 '16 at 21:00
  • Yes, your proposed function gets cheated too by the same case ;-), Because str_split splits into individual bytes for multibytes chars. May be we should have a look at functions `mb_*` which should handle multibytes chars. But it is becoming very late here... – Zimmi Mar 17 '16 at 21:05
  • Gah! Damn multi-bytes lol. Looks like PHP might be one step ahead of us with [`mb_split()`](http://php.net/manual/en/function.mb-split.php) :) but unfortunately I cannot find an **mb_\*** equivalent for `count_chars()` :( – MonkeyZeus Mar 17 '16 at 21:08
3

I would go for something like this:

function isSubstring($s1, $s2)
{
    // If the strings match exactly then no need to proceed
    if($s1 === $s2)
    {
        echo "it is!";
        return;
    }
    elseif(strlen($s1) !== strlen($s2))
    {
        // Strings must be of equal length or else no need to proceed
        echo "nope";
        return;
    }

    // Put each character into an array
    $s1 = str_split($s1);
    $s2 = str_split($s2);

    // Sort alphabetically based on value
    sort($s1);
    sort($s2);

    // Triple check the arrays against one-another
    if($s1 === $s2)
    {
        echo "it is!";
    }
    else
    {
        echo "nope";
    }
}
MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
  • 1
    What does "one ... rotation of another" mean? I would interpret "rotation" to mean the same characters, but shifted. Those dropping off the end go the beginning. `ABCDEF` and `DEFABC` or `FABCDE' The answer only tested if they have been shuffled. – BryanT Mar 17 '16 at 19:29
  • @BryanT That's a question you should ask OP but anyways, based on OP's `isSubstring("hello", "helol");` example I presumed that the word "rotation" should not be taken literally and that OP simply wants to check two strings and see if all of their chars match regardless of order. According to OP's acceptance of my answer, I safely assume that my guess is correct. Maybe "rotation" could be replaced with "combination" in OP's wording? – MonkeyZeus Mar 17 '16 at 19:32
  • I see his test strings now (missed that). The function name `isSubstring` is misleading too. – BryanT Mar 17 '16 at 20:22
  • @BryanT No sweat, the question itself is quite misleading at multiple points. – MonkeyZeus Mar 17 '16 at 20:44
1

Here is a multibyte safe function to compare the two strings:

function mb_isAnagram($s1, $s2) {
    if (strlen($s1) != strlen($s2)) {
        return false;
    } else {
        $c1 = preg_split('//u', $s1, null, PREG_SPLIT_NO_EMPTY);
        $c2 = preg_split('//u', $s2, null, PREG_SPLIT_NO_EMPTY);
        sort($c1);
        sort($c2);
        if ($c1 === $c2) {
            return true;
        } else {
            return false;
        }
    }
}
0

You could split each string and sort it, like this:

$split1 = unpack("C*",$s1);
asort($split1);

Then you can traverse both arrays comparing the values.

TheMagicCow
  • 396
  • 1
  • 10
0
<?php
function isRotationalString($str1,$str2){
    $len = strlen($str1); 
    if($str1 === $str2){
        return true;
    }else{
        if($len == strlen($str2)){
            $flag = true;
            for($i=0;$i<$len;$i++){
                if($str1[0]==$str2[$i]){
                    $tst = $i;$start = true;break;
                }
            }
            if($start){
                for($j=0;$j<$len;$j++){
                    $m = $j+$tst; 
                    if($m < $len){
                        if($str1[$j] != $str2[$m]){
                            $flag = false;break;
                        }
                    }else{
                        if($m>=$len)
                        {
                            $k = $m - $len;
                            if($str1[$j] != $str2[$k]){
                                $flag = false;break;   
                            }
                        }
                    }      
                }  
            }else{
                $flag = false;
            }
            return $flag;
        }
    }
}
echo isRotationalString("abcd","bcda")?'It is':'It is not';
?>

above script will check whether a string is a rotation of another string or not?
isRotationalString("abcd","bcda") => It is
isRotationalString("abcd","cbda") => It is Not

Onkar
  • 11
  • 4
0

This is the function for string rotation.

echo isRotationalString("abcdef","efabcd")?'It is':'It is not';

function isRotationalString($str1,$str2){
    $len = strlen($str1); 
    if($str1 === $str2){
        return true;
    } else {
        if($len == strlen($str2)) {
    
            $stringMatchedArr1 = $stringMatchedArr2 = [];
            for($i=0; $i<$len; $i++) {
                $substr = substr($str1,$i );
                $pos = strpos($str2, $substr);
                if($pos !== false) {
                    $stringMatchedArr1[] = $substr;
                }
            }
        
            for($j=1; $j <= $len; $j++) {
                $substr = substr($str1, 0, $j );
                $pos = strpos($str2, $substr);
                if($pos !== false) {
                    $stringMatchedArr2[] = $substr;
                }
            }
        
            foreach($stringMatchedArr2 as  $string1) {
                foreach($stringMatchedArr1 as $string2) {
                    if($string1.$string2 == $str1)
                         return true;
                }
            }
       
        }
    }
}
-3

I would sort the characters in the strings by making it an array and then imploding them to a string again.

if (sort(str_split($s1)) == sort(str_split($s2))) {

That would do the trick in one line.

Edit: Thanks Don't Panic, edited my answer!

Rolf
  • 78
  • 6