Skip to content

Commit 73fa0ca

Browse files
author
aarav570
committed
feat(maths): add Farey sequence generator
1 parent 6e03a48 commit 73fa0ca

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

‎maths/farey_sequence.py‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Farey Sequence Generator
3+
4+
The Farey sequence of order n is the sequence of completely reduced
5+
fractions between 0 and 1 which have denominators less than or equal to n,
6+
arranged in increasing order.
7+
8+
Reference: https://en.wikipedia.org/wiki/Farey_sequence
9+
"""
10+
11+
from fractions import Fraction
12+
13+
14+
def farey_sequence(order: int) -> list[Fraction]:
15+
"""
16+
Generate the Farey sequence of a given order in ascending order.
17+
18+
:param order: The maximum denominator allowed in the fractions.
19+
:return: A list of Fraction objects in ascending order.
20+
21+
>>> farey_sequence(1)
22+
[Fraction(0, 1), Fraction(1, 1)]
23+
>>> farey_sequence(2)
24+
[Fraction(0, 1), Fraction(1, 2), Fraction(1, 1)]
25+
>>> farey_sequence(5)
26+
[Fraction(0, 1), Fraction(1, 5), Fraction(1, 4), Fraction(1, 3), Fraction(2, 5), Fraction(1, 2), Fraction(3, 5), Fraction(2, 3), Fraction(3, 4), Fraction(4, 5), Fraction(1, 1)]
27+
>>> farey_sequence(0)
28+
Traceback (most recent call last):
29+
...
30+
ValueError: Order must be a positive integer
31+
>>> farey_sequence(-3)
32+
Traceback (most recent call last):
33+
...
34+
ValueError: Order must be a positive integer
35+
>>> farey_sequence("5")
36+
Traceback (most recent call last):
37+
...
38+
TypeError: Order must be an integer
39+
"""
40+
if not isinstance(order, int) or isinstance(order, bool):
41+
raise TypeError("Order must be an integer")
42+
if order < 1:
43+
raise ValueError("Order must be a positive integer")
44+
45+
sequence: list[Fraction] = [Fraction(0, 1)]
46+
numerator1, denominator1 = 0, 1
47+
numerator2, denominator2 = 1, order
48+
49+
sequence.append(Fraction(numerator2, denominator2))
50+
51+
while numerator2 != 1 or denominator2 != 1:
52+
scale_factor = (denominator1 + order) // denominator2
53+
next_numerator = scale_factor * numerator2 - numerator1
54+
next_denominator = scale_factor * denominator2 - denominator1
55+
56+
sequence.append(Fraction(next_numerator, next_denominator))
57+
58+
numerator1, denominator1 = numerator2, denominator2
59+
numerator2, denominator2 = next_numerator, next_denominator
60+
61+
return sequence
62+
63+
64+
if __name__ == "__main__":
65+
import doctest
66+
67+
doctest.testmod()
68+
69+
print("Farey sequence of order 4:")
70+
print(farey_sequence(4))
71+

0 commit comments

Comments
 (0)