Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gmolveau
GitHub Repository: gmolveau/python_full_course
Path: blob/master/exercices/oop/numbered_indentation/solution_numbered.py
306 views
1
import re
2
3
text_input = """a
4
b
5
c
6
d
7
e
8
f
9
"""
10
11
text_output = """1. a
12
1.1. b
13
1.1.1. c
14
1.1.2. d
15
1.2. e
16
2. f
17
"""
18
19
IGNORE_PATTERN = "//"
20
DEPTH_PATTERN = " " * 4 # 4 spaces
21
22
23
class Numerotation:
24
def __init__(self) -> None:
25
self._positions = [0]
26
27
def update(self, depth):
28
max_index = len(self._positions) - 1
29
if depth > max_index:
30
# to avoid the case with an identation level error
31
# for example jumping from 2. to 2.1.1.
32
# we keep adding depths
33
for _ in range(depth - max_index):
34
self._positions.append(1)
35
elif depth == max_index:
36
# we are still at the deepest level so we increment
37
self._positions[depth] += 1
38
else:
39
# we are one or more level higher, we increment this level
40
self._positions[depth] += 1
41
# and delete the sub levels
42
for _ in range(max_index - depth):
43
self._positions.pop()
44
45
def __str__(self):
46
# we convert the list of int to a list of string first
47
# then separate it with a dot and add a final dot
48
o = ".".join(map(str, self._positions))
49
return f"{o}."
50
51
52
def main():
53
lines = text_input.splitlines()
54
numerotation = Numerotation()
55
output = []
56
for line in lines:
57
print(numerotation)
58
if not line:
59
continue
60
if line.startswith(IGNORE_PATTERN):
61
output.append(f"{line}\n")
62
continue
63
if not line.startswith(DEPTH_PATTERN):
64
depth = 0
65
numerotation.update(depth)
66
output.append(f"{numerotation} {line}\n")
67
continue
68
depth = len(re.findall(DEPTH_PATTERN, line))
69
if depth > 0:
70
numerotation.update(depth)
71
# we need to inject the numerotation after the depth patterns
72
index_after_patterns = depth * len(DEPTH_PATTERN)
73
o_line = f"{line[:index_after_patterns]}{numerotation} {line[index_after_patterns:]}\n"
74
output.append(o_line)
75
continue
76
return "".join(output)
77
78
79
if __name__ == "__main__":
80
o = main()
81
assert o == text_output
82
83