중복없는 조합을 만들어내는 프로그램의 알고리즘....
글쓴이: moonrepeat / 작성시간: 수, 2006/11/15 - 8:55오후
현재 중복없는 조합을 만들어 내는 프로그램을 만들고 싶은데 어떤 식으로 만들어
야 할지 난감해서 조언 부탁드립니다.
구현하고자 하는 프로그램은 n 이라는 값을 입력받으면 1~n 까지 정수를 이용해
중복이 없는 모든 조합을 만들어 내는 프로그램입니다.
예를 들면 4라는 숫자를 입력하면
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
.
.
.
4 3 2 1
이런식의 조합을 출력하는 프로그램을 만들려고 합니다.
걍 전부 재귀호출로 조합을 만들면서 중복되면 break 하는 식으로
할려고 했는데 속도가 우선시 되는 프로그램이라 조금 효율적인 방법
이 혹시 있을까 해서 질문을 올립니다.
(추가 질문 : 이런 프로그램을 자바로 짜도 될까요?)
Forums:
구현하시려는 프로그램이...
STL의 알고리즘 쓰면, 이렇게 구현하면 될 것 같습니다.-_-a
그리고, 직접구하는 건 예전에 백트래킹으로 구했던 것 같습니다.
(기억이 가물해서..)
토나오게...
Haskell 공부하고 있어서
Haskell로 짜보다가 포기 :(
인터넷에 찾아보니 이렇게 하면 되네요.
( http://www.polyomino.f2s.com/david/haskell/codeindex.html )
"1부터 n까지 수 중에서 하나를 뽑아서 앞에 두고 나머지를 가지고 permutation한 것들을 뒤에 붙인다. 이것을 모든 1부터 n까지의 수에 대해서 한다."라는 알고리즘이네요.
조합이 아니라 순열이네요.
만일 순서가 꼭 나열한 방식이 아니어도 상관없다면
Horowitz 와 Sahni 의 Data Structure 에 나옵니다.
물론 Java 로 짜도 상관없죠.
음... 같은 숫자가 없다면 나열하신 순서로 나오는 다음의 code 는 ICPC 준비하면서 작성한 것이긴 한데...
어찌되었든 재귀호출은 필요합니다.
Bug 가 없음을 보장하지는 못합니다.
N 배열과 number 의 초기화는 빠져있습니다.
number 가 조금만 커져도 출력은 끝이 안 날 수 있으므로 조심하세요.
답변
답변 감사합니다.
완성시키면 다시 답급 달겠습니다.
------------------------
삽질은 계속되어야 한다....... 쭉.........
삽질은 계속되어야 한다....... 쭉.........
1 2 3 4 1 2 4 3 1 3 2 4 1 3
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
처럼 하나의 숫자로 시작하는 것을 만드는 것은
이미 만드신 알고리즘으로 처리하시구요.
나머진 시간 절약을 위해서 이 데이터를 한칸씩 쉬프트해줍니다.
2 3 4 1
2 4 3 1
3 2 4 1
3 4 2 1
4 2 3 1
4 3 2 1
이렇게...
쉬프트를 n-1번 해주면 되겠네요. ^^;; 속도도 빠르고..
버그가 있으려나요? --;;
Haskell 로 만들어 봤어요.
제대로 못 만든 건지 속도가 안 빨라지네요.
세가지 버젼의 permutation 함수가 있어요. 그냥 permutation, rotation 무식하게 적용한 permutation', rotation 머리 쓴다고 어렵게 적용한 permutation'' 입니다.
어떻게 하면 개선할 수 있을지...
--------------
조금 빨라졌네요. permutation' 은 오히려 느려졌지만요.
좀 더 개선을 했는데... super_permutations
하나 아래 단계의 permutation의 rotation을 한 것이 아니라 처음부터 rotation을 해서 permutation을 구하는 permutations'''를 만들었습니다. 더 빨라졌네요.
처음 이 코드를 인터프리터에서 돌렸을 때 permutation, permutation' 함수에서는 시간이 엄청나게 걸리더군요. 그런데 컴파일하고 인터프리터에서 돌리니까 전과 같은 속도가 나네요. binary code를 인터프리터가 읽어 오는 것 같네요. 그런데 permutations'''과 permutations''는 컴파일 전도 컴파일 후보다는 느렸지만 괜찮게 나왔는데 말이죠.
확실히 list 가 잘 어울리는 구조군요.
esrevinu 씨의 글을 보니 제 code 도 list 를 사용하는 것이 회전시킬 때 좋겠네요.
(그러고 보면 STL 의 list 의 splice 도 회전 algorithm 으로 쓸 수 있겠네요.)
Haskell code 의 algorithm 을 곰곰히 생각해보니 정말 멋진 algorithm 입니다.
계속 배열과 vector 만 가지고 놀았더니 유연한 사고가 안 나오는군요.
뭐랄까 사람이 기본적으로 permutation 하는 방식과 유사하다고 할까요?
배열가지고 특히 추가적인 memory 를 되도록 사용하지 않는 것에만 익숙해진 저에게는 신선한 충격입니다.
Horowitz 와 Sahni 의 책에 나온 permutation algorithm 을 보고 이해하는데 난감하면서
그 미묘한 trick 적인 느낌에 충격을 받았는데 이것은 더한 충격입니다.
저는 list 를 사용하는 좋은 algorithm 이란 것을 찾기가 어려웠었습니다..
오늘 하나 추가입니다.
댓글 달기