40

Some time ago during a job interview I got the task to reverse a string in PHP without using strrev.

My first solution was something like this:

$s = 'abcdefg';
$temp = '';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $temp .= $s{$length - $i - 1};
}
var_dump($temp);
// outputs string(7) "gfedcba"

then they asked me if I could do this without doubling the memory usage (not using the $temp variable or any variable to copy the reversed string to) and I failed. This kept bugging me and since then I tried to solve this multiple times but I constantly failed.

My latest try looks like this:

$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i * 2} . $s;
}
var_dump($s);
// outputs string(14) "gfedcbaabcdefg"

It's not a solution to chop off "abcdefg" after the loop because then I would still double the amount of memory used. I need to remove the last character in every iteration of the loop.

I tried to use mb_substr like this:

$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i * 2} . mb_substr($s, $length - $i - 1, 1);
}
var_dump($s);

but it only gives me Uninitialized string offset errors.

This is where I'm stuck (again). I tried googling but all the solutions I found either echo the characters directly or use a temporary variable.

I also found the Question PHP String reversal without using extra memory but there's no answer that fits my needs.

Community
  • 1
  • 1
prehfeldt
  • 2,184
  • 2
  • 28
  • 48
  • 1
    You could XOR each byte with its opposite byte, but AFAIK PHP doesn't support bitwise operators on strings (you could do this in C.) – Thomas O Apr 23 '15 at 08:37
  • 1
    @ThomasO wow, the C people are crazy http://stackoverflow.com/a/198264/746383 :) – prehfeldt Apr 23 '15 at 08:55
  • 3
    @prehfeldt So are the PHP people: http://3v4l.org/2W3Ei – Rizier123 Apr 23 '15 at 09:00
  • 1
    @prehfeldt fun fact: doing the xor swap is way, way slower than the obvious code. Penny wise and pound foolish – Voo Apr 23 '15 at 18:46
  • People ask ridiculous questions during programmer job interviews! A non-programming interviewer would be impressed by "Why would you want me to re-invent the (not round!) wheel?" – Fr0zenFyr Sep 21 '16 at 11:58

23 Answers23

45

That's an interesting one. Here's something I just came up with:

$s = 'abcdefghijklm';
for($i=strlen($s)-1, $j=0; $j<$i; $i--, $j++) {
    list($s[$j], $s[$i]) = array($s[$i], $s[$j]);
}
echo $s;

list() can be used to assign a list of variables in one operation. So what I am doing is simply swapping characters (starting with first and last, then second-first and second-last and so on, till it reaches the middle of the string)

Output is mlkjihgfedcba. Not using any other variables than $s and the counters, so I hope that fits your criteria.

ksbg
  • 3,214
  • 1
  • 22
  • 35
25

You can use the fact that in PHP a string can be thought of as an array of characters.

Then basically what you want to do is to replace each character $i on the left side of the middle of the string with the character $j on the right side of the middle with the same distance.

For example, in a string of seven characters the middle character is on position 3. The character on position 0 (distance 3) needs to be swapped with the character on position 6 (3 + 3), the character on position 1 (distance 2) needs to be swapped with the character on position 5 (3 + 2), etc.

This algorithm can be implemented as follows:

$s = 'abcdefg';

$length = strlen($s); 
for ($i = 0, $j = $length-1; $i < ($length / 2); $i++, $j--) {
    $t = $s[$i];
    $s[$i] = $s[$j];
    $s[$j] = $t;
}

var_dump($s);
ebo
  • 2,717
  • 1
  • 27
  • 22
10
$string = 'abc';

$reverted = implode(array_reverse(str_split($string)));
Bartłomiej Wach
  • 1,968
  • 1
  • 11
  • 17
7

Try this:

$s = 'abcdefg';

for ($i = strlen($s)-1; $i>=0; $i--) {
       $s .= $s[$i];
       $s[$i] = NULL;
 }
var_dump(trim($s));
Bushra Shahid
  • 781
  • 7
  • 20
7

You could use the XOR swap trick.

function rev($str) {
    $len = strlen($str);

    for($i = 0; $i < floor($len / 2); ++$i) {
        $str[$i] = $str[$i] ^ $str[$len - $i - 1];
        $str[$len - $i - 1] = $str[$i] ^ $str[$len - $i - 1];
        $str[$i] = $str[$i] ^ $str[$len - $i - 1];
    }

    return $str;
}

print rev("example");
Gerard
  • 831
  • 6
  • 15
6

Here it is PHP7 version of this:

echo "\u{202E}abcdefg"; // outs: gfedcba
George G
  • 7,443
  • 12
  • 45
  • 59
  • 1
    pretty awesome, whats that ? can you explain the function name can you add more details – Muhammad Aug 18 '16 at 18:51
  • Extremely fast, but it can't be used to reverse an integer. For example, this code will output zero: $i = 123; $i = (int) "\u{202E}$i"; echo $i; // 0 – MAChitgarha Oct 19 '17 at 14:02
  • 1
    @MAChitgarha unicode codepoint `\u202E` is an invisible character (as u can read from docs also), so what really happens is that that character literally leads the string, so when u typecast to int, of course it returns 0, but if you just echo `\u{202E}123` it will print `321` but to see any invisible characters in string also you could user `echo json_encode($str)` https://stackoverflow.com/questions/9345841/php-is-there-a-way-to-see-invisible-characters-like-n/27167448#27167448 – George G Oct 19 '17 at 15:13
5

PHP strings are kinda-sorta mutable, but due to copy-on-write it's very difficult to modify them in-place without a copy being made. Some of the above solutions work, but only because they're stand-alone; some already fail because they define a function without a pass-by-reference argument. To get the code to actually operate in-place in a larger program, you'd need to pay careful attention to assignments, function arguments, and scopes.

Example:

$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");

> "abc, bbc"

I suppose that if between initializing the variable and modifying it you only ever used by-reference assignments (&=) and reference arguments (function rev(&$string)) (or assign the string to an object property initially, and then never assign it to any other variable), you might be able to change the original value of the string without making any copies. That's a bit ridiculous, however, and I'd assume that the interviewer who came up with that question didn't know about copy-on-write.

This isn't quite the same as immutability in other languages, by the way, because it applies to arrays too:

$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));

> "012112"

To sum up, all types (except for objects as of PHP5) are assigned with copy-on-write unless you specifically use the &= operator. The assignment doesn't copy them, but unlike most other languages (C, Java, Python...) that either change the original value (arrays) or don't allow write access at all (strings), PHP will silently create a copy before making any changes.

Of course, if you switched to a language with more conventional pointers and also switched to byte arrays instead of strings, you could use XOR to swap each pair of characters in place:

for i = 0 ... string.length / 2:
    string[i] ^= string[string.length-1-i] 
    string[string.length-1-i] ^= string[i]
    string[i] ^= string[string.length-1-i]
Community
  • 1
  • 1
Christoph Burschka
  • 4,467
  • 3
  • 16
  • 31
4

Basically @EricBouwers answer, but you can remove the 2nd placeholder variable $j

function strrev2($str)
{
    $len = strlen($str);
    for($i=0;$i<$len/2;$i++)
    {
        $tmp = $str[$i];
        $str[$i] = $str[$len-$i-1];
        $str[$len-$i-1] = $tmp;
    }

    return $str;
}

Test for the output:

echo strrev2("Hi there!"); // "!ereht iH"
echo PHP_EOL;
echo strrev2("Hello World!"); // "!dlroW olleH"

This will go through the list and stop halfway, it swaps the leftmost and rightmost, and works it's way inward, and stops at the middle. If odd numbered, the pivot digit is never swapped with itself, and if even, it swaps the middle two and stops. The only extra memory used is $len for convenience and $tmp for swapping.

If you want a function that doesn't return a new copy of the string, but just edits the old one in place you can use the following:

function strrev3(&$str)
{
    $len = strlen($str);
    for($i=0;$i<$len/2;$i++)
    {
        $tmp = $str[$i];
        $str[$i] = $str[$len-$i-1];
        $str[$len-$i-1] = $tmp;
    }
}

$x = "Test String";
echo $x;           // "Test String"
strrev3($x);
echo PHP_EOL;
echo $x;           // "gnirtS tseT"

Using &$str passes a direct pointer the the string for editing in place.

And for a simpler implementation like @treegardens, you can rewrite as:

$s = 'abcdefghijklm';
$len = strlen($s);
for($i=0; $i < $len/2; $i++) {
    list($s[$i], $s[$len-$i-1]) = array($s[$len-$i-1], $s[$i]);
}
echo $s;

It has the similar logic, but I simplified the for-loop quite a bit.

JPMC
  • 1,043
  • 1
  • 13
  • 16
4

Its Too Simple

//Reverse a String

$string = 'Basant Kumar';
$length = strlen($string);

for($i=$length-1;$i >=0;$i--){
    echo $string[$i];
}
Ian
  • 30,182
  • 19
  • 69
  • 107
3

Here is my code to solve your problem

 <?php
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i}.mb_substr($s,0,$i).mb_substr($s,$i+1);
}
var_dump($s);
?>
Islam Zedan
  • 656
  • 4
  • 21
3

You could also use a recursion to reverse the string. Something like this for example:

function reverse($s) {

    if(strlen($s) === 1) return $s;

    return substr($s, strlen($s)-1) . reverse(substr($s , 0, strlen($s)-1));
}

What you do here is actually returning the last character of the string and then calling again the same function with the substring that contains the initial string without the last character. When you reach the point when your string is just one character then you end the recursion.

csdinos
  • 197
  • 2
  • 6
1

You can use this code to reverse a string without using the reserved function in php.

Code:

<?php

function str_rev($y)// function for reversing a string by passing parameters
{
for ($x = strlen($y)-1; $x>=0; $x--) {
       $y .= $y[$x];
       $y[$x] = NULL;
 }

echo $y;

}
str_rev("I am a student");
?>

Output:

tneduts a ma I

In the above code, we have passed the value of the string as the parameter.We have performed the string reversal using for loop.

atif
  • 87
  • 1
  • 3
1

you could use substr with negative start.

Theory & Explanation

you can start with for loop with counter from 1 to length of string, and call substr inside iteration with counter * -1 (which will convert the counter into negative value) and length of 1.

So for the first time counter would be 1 and by multiplying with -1 will turn it to -1

Hence substr('abcdefg', -1, 1); will get you g
and next iteration substr('abcdefg', -2, 1); will get you f
and                       substr('abcdefg', -3, 1); will get you e
and so on ...

Code

$str = 'abcdefghijklmnopqrstuvwxyz';
for($i=1; $i <= strlen($str); $i++) {
    echo substr($str, $i*-1, 1);
}

In Action: https://eval.in/583208

kamal pal
  • 4,187
  • 5
  • 25
  • 40
0
public function checkString($str){
    if(!empty($str)){ 
        $i = 0;
        $str_reverse = '';

        while(isset($str[$i])){ 
            $strArr[] = $str[$i];
            $i++;
        }
        for($j = count($strArr); $j>= 0; $j--){ 
            if(isset($strArr[$j])){
                $str_reverse .= $strArr[$j];
            }
        }
        if($str == $str_reverse){ 
            echo 'It is a correct string';
        }else{
            echo 'Invalid string';
        }
    }
    else{
        echo 'string not found.';
    }
}
Sanjay Verma
  • 397
  • 3
  • 3
0
//Reverse String word by word
$str = "Reverse string word by word";
$i = 0;
while ($d = $str[$i]) {
    if($d == " ") {
        $out = " ".$temp.$out;
        $temp = "";
    }
    else
        $temp .= $d;

    $i++;
}
echo $temp.$out;
Vini.g.fer
  • 11,639
  • 16
  • 61
  • 90
0

The following solution is very simple, but it does the job:

$string = 'Andreas';
$reversedString = '';

for($i = mb_strlen($string) - 1; $i >= 0; $i--){
    $reversedString .= $string[$i];
}

var_dump($reversedString) then results: string(7) "saerdnA"

Andreas
  • 2,821
  • 25
  • 30
0
   <?php
     $value = 'abcdefg';
     $length_value = strlen($value);
     for($i = $length_value-1; $i >=0 ;$i--){    
       echo $value[$i];
     }
   ?>
Siddharth Shukla
  • 1,063
  • 15
  • 14
  • 1
    Thank you for this code snippet, which may provide some immediate help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its educational value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with similar, but not identical, questions. Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Jul 26 '17 at 12:10
0

you can try this..

$string = "NASEEM";
$total_word = strlen($string);      
for($i=0; $i<=$total_word; $i++)
{
   echo substr($string,$total_word-$i,1);
}
Naseem Ahmad
  • 111
  • 1
  • 4
0

i have used some built in function but without str_rev function .

<?php


$text = "red";

$arr = str_split($text);

$rev_text =  array_reverse($arr);

echo join(" ",$rev_text);


?>
Nahid Hasan
  • 687
  • 1
  • 10
  • 34
0

Try This

<?php
$str="abcde";
for($i=strlen($str)-1;$i>=0;$i--){
    echo $str[$i];
}
?>

output

edcba

Pavan Hukerikar
  • 175
  • 1
  • 8
0

This is my solution to solve this.

$in = 'This is a test text';
$out = '';
// find string length
$len = strlen($in);

// loop through it and print  it reverse
for ( $i = $len - 1; $i >=0;$i-- )
{
    $out = $out.$in[$i];
 }

echo $out;
Ihor
  • 53
  • 8
0

Reverse string using recursion function.

$reverseString = '';
function Reverse($str, $len)
{
    if ($len == 0) {
        return $GLOBALS['reverseString'];
    } else {
        $len--;
        $GLOBALS['reverseString'] .= $str[$len];

        return Reverse($str, $len);
    }
}

$str = 'Demo text';
$len = strlen($str);
echo Reverse($str, $len)
Rupesh Wankhede
  • 457
  • 5
  • 16
-1

Try this

$warn = 'this is a test'; 
$i=0;
while(@$warn[$i]){
  $i++;} 
while($i>0) 
{ 
  echo $warn[$i-1]; $i--;
}
Alwi
  • 1