주사위 고르기

주사위 고르기

A와 B가 n개의 주사위를 가지고 승부를 합니다. 주사위의 6개 면에 각각 하나의 수가 쓰여 있으며, 주사위를 던졌을 때 각 면이 나올 확률은 동일합니다. 각 주사위는 1 ~ n의 번호를 가지고 있으며, 주사위에 쓰인 수의 구성은 모두 다릅니다.

A가 먼저 n / 2개의 주사위를 가져가면 B가 남은 n / 2개의 주사위를 가져갑니다. 각각 가져간 주사위를 모두 굴린 뒤, 나온 수들을 모두 합해 점수를 계산합니다. 점수가 더 큰 쪽이 승리하며, 점수가 같다면 무승부입니다.

A는 자신이 승리할 확률이 가장 높아지도록 주사위를 가져가려 합니다.

https://school.programmers.co.kr/learn/courses/30/lessons/258709


import java.util.*;

/**
 * 생성한 정점의 번호, 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수를 순서대로 1차원 정수 배열에 담아 return 하도록 solution 함수를 완성해 주세요.
 * [생성한 정점의 번호, 도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프]
 */

public class Main4 {
    public static void main(String[] args) {
        int[][] dice_1 = {{1, 2, 3, 4, 5, 6}, {3, 3, 3, 3, 4, 4}, {1, 3, 3, 4, 4, 4}, {1, 1, 4, 4, 5, 5}};
        int[][] dice_2 = {{1, 2, 3, 4, 5, 6}, {2, 2, 4, 4, 6, 6}};
        int[][] dice_3 = {{40, 41, 42, 43, 44, 45}, {43, 43, 42, 42, 41, 41}, {1, 1, 80, 80, 80, 80}, {70, 70, 1, 1, 70, 70}};

        solution(dice_1);
    }


    public static int[] solution(int[][] dice) {
        Dice.initDice(dice);
        List<List<List<Dice>>> allDistributionCase = Dice.allDistributionCase();

        double maxWinning_persent = 0;
        List<Dice> maxWinning_Dice = new ArrayList<>();

        for (List<List<Dice>> list : allDistributionCase) {
            List<Dice> user_A = list.get(0);
            List<Integer> user_A_result = new ArrayList<>();
            Dice.generateSums(user_A, 0, 0, user_A_result);

            List<Dice> user_B = list.get(1);
            List<Integer> user_B_result = new ArrayList<>();
            Dice.generateSums(user_B, 0, 0, user_B_result);

            double result = calculateProbability(user_A_result, user_B_result);
            if (maxWinning_persent < result) {
                maxWinning_persent = result;
                maxWinning_Dice = user_A;
            }
            System.out.println(result);

        }
        System.out.println(maxWinning_Dice);
        System.out.println(maxWinning_persent);

        List<Integer> result = new ArrayList<>();

        for (Dice temp : maxWinning_Dice) {
            for (int i = 0; i < Dice.allDice.size(); i++) {
                if (temp == Dice.allDice.get(i)) {
                    result.add(i+1);
                }
            }
        }

        Collections.sort(result);

        System.out.println(result);

        return result.stream().mapToInt(Integer::intValue).toArray();
    }

    public static double calculateProbability(List<Integer> a, List<Integer> b) {
        int aGreaterCount = 0;
        int totalCount = a.size() * b.size();

        for (int numA : a) {
            for (int numB : b) {
                if (numA > numB) {
                    aGreaterCount++;
                }
            }
        }

        return (double) aGreaterCount / totalCount;
    }

}

class Dice {
    static List<Dice> allDice = new ArrayList<>();

    int[] diceNumber;

    Dice(int[] diceNumbers) {
        this.diceNumber = diceNumbers;
    }

    @Override
    public String toString() {
        return "Dice{" +
                "diceNumber=" + Arrays.toString(diceNumber) +
                '}';
    }

    static List<Dice> initDice(int[][] diceData) {
        for (int[] diceNumbers : diceData) {
            allDice.add(new Dice(diceNumbers));
        }

        return allDice;
    }

    /**
     * 분배 경우의 수
     */
    static List<List<List<Dice>>> allDistributionCase() {
        int allDiceCount = allDice.size();

        int choiceCount = allDiceCount / 2; // 선택 개수

        List<List<Object>> result_combination = new ArrayList<>();
        generateCombinations(Dice.allDice.toArray(), choiceCount, 0, new ArrayList<>(), result_combination);

        List<List<List<Dice>>> result = result_combination.stream().map(objects -> {
            List<Dice> a = objects.stream().map(o -> (Dice) o).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
            List<Dice> b = Dice.allDice.stream().filter(dice -> !a.contains(dice)).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

            List<List<Dice>> temp = new ArrayList<>();
            temp.add(a);
            temp.add(b);

            return temp;
        }).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

        return result;
    }

    static void generateCombinations(Object[] arry, int count, int start, List<Object> current, List<List<Object>> result) {
        if (current.size() == count) {
            result.add(new ArrayList<>(current));
            return;
        }

        for (int i = start; i < arry.length; i++) {
            current.add(arry[i]);
            generateCombinations(arry, count, i + 1, current, result);
            current.remove(current.size() - 1); // 마지막 요소 제거 (백트래킹)
        }
    }

    static void generateSums(List<Dice> dice, int index, int currentSum, List<Integer> result) {
        if (index == dice.size()) {
            result.add(currentSum);
            return;
        }

        for (int value : dice.get(index).diceNumber) {
            generateSums(dice, index + 1, currentSum + value, result);
        }
    }

    static void generateSums(int[][] dice, int index, int currentSum, Set<Integer> result) {
        if (index == dice.length) {
            result.add(currentSum);
            return;
        }

        for (int value : dice[index]) {
            generateSums(dice, index + 1, currentSum + value, result);
        }
    }

}

이번에 경우의 수 케이스를 구하는 로직을 짜는게 좀..