1

I want to combine strings in PHP. My script creates every possible combination like below.

$part1 = array('','d','n','s','g');
$part2 = array('a','e','o','oo');
$part3 = array('m','n','s','d','l','t','g','j','p');
$part4 = array('g','p','l','');
$part5 = array('g','p','l');
$part6 = array('a','e','o');
$part7 = array('d','l','r','');

$names = array();

foreach ($part1 as $letter1) {
    foreach ($part2 as $letter2) {
        foreach ($part3 as $letter3) {
            foreach ($part4 as $letter4) {
                foreach ($part5 as $letter5) {
                    foreach ($part6 as $letter6) {
                        foreach ($part7 as $letter7) {
                            $names[] = $letter1 . $letter2 . $letter3 . $letter4 . $letter5 . $letter6 . $letter7;
                        }
                    }
                }
            }
        }
    }
}

But I am not happy with my solution. I is quick and dirty code. Is there a solution wich works with a flexible number of part arrays, so I can extend the script by e.g. $part8 easiely? (without changing the loop construction)

danijar
  • 32,406
  • 45
  • 166
  • 297
  • possible duplicate of http://stackoverflow.com/questions/2516599/php-2d-array-output-all-combinations. seems like you're looking for the cartesian product of a set of arrays. – nathan gonzalez Feb 04 '12 at 21:18
  • might be a stupid question, but what is that code for? I can see what it does, but with those letters I just can't see what you would use it for. – Steve Feb 04 '12 at 21:40
  • @Steve: It is going to become a name generator. – danijar Feb 04 '12 at 21:44

2 Answers2

4

Recursive one:

function buildNames( $parts, $chars = ''){
  // Nothing to do, shouldn't happen
  if( !count( $parts)){
    return array();
  }

  $names = array();
  $part = array_shift( $parts);
  // Max level, we can build final names from characters
  if( !count( $parts)){
     foreach( $part as $char){
        $names[] = $chars . $char;
     }
     return $names;
  }

  // "We need to go deeper" and build one more level with remembered chars so far
  foreach( $part as $char){
     $names = array_merge( $names, buildNames( $parts, $chars . $char));
  }

  return $names;
}

$parts = array( $part1, $part2, $part3, $part4, $part5, $part6, $part7);
$names = buildNames( $parts);

From head, from scratch, comment if something, but idea should be good

Vyktor
  • 20,559
  • 6
  • 64
  • 96
  • Nice idea! But it seems to be an infinite loop because I get timeout errors. – danijar Feb 04 '12 at 21:36
  • It shouldn't... Try to debug it and let me know where the error was I just don't see it :-/ – Vyktor Feb 04 '12 at 21:44
  • I am not an advanced programmer being not familiar with recursive functions. So I don't know how to debug this successfully. I added a simple `echo '.';` at the top of the function. It echoed millions of dots. – danijar Feb 04 '12 at 21:52
  • @sharethis your example array above returned 25919 (run about second on my desktop), try to add `echo $chars . $char . "\n"` after `$names[] = $chars . $char;` .) This baby grows exponentially. – Vyktor Feb 04 '12 at 21:56
  • Ok, got it working. It just was a different problem with my script. Thanks for your answer, nice! – danijar Feb 04 '12 at 22:02
1

You could reduce this problem to six cartesian products:

cartesianProduct($part1, 
  cartesianProduct($part2, 
    cartesianProduct($part3, 
      cartesianProduct($part4, 
        cartesianProduct($part5, 
          cartesianProduct($part6, $part7))))));


function cartesianProduct($p1, $p2) {
   $ret = array();
   foreach($p1 as $l1)
     foreach($p2 as $l2) 
        $ret[] = $l1 . $l2;
   return $ret;
}
onof
  • 17,167
  • 7
  • 49
  • 85