1

I have this text: abcdzwxy and I want to encrypt him with Atbash method So I create an array, that have all the letters and for every one I replace with his Atbash. There is example in hebrew:

$text = 'abcdzwxy';
$letters2 = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
$letters3 = ['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'];

$i = 0;
foreach($letters2 as $l) {
    $text = str_replace($l, $letters3[$i], $text);
    $i++;
}

echo $text;

the result its: abcdabcd instead of zwxyabcd - because when its replace a to z (by the array) its need in the future to replace z to a - so its almost "duplicate" the string.. and solution?

  • anyone help please? – Amanda White Mar 25 '19 at 08:21
  • Yes, you can't use `str_replace()` because it works on the entire string and so it produces incorrect results. Instead you should iterate over the characters of your string, and subtitute each character separately. Also I think it would be easier if you have your `$letters2` and `$letters3` arrays in a single associative array. – t.m.adam Mar 25 '19 at 08:42
  • @t.m.adam I did not really understand your offer. can you post an example please? – Amanda White Mar 25 '19 at 08:47

1 Answers1

3

You can't use str_replace() here because, as you've mentioned, it may replace characters more than one time as you iterate over you array. Instead you should iterate over the characters of your string and subtitute each character separately, by index.

for ($i = 0; $i < strlen($text); $i++) {
    $text[$i] = $letters3[array_search($text[$i], $letters2)];
}

While you could use two arrays for the alphabet and substitution characters, I think an associative array is a more appropriate structure for this task.

$text = 'abcdzwxy';
$letters2 = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
$letters3 = ['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'];
$map = array_combine($letters2, $letters3);

for ($i = 0; $i < strlen($text); $i++) {
    $text[$i] = array_search($text[$i], $map);
}
echo $text;

If the string contains Hebrew or other UTF-8 characters you can't iterate over it because a character may contain more than one bytes. In this case you could use preg_split() to create an array of UTF-8 characters.

$text = preg_split('//u', $text, null, PREG_SPLIT_NO_EMPTY);

(code taken from this answer)

The rest of the code is mostly the same, but now $text is an array and it must be converted back to string.

function str_to_array($str) {
    return preg_split('//u', $str, null, PREG_SPLIT_NO_EMPTY);
}

$text = "תשר";
$text = str_to_array($text);
$alphabet = str_to_array("אבגדהוזחטיךכלםמןנסעףפץצקרשת");
$map = array_combine($alphabet, array_reverse($alphabet));

for ($i = 0; $i < sizeof($text); $i++) {
    $char = array_search($text[$i], $map);
    if ($char) {
        $text[$i] = $char;
    }
}
$text = implode($text);
t.m.adam
  • 15,106
  • 3
  • 32
  • 52
  • thanks for you best answer, but I have question, why its not work with utf-8? I mean with `Hebrew` language for example – Amanda White Mar 25 '19 at 09:24
  • UTF-8 characters may conain more than one and up to four bytes, so we can't iterate over each character like in ASCII. But it may be possible if you create an array of characters from the string. – t.m.adam Mar 25 '19 at 09:42
  • I saw right now your update, its work fine! but its remove the spaces between words (I dont know to use preg_split) so I need to access the spaces to stay in their positions. its possible? – Amanda White Mar 25 '19 at 11:24
  • 1
    I think that's because `array_search()` can't find a space in `$map` and returns false. I've updated the code to ignore those cases so characters that are not in `$map` are not modified. – t.m.adam Mar 25 '19 at 11:38
  • Thank you very much you help me a lot ;) have a awesome day hope your life be the best as the world can offer ♥ – Amanda White Mar 25 '19 at 11:55