2011-09-13 9 views
3

"펼침"각 캐릭터는 파이프에 의해 분리 된 세그먼트들의 가변 개수 (|) 등을 갖는다 모든 가능한 하나 개의 문자 조합, 3 개 세그먼트에 대해 다음 "알고리즘은"훌륭하게 작동합니다문자열 I 문자열의 집합을

$result = array(); 
$string = explode('|', 'abc|b|ac'); 

foreach (str_split($string[0]) as $i) 
{ 
    foreach (str_split($string[1]) as $j) 
    { 
     foreach (str_split($string[2]) as $k) 
     { 
      $result[] = implode('|', array($i, $j, $k)); // more... 
     } 
    } 
} 

print_r($result); 

출력 :

$result = array('a|b|a', 'a|b|c', 'b|b|a', 'b|b|c', 'c|b|a', 'c|b|c'); 

분명히, 3 개 이상의 세그먼트의 경우 코드가 매우 복잡해지기 시작합니다. 점점 더 많은 내부 루프를 추가 (확인)해야하기 때문입니다. 나는 역동적 인 해결책을 찾으려고 노력했지만 모든 세그먼트 (개별 및 전체)에 대해 올바른 조합을 생성하는 방법을 파악할 수는 없습니다. 또한 일부 조합 전략 소스 코드를 살펴 보았지만 여러 세그먼트 조합을 결합 할 수는 없습니다.

누구든지 올바른 방향으로 나를 가리킬 수 있다면 고맙습니다. 구조에

+0

주문의 중요도는 어느 정도입니까? 아니면 모든 조합을 생성하는 것만으로도 괜찮습니까? – NullUserException

+0

@NullUserException : 각 세그먼트의 순서가 중요합니다. 특정 세그먼트에서 각 문자가 나타나는 순서는 ofc가 중복되지 않는 한 부적절합니다. –

답변

3

Recursion은 (당신이 가장자리 사례를 충당하기 위해 조금 조정할해야 할 수도 있습니다,하지만 작동) :

function explodinator($str) { 
    $segments = explode('|', $str); 
    $pieces = array_map('str_split', $segments); 

    return e_helper($pieces); 
} 

function e_helper($pieces) { 

    if (count($pieces) == 1) 
     return $pieces[0]; 

    $first = array_shift($pieces); 
    $subs = e_helper($pieces); 

    foreach($first as $char) { 
     foreach ($subs as $sub) { 
      $result[] = $char . '|' . $sub; 
     } 
    } 

    return $result; 
} 

print_r(explodinator('abc|b|ac')); 

출력을 :

Array 
(
    [0] => a|b|a 
    [1] => a|b|c 
    [2] => b|b|a 
    [3] => b|b|c 
    [4] => c|b|a 
    [5] => c|b|c 
) 

ideone에서 볼 수 있듯이.

+0

하하, 재귀 적 링크 만 +1. ;) 고마워, 나는 그것을 아침에 파헤쳐 볼 것이다. –

+0

@stereo 좋은 지적, 고정. – NullUserException

+0

멋지게 완료되었습니다. 완벽하게 작동합니다. Obrigado! =) @stereofrog : 잘 잡으세요. –

1

두 개의 배열을 가질 수 있습니다 : 대안과 현재 카운터.

나서, 루프에서는 카운터 "마지막 자릿수를"증가, 그리고 그 위치에 대한 대안의 수와 동일한 경우 0으로하는 "숫자"리셋 "증분 자리 "왼쪽. 이것은 십진수로 계산하는 것과 같습니다.

각 단계의 문자열은 각 숫자에 $alternatives[$i][$counter[$i]]을 연결하여 만들어집니다.

"첫 번째 숫자"가 해당 숫자의 대체 숫자만큼 커지면 완료됩니다.

예 : 위의 변수, 카운터가 단계에서 다음 값을 얻을 것입니다 :

0,0,0 
0,0,1 
1,0,0 (overflow in the last two digit) 
1,0,1 
2,0,0 (overflow in the last two digits) 
2,0,1 
3,0,0 (finished, since the first "digit" has only 3 alternatives) 
+0

실제 예제를 보여줄 수 있습니까? 이것은 나를 조금 혼란스럽게합니다. – NullUserException

+0

아마도이 예제가 약간 도움이 될 것입니다. 내가 언어를 잘 모르기 때문에 나는 PHP로 예제를 작성하지 않았다. –

+0

@Roland 다른 언어로도 표시 할 수 있습니다 – tttony

2

이 재귀 프로그래밍을위한 작업처럼 보인다! : P 나는 이것을 처음 보았고 그것이 라이너가 될 것이라고 생각했다. (아마 perl에있다.) 다른 재귀 적 방법이 있습니다 (예 : 세그먼트의 모든 인덱스 조합을 세그먼트로 열거). 그러나이 방법이 더 흥미롭고, 아마도 '더 나은'것이라고 생각합니다.

$str = explode('|', 'abc|b|ac'); 
$strlen = count($str); 
$results = array(); 

function splitAndForeach($bchar , $oldindex, $tempthread) { 
    global $strlen, $str, $results; 
    $temp = $tempthread; 
    $newindex = $oldindex + 1; 

    if ($bchar != '') { array_push($temp, $bchar); } 

    if ($newindex <= $strlen){ 
     print "starting foreach loop on string '".$str[$newindex-1]."' \n"; 

     foreach(str_split($str[$newindex - 1]) as $c) { 
      print "Going into next depth ($newindex) of recursion on char $c \n"; 
      splitAndForeach($c , $newindex, $temp); 
     } 

    } else { 

     $found = implode('|', $temp); 
     print "Array length (max recursion depth) reached, result: $found \n"; 

     array_push($results, $found); 
     $temp = $tempthread; 
     $index = 0; 
     print "***************** Reset index to 0 *****************\n\n"; 
    } 
} 

splitAndForeach('', 0, array()); 
print "your results: \n"; 
print_r($results); 
+0

Dammit, 내가 글을 쓰기 시작했을 때 답이 나오지 않았지만 끝내기 전에 이메일을 확인했다. 오 잘, 물건을 명확하게하는 데 도움이되기를 바랍니다 (더 작고 깔끔하게 보일 수도 있지만 표현력이 있으면 뭔가를 보여줄 수 있다고 생각합니다). – sillyMunky

+0

NullUserException에 대한 답을 참조하십시오. Mine은 OP가 재귀 적으로 처리하려고하는 코드 블록의 '순수한'버전이지만,이 코드는 응답의 코드보다 효율적이지 않습니다 (둘 다 큰 문자열로 콘솔에서 실행되도록 타이밍을 잡았습니다). 속도가 중요하다면 그를 사용하십시오. 가독성/사용자 정의가 더 중요하고 코드가 의미가있는 경우 사용하십시오. – sillyMunky