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");

?>
5
  • Just check if all symbols of one string are in another. Or sort symbols and check if they are the same. Commented Mar 17, 2016 at 17:54
  • I would sort both strings (alphabetically) and then compare. stackoverflow.com/questions/9912469/… Commented Mar 17, 2016 at 17:55
  • Use strrev it will do exactly what you want Commented Mar 17, 2016 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. Commented Mar 17, 2016 at 18:04
  • @don't panic, yes you are right, I missed the last line when reading the question Commented Mar 17, 2016 at 18:06

7 Answers 7

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.

Sign up to request clarification or add additional context in comments.

8 Comments

This is impressive, I like it :)
I wonder if this will exhibit weird behavior when using using stuff like count_chars('Ýô', 1);
@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.
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 Broken! :-) See updated answer. Thanks. But your proposed function gets cheated too by the same case ;-)
|
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";
    }
}

4 Comments

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 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?
I see his test strings now (missed that). The function name isSubstring is misleading too.
@BryanT No sweat, the question itself is quite misleading at multiple points.
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;
        }
    }
}

Comments

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.

Comments

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

Comments

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;
                }
            }
       
        }
    }
}

Comments

-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!

2 Comments

It isn't necessary to implode; the arrays are comparable.
sort() accepts the array by reference and returns a boolean.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.