[JAVA] 자바 순열 조합

[JAVA] 자바 순열 조합

직접 짠 순열 조합.

public class TestGetCombination {

    public static void main(String[] args) {
        TestGetCombination testGetCombination = new TestGetCombination();
        testGetCombination.start();
    }
   
   
    public void start() {
        // 인덱스 4개 중 3개 선택하기 예제
        // ex) 0, 1, 2, 3, 4
        int totalCount = 4;
        int countToGet = 3;
       
        ArrayList<ArrayList<Integer>> resultList = null;
       
        // 조합 구하기
        System.out.println(totalCount +  “개 중 ” + countToGet + “개 조합 경우의 수 구하기”);
        resultList = getCombination(totalCount, countToGet);
        if (resultList != null && resultList.size() > 0) {
            int count = resultList.size();
            System.out.println(“count : ” + count);
            for (int i=0; i<count; i++) {
                System.out.println(i + ” : ” + resultList.get(i));
            }
        }
       
        System.out.println();
       
        // 순열 구하기
        System.out.println(totalCount +  “개 중 ” + countToGet + “개 순열 경우의 수 구하기”);
        resultList = getPermutation(totalCount, countToGet);
        if (resultList != null && resultList.size() > 0) {
            int count = resultList.size();
            System.out.println(“count : ” + count);
            for (int i=0; i<count; i++) {
                System.out.println(i + ” : ” + resultList.get(i));
            }
        }
    }
   
   
    /**
     * 조합 구하기
     *
     * ex 1) totalCount == 4
     *          countToGet == 1
     *       resultList == [[0],
     *                       [1],
     *                       [2],
     *                       [3]]
     *
     * ex 2) totalCount == 4
     *       countToGet == 2
     *       resultList == [[0, 1],
     *                       [0, 2],
     *                       [0, 3],
     *                       [1, 2],
     *                       [1, 3],
     *                       [2, 3]]
     *      
     * ex 3) totalCount == 4
     *       countToGet == 3
     *       resultList == [[0, 1, 2],
     *                       [0, 1, 3],
     *                       [0, 2, 3],
     *                       [1, 2, 3]]
     *            
     *      
     *      
     * @param totalCount
     * @param countToGet
     * @return
     */
    public ArrayList<ArrayList<Integer>> getCombination(int totalCount, int countToGet) {
        ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>();
        getCombinationCore(resultList, null, 0, totalCount, countToGet);
        return resultList;
    }
   
   
    /**
     * 조합 구하기 재귀메서드
     * 넘겨받은 resultList 객체에 경우의 수를 담는다. resultList 가 사실상의 리턴값이다.
     *
     * @param resultList
     * @param inputResult
     * @param axisIndex
     * @param totalCount
     * @param countToGet
     */
    private void getCombinationCore(ArrayList<ArrayList<Integer>> resultList, ArrayList<Integer> inputResult, int axisIndex, int totalCount, int countToGet) {
        for (int i=axisIndex; i<totalCount; i++) {
            ArrayList<Integer> oneResult = null;
            if (axisIndex == 0) {
                oneResult = new ArrayList<Integer>();
            } else {
                oneResult = (ArrayList<Integer>) inputResult.clone();
            }
           
            // 1개씩 인덱스를 담는다.
            oneResult.add(i);
           
            if (oneResult.size() == countToGet) {
                // countToGet 개 만큼 담았으면 resultList 객체에 추가한다.
                resultList.add(oneResult);
               
            } else if (oneResult.size() < countToGet) {
                // countToGet 개 만큼 담을 때까지 재귀한다.
                getCombinationCore(resultList, oneResult, i + 1, totalCount, countToGet);
               
            } else {
                break;
            }
        }
    }
   
   
    /**
     * 순열 구하기
     *
     * ex 1) totalCount == 4
     *          countToGet == 1
     *       resultList == [[0],
     *                       [1],
     *                       [2],
     *                       [3]]
     *      
     * ex 2) totalCount == 4
     *       countToGet == 2
     *       resultList == [[0, 1], [1, 0],
     *                       [0, 2], [2, 0],
     *                       [0, 3], [3, 0],
     *                       [1, 2], [2, 1],
     *                       [1, 3], [3, 1],
     *                       [2, 3], [3, 2]]
     *
     * ex 3) totalCount == 4
     *       countToGet == 3
     *       resultList == [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0],
     *                       [0, 1, 3], [0, 3, 1], [1, 0, 3], [1, 3, 0], [3, 0, 1], [3, 1, 0],
     *                       [0, 2, 3], [0, 3, 2], [2, 0, 3], [2, 3, 0], [3, 0, 2], [3, 2, 0],
     *                       [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
     *
     * @param totalCount
     * @param countToGet
     * @return
     */
    public ArrayList<ArrayList<Integer>> getPermutation(int totalCount, int countToGet) {
        // 1. 조합 구하기
        ArrayList<ArrayList<Integer>> combinationList = getCombination(totalCount, countToGet);
        if (combinationList == null || combinationList.size() == 0) {
            return null;
        }

        // 2. 모든 조합에 대해 순열 구하기. 다시 말해, 각 조합에 대해 순서 바꾸기.
        ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>();
        int count = combinationList.size();
        for (int i=0; i<count; i++) {
            // 특정 조합에 대해 순열 구하기
            getPermutationCore(resultList, combinationList.get(i));
        }
       
        return resultList;
       
    }
   
   
    /**
     * 특정 조합에 대해 순열 구하기. 다시 말해, 각 조합에 대해 순서 바꾸기.
     * 넘겨받은 resultList 객체에 경우의 수를 담는다. resultList 가 사실상의 리턴값이다.
     *
     * ex 1) inputList ==  [0]
     *       resultList 객체에 [[0]] 추가
     *      
     * ex 2) inputList ==  [0, 1]
     *       resultList 객체에 [[0, 1], [1, 0]] 추가
     *
     * ex 3) inputList == [0, 1, 2]
     *       resultList 객체에 [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]] 추가
     *      
     * ex 4) inputList == [1, 2, 3]
     *          resultList 객체에 [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 추가
     *
     * @param resultList
     * @param inputList
     */
    private void getPermutationCore(ArrayList<ArrayList<Integer>> resultList, ArrayList<Integer> inputList) {
       
        // 인덱스리스트 구하기
        ArrayList<ArrayList<Integer>> suffledIndexList = getSuffledIndexList(inputList.size());
        if (suffledIndexList == null || suffledIndexList.size() == 0) {
            return;
        }
       
        int count = suffledIndexList.size();
        for (int i=0; i<count; i++) {
            ArrayList<Integer> oneResult = new ArrayList<Integer>();
           
            ArrayList<Integer> indexList = suffledIndexList.get(i);
            for (int j=0; j<indexList.size(); j++) {
                oneResult.add(inputList.get(indexList.get(j)));
            }
           
            resultList.add(oneResult);
        }
    }
   
   
    /**
     * 인덱스리스트 구하기
     *
     * ex 1) totalCount == 1 일 경우, [[0]] 리턴
     * ex 2) totalCount == 2 일 경우, [[0, 1], [1, 0]] 리턴
     * ex 3) totalCount == 3 일 경우, [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]] 리턴
     *
     * @param count
     * @return
     */
    private ArrayList<ArrayList<Integer>> getSuffledIndexList(int count) {
        ArrayList<ArrayList<Integer>> suffledIndexList = new ArrayList<ArrayList<Integer>>();
        shuffleRecursively(suffledIndexList, null, count, null);
        return suffledIndexList;
    }
   
   
    /**
     * 인덱스리스트 구하기 재귀메서드
     * 넘겨받은 resultList 객체에 경우의 수를 담는다. resultList 가 사실상의 리턴값이다.
     *
     * @param resultList
     * @param inputResult
     * @param totalCount
     * @param exceptList
     */
    private void shuffleRecursively(ArrayList<ArrayList<Integer>> resultList, ArrayList<Integer> inputResult, int totalCount, ArrayList<Integer> exceptList) {
        if (exceptList == null) {
            exceptList = new ArrayList<Integer>();
        }
       
        for (int i=0; i<totalCount; i++) {
            if (exceptList.contains(i)) {
                continue;
            }
           
            ArrayList<Integer> oneResult = null;
            if (exceptList.size() == 0) {
                oneResult = new ArrayList<Integer>();
            } else {
                oneResult = (ArrayList<Integer>) inputResult.clone();
            }
           
            if (oneResult.size() < totalCount) {
                oneResult.add(i);
               
                if (oneResult.size() == totalCount) {
                    resultList.add(oneResult);
                   
                } else if (oneResult.size() < totalCount) {
                    ArrayList<Integer> newExceptList = (ArrayList<Integer>) exceptList.clone();
                    newExceptList.add(i);
                   
                    shuffleRecursively(resultList, oneResult, totalCount, newExceptList);
                }
            }
        }
    }
}