puzzle contents
Contents
raw puzzle

Tipping Point Problem

Robert Eisele

Given two mobile phone contracts. The first contract has a base price of 129€ and 34.95€ per year. The contract contains 100 free SMS per month and every additional SMS costs 9 Cent. The second contract has a base price of 119€ and 24.95€ as well as no free SMS. Every SMS costs 19Cent. What is the break even point, given the average number of SMS per month where the first contract is firstly more expensive than the other one. For the given example 57 is the tipping point.

Solution

Lets assume we have a base price \(b_k\) and costs per SMS \(s_k\) after \(f_k\) free SMS have been used for contract \(k\). The cost \(C_k\) for the two contracts can then be calculated if \(x\) is the number of SMS for which we try to find the tipping point:

\[C_1 = b_1 + s_1\cdot\max(0, x - f_1)\]

\[C_2 = b_2 + s_2\cdot\max(0, x - f_2)\]

Case 1 \(f_1 \leq x\) and \(f_2 \leq x\) and \(s_1\neq s_2\):

The first case is about the possibility that the free SMS for both contracts have been used but are not exhausted yet or maybe that no free SMS are contained in the contract (\(f_k=0\)).

\[b_1 + s_1\cdot(x - f_1) = b_2 + s_2\cdot(x - f_2)\Leftrightarrow x = \frac{f_1s_1 - f_2s_2 + b_2 - b_1}{s_1 - s_2}\]

Case 2 \(f_1 \leq x\) and \(f_2 > x\) and \(s_1>0\):

\[b_1 + s_1\cdot(x - f_1) = b_2\Leftrightarrow x = \frac{b_2 - b_1 + s_1f_1}{s_1}\]

Case 3 \(f_1 > x\) and \(f_2 \leq x\) and \(s_2>0\):

\[b_1 = b_2 + s_2\cdot(x - f_2)\Leftrightarrow x=\frac{b_1-b_2+s_2f_2}{s_2}\]

The tipping point is therefore the smallest \(x\), if such an \(x\) exists. If not, no tipping point can be existent (if the price curves are parallel). When implemented in JavaScript, the following snippet solves the problem:

function getTippingPoint(x1, x2) {

  var res = [];
  if (x1.s != x2.s) {
    var x = ((x1.f * x1.s - x2.f*x2.s + x2.g-x1.g) / (x1.s - x2.s));
    if (x1.f <= x && x2.f <= x) res.push(x);
  }
  if (x1.s > 0) {
    var x = ((x2.g - x1.g + x1.s * x1.f) / x1.s);
    if (x1.f <= x && x2.f > x) res.push(x);
  }
  if (x2.s > 0) {
    var x = ((x1.g - x2.g + x2.s * x2.f) / x2.s);
    if (x1.f > x && x2.f <= x) res.push(x);
  }
  return Math.min.apply(null, res);
}

getTippingPoint({
  g: 129 + 34.95 * 12,
  s: 0.09 * 12,
  f: 100}, {
  g: 119 + 24.95 * 12,
  s: 0.19 * 12,
  f: 0
});