Problem 236: Luxury Hampers
View on Project EulerProject Euler Problem 236 Solution
EulerSolve provides an optimized solution for Project Euler Problem 236, Luxury Hampers, with C++, Python, Java, and a step-by-step mathematical explanation.
Problem Summary The problem gives five product totals for two suppliers' luxury hampers. To keep the algebra neutral, write those totals as $P=(5248,1312,2624,5760,3936),\qquad Q=(640,1888,3776,3776,5664).$ Their grand totals are $T_P=18880,\qquad T_Q=15744.$ We seek the largest rational number \(m>1\) for which one can choose positive integers \(p_i\) and \(q_i\) for all five products so that the same multiplicative bias \(m\) holds both product-by-product and after the five products are combined. The direct search over all five pairs \((p_i,q_i)\) is far too large, so the solution looks for structure in the fixed supplier totals. Mathematical Approach Write the desired multiplier as \(m=\frac{u}{v}\) in lowest terms. The implementations turn the problem into an exact arithmetic feasibility test: first generate all possible rational candidates for \(m\), then decide which of them admit positive integer counts satisfying the product constraints and the global consistency equation. Ratio Equations for the Five Products For each product \(i\), the implementation works with positive integers \(p_i\) and \(q_i\) constrained by $vP_iq_i=uQ_ip_i.$ The combined condition over all five products is $vT_Q\sum_{i=1}^{5}p_i=uT_P\sum_{i=1}^{5}q_i.$ So a candidate \(m\) is valid if and only if these six integer equations can be satisfied simultaneously with every \(p_i,q_i\ge 1\)....
Detailed mathematical approach
Problem Summary
The problem gives five product totals for two suppliers' luxury hampers. To keep the algebra neutral, write those totals as
$P=(5248,1312,2624,5760,3936),\qquad Q=(640,1888,3776,3776,5664).$
Their grand totals are
$T_P=18880,\qquad T_Q=15744.$
We seek the largest rational number \(m>1\) for which one can choose positive integers \(p_i\) and \(q_i\) for all five products so that the same multiplicative bias \(m\) holds both product-by-product and after the five products are combined. The direct search over all five pairs \((p_i,q_i)\) is far too large, so the solution looks for structure in the fixed supplier totals.
Mathematical Approach
Write the desired multiplier as \(m=\frac{u}{v}\) in lowest terms. The implementations turn the problem into an exact arithmetic feasibility test: first generate all possible rational candidates for \(m\), then decide which of them admit positive integer counts satisfying the product constraints and the global consistency equation.
Ratio Equations for the Five Products
For each product \(i\), the implementation works with positive integers \(p_i\) and \(q_i\) constrained by
$vP_iq_i=uQ_ip_i.$
The combined condition over all five products is
$vT_Q\sum_{i=1}^{5}p_i=uT_P\sum_{i=1}^{5}q_i.$
So a candidate \(m\) is valid if and only if these six integer equations can be satisfied simultaneously with every \(p_i,q_i\ge 1\).
Why Product 1 Generates Every Candidate
From the first product we have \(P_1=5248\) and \(Q_1=640\), so
$\frac{u}{v}=\frac{P_1q_1}{Q_1p_1}=\frac{5248\,q_1}{640\,p_1}=\frac{41q_1}{5p_1}.$
Because \(1\le p_1\le P_1\) and \(1\le q_1\le Q_1\), every valid multiplier must appear among the reduced fractions
$m=\frac{41b}{5a},\qquad 1\le a\le 5248,\quad 1\le b\le 640,\quad m>1.$
This is the key finiteness argument: the search never needs to guess arbitrary rationals. It only needs to enumerate, reduce, sort, and deduplicate the fractions forced by product 1.
Five Products Collapse to Three Ratio Groups
The five supplier ratios are not all different:
$\frac{Q_1}{P_1}=\frac{5}{41},\qquad \frac{Q_2}{P_2}=\frac{Q_3}{P_3}=\frac{Q_5}{P_5}=\frac{59}{41},\qquad \frac{Q_4}{P_4}=\frac{59}{90}.$
So the products split naturally into three groups:
$G_0=\{1\},\qquad G_1=\{2,3,5\},\qquad G_2=\{4\}.$
For a fixed candidate \(m=\frac{u}{v}\), let the base ratio of group \(g\) be \(\frac{\beta_g}{\alpha_g}\), so the three values are \(\frac{5}{41}\), \(\frac{59}{41}\), and \(\frac{59}{90}\). Reduce
$\frac{u\beta_g}{v\alpha_g}=\frac{n_g}{d_g}$
to lowest terms. Then every product \(i\in G_g\) must satisfy
$\frac{q_i}{p_i}=\frac{uQ_i}{vP_i}=\frac{n_g}{d_g},$
hence there is a positive integer \(t_i\) such that
$p_i=d_gt_i,\qquad q_i=n_gt_i.$
This is the central simplification: once \(m\) is fixed, each product contributes only one new integer parameter \(t_i\), and products that share the same supplier ratio also share the same pair \((n_g,d_g)\).
Bounds and the Group-Sum Interval
The chosen counts cannot exceed the supplier totals, so for every product \(i\in G_g\),
$1\le t_i\le \min\left(\left\lfloor\frac{P_i}{d_g}\right\rfloor,\left\lfloor\frac{Q_i}{n_g}\right\rfloor\right).$
Now define one sum per group:
$s_g=\sum_{i\in G_g}t_i.$
If a group contains \(|G_g|\) products, then the smallest possible value is
$L_g=|G_g|,$
because each \(t_i\ge 1\). The largest possible value is
$H_g=\sum_{i\in G_g}\min\left(\left\lfloor\frac{P_i}{d_g}\right\rfloor,\left\lfloor\frac{Q_i}{n_g}\right\rfloor\right).$
A useful observation is that every integer between \(L_g\) and \(H_g\) is achievable. There is no subset-sum complication here: all \(t_i\) move in steps of 1, so starting from the minimum assignment \(t_i=1\), we can increase variables one by one until any target group sum in the interval is reached.
Thus the five original parameters \(t_1,\dots,t_5\) can be replaced by the three interval-constrained sums
$s_0\in[L_0,H_0],\qquad s_1\in[L_1,H_1],\qquad s_2\in[L_2,H_2],$
with \(L_0=1\), \(L_1=3\), and \(L_2=1\).
The Final Feasibility Test Is a Bounded Linear Diophantine Equation
Substituting \(p_i=d_gt_i\) and \(q_i=n_gt_i\) into the global condition gives
$vT_Q\sum_{g=0}^{2}d_gs_g=uT_P\sum_{g=0}^{2}n_gs_g.$
Move everything to one side and define
$c_g=vT_Qd_g-uT_Pn_g.$
Then \(m\) is feasible if and only if there exist integers \(s_0,s_1,s_2\) in their intervals such that
$c_0s_0+c_1s_1+c_2s_2=0.$
The implementation fixes \(s_0\) and rewrites the problem as
$c_1s_1+c_2s_2=r,\qquad r=-c_0s_0.$
If \(g=\gcd(c_1,c_2)\) does not divide \(r\), there is no solution. Otherwise, if
$c_1x_0+c_2y_0=g,$
then every solution is of the form
$s_1=x_0\frac{r}{g}+\frac{c_2}{g}t,\qquad s_2=y_0\frac{r}{g}-\frac{c_1}{g}t,\qquad t\in\mathbb{Z}.$
The remaining task is purely interval arithmetic: intersect the range of \(t\) forced by \(L_1\le s_1\le H_1\) with the range forced by \(L_2\le s_2\le H_2\). A non-empty intersection means the candidate \(m\) works.
Worked Example: The Maximal Candidate
The implementations ultimately find that the largest feasible multiplier is
$m=\frac{123}{59}.$
For this value, the three group reductions are
$\frac{123\cdot 5}{59\cdot 41}=\frac{15}{59},\qquad \frac{123\cdot 59}{59\cdot 41}=3=\frac{3}{1},\qquad \frac{123\cdot 59}{59\cdot 90}=\frac{41}{30}.$
So the group parameters are
$ (d_0,n_0)=(59,15),\qquad (d_1,n_1)=(1,3),\qquad (d_2,n_2)=(30,41). $
The corresponding upper bounds are
$H_0=\min\!\left(\left\lfloor\frac{5248}{59}\right\rfloor,\left\lfloor\frac{640}{15}\right\rfloor\right)=42,$
$H_1=\min\!\left(\left\lfloor\frac{1312}{1}\right\rfloor,\left\lfloor\frac{1888}{3}\right\rfloor\right)+\min\!\left(\left\lfloor\frac{2624}{1}\right\rfloor,\left\lfloor\frac{3776}{3}\right\rfloor\right)+\min\!\left(\left\lfloor\frac{3936}{1}\right\rfloor,\left\lfloor\frac{5664}{3}\right\rfloor\right)=629+1258+1888=3775,$
$H_2=\min\!\left(\left\lfloor\frac{5760}{30}\right\rfloor,\left\lfloor\frac{3776}{41}\right\rfloor\right)=92.$
The coefficients become
$ (c_0,c_1,c_2)=(19971264,-6037824,-67344960)=464448\,(43,-13,-145). $
So feasibility is equivalent to
$43s_0-13s_1-145s_2=0.$
One valid choice is
$ (s_0,s_1,s_2)=(7,12,1), $
because \(43\cdot 7-13\cdot 12-145\cdot 1=0\). The middle-group sum \(s_1=12\) is easy to realize, for example by taking the three product parameters there as \(1,1,10\). This concrete construction shows why \(\frac{123}{59}\) passes the feasibility test.
How the Code Works
The C++, Python, and Java implementations follow the derivation directly. They never enumerate arbitrary five-tuples of product counts. Instead, they search the rational candidate set forced by the first product and test each candidate with exact integer arithmetic.
Candidate Enumeration
The implementation loops over all possible positive counts for product 1, forms the reduced fraction \(\frac{41b}{5a}\), discards candidates with \(m\le 1\), sorts the remaining fractions, and removes duplicates. This step constructs the complete finite search space.
Feasibility Test for One Candidate
For a fixed candidate \(m=\frac{u}{v}\), the implementation computes the three reduced group ratios \(\frac{n_g}{d_g}\), then the upper bound for each product and the interval \([L_g,H_g]\) for each group sum \(s_g\). If any product has no positive admissible value, the candidate is rejected immediately.
Otherwise it forms the coefficients \(c_g=vT_Qd_g-uT_Pn_g\), loops over all admissible \(s_0\), and for each one checks whether the remaining two-variable equation has a solution inside the intervals. That check uses the extended Euclidean algorithm together with interval tightening for the free parameter \(t\).
Collecting the Answer
Each candidate can be tested independently. The C++ and Java implementations distribute those tests across multiple threads; the Python implementation performs the same arithmetic serially. After all feasible candidates are collected, the largest reduced fraction is returned.
Complexity Analysis
Candidate generation starts from the \(5248\cdot 640=3{,}358{,}720\) raw fractions forced by product 1. Sorting and deduplicating them costs \(O(M\log M)\) with \(M=3{,}358{,}720\).
For each distinct candidate, the group preprocessing is constant-time, and the main loop scans only the possible values of \(s_0\). Since the first group contains a single product, \(s_0\) never ranges over more than a few hundred values. The two-variable Diophantine check is \(O(1)\) once the gcd and parameter intervals are computed. So the practical running time is dominated by candidate enumeration plus an \(O(C\cdot R)\) feasibility phase, where \(C\) is the number of distinct candidates and \(R\) is the width of the first group's interval. Memory usage is \(O(C)\) for storing the candidate list, plus constant auxiliary state for each test. Parallelism improves wall-clock time but does not change the asymptotic bounds.
Footnotes and References
- Problem page: https://projecteuler.net/problem=236
- Rational number: Wikipedia - Rational number
- Linear Diophantine equation: Wikipedia - Linear Diophantine equation
- Bézout's identity: Wikipedia - Bézout's identity
- Extended Euclidean algorithm: Wikipedia - Extended Euclidean algorithm
- Greatest common divisor: Wikipedia - Greatest common divisor