이전 포스팅에서 C++, MATLAB 을 사용하여 Cartesian Product 를 구하는 방법에 대해 알아본 적이 있습니다.



2013/08/18 - [programming language/MATLAB] - MATLAB 모든 경우의 수 뽑기 Cartesian Product


2014/03/01 - [programming language/C/C++] - C++ Cartesian Product


2013/08/18 - [programming language/powershell] - Powershell 경우의 수 조합 다 구하기(Cartesian Product)


 

이번에는 python 에서 Cartesian Product 를 구하는 방법에 대해 확인해 보니 이전의 방법들 보다 훨씬 더 쉽더군요.

 

아래 주소에 그 방법이 나와 있었습니다.

 

http://stackoverflow.com/questions/9101101/python-cartesian-product

 

itertools.product() 함수를 사용하는 방식이며 Document 는 아래 주소에서 확인 할 수 있습니다.

 

https://docs.python.org/2/library/itertools.html#itertools.product

 


다음과 같은 결과가 나옵니다.

 

bad

baf

bed

bef

cad

caf

ced

cef


이전 포스팅들에서도 소개한 Cartesian Product 를 C++ 를 사용하여 구성하는 방법에 대해 소개해 드리려 합니다.

  

2013/08/18 - [programming language/MATLAB] - MATLAB 모든 경우의 수 뽑기 Cartesian Product


2013/08/18 - [programming language/powershell] - Powershell 경우의 수 조합 다 구하기(Cartesian Product)

 

아래 주소를 보니 Cartesian Product 와 관련하여 좋은 예제들이 많이 있더군요.

 

http://stackoverflow.com/questions/5279051/how-can-i-create-cartesian-product-of-vector-of-vectors

 

그 중에서 저는 가장 간단해 보이는 anumi 라는 분의 코드를 가져다 사용했습니다.

 

물론 template 형태로 약간 수정만 했습니다.

 

코드를 보다 보니 vector 의 swap 함수를 사용했더군요. Swap 함수는 말 그대로 벡터간에 값을 교환하는 겁니다.

 

Vector 의 Swap 에 대한 설명은 아래 주소 참조바랍니다.

 

http://www.cplusplus.com/reference/vector/vector/swap/

 

요즘 C++ STL 은 정말 좋은 것 같습니다.

 

결과적으로 작성된 cartesian.h 파일은 아래와 같습니다. 

  

cartesian.h


#include <vector>

 

using namespace std;

 

template<typename T>

vector<vector<T>> cart_product (const vector<vector<T>>& v) {

vector<vector<T>> s = {{}};

for (auto& u : v) {

vector<vector<T>> r;

for (auto& x : s) {

for (auto y : u) {

r.push_back(x);

r.back().push_back(y);

}

}

s.swap(r);

}

return s;

}

 

테스트를 위한 main.cpp 파일은 아래와 같이 작성했습니다.

 

#include <iostream>

#include "cartesian.h"

 

using namespace std;

 

int main()

{

    vector<vector<int>> test{{1,2, 56 ,3}, {4,5,6}, {12,32,56}};

    vector<vector<int>> cartprodResult; // result

 

    cartprodResult=cart_product(test); // Cartesian Product

 

    int cnt=0;

 

    for (auto& x : cartprodResult)

    {

        ++cnt;

        cout << cnt << ": \t";

 

        for (auto y : x)

        {

            cout << y << "\t";

        }

        cout << endl;

    }

 

    return 0;

}

 

Cartesian product 를 수행해보면 아래와 같이 결과가 나오는 것을 확인 할 수 있습니다. 간단하죠~ 현재 컴파일러는 gcc (tdm64-2) 4.8.1 이고~ C++11 Compiler Flag를 On 했습니다.



아래 글에서는 Powershell 에서 Cartesian Product 를 구하는 방법에 대해 설명드렸었는데~ 


2013/08/18 - [powershell] - Powershell 경우의 수 조합 다 구하기(Cartesian Product)

 

이번 포스팅에서는 MATLAB에서 Cartesian Product 를 구하는 방법에 대해 설명 드리려 합니다.

 

사실 MATLAB 에서 Cartesian Product 를 구하는 방법은 매우 간단합니다.

 

바로 ndgrid() 함수를 이용하는 방법인데요~

 

다음과 같은 set 에 대해 조합의 경우의 수를 구해보죠~

 

A=[1 2];

B=[3 4];

C=[5 6];

 

경우의 수는 2 x 2 x 2 니까 8 개가 나오겠고 단순히 생각하면 for 문을 3개 중첩되게 만들면 해결 되겠지만~ 이보다는 ndgrid() 함수를 사용해서 아래와 같이 코딩하는게 더 좋은 방법이라고 생각됩니다.

 

A=[1 2];

B=[3 4];

C=[5 6];

 

sets = {A, B, C};

[x y z] = ndgrid(sets{:});

cartProd = [x(:) y(:) z(:)];


 

보시다 시피 굉장히 간단하게 구해지죠~ 위 코드를 실행 시켜보면 cartProd 변수에 결과가 저장되지만 아래 결과처럼 첫번째 열이 정렬이 안 되서 나옵니다.


 

경우에 따라 정렬이 필요하신 경우에는 sortrows() 함수를 사용해서 정렬 하시면 됩니다. sortrows() 함수의 두번째 인자는 정렬 기준이 되는 column index 를 의미 합니다.

 

2번째 column 을 기준으로 정렬하고 싶으신 분들은 아래 코드의 두번째 인자인 1 을 2로 바꾸시면 되겠죠~

 

sorted_cartProd =sortrows(cartProd, 1)

 

 

 

아래 주소에는 이에 대한 cartesianProduct() 라는 함수도 소개되고 있으니 필요하신 분들은 사용해 보시기 바랍니다.

 

http://stackoverflow.com/questions/4165859/matlab-generate-all-possible-combinations-of-the-elements-of-some-vectors


실험을 하다 보면 경우의 수의 조합들을 다 구해서 실험을 해야 하는 경우가 있습니다.

 

이러한 조합의 경우의 수를 구하는 것을 Cartesian Product 라고 하는데요.

 

단순히 생각하면 Cartesian Product 를 구하기 위해서는 for 문을 계속 중첩해서 사용해야 하지만 이게 두~세개만 넘어가도 굉장히 헷갈리고 힘든일이 됩니다.

 

이러한 경우 Cartesian Product 를 구하는 함수를 만들어 놓고 사용한다면~ 굉장히 편리하죠~

 

저는 Powershell 에서 Cartesian Product 를 구해야 하는 경우가 있었는데~ 아래 주소에 그 코드가 있더군요. 좋은 코드 같아서 여러분들께도 소개하려 합니다.

 

코드 출처 : http://makeyourownmistakes.wordpress.com/2012/04/17/simple-n-ary-product-generic-cartesian-product-in-powershell-20/

 

function CartesianProduct

{

$returnValue = @()

foreach ($parameter in $MyInvocation.UnboundArguments)

{

$returnValue = AddToAll $returnValue $parameter

}

return $returnValue

}

 

function AddToAll($currentResult, $valuesToAdd)

{

$returnValue = @()

if ($valuesToAdd -ne $null)

{

foreach ($value in $valuesToAdd)

{

if ($currentResult -ne $null)

{

foreach ($result in $currentResult)

{

$newResult = @($result)

$newResult += ,$value

$returnValue += ,$newResult

}

}

else

{

$returnValue += ,$value

}

}

}

else

{

$returnValue = $currentResult

}

return $returnValue

}

 

$values1 = @("html", "csv", "email")

$values2 = @("1", "7", "14")

$values3 = @("12", "24")

$values4 = @("server1.mydomain.com")

$product = CartesianProduct $values1 $values2 $values3 $values4

 

위 코드를 실행시켜보면~ $product 에는 $values1 ~ $values4 의 모든 경우의 수의 조합이 다 생성되서 들어가게 되고~

 

$product 의 각 인자들은 아래와 같습니다.


 

$product[0], $product[1]… 의 각 값들은 –split 를 이용해서 나눌수가 있으며 아래와 같이 $c 변수의 인덱스를 이용해서 접근 할 수 있습니다.


+ Recent posts