Project Euler Problem 470

Consider a single game of Ramvok: Let t represent the maximum number of turns the game lasts.

Project Euler Problem 470

Solution

Answer: 147668794

Let the set of currently visible die faces be $V\subseteq {1,\dots,d}$, with $|V|=k$.

1. Ramvok analysis

For a fixed die state $V$, define $H_t(V)$ as the optimal expected prize (before cost) when at most $t$ turns are allowed.

We have:

  • $H_0(V)=0$
  • $H_1(V)=\frac1k\sum_{x\in V}x$
  • For $t\ge 1$,

$$H_{t+1}(V) = \frac1k\sum_{x\in V}\max(x,H_t(V))$$

because after seeing roll $x$, we either stop and take $x$, or continue with value $H_t(V)$.

If the up-front cost is $ct$, then the expected profit is

$$R_t(V,c)=H_t(V)-ct$$

and

$$R(V,c)=\max_{t\ge0} R_t(V,c).$$

For $c=0$, the optimal strategy is to wait forever until the maximum visible face appears, so:

$$R(V,0)=\max(V).$$

For $c>0$, the marginal improvement

$$H_{t+1}(V)-H_t(V)$$

decreases monotonically, so we iterate until it falls below $c$.

Checking the example:

$$R({1,2,3,4},0.2)=2.65$$

which matches the statement.


2. Super Ramvok analysis

Let a state be the subset $V$ of visible faces.

After each Ramvok game, one uniformly random face is toggled (visible ↔ blank). If all faces become blank, the process ends.

Let $S(V,c)$ be the optimal expected future profit starting from state $V$. Then:

$$S(\varnothing,c)=0$$

and for $V\neq\varnothing$,

$$S(V,c) = R(V,c) + \frac1d \sum_{i=1}^{d} S(V\triangle {i},c)$$

where $\triangle$ denotes toggling a face.

By symmetry of the hypercube walk, all subsets of the same size are equally likely when conditioned on Hamming weight. Therefore:

$$S(d,c) = \sum_{k=1}^{d} N_{d,k}, \overline{R}_{d,k}(c)$$

where:

  • $N_{d,k}$ = expected number of visits to weight-$k$ states before absorption at the empty set,
  • $\overline{R}_{d,k}(c)$ = average Ramvok profit over all $k$-subsets of ${1,\dots,d}$.

The $N_{d,k}$ values come from the birth–death chain on weights:

$$k \to k-1 \text{ with prob } \frac{k}{d}, \qquad k \to k+1 \text{ with prob } \frac{d-k}{d}.$$

Solving this transient Markov system gives the expected visit counts.

The example verifies correctly:

$$S(6,1)=208.3$$

matching the problem statement.

3. Python implementation

import math
import itertools
import numpy as np

def expected_visits(d):
    """
    Expected number of visits to each weight k=1..d
    before absorption at 0, starting from weight d.
    """
    A = np.zeros((d, d))

    for k in range(1, d + 1):
        i = k - 1
        A[i, i] = 1.0

        # Transition to k-1
        if k > 1:
            A[i, k - 2] -= k / d

        # Transition to k+1
        if k < d:
            A[i, k] -= (d - k) / d

    # Fundamental matrix row for starting state d
    N = np.linalg.inv(A)
    return N[d - 1]

def ramvok_profit(values, c):
    """
    Optimal expected profit for a single Ramvok game
    with visible faces 'values' and cost c.
    """
    values = tuple(sorted(values))

    # c = 0 -> wait forever for max value
    if c == 0:
        return values[-1]

    k = len(values)
    H = 0.0
    best = 0.0
    turns = 0

    while True:
        turns += 1

        # H_{t+1} = E[max(x, H_t)]
        new_H = sum(max(x, H) for x in values) / k

        profit = new_H - c * turns
        best = max(best, profit)

        marginal_gain = new_H - H

        # Further turns can no longer improve value
        if marginal_gain < c:
            break

        H = new_H

    return best

def super_ramvok(d, c):
    visits = expected_visits(d)

    total = 0.0

    for k in range(1, d + 1):
        subset_sum = 0.0

        for subset in itertools.combinations(range(1, d + 1), k):
            subset_sum += ramvok_profit(subset, c)

        avg_profit = subset_sum / math.comb(d, k)
        total += visits[k - 1] * avg_profit

    return total

def F(n):
    total = 0.0

    for d in range(4, n + 1):
        for c in range(n + 1):
            total += super_ramvok(d, c)

    return round(total)

print(super_ramvok(6, 1))  # 208.3
print(F(20))

4. Verification

  • $R(4,0.2)=2.65$ ✓
  • $S(6,1)=208.3$ ✓
  • Final accumulated value:

$$F(20)=147668793.787154\ldots$$

Rounded to the nearest integer:

Answer: 147668794