Skip to content

Commit 041b0ed

Browse files
authored
Create look_and_say_sequence.py
1 parent 791deb4 commit 041b0ed

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

maths/look_and_say_sequence.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"""
2+
Look-and-Say Sequence
3+
=====================
4+
The Look-and-Say sequence is a sequence of integers where each term is
5+
generated by reading the digits of the previous term aloud.
6+
7+
Starting from "1":
8+
1 -> "one 1" -> 11
9+
11 -> "two 1s" -> 21
10+
21 -> "one 2, one 1" -> 1211
11+
1211 -> "one 1, one 2, two 1s" -> 111221
12+
...
13+
14+
Reference: https://en.wikipedia.org/wiki/Look-and-say_sequence
15+
16+
Examples:
17+
>>> list(look_and_say_sequence(1))
18+
['1']
19+
>>> list(look_and_say_sequence(5))
20+
['1', '11', '21', '1211', '111221']
21+
>>> next_term('1')
22+
'11'
23+
>>> next_term('111221')
24+
'312211'
25+
>>> next_term('')
26+
Traceback (most recent call last):
27+
...
28+
ValueError: Input term must be a non-empty string of digits.
29+
"""
30+
31+
from itertools import groupby
32+
33+
34+
def next_term(term: str) -> str:
35+
"""
36+
Generate the next term in the Look-and-Say sequence.
37+
38+
Each group of consecutive identical digits is replaced by
39+
the count of digits followed by the digit itself.
40+
41+
Args:
42+
term: A non-empty string of digits representing the current term.
43+
44+
Returns:
45+
The next term in the sequence as a string.
46+
47+
Raises:
48+
ValueError: If the input term is empty.
49+
50+
Examples:
51+
>>> next_term('1')
52+
'11'
53+
>>> next_term('11')
54+
'21'
55+
>>> next_term('21')
56+
'1211'
57+
>>> next_term('1211')
58+
'111221'
59+
>>> next_term('111221')
60+
'312211'
61+
"""
62+
if not term:
63+
raise ValueError("Input term must be a non-empty string of digits.")
64+
return "".join(str(len(list(group))) + digit for digit, group in groupby(term))
65+
66+
67+
def look_and_say_sequence(num_terms: int, start: str = "1"):
68+
"""
69+
Generate the Look-and-Say sequence up to num_terms terms.
70+
71+
Args:
72+
num_terms: The number of terms to generate (must be >= 1).
73+
start: The starting term (default is "1").
74+
75+
Yields:
76+
Each term of the sequence as a string.
77+
78+
Raises:
79+
ValueError: If num_terms is less than 1.
80+
81+
Examples:
82+
>>> list(look_and_say_sequence(1))
83+
['1']
84+
>>> list(look_and_say_sequence(5))
85+
['1', '11', '21', '1211', '111221']
86+
>>> list(look_and_say_sequence(6))
87+
['1', '11', '21', '1211', '111221', '312211']
88+
>>> list(look_and_say_sequence(0))
89+
Traceback (most recent call last):
90+
...
91+
ValueError: num_terms must be a positive integer.
92+
"""
93+
if num_terms < 1:
94+
raise ValueError("num_terms must be a positive integer.")
95+
term = start
96+
for _ in range(num_terms):
97+
yield term
98+
term = next_term(term)
99+
100+
101+
if __name__ == "__main__":
102+
import doctest
103+
104+
doctest.testmod()
105+
106+
print("Look-and-Say Sequence (first 8 terms):")
107+
for i, term in enumerate(look_and_say_sequence(8), start=1):
108+
print(f" Term {i}: {term}")

0 commit comments

Comments
 (0)