Skip to content

Commit dacd023

Browse files
Merge pull request steam-bell-92#803 from mrdeyroy/fix/math-projects-guidelines
Fix/math projects guidelines
2 parents 5e2a2c4 + b14bc06 commit dacd023

22 files changed

Lines changed: 1677 additions & 1950 deletions

File tree

math/AP-GP-AGP-HP-Recognizer/AP-GP-AGP-HP-Recognizer.py

Lines changed: 125 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,162 @@
1+
import math
2+
13
print("=" * 58)
2-
print("AP / GP / AGP / HP RECOGNIZER")
4+
print("📊 AP / GP / AGP / HP RECOGNIZER 📊")
35
print("=" * 58)
4-
print("Enter at least 4 numbers separated by commas.")
5-
print("Example: 2, 4, 6, 8 or 3, 6, 12, 24")
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")
68

79
EPS = 1e-9
810

11+
while True:
12+
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()
918

10-
def is_close(a, b, eps=EPS):
11-
return abs(a - b) <= eps
19+
if choice == "2":
20+
print("\n👋 Thanks for using the recognizer. Keep practicing! ✨\n")
21+
break
1222

23+
if choice != "1":
24+
print("❌ Please choose 1 or 2.")
25+
continue
1326

14-
def parse_sequence(raw):
15-
parts = [item.strip() for item in raw.split(",") if item.strip()]
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()]
1634
if len(parts) < 4:
17-
return None, "Please enter at least 4 values."
35+
print("❌ Please enter at least 4 values.")
36+
continue
1837

1938
sequence = []
39+
parse_error = False
2040
for part in parts:
2141
try:
2242
sequence.append(float(part))
2343
except ValueError:
24-
return None, f"Invalid number: {part}"
25-
26-
return sequence, ""
27-
28-
29-
def check_ap(sequence):
30-
diff = sequence[1] - sequence[0]
31-
for i in range(2, len(sequence)):
32-
if not is_close(sequence[i] - sequence[i - 1], diff):
33-
return False, None
34-
return True, diff
35-
44+
print(f"❌ Invalid number: {part}")
45+
parse_error = True
46+
break
3647

37-
def check_gp(sequence):
38-
if all(is_close(value, 0.0) for value in sequence):
39-
return True, 0.0
48+
if parse_error:
49+
continue
4050

41-
if any(is_close(sequence[i - 1], 0.0) for i in range(1, len(sequence))):
42-
return False, None
51+
matched_types = []
4352

44-
ratio = sequence[1] / sequence[0]
53+
# 1. Check AP (Arithmetic Progression)
54+
is_ap = True
55+
ap_diff = sequence[1] - sequence[0]
4556
for i in range(2, len(sequence)):
46-
if not is_close(sequence[i] / sequence[i - 1], ratio):
47-
return False, None
48-
49-
return True, ratio
50-
51-
52-
def check_hp(sequence):
53-
if any(is_close(value, 0.0) for value in sequence):
54-
return False, None
57+
if abs((sequence[i] - sequence[i - 1]) - ap_diff) > EPS:
58+
is_ap = False
59+
break
60+
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})")
66+
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
79+
break
5580

56-
reciprocal = [1 / value for value in sequence]
57-
is_ap, reciprocal_diff = check_ap(reciprocal)
58-
if not is_ap:
59-
return False, None
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})")
6085

61-
return True, reciprocal_diff
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
97+
break
6298

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})")
63103

64-
def agp_candidates(sequence):
104+
# 4. Check AGP (Arithmetico-Geometric Progression)
105+
is_agp = False
106+
agp_ratio = 0.0
107+
108+
# Generate AGP ratio candidates
65109
s0, s1, s2 = sequence[0], sequence[1], sequence[2]
66-
67-
if is_close(s0, 0.0):
68-
if is_close(s1, 0.0):
69-
return []
70-
return [s2 / (2 * s1)]
71-
72-
a = s0
73-
b = -2 * s1
74-
c = s2
75-
disc = b * b - 4 * a * c
76-
77-
if disc < -EPS:
78-
return []
79-
80-
if is_close(disc, 0.0):
81-
return [-b / (2 * a)]
82-
83-
if disc < 0:
84-
return []
85-
86-
sqrt_disc = disc ** 0.5
87-
r1 = (-b + sqrt_disc) / (2 * a)
88-
r2 = (-b - sqrt_disc) / (2 * a)
89-
90-
if is_close(r1, r2):
91-
return [r1]
92-
93-
return [r1, r2]
94-
95-
96-
def check_agp(sequence):
97-
for ratio in agp_candidates(sequence):
98-
a = sequence[0]
99-
if is_close(ratio, 0.0):
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:
100129
# If common ratio r = 0, all terms from index 1 onwards must be 0
101-
if all(is_close(x, 0.0) for x in sequence[1:]):
102-
return True, ratio
130+
if all(abs(x) <= EPS for x in sequence[1:]):
131+
is_agp = True
132+
agp_ratio = r
133+
break
103134
continue
104135

105-
d = (sequence[1] / ratio) - a
106136
valid = True
107-
for i in range(len(sequence)):
108-
expected = (a + i * d) * (ratio ** i)
109-
if not is_close(sequence[i], expected, eps=1e-7):
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:
110140
valid = False
111141
break
112142
if valid:
113-
return True, ratio
114-
115-
return False, None
116-
117-
118-
def format_number(value):
119-
if is_close(value, round(value)):
120-
return str(int(round(value)))
121-
return f"{value:.6g}"
122-
123-
124-
while True:
125-
print("\nChoose an option:")
126-
print("1. Recognize sequence type")
127-
print("2. Exit")
128-
129-
choice = input("Enter your choice (1-2): ").strip()
130-
131-
if choice == "2":
132-
print("\nThanks for using the recognizer. Keep practicing! ✨")
133-
break
134-
135-
if choice != "1":
136-
print("Please choose 1 or 2.")
137-
continue
138-
139-
user_input = input("\nEnter sequence values separated by commas: ")
140-
sequence, error = parse_sequence(user_input)
141-
142-
if error:
143-
print(f"❌ {error}")
144-
continue
145-
146-
matched_types = []
147-
148-
ap_ok, ap_diff = check_ap(sequence)
149-
if ap_ok:
150-
matched_types.append(f"AP (common difference d = {format_number(ap_diff)})")
151-
152-
gp_ok, gp_ratio = check_gp(sequence)
153-
if gp_ok:
154-
matched_types.append(f"GP (common ratio r = {format_number(gp_ratio)})")
155-
156-
agp_ok, agp_ratio = check_agp(sequence)
157-
if agp_ok:
158-
matched_types.append(f"AGP (repetition ratio r = {format_number(agp_ratio)})")
143+
is_agp = True
144+
agp_ratio = r
145+
break
159146

160-
hp_ok, hp_diff = check_hp(sequence)
161-
if hp_ok:
162-
matched_types.append(
163-
f"HP (reciprocal AP difference = {format_number(hp_diff)})"
164-
)
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})")
165151

166-
print("\nResult")
152+
# Display Results
153+
print("\n💡 Result")
167154
print("-" * 58)
168-
print("Sequence:", ", ".join(format_number(x) for x in sequence))
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))
169160

170161
if matched_types:
171162
print("✅ Recognized as:")

0 commit comments

Comments
 (0)