views:

151

answers:

3

Hi, This question is already asked/answered by other members but my case is a bit different..

Problem: How to reverse words in a string? You can use strpos(), strlen(), substr() but not other very useful functions such as explode(), strrev() etc.

This is basically an interview question so I need to demonstrate ability to manipulate strings.

Example:

$string = "I am a boy"

Answer:

"I ma a yob"

Below is my solution that took me 2 days(sigh) but there gotta be more elegant solution. My code looks very long..

Thanks in advance!

My intention:

1. get number of word
2. based on number of word count, grab each word and store into array
3. loop through array and output each word in reverse order

Code:

<?php

$str = "I am a boy";

echo reverse_word($str) . "\n";

function reverse_word($input) {
    //first find how many words in the string based on whitespace
    $num_ws = 0;
    $p = 0;
    while(strpos($input, " ", $p) !== false) {
        $num_ws ++;
        $p = strpos($input, ' ', $p) + 1;
    }

    echo "num ws is $num_ws\n";

    //now start grabbing word and store into array
    $p = 0;
    for($i=0; $i<$num_ws + 1; $i++) {
        $ws_index = strpos($input, " ", $p);
        //if no more ws, grab the rest
        if($ws_index === false) {
            $word = substr($input, $p);
        }
        else {
            $length = $ws_index - $p;
            $word = substr($input, $p, $length);
        }
        $result[] = $word;
        $p = $ws_index + 1; //move onto first char of next word
    }

    print_r($result);
    //append reversed words
    $str = '';
    for($i=0; $i<count($result); $i++) {
        $str .= reverse($result[$i]) . " ";
    }
    return $str;
}

function reverse($str) {
    $a = 0;
    $b = strlen($str)-1;
    while($a < $b) {
        swap($str, $a, $b);
        $a ++;
        $b --;
    }
    return $str;
}

function swap(&$str, $i1, $i2) {
    $tmp = $str[$i1];
    $str[$i1] = $str[$i2];
    $str[$i2] = $tmp;
}

?>
A: 

http://php.net/strrev

Edit: You asked for each word to be reversed, but still in "word" order. Something like this might work better:

$string = "I am a boy!";
$array = explode(" ", $string);
foreach ($array as &$word) {
    $word = strrev($word);
}
$rev_string = implode(" ", $array);
gms8994
His/Her question disallows that!
Martin Smith
Yeah, saw that after I replied :)
gms8994
It won't yield the correct answer, either. He wants to reverse each word individually.
webbiedave
He can't use explode.
webbiedave
+4  A: 
$string = "I am a boy";

$reversed = "";
$tmp = "";
for($i = 0; $i < strlen($string); $i++) {
    if($string[$i] == " ") {
        $reversed .= $tmp . " ";
        $tmp = "";
        continue;
    }
    $tmp = $string[$i] . $tmp;    
}
$reversed .= $tmp;

print $reversed . PHP_EOL;
>> I ma a yob
thetaiko
You're hired!!!
webbiedave
Thanks for the answer, amazing solution...
masato-san
+1  A: 

Whoops! Mis-read the question. Here you go (Note that this will split on all non-letter boundaries, not just space. If you want a character not to be split upon, just add it to $wordChars):

function revWords($string) {
    //We need to find word boundries
    $wordChars = 'abcdefghijklmnopqrstuvwxyz';
    $buffer = '';
    $return = '';
    $len = strlen($string);
    $i = 0;
    while ($i < $len) {
        $chr = $string[$i];
        if (($chr & 0xC0) == 0xC0) {
            //UTF8 Characer!
            if (($chr & 0xF0) == 0xF0) {
                //4 Byte Sequence
                $chr .= substr($string, $i + 1, 3);
                $i += 3;
            } elseif (($chr & 0xE0) == 0xE0) {
                //3 Byte Sequence
                $chr .= substr($string, $i + 1, 2);
                $i += 2;
            } else {
                //2 Byte Sequence
                $i++;
                $chr .= $string[$i];
            }
        }
        if (stripos($wordChars, $chr) !== false) {
            $buffer = $chr . $buffer;
        } else {
            $return .= $buffer . $chr;
            $buffer = '';
        }
        $i++;
    }
    return $return . $buffer;
}

Edit: Now it's a single function, and stores the buffer naively in reversed notation.

Edit2: Now handles UTF8 characters (just add "word" characters to the $wordChars string)...

ircmaxell
question disallows use of strrev()
thetaiko
@thetaiko Thanks, I mis-read the question initially. Edited in a solution...
ircmaxell