php: converting number to alphabet and vice versa

76,800

Solution 1

I don't understand at all the logic you're trying to use in that function. What you're trying to do seems very strange (why does 'a' map to zero and yet 'aa' maps to 26?), but this appears to work. (You will want to use some more test cases, I only checked that it gives the correct output for the case 'aba'.)

function toNum($data) {
    $alphabet = array( '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'
                       );
    $alpha_flip = array_flip($alphabet);
    $return_value = -1;
    $length = strlen($data);
    for ($i = 0; $i < $length; $i++) {
        $return_value +=
            ($alpha_flip[$data[$i]] + 1) * pow(26, ($length - $i - 1));
    }
    return $return_value;
}

Solution 2

Shortest way, in PHP >= 4.1.0

$alphabet = range('A', 'Z');

echo $alphabet[3]; // returns D

echo array_search('D', $alphabet); // returns 3

Solution 3

There is a very clever solution by Theriault in the comments of PHPs base_convert function

/**
* Converts an integer into the alphabet base (A-Z).
*
* @param int $n This is the number to convert.
* @return string The converted number.
* @author Theriault
* 
*/
function num2alpha($n) {
    $r = '';
    for ($i = 1; $n >= 0 && $i < 10; $i++) {
    $r = chr(0x41 + ($n % pow(26, $i) / pow(26, $i - 1))) . $r;
    $n -= pow(26, $i);
    }
    return $r;
}
/**
* Converts an alphabetic string into an integer.
*
* @param int $n This is the number to convert.
* @return string The converted number.
* @author Theriault
* 
*/
function alpha2num($a) {
    $r = 0;
    $l = strlen($a);
    for ($i = 0; $i < $l; $i++) {
    $r += pow(26, $i) * (ord($a[$l - $i - 1]) - 0x40);
    }
    return $r - 1;
}

Solution 4

From number to alphabet (with A=0, B=1, etc...):

function toAlpha($num){
    return chr(substr("000".($num+65),-3));
}

You can do the same from alphabet to number with the function ord().

Changing 65 with 97, you can obtain the lowercase values.

Solution 5

Your problems comes from your map. Look at this:

$alpha[0] = 'Alphabet';
for ($i = 'a'; $i<'z'; $i++) {
    $alpha[] = $i;
}
$alpha[26] = 'z';

You can run this as high as you want and your server memory will allow. The PHP is buggy, and (at least on my server) if you use the <= operator:

$alpha[0] = 'Alphabet';
for ($i = 'a'; $i<='z'; $i++) {
    $alpha[] = $i;
}

then it will map all the way to [676]=> string(2) "yz"! You just have to play with it.

I didn't want to map a letter to [0] so I just put a title in there. Obviously you can leave it out if you want 0=>a, 1=>b, etc.

Once the array is correct, the function is trivial.

Share:
76,800
pillarOfLight
Author by

pillarOfLight

Updated on November 04, 2020

Comments

  • pillarOfLight
    pillarOfLight over 3 years

    So I have this function:

    function toAlpha($data){
        $alphabet =   array('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');
        $alpha_flip = array_flip($alphabet);
        if($data <= 25){
          return $alphabet[$data];
        }
        elseif($data > 25){
          $dividend = ($data + 1);
          $alpha = '';
          $modulo;
          while ($dividend > 0){
            $modulo = ($dividend - 1) % 26;
            $alpha = $alphabet[$modulo] . $alpha;
            $dividend = floor((($dividend - $modulo) / 26));
          } 
          return $alpha;
        }
    }
    

    which given a number converts it into character and it works fine

    but then I also want a reverse function of this that given any output of this function, return the exact input that was put in to produce that output and I tried this:

    function toNum($data){
    $alphabet =   array('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');
        $alpha_flip = array_flip($alphabet);
      if(strlen($data) == 1){
              return (isset($alpha_flip[$data]) ? $alpha_flip[$data] : FALSE);
            }
            else if(strlen($data) > 1){
              $num = 1;
              for($i = 0; $i < strlen($data); $i++){
                if(($i + 1) < strlen($data)){
                  $num *= (26 * ($alpha_flip[$data[$i]] + 1));
                }
                else{
                  $num += ($alpha_flip[$data[$i]] + 1);
                }
              }
              return ($num + 25);
            }
    }
    

    but it's not working properly...toAlpha(728) is producing 'aba' but toNum('aba') is producing 1378 rather than 728...

    what did I do wrong? how can I fix the reverse function so that it works properly?

    thanks in advance!