All Euler problems
Project Euler

Bouncy Numbers

A positive integer is increasing if its digits form a non-decreasing sequence from left to right, decreasing if they form a non-increasing sequence, and bouncy if it is neither. Find the least posi...

Source sync Apr 19, 2026
Problem #0112
Level Level 03
Solved By 27,464
Languages C++, Python
Answer 1587000
Length 401 words
modular_arithmeticsequencealgebra

Problem Statement

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

Working from left-to-right if no digit is exceeded by the digit to its left it is called an increasing number; for example, \(134468\).

Similarly if no digit is exceeded by the digit to its right it is called a decreasing number; for example, \(66420\).

We shall call a positive integer that is neither increasing nor decreasing a "bouncy" number; for example, \(155349\).

Clearly there cannot be any bouncy numbers below one-hundred, but just over half of the numbers below one-thousand (\(525\)) are bouncy. In fact, the least number for which the proportion of bouncy numbers first reaches \(50\%\) is \(538\).

Surprisingly, bouncy numbers become more and more common and by the time we reach \(21780\) the proportion of bouncy numbers is equal to \(90\%\).

Find the least number for which the proportion of bouncy numbers is exactly \(99\%\).

Problem 112: Bouncy Numbers

Mathematical Development

Definition 1. Let nn be a positive integer with decimal representation d1d2dkd_1 d_2 \cdots d_k (left to right). We say nn is increasing if didi+1d_i \leq d_{i+1} for all 1i<k1 \leq i < k, decreasing if didi+1d_i \geq d_{i+1} for all 1i<k1 \leq i < k, and bouncy if it is neither increasing nor decreasing.

Theorem 1 (Small numbers are non-bouncy). Every positive integer n<100n < 100 is non-bouncy.

Proof. A single-digit number (n<10n < 10) has a digit sequence of length 1, which vacuously satisfies both the non-decreasing and non-increasing conditions. A two-digit number d1d2d_1 d_2 with d11d_1 \geq 1 satisfies either d1d2d_1 \leq d_2 or d1>d2d_1 > d_2, since any two integers are totally ordered. In the first case nn is increasing; in the second, nn is decreasing (in fact, strictly so). Hence no number below 100 is bouncy. \blacksquare

Theorem 2 (Bouncy density approaches 1). Let B(n)B(n) denote the number of bouncy integers in {1,2,,n}\{1, 2, \ldots, n\}. Then B(n)/n1B(n)/n \to 1 as nn \to \infty.

Proof. The count of non-bouncy (increasing or decreasing) positive integers with at most kk digits is a polynomial in kk of degree at most 10 (see Problem 113, where the exact formula is (k+99)+(k+1010)10k2\binom{k+9}{9} + \binom{k+10}{10} - 10k - 2). The total count of positive integers with at most kk digits is 10k110^k - 1. Since polynomial growth is dominated by exponential growth, the fraction of non-bouncy numbers tends to 0, and consequently B(n)/n1B(n)/n \to 1. \blacksquare

Lemma 1 (Divisibility constraint). If B(n)/n=99/100B(n)/n = 99/100, then 100n100 \mid n.

Proof. The equation B(n)/n=99/100B(n)/n = 99/100 is equivalent to 100B(n)=99n100 \cdot B(n) = 99n, i.e., n=100(nB(n))n = 100(n - B(n)). Since nB(n)n - B(n) is a positive integer (it counts the non-bouncy numbers up to nn), it follows that 100n100 \mid n. \blacksquare

Theorem 3 (Existence and computability). There exists a least nn with B(n)/n=99/100B(n)/n = 99/100, and a sequential scan over all positive integers finds it in finite time.

Proof. By Theorem 2, B(n)/nB(n)/n eventually exceeds any constant less than 1, including 99/10099/100. At n=100n = 100, B(100)=0B(100) = 0 (Theorem 1), so B(100)/100=0<99/100B(100)/100 = 0 < 99/100. By Lemma 1, the target must be a multiple of 100. As nn increases, the non-bouncy count nB(n)n - B(n) grows subexponentially while n/100n/100 grows linearly, so a crossing must occur. A sequential scan checks every integer, maintains an exact count, and cannot miss the first qualifying nn. \blacksquare

Editorial

We enumerate the admissible parameter range, discard candidates that violate the derived bounds or arithmetic constraints, and update the final set or total whenever a candidate passes the acceptance test.

Pseudocode

    bouncy_count = 0
    for n = 1, 2, 3, ...:
        If IsBouncy(n) then
            bouncy_count += 1
        If 100 * bouncy_count == 99 * n then
            Return n

    digits = decimal_digits(n)
    has_increase = false
    has_decrease = false
    For i from 1 to len(digits) - 1:
        if digits[i] > digits[i-1]: has_increase = true
        if digits[i] < digits[i-1]: has_decrease = true
    Return has_increase and has_decrease

Complexity Analysis

  • Time. O(NlogN)O(N \log N) where N=1,587,000N = 1{,}587{,}000 is the answer. Each number requires O(logn)O(\log n) work for digit extraction and comparison. The total work is n=1NO(logn)=O(NlogN)\sum_{n=1}^{N} O(\log n) = O(N \log N).
  • Space. O(logN)O(\log N) for storing the digit representation of the current number.

Answer

1587000\boxed{1587000}

Code

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

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

bool is_bouncy(int n) {
    int prev = n % 10;
    n /= 10;
    bool inc = true, dec = true;
    while (n > 0) {
        int d = n % 10;
        if (d > prev) inc = false;
        if (d < prev) dec = false;
        prev = d;
        n /= 10;
    }
    return !inc && !dec;
}

int main() {
    int bouncy = 0;
    for (int n = 1;; n++) {
        if (is_bouncy(n)) bouncy++;
        if (100 * bouncy == 99 * n) {
            cout << n << endl;
            return 0;
        }
    }
}