Search code examples
phpmathcombinationspermutation

How to generate all the permutations of 2 letters and 2 numbers in PHP


So, I have been trying to adapt all the examples I have found but haven't quite found the solution. What I would like to end up with is a list off all the permutations of a combination of letters and numbers but the output is always has 2 letters and 2 numbers (in all orders).

What I have so far is:

function combinations($arrays, $i = 0) {
    if (!isset($arrays[$i])) {
        return array();
    }
    if ($i == count($arrays) - 1) {
        return $arrays[$i];
    }

    // get combinations from subsequent arrays
    $tmp = combinations($arrays, $i + 1);

    $result = array();

    // concat each array from tmp with each element from $arrays[$i]
    foreach ($arrays[$i] as $v) {
        foreach ($tmp as $t) {
            $result[] = is_array($t) ? 
                array_merge(array($v), $t) :
                array($v, $t);
        }
    }
    return $result;
}

$letters = 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");
$numbers = array("0","1","2","3","4","5","6","7","8","9");

$combinations = combinations(array( $letters, $letters, $numbers, $numbers));

foreach ($combinations as $values) {
    echo implode("",$values).'<br>';
}

But that only outputs results in the order of 2 letters first followed by the two numbers.

Also bonus question, how do I calculate the total results I should be expecting, I know if it was all letters, it would be 26x26x26x26 so 4 letters only I would be expecting 456,976, but what about 2 letters & 2 numbers?


Solution

  • Treat them separately at first. Choose your 2 numbers in (strictly?) increasing order, then choose your 2 letters in (strictly?) increasing order, and calculate all the permutations of the result. Whether they are strictly increasing or not depends on whether or not you want to be able to have both numbers or both letters the same.

    For the case where you allow the two numbers or letters to be the same, you have

    No. of (not strictly) increasing pairs of numbers P_Num = 1 + ... + 10 = 55. 
    
    No. of (not strictly) increasing pairs of letters P_Let = 1 + ... + 26 = 351. 
    

    For the case where you don't allow the two numbers or letters to be the same, you have

    No. of strictly increasing pairs of numbers P_Num = 1 + ... + 9 = 45. 
    
    No. of strictly increasing pairs of letters P_Let = 1 + ... + 25 = 325. 
    

    There are 4! = 24 permutations of 4 distinct elements, giving 24*45*325 = 351,000 combinations.

    There are 10 cases where the two numbers are the same, and assuming the letters are not the same, the number of permutations of 4 elements where 2 are the same is 4!/2! = 12 giving another 12*325*10 = 39,000 combinations.

    There are 26 cases where the two letters are the same, and assuming the numbers are not the same, the number of permutations of 4 elements where 2 are the same is 4!/2! = 12 giving another 12*45*26 = 14,040 combinations.

    There are 260 cases where the two letters and numbers are the same, the number of permutations of 4 elements where 2 pairs are the same is 4!/(2! * 2!) = 6 giving another 6*260 = 1,560 combinations.

    So, if you allow the letters and numbers to be the same, you have

    351,000 + 39,000 + 14,040 + 1,560 = 405600 combinations.

    A naive way to generate such combinations which isn't so inefficient in this case, would be to generate all the 24*55*351 = 463,320 combinations and exclude those combinations where the indexes of the duplicated elements are not in strictly increasing order.