Thursday, December 18, 2014

What are the odds 7 dice roll a higher number than 8 dice?

7 dice wins 129007254816 vs. 8 dice... 316648728585

129007254816 rolls of the 470184984576 rolls. Or 27.437553101%




    
    static final int SIDES = 6;
    static final int MINROLL = 1;
    
    public long combinatoricaldice(int d0, int d1) {    
        int[] dist0 = convolvedistribution(d0);
        int[] dist1 = convolvedistribution(d1);
        long wins = combdice(dist0,dist1);
        System.out.println(d0 + " dice wins " + wins + " vs. " + d1 + " dice.");
        return wins;
    }
    
    public int[] convolvedistribution(int dice) {
        int[] roll = new int[((SIDES -1 + MINROLL) * dice) + 1];
        for (int i = 0; i < SIDES; i++) {
            roll[i + MINROLL] = 1;
        }
        return convolvedistribution(roll,dice-1, new int[roll.length]);
    }
    public int[] convolvedistribution(int[] roll, int dice, int[] temp) {
        if (dice == 0) return roll;
        Arrays.fill(temp, 0);
        for (int i = 0, s = roll.length; i < s; i++) {
            for (int q = i + MINROLL, m = i + SIDES + MINROLL; q < m && q < s; q++) {
                temp[q] += roll[i];
            }
        }
        System.arraycopy(temp, 0, roll, 0, temp.length);
        return convolvedistribution(roll, dice-1, temp);
    }
    
    public long combdice(int[] sumdistribution0, int[] sumdistribution1) {
        long winning = 0;
        for (int m = 0; m < sumdistribution0.length; m++) {
            long s0 = (long) sumdistribution0[m];
            long winsagainst = Arrays.stream(sumdistribution1).limit(m).sum();
            winning += (s0 * winsagainst);
        }
        return winning;
    }
    
    
    

    public boolean incrementDice(int[] dice) {
        for (int m = 0; m < dice.length; m++) {
            if ((dice[m] - MINROLL) + 1 < SIDES) {
                dice[m]++;
                for (m = m - 1; m >= 0; m--) {
                    dice[m] = MINROLL;
                }
                return true;
            }
        }
        return false;
    }
    public int[] sumdistribution(int d0) {
        int[] dice = new int[d0];
        Arrays.fill(dice, MINROLL);
        
        int[] dist = new int[((SIDES - 1 + MINROLL)*d0) + 1];
        do {
            int sum0 = Arrays.stream(dice).sum();
            dist[sum0]++;
        } while (incrementDice(dice));
        return dist;
    }