1

I'm a beginner with PHP (and programming in general). To test what I've learned so far I wrote this code, which prints all the possibile combinations of a set number of dice with a certain number of faces. (you'll find the code at the end).

What I want to do is dynamically change the number of nested for loops according to the $dicenumber variable. Right now it can only process 3 dice, since the code is:

            for ($d1=1; $d1 <= $d1value ; $d1++) { 
                for ($d2=1; $d2 <= $d2value ; $d2++) { 
                for ($d3=1; $d3 <= $d3value ; $d3++) { 
                        array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
                    }
                }
            }

But I want to change it so that, for example, if $dicenumber were 2, it would produce something like:

            for ($d1=1; $d1 <= $d1value ; $d1++) { 
                for ($d2=1; $d2 <= $d2value ; $d2++) { 
                        array_push(${sum.($d1+$d2)}, "$d1"."$d2");
                }
            }

I want the code to process for whatever number $dicenumber may be, without limits. Looking around, it seems like I have to add some kind of recursive code, but I don't know how to do that. Any tips? Also, any feedback on what I did wrong in general, would be extremely helpful! thanks!

            <?php
            //defines the number and type of dice
            $dicenumber = 3;
            $dtype = 6;
            //defines the maximum value of every die 
            for ($i=1; $i <=$dicenumber ; $i++) { 
                ${d.$i.value} = $dtype;
            }
            //defines and array for each possible sum resulting from the roll of the given number of dice. 
            for ($i=$dicenumber; $i <= ($dtype*$dicenumber) ; $i++) { 
            ${sum.$i} = array();
            }

            //the troublesome piece of code I want to change    

            for ($d1=1; $d1 <= $d1value ; $d1++) { 
                for ($d2=1; $d2 <= $d2value ; $d2++) { 
                for ($d3=1; $d3 <= $d3value ; $d3++) { 
                        array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
                    }
                }
            }

            //prints all the possible roll combinations, each line lists combination that share the same sum
            for ($i=$dicenumber; $i <= ($dtype*$dicenumber); $i++) { 
        print join(" ", ${sum.$i})."<br />";
        }
        ?>

2 Answers2

1

Here we have a two-function process. The first function, buildArrays, creates arrays in the proper format to feed into the second function, allCombinations. So, for this example with 3 d6's in play, buildArrays will produce an array equivalent to this:

$data = array(
    array(1, 2, 3, 4, 5, 6),
    array(1, 2, 3, 4, 5, 6),
    array(1, 2, 3, 4, 5, 6));

I will warn you that as you increase the number of dice and the number of sides, the number of possible combinations increases exponentially! This means that you could place a very large demand on the server, and both timeout and max memory limits will quickly come into play. The arrays generated could be very, very large and quickly consume more than the max memory limit. That said, here we go:

function buildArrays($dicenumber, $dtype){

    for ($i = 0; $i<$dicenumber; $i++){
        $tmp = array();
        for ($j = 1; $j<=$dtype; $j++){
            $tmp[] = $j;
        }
        $data[$i] = $tmp;
    }
    return $data;
}



function allCombinations($data){

    $result = array(array()); //this is crucial, dark magic.

    foreach ($data as $key => $array) {
        $new_result = array();
        foreach ($result as $old_element){
            foreach ($array as $element){
                if ($key == 0){
                    $new_result[] = $element;
                } else {
                    $new_result[] = $old_element.$element;
                }
            }
        $result = $new_result;
        }
    }
    return $result;
}

//set variables
$dicenumber = 3;
$dtype = 6;

//set_time_limit(0); //You may need to uncomment this for large values.

//call functions
$data = buildArrays($dicenumber, $dtype);
$results = allCombinations($data);

//print out the results
foreach ($results as $result){
    echo $result."<br/>";   
}

N.B. This answer is a variant of the cartesian product code

Community
  • 1
  • 1
larsAnders
  • 3,813
  • 1
  • 15
  • 19
  • Thank you so much!! You have no idea how informative this is to me. I see this code prints out the combinations one after another, while my original wonky code printed them in rows sorted by sum. Your process is clearly more flexible because I can manipulate the output in whatever way I like, including sorting them in rows, which is the next thing I'll try do do :) Thanks again! Really really appreciate it. – user3507868 Apr 08 '14 at 00:15
0

If you have learned functions, you can do a recursive call and keep track of what dicenumber you're on, then increment it each call to the function (and end the loop once you've hit your #). understanding basic recursion

Community
  • 1
  • 1
  • Thank you for the reply. I've got some notion of user-made function (i.e. i did that unit in CodeCademy), I've been fiddling with it the last couple of hours, but I'm stuck because I can't find a way to add that array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3"); dynamically into the recursive function... any suggestion? – user3507868 Apr 07 '14 at 21:59