Skip to content

Commit e783e14

Browse files
committed
added DSA problem of rare_number
1 parent e2a78d4 commit e783e14

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

maths/rare_number.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""
2+
Rare numbers are special non-palindromic numbers N such that both N + rev(N)
3+
and N - rev(N) are perfect squares, where rev(N) is the reverse of the digits
4+
of N.
5+
6+
This module provides functions to check and generate rare numbers in a given
7+
range. Rare numbers are useful in number theory and pattern-based algorithm
8+
analysis.
9+
10+
For more information about rare numbers, refer to:
11+
[https://www.geeksforgeeks.org/dsa/rare-numbers/](https://www.geeksforgeeks.org/dsa/rare-numbers/)
12+
"""
13+
14+
import math
15+
16+
17+
def rare_numbers(start: int, end: int) -> list[int]:
18+
"""
19+
Find all rare numbers between the given start and end range (inclusive).
20+
21+
A rare number N satisfies both:
22+
1. N + rev(N) is a perfect square.
23+
2. N - rev(N) is a perfect square.
24+
where rev(N) is the reverse of the digits of N,
25+
and N must not be a palindrome.
26+
27+
Args:
28+
start (int): The lower bound of the range (inclusive).
29+
end (int): The upper bound of the range (inclusive).
30+
31+
Returns:
32+
list[int]: A list of rare numbers within the specified range.
33+
34+
Raises:
35+
ValueError: If start or end is negative, or start > end.
36+
37+
Examples:
38+
>>> rare_numbers(-1, 100)
39+
Traceback (most recent call last):
40+
...
41+
ValueError: Range limits must be non-negative and start <= end
42+
>>> rare_numbers(1, 100)
43+
[]
44+
>>> rare_numbers(1, 1000)
45+
[65]
46+
"""
47+
if start < 0 or end < 0 or start > end:
48+
raise ValueError("Range limits must be non-negative and start <= end")
49+
50+
rares = []
51+
for n in range(start, end + 1):
52+
rev_n = _reverse_number(n)
53+
if n == rev_n:
54+
continue # skip palindromes
55+
if _is_perfect_square(n + rev_n) and _is_perfect_square(abs(n - rev_n)):
56+
rares.append(n)
57+
return rares
58+
59+
60+
def _reverse_number(num: int) -> int:
61+
"""
62+
Reverse the digits of a given integer.
63+
64+
Args:
65+
num (int): The integer to reverse.
66+
67+
Returns:
68+
int: The reversed integer.
69+
70+
Examples:
71+
>>> _reverse_number(123)
72+
321
73+
>>> _reverse_number(400)
74+
4
75+
"""
76+
rev = 0
77+
while num > 0:
78+
rev = rev * 10 + num % 10
79+
num //= 10
80+
return rev
81+
82+
83+
def _is_perfect_square(n: int) -> bool:
84+
"""
85+
Check if a number is a perfect square.
86+
87+
Args:
88+
n (int): The number to check.
89+
90+
Returns:
91+
bool: True if n is a perfect square, False otherwise.
92+
93+
Examples:
94+
>>> _is_perfect_square(16)
95+
True
96+
>>> _is_perfect_square(20)
97+
False
98+
"""
99+
if n < 0:
100+
return False
101+
root = int(math.isqrt(n))
102+
return root * root == n
103+
104+
105+
if __name__ == "__main__":
106+
import doctest
107+
doctest.testmod()

0 commit comments

Comments
 (0)