All Euler problems
Project Euler

Dice Game

Peter has nine four-sided (pyramidal) dice, each with faces numbered 1 to 4. Colin has six six-sided (cubic) dice, each with faces numbered 1 to 6. Peter and Colin roll their dice and compare total...

Source sync May 21, 2026
Problem #0205
Level Level 03
Solved By 16,470
Languages C++, Python
Answer 0.5731441
Length 314 words
probabilitygame_theorylinear_algebra

Problem Statement

This archive keeps the full statement, math, and original media on the page.

Peter has nine four-sided (pyramidal) dice, each with faces numbered \(1, 2, 3, 4\).

Colin has six six-sided (cubic) dice, each with faces numbered \(1, 2, 3, 4, 5, 6\).

Peter and Colin roll their dice and compare totals: the highest total wins. The result is a draw if the totals are equal.

What is the probability that Pyramidal Peter beats Cubic Colin? Give your answer rounded to seven decimal places in the form 0.abcdefg.

Problem 205: Dice Game

Mathematical Development

Theorem (Convolution of Discrete Uniform Distributions). Let X1,X2,…,XnX_1, X_2, \ldots, X_n be independent random variables, each uniformly distributed on {1,2,…,d}\{1, 2, \ldots, d\}. The probability mass function of Sn=∑i=1nXiS_n = \sum_{i=1}^{n} X_i is the nn-fold convolution of the individual distributions. Equivalently, the number of ways to realize total ss is the coefficient of xsx^s in (x+x2+⋯+xd)n(x + x^2 + \cdots + x^d)^n.

Proof. For independent discrete random variables, the probability mass function of the sum is obtained by convolution. The generating-function statement is the coefficient form of the same recurrence. □\square

Theorem (Winning Probability). Let PP be Peter’s total and CC be Colin’s total. Then

Pr⁡(P>C)=149⋅66∑p=936fP(p)⋅FC(p−1),\Pr(P > C) = \frac{1}{4^9 \cdot 6^6} \sum_{p=9}^{36} f_P(p) \cdot F_C(p-1),

where fP(p)f_P(p) is the number of Peter outcomes with total pp, and FC(t)=∑c=6tfC(c)F_C(t) = \sum_{c=6}^{t} f_C(c) is Colin’s cumulative frequency table.

Proof. Since PP and CC are independent,

Pr⁡(P>C)=∑pPr⁡(P=p)Pr⁡(C<p).\Pr(P > C) = \sum_p \Pr(P = p)\Pr(C < p).

Writing these probabilities in terms of outcome counts yields the stated formula. □\square

Lemma (Range Constraints). Peter’s sum lies in [9,36][9, 36] and Colin’s sum lies in [6,36][6, 36].

Proof. The minimum of nn dice is nn, and the maximum is ndnd. □\square

Editorial

The clean approach is to compute the exact sum distribution for each player. Repeated convolution gives the number of ways Peter can make each total from 9 to 36 and the number of ways Colin can make each total from 6 to 36.

After that, the probability calculation is just bookkeeping. For a fixed Peter total pp, every Colin total below pp is a win, so a cumulative table for Colin turns the double sum into a single pass over Peter’s distribution. Dividing the final win count by 49664^9 6^6 gives the exact probability, which is then rounded to seven decimals.

Pseudocode

BuildDistribution(number_of_dice, faces):
    Start with freq[0] = 1.
    Repeat once per die:
        Create an empty table next.
        For every current sum s with frequency count:
            For face from 1 to faces:
                Add count to next[s + face].
        Replace freq by next.
    Return freq

Let peter = BuildDistribution(9, 4).
Let colin = BuildDistribution(6, 6).

Build a cumulative table smaller_colin where smaller_colin[p]
is the number of Colin outcomes with total strictly less than p.

winning_count = 0
For each Peter total p:
    winning_count += peter[p] * smaller_colin[p]

Return winning_count / (4^9 * 6^6), rounded to seven decimals

Complexity Analysis

  • Time: O(nPdPsmax⁡+nCdCsmax⁡+smax⁡)O(n_P d_P s_{\max} + n_C d_C s_{\max} + s_{\max}), where smax⁡=36s_{\max} = 36.
  • Space: O(smax⁡)O(s_{\max}) for the two distribution tables and Colin’s cumulative table.

Answer

0.5731441\boxed{0.5731441}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_205/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main(){
    // Peter: 9 four-sided dice. Colin: 6 six-sided dice.
    // P(Peter > Colin) rounded to 7 decimal places.

    // Compute frequency distribution for sum of n dice with faces 1..f
    auto dice_dist = [](int n, int f) -> vector<long long> {
        int maxsum = n * f;
        vector<long long> freq(maxsum + 1, 0);
        freq[0] = 1;
        for(int die = 0; die < n; die++){
            vector<long long> nf(maxsum + 1, 0);
            for(int s = 0; s <= maxsum; s++){
                if(freq[s] == 0) continue;
                for(int face = 1; face <= f && s + face <= maxsum; face++){
                    nf[s + face] += freq[s];
                }
            }
            freq = nf;
        }
        return freq;
    };

    auto peter = dice_dist(9, 4);  // indices 0..36, nonzero for 9..36
    auto colin = dice_dist(6, 6);  // indices 0..36, nonzero for 6..36

    // Cumulative sum for Colin
    vector<long long> colin_cum(37, 0);
    for(int s = 1; s <= 36; s++){
        colin_cum[s] = colin_cum[s-1] + colin[s];
    }

    // P(Peter > Colin) = sum over p of peter[p] * colin_cum[p-1]
    long long win = 0;
    for(int p = 9; p <= 36; p++){
        win += peter[p] * colin_cum[p-1];
    }

    double total = (double)(1LL << 18) * 46656.0; // 4^9 * 6^6 = 262144 * 46656
    double prob = (double)win / (262144.0 * 46656.0);

    cout << fixed << setprecision(7) << prob << endl;
    return 0;
}