|
1 | 1 | import math |
2 | 2 |
|
3 | | -print("=" * 58) |
4 | | -print("📊 AP / GP / AGP / HP RECOGNIZER 📊") |
5 | | -print("=" * 58) |
6 | | -print("Enter at least 4 numbers separated by commas to recognize the progression.") |
7 | | -print("Example: 2, 4, 6, 8 or 3, 6, 12, 24\n") |
8 | | - |
9 | 3 | EPS = 1e-9 |
10 | 4 |
|
11 | | -while True: |
| 5 | + |
| 6 | +def main(): |
12 | 7 | print("=" * 58) |
13 | | - print("Choose an option:") |
14 | | - print("1️⃣ Recognize sequence type") |
15 | | - print("2️⃣ Exit") |
16 | | - |
17 | | - choice = input("🎯 Enter your choice (1-2): ").strip() |
18 | | - |
19 | | - if choice == "2": |
20 | | - print("\n👋 Thanks for using the recognizer. Keep practicing! ✨\n") |
21 | | - break |
22 | | - |
23 | | - if choice != "1": |
24 | | - print("❌ Please choose 1 or 2.") |
25 | | - continue |
26 | | - |
27 | | - user_input = input("\n📝 Enter sequence values separated by commas: ").strip() |
28 | | - if not user_input: |
29 | | - print("❌ Error: Input cannot be empty.") |
30 | | - continue |
31 | | - |
32 | | - # Parse sequence |
33 | | - parts = [item.strip() for item in user_input.split(",") if item.strip()] |
34 | | - if len(parts) < 4: |
35 | | - print("❌ Please enter at least 4 values.") |
36 | | - continue |
37 | | - |
38 | | - sequence = [] |
39 | | - parse_error = False |
40 | | - for part in parts: |
41 | | - try: |
42 | | - sequence.append(float(part)) |
43 | | - except ValueError: |
44 | | - print(f"❌ Invalid number: {part}") |
45 | | - parse_error = True |
46 | | - break |
| 8 | + print("📊 AP / GP / AGP / HP RECOGNIZER 📊") |
| 9 | + print("=" * 58) |
| 10 | + print("Enter at least 4 numbers separated by commas to recognize the progression.") |
| 11 | + print("Example: 2, 4, 6, 8 or 3, 6, 12, 24\n") |
47 | 12 |
|
48 | | - if parse_error: |
49 | | - continue |
| 13 | + while True: |
| 14 | + print("=" * 58) |
| 15 | + print("Choose an option:") |
| 16 | + print("1️⃣ Recognize sequence type") |
| 17 | + print("2️⃣ Exit") |
50 | 18 |
|
51 | | - matched_types = [] |
| 19 | + choice = input("🎯 Enter your choice (1-2): ").strip() |
52 | 20 |
|
53 | | - # 1. Check AP (Arithmetic Progression) |
54 | | - is_ap = True |
55 | | - ap_diff = sequence[1] - sequence[0] |
56 | | - for i in range(2, len(sequence)): |
57 | | - if abs((sequence[i] - sequence[i - 1]) - ap_diff) > EPS: |
58 | | - is_ap = False |
| 21 | + if choice == "2": |
| 22 | + print("\n👋 Thanks for using the recognizer. Keep practicing! ✨\n") |
59 | 23 | break |
60 | 24 |
|
61 | | - if is_ap: |
62 | | - # Format helper |
63 | | - val = ap_diff |
64 | | - ap_diff_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
65 | | - matched_types.append(f"AP (common difference d = {ap_diff_str})") |
| 25 | + if choice != "1": |
| 26 | + print("❌ Please choose 1 or 2.") |
| 27 | + continue |
66 | 28 |
|
67 | | - # 2. Check GP (Geometric Progression) |
68 | | - is_gp = True |
69 | | - gp_ratio = 0.0 |
70 | | - if all(abs(x) <= EPS for x in sequence): |
71 | | - gp_ratio = 0.0 |
72 | | - elif any(abs(sequence[i - 1]) <= EPS for i in range(1, len(sequence))): |
73 | | - is_gp = False |
74 | | - else: |
75 | | - gp_ratio = sequence[1] / sequence[0] |
76 | | - for i in range(2, len(sequence)): |
77 | | - if abs((sequence[i] / sequence[i - 1]) - gp_ratio) > EPS: |
78 | | - is_gp = False |
| 29 | + user_input = input("\n📝 Enter sequence values separated by commas: ").strip() |
| 30 | + if not user_input: |
| 31 | + print("❌ Error: Input cannot be empty.") |
| 32 | + continue |
| 33 | + |
| 34 | + # Parse sequence |
| 35 | + parts = [item.strip() for item in user_input.split(",") if item.strip()] |
| 36 | + if len(parts) < 4: |
| 37 | + print("❌ Please enter at least 4 values.") |
| 38 | + continue |
| 39 | + |
| 40 | + sequence = [] |
| 41 | + parse_error = False |
| 42 | + for part in parts: |
| 43 | + try: |
| 44 | + sequence.append(float(part)) |
| 45 | + except ValueError: |
| 46 | + print(f"❌ Invalid number: {part}") |
| 47 | + parse_error = True |
79 | 48 | break |
80 | 49 |
|
81 | | - if is_gp: |
82 | | - val = gp_ratio |
83 | | - gp_ratio_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
84 | | - matched_types.append(f"GP (common ratio r = {gp_ratio_str})") |
85 | | - |
86 | | - # 3. Check HP (Harmonic Progression) |
87 | | - is_hp = True |
88 | | - hp_diff = 0.0 |
89 | | - if any(abs(x) <= EPS for x in sequence): |
90 | | - is_hp = False |
91 | | - else: |
92 | | - reciprocal = [1.0 / x for x in sequence] |
93 | | - hp_diff = reciprocal[1] - reciprocal[0] |
94 | | - for i in range(2, len(reciprocal)): |
95 | | - if abs((reciprocal[i] - reciprocal[i - 1]) - hp_diff) > EPS: |
96 | | - is_hp = False |
| 50 | + if parse_error: |
| 51 | + continue |
| 52 | + |
| 53 | + matched_types = [] |
| 54 | + |
| 55 | + # 1. Check AP (Arithmetic Progression) |
| 56 | + is_ap = True |
| 57 | + ap_diff = sequence[1] - sequence[0] |
| 58 | + for i in range(2, len(sequence)): |
| 59 | + if abs((sequence[i] - sequence[i - 1]) - ap_diff) > EPS: |
| 60 | + is_ap = False |
97 | 61 | break |
98 | 62 |
|
99 | | - if is_hp: |
100 | | - val = hp_diff |
101 | | - hp_diff_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
102 | | - matched_types.append(f"HP (reciprocal AP difference = {hp_diff_str})") |
103 | | - |
104 | | - # 4. Check AGP (Arithmetico-Geometric Progression) |
105 | | - is_agp = False |
106 | | - agp_ratio = 0.0 |
107 | | - |
108 | | - # Generate AGP ratio candidates |
109 | | - s0, s1, s2 = sequence[0], sequence[1], sequence[2] |
110 | | - candidates = [] |
111 | | - if abs(s0) <= EPS: |
112 | | - if abs(s1) > EPS: |
113 | | - candidates.append(s2 / (2 * s1)) |
114 | | - else: |
115 | | - a = s0 |
116 | | - b = -2 * s1 |
117 | | - c = s2 |
118 | | - disc = b * b - 4 * a * c |
119 | | - if disc >= -EPS: |
120 | | - if abs(disc) <= EPS: |
121 | | - candidates.append(-b / (2 * a)) |
122 | | - else: |
123 | | - sqrt_disc = math.sqrt(disc) |
124 | | - candidates.append((-b + sqrt_disc) / (2 * a)) |
125 | | - candidates.append((-b - sqrt_disc) / (2 * a)) |
126 | | - |
127 | | - for r in candidates: |
128 | | - if abs(r) <= EPS: |
129 | | - # If common ratio r = 0, all terms from index 1 onwards must be 0 |
130 | | - if all(abs(x) <= EPS for x in sequence[1:]): |
| 63 | + if is_ap: |
| 64 | + # Format helper |
| 65 | + val = ap_diff |
| 66 | + ap_diff_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
| 67 | + matched_types.append(f"AP (common difference d = {ap_diff_str})") |
| 68 | + |
| 69 | + # 2. Check GP (Geometric Progression) |
| 70 | + is_gp = True |
| 71 | + gp_ratio = 0.0 |
| 72 | + if all(abs(x) <= EPS for x in sequence): |
| 73 | + gp_ratio = 0.0 |
| 74 | + elif any(abs(sequence[i - 1]) <= EPS for i in range(1, len(sequence))): |
| 75 | + is_gp = False |
| 76 | + else: |
| 77 | + gp_ratio = sequence[1] / sequence[0] |
| 78 | + for i in range(2, len(sequence)): |
| 79 | + if abs((sequence[i] / sequence[i - 1]) - gp_ratio) > EPS: |
| 80 | + is_gp = False |
| 81 | + break |
| 82 | + |
| 83 | + if is_gp: |
| 84 | + val = gp_ratio |
| 85 | + gp_ratio_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
| 86 | + matched_types.append(f"GP (common ratio r = {gp_ratio_str})") |
| 87 | + |
| 88 | + # 3. Check HP (Harmonic Progression) |
| 89 | + is_hp = True |
| 90 | + hp_diff = 0.0 |
| 91 | + if any(abs(x) <= EPS for x in sequence): |
| 92 | + is_hp = False |
| 93 | + else: |
| 94 | + reciprocal = [1.0 / x for x in sequence] |
| 95 | + hp_diff = reciprocal[1] - reciprocal[0] |
| 96 | + for i in range(2, len(reciprocal)): |
| 97 | + if abs((reciprocal[i] - reciprocal[i - 1]) - hp_diff) > EPS: |
| 98 | + is_hp = False |
| 99 | + break |
| 100 | + |
| 101 | + if is_hp: |
| 102 | + val = hp_diff |
| 103 | + hp_diff_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
| 104 | + matched_types.append(f"HP (reciprocal AP difference = {hp_diff_str})") |
| 105 | + |
| 106 | + # 4. Check AGP (Arithmetico-Geometric Progression) |
| 107 | + is_agp = False |
| 108 | + agp_ratio = 0.0 |
| 109 | + |
| 110 | + # Generate AGP ratio candidates |
| 111 | + s0, s1, s2 = sequence[0], sequence[1], sequence[2] |
| 112 | + candidates = [] |
| 113 | + if abs(s0) <= EPS: |
| 114 | + if abs(s1) > EPS: |
| 115 | + candidates.append(s2 / (2 * s1)) |
| 116 | + else: |
| 117 | + a = s0 |
| 118 | + b = -2 * s1 |
| 119 | + c = s2 |
| 120 | + disc = b * b - 4 * a * c |
| 121 | + if disc >= -EPS: |
| 122 | + if abs(disc) <= EPS: |
| 123 | + candidates.append(-b / (2 * a)) |
| 124 | + else: |
| 125 | + sqrt_disc = math.sqrt(disc) |
| 126 | + candidates.append((-b + sqrt_disc) / (2 * a)) |
| 127 | + candidates.append((-b - sqrt_disc) / (2 * a)) |
| 128 | + |
| 129 | + for r in candidates: |
| 130 | + if abs(r) <= EPS: |
| 131 | + # If common ratio r = 0, all terms from index 1 onwards must be 0 |
| 132 | + if all(abs(x) <= EPS for x in sequence[1:]): |
| 133 | + is_agp = True |
| 134 | + agp_ratio = r |
| 135 | + break |
| 136 | + continue |
| 137 | + |
| 138 | + valid = True |
| 139 | + for i in range(2, len(sequence)): |
| 140 | + expected = 2 * r * sequence[i - 1] - (r * r) * sequence[i - 2] |
| 141 | + if abs(sequence[i] - expected) > 1e-7: |
| 142 | + valid = False |
| 143 | + break |
| 144 | + if valid: |
131 | 145 | is_agp = True |
132 | 146 | agp_ratio = r |
133 | 147 | break |
134 | | - continue |
135 | 148 |
|
136 | | - valid = True |
137 | | - for i in range(2, len(sequence)): |
138 | | - expected = 2 * r * sequence[i - 1] - (r * r) * sequence[i - 2] |
139 | | - if abs(sequence[i] - expected) > 1e-7: |
140 | | - valid = False |
141 | | - break |
142 | | - if valid: |
143 | | - is_agp = True |
144 | | - agp_ratio = r |
145 | | - break |
| 149 | + if is_agp: |
| 150 | + val = agp_ratio |
| 151 | + agp_ratio_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
| 152 | + matched_types.append(f"AGP (repetition ratio r = {agp_ratio_str})") |
| 153 | + |
| 154 | + # Display Results |
| 155 | + print("\n💡 Result") |
| 156 | + print("-" * 58) |
| 157 | + formatted_seq = [] |
| 158 | + for x in sequence: |
| 159 | + f_str = str(int(round(x))) if abs(x - round(x)) < 1e-9 else f"{x:.6g}" |
| 160 | + formatted_seq.append(f_str) |
| 161 | + print("Sequence:", ", ".join(formatted_seq)) |
| 162 | + |
| 163 | + if matched_types: |
| 164 | + print("✅ Recognized as:") |
| 165 | + for seq_type in matched_types: |
| 166 | + print(" -", seq_type) |
| 167 | + else: |
| 168 | + print("❌ Not AP, GP, AGP, or HP for the given values.") |
| 169 | + |
| 170 | + print("-" * 58) |
| 171 | + |
146 | 172 |
|
147 | | - if is_agp: |
148 | | - val = agp_ratio |
149 | | - agp_ratio_str = str(int(round(val))) if abs(val - round(val)) < 1e-9 else f"{val:.6g}" |
150 | | - matched_types.append(f"AGP (repetition ratio r = {agp_ratio_str})") |
151 | | - |
152 | | - # Display Results |
153 | | - print("\n💡 Result") |
154 | | - print("-" * 58) |
155 | | - formatted_seq = [] |
156 | | - for x in sequence: |
157 | | - f_str = str(int(round(x))) if abs(x - round(x)) < 1e-9 else f"{x:.6g}" |
158 | | - formatted_seq.append(f_str) |
159 | | - print("Sequence:", ", ".join(formatted_seq)) |
160 | | - |
161 | | - if matched_types: |
162 | | - print("✅ Recognized as:") |
163 | | - for seq_type in matched_types: |
164 | | - print(" -", seq_type) |
165 | | - else: |
166 | | - print("❌ Not AP, GP, AGP, or HP for the given values.") |
167 | | - |
168 | | - print("-" * 58) |
| 173 | +if __name__ == "__main__": |
| 174 | + main() |
0 commit comments