3

I want an multidimensional array, where each element is an array of X elements - lets say 3.

I basically want to count from 0 to y (lets say 12) in the 3rd element, then after 0,0,12 I want the next element in the array to be the array 0,1,0 - finished with 12,12,12.

I'm sort of counting up in base...12, ticking over to the next element in the array when it's done.

e.g.

0,0,0
0,0,1
...
0,0,12
0,1,0
0,1,1
0,1,2
...
0,1,12
0,2,0
...
12,12,12

ok, fine - I can do that like this

$maxCountNumber= 12;
$i=1;
for ($j=0; $j < $maxCountNumber+1; $j++) { 
    for ($k=0; $k < $maxCountNumber+1; $k++) { 
        for ($l=0; $l < $maxCountNumber+1; $l++) { 
                print "<br/>$i: $j, $k, $l";
                $results[$i] = array($j, $k, $l);
                $i++;
        }
    }
}

But what if I don't want just 3 elements every-time - sometimes i'll want 4 - Rather than hundreds, tens and units I want Thousands, Hundreds, tens and units... or how about 7 elements?

I'm sure recursion is the answer but I just can't seem to bend my head around this particular problem.

Unless there's something that will count up for me in 12s rather than 10s?

Thank you for all and any advice.

12
  • Modulus is usually used for things like this. Also have you seen base_convert? Commented Mar 20, 2013 at 16:19
  • 3
    Note that your implementation is actually base 13; you're counting from 0 to 12, inclusive, which is 13 numbers. Also, are you just trying to count or are you expecting to do something at each point in your arbitrary loop? Commented Mar 20, 2013 at 16:28
  • Yes, there will be more - I want to create an array where all elements in the array add up to the total I'm going up to - so when array[1] + array[2] + array[3] = 12, put it into the result array. Commented Mar 20, 2013 at 16:42
  • 1
    Hey AmyKate...I think I've got something for you now. You sure know how to pick the problems...the solution is somewhat simply, but difficult to figure out...at least it was for me. Commented Mar 20, 2013 at 17:14
  • 1
    Hey guys I got it! :D And @NathanielFord it's indeed base 13. Im pretty proud of my solution, at least compared to the others and considering that I'm not too good at maths. (Although I'm Asian xD) Commented Mar 21, 2013 at 9:57

3 Answers 3

2

This algorithm precalculates the number of loops needed in total, then use $i to calculate each array position's value.

$max= 13;
$elements = 4;
$loops = pow($max, $elements);

$main_array = array();

for($i = 0; $i < $loops; $i++){
    for($j = 0; $j < $elements; $j++){
        $main_array[$i][$j] = floor($i/pow($max,$elements-1-$j))%$max;
    }
}

This is the most elegant solution I found, just 2 nested loops with 1 arithmetic operation using power and modulus to get the desired array each time.

You just have to adjust the elements and/or the base number.

took 0.014s to calculate the array with 3 positions.

took 0.25s to calculate the array with 4 positions.

took 4.08s to calculate the array with 5 positions*

*for 5 positions I needed to increase the memory_limit, I guess because the array gets too big, this script would be much lighter if you did just the output of the numbers instead of storing a huge array.

Sign up to request clarification or add additional context in comments.

2 Comments

Ah! I see. I think I was pretty unclear on the formulation of the array desired; the outer hash array contains places, not actual values. +1 for this and the precalculation.
I actually stumbled on this solution by luck somehow, my initial code was quite different, then suddenly I tried to precalculate all the posibilities and everything came together automatically xD
2

Okay now, let's see...

$numberOfDimensions = 3;
$base = 13;

$YourArray = array();    //This array will hold the complete data.
$LastArray = array();
for($o = 0; $o < $numberOfDimensions; ++$o) //Gives us something to start with.
    $LastArray[$o] = 0;    

while($LastArray[0] < $base) {      //Makes sure, we're not going out of bounds
    $index = $numberOfDimensions - 1;
    $YourArray[] = $LastArray;      //Adds the array you filled last to the result array.
    while($index >= 0) {            //This is where things start to get interesting.
        if(++$LastArray[$index] < $base) break;  //Still in bounds, continue.
        else {
            if($index)              //Overflow for all but the first element..
                $LastArray[$index] = 0;
            --$index;               //Moving on to the previous digit.
        }
    }
}

echo "<pre>";
echo print_r($YourArray);
echo "</pre>";

Phew...that was more difficult on my tired brain than I thought when I read the question. This should work...if you have questions regarding the code, feel free to ask.

I've tested it now, and it does what is to be expected. During my tests I encountered a foolish error, which is hereby fixed. Sorry for the delay.

Comments

0

Your basic recursion is as follows:

<?php 
class StrangeBase { 
  private static function loopOnStrangeBase($place, $base, $printstr) { 
    if (($place < 0) || ($base < 0)){ return; }//edge case 
    for ($idx=0; $idx<$base; $idx++) { 
      if ($place == 0) { 
        echo "$printstr,$idx\n"; 
      } else {
        if($printStr !== ''){ 
          StrangeBase::loopOnStrangeBase($place - 1, $base, $printstr.",$idx");
        } else {
          StrangeBase::loopOnStrangeBase($place - 1, $base, "$idx");
        }
      }
    } 
  }

  public static function printStrangeBase($places, $base) {
    StrangeBase::loopOnStrangeBase($places, $base, "");
  }
} 

StrangeBase::printStrangeBase(3, 12); 

Now, you can modify this to not be static functions, but rather also save out to an array. To do this, your array should grow 'backwards'; that is the first element in the array is the lowest-order place in your number. You can then further modify the recursive function to take a function pointer and run arbitrary code rather than simply print out where it is.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.