Skip to content

Commit c8c8fd0

Browse files
fpringlestokhos
authored andcommitted
Add solution for Project Euler problem 113 (TheAlgorithms#3109)
* Added solution for Project Euler problem 113. TheAlgorithms#2695 * Updated formatting and doctests. Reference: TheAlgorithms#3256
1 parent ef92379 commit c8c8fd0

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

Diff for: project_euler/problem_113/__init__.py

Whitespace-only changes.

Diff for: project_euler/problem_113/sol1.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
Project Euler Problem 113: https://projecteuler.net/problem=113
3+
4+
Working from left-to-right if no digit is exceeded by the digit to its left it is
5+
called an increasing number; for example, 134468.
6+
7+
Similarly if no digit is exceeded by the digit to its right it is called a decreasing
8+
number; for example, 66420.
9+
10+
We shall call a positive integer that is neither increasing nor decreasing a
11+
"bouncy" number; for example, 155349.
12+
13+
As n increases, the proportion of bouncy numbers below n increases such that there
14+
are only 12951 numbers below one-million that are not bouncy and only 277032
15+
non-bouncy numbers below 10^10.
16+
17+
How many numbers below a googol (10^100) are not bouncy?
18+
"""
19+
20+
21+
def choose(n: int, r: int) -> int:
22+
"""
23+
Calculate the binomial coefficient c(n,r) using the multiplicative formula.
24+
>>> choose(4,2)
25+
6
26+
>>> choose(5,3)
27+
10
28+
>>> choose(20,6)
29+
38760
30+
"""
31+
ret = 1.0
32+
for i in range(1, r + 1):
33+
ret *= (n + 1 - i) / i
34+
return round(ret)
35+
36+
37+
def non_bouncy_exact(n: int) -> int:
38+
"""
39+
Calculate the number of non-bouncy numbers with at most n digits.
40+
>>> non_bouncy_exact(1)
41+
9
42+
>>> non_bouncy_exact(6)
43+
7998
44+
>>> non_bouncy_exact(10)
45+
136126
46+
"""
47+
return choose(8 + n, n) + choose(9 + n, n) - 10
48+
49+
50+
def non_bouncy_upto(n: int) -> int:
51+
"""
52+
Calculate the number of non-bouncy numbers with at most n digits.
53+
>>> non_bouncy_upto(1)
54+
9
55+
>>> non_bouncy_upto(6)
56+
12951
57+
>>> non_bouncy_upto(10)
58+
277032
59+
"""
60+
return sum(non_bouncy_exact(i) for i in range(1, n + 1))
61+
62+
63+
def solution(num_digits: int = 100) -> int:
64+
"""
65+
Caclulate the number of non-bouncy numbers less than a googol.
66+
>>> solution(6)
67+
12951
68+
>>> solution(10)
69+
277032
70+
"""
71+
return non_bouncy_upto(num_digits)
72+
73+
74+
if __name__ == "__main__":
75+
print(f"{solution() = }")

0 commit comments

Comments
 (0)