j-js commited on
Commit
ffa09d9
·
verified ·
1 Parent(s): fc53c42

Create solver_ratio.py

Browse files
Files changed (1) hide show
  1. solver_ratio.py +157 -0
solver_ratio.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from math import gcd
5
+ from typing import Optional, List
6
+
7
+ from models import SolverResult
8
+
9
+
10
+ def _nums(text: str) -> List[float]:
11
+ return [float(x) for x in re.findall(r"-?\d+(?:\.\d+)?", text)]
12
+
13
+
14
+ def _reduce_ratio(a: int, b: int) -> tuple[int, int]:
15
+ if a == 0 and b == 0:
16
+ return (0, 0)
17
+ g = gcd(abs(a), abs(b))
18
+ return (a // g, b // g)
19
+
20
+
21
+ def solve_ratio(text: str) -> Optional[SolverResult]:
22
+ lower = (text or "").lower()
23
+
24
+ if "ratio" not in lower and ":" not in lower:
25
+ return None
26
+
27
+ # Pattern 1: "ratio of x to y"
28
+ m = re.search(r"ratio\s+of\s+(-?\d+)\s+to\s+(-?\d+)", lower)
29
+ if m:
30
+ a = int(m.group(1))
31
+ b = int(m.group(2))
32
+ if b == 0 and a == 0:
33
+ return None
34
+ ra, rb = _reduce_ratio(a, b)
35
+ return SolverResult(
36
+ domain="quant",
37
+ solved=True,
38
+ topic="ratio",
39
+ answer_value=f"{ra}:{rb}",
40
+ internal_answer=f"{ra}:{rb}",
41
+ steps=[
42
+ "Write the ratio in order.",
43
+ "Reduce both parts by their greatest common factor.",
44
+ ],
45
+ )
46
+
47
+ # Pattern 2: "a:b = 2:3 and total is 40"
48
+ m = re.search(
49
+ r"(\d+)\s*:\s*(\d+).*?(?:sum|total).*?(\d+(?:\.\d+)?)",
50
+ lower,
51
+ )
52
+ if m:
53
+ a = float(m.group(1))
54
+ b = float(m.group(2))
55
+ total = float(m.group(3))
56
+ parts = a + b
57
+ if parts == 0:
58
+ return None
59
+ unit = total / parts
60
+ first = a * unit
61
+ second = b * unit
62
+ return SolverResult(
63
+ domain="quant",
64
+ solved=True,
65
+ topic="ratio_partition",
66
+ answer_value=f"{first:g}, {second:g}",
67
+ internal_answer=f"{first:g}, {second:g}",
68
+ steps=[
69
+ "Add the ratio parts.",
70
+ "Divide the total by the total number of parts to get one unit.",
71
+ "Multiply each ratio part by the unit value.",
72
+ ],
73
+ )
74
+
75
+ # Pattern 3: "ratio is 2:3, one part is 10 more than the other"
76
+ m = re.search(
77
+ r"(\d+)\s*:\s*(\d+).*?(\d+(?:\.\d+)?)\s+more\s+than",
78
+ lower,
79
+ )
80
+ if m:
81
+ a = float(m.group(1))
82
+ b = float(m.group(2))
83
+ diff_val = float(m.group(3))
84
+ diff_parts = abs(a - b)
85
+ if diff_parts == 0:
86
+ return None
87
+ unit = diff_val / diff_parts
88
+ first = a * unit
89
+ second = b * unit
90
+ return SolverResult(
91
+ domain="quant",
92
+ solved=True,
93
+ topic="ratio_difference",
94
+ answer_value=f"{first:g}, {second:g}",
95
+ internal_answer=f"{first:g}, {second:g}",
96
+ steps=[
97
+ "Find the difference in ratio parts.",
98
+ "Match that to the actual difference to get one unit.",
99
+ "Multiply each ratio part by the unit value.",
100
+ ],
101
+ )
102
+
103
+ # Pattern 4: "If x:y = 2:3 and y:z = 4:5, find x:z"
104
+ m = re.search(
105
+ r"(\w+)\s*:\s*(\w+)\s*=\s*(\d+)\s*:\s*(\d+).*?(\w+)\s*:\s*(\w+)\s*=\s*(\d+)\s*:\s*(\d+).*?find\s+(\w+)\s*:\s*(\w+)",
106
+ lower,
107
+ )
108
+ if m:
109
+ left1, right1, a, b = m.group(1), m.group(2), int(m.group(3)), int(m.group(4))
110
+ left2, right2, c, d = m.group(5), m.group(6), int(m.group(7)), int(m.group(8))
111
+ target1, target2 = m.group(9), m.group(10)
112
+
113
+ if right1 == left2:
114
+ lcm_base = b * c // gcd(b, c)
115
+ mul1 = lcm_base // b
116
+ mul2 = lcm_base // c
117
+ first = a * mul1
118
+ middle = lcm_base
119
+ third = d * mul2
120
+
121
+ mapping = {left1: first, right1: middle, right2: third}
122
+ if target1 in mapping and target2 in mapping:
123
+ x = mapping[target1]
124
+ y = mapping[target2]
125
+ rx, ry = _reduce_ratio(int(x), int(y))
126
+ return SolverResult(
127
+ domain="quant",
128
+ solved=True,
129
+ topic="ratio_chain",
130
+ answer_value=f"{rx}:{ry}",
131
+ internal_answer=f"{rx}:{ry}",
132
+ steps=[
133
+ "Match the common middle term across both ratios.",
134
+ "Scale the ratios so the shared term is equal.",
135
+ "Read off the requested ratio and simplify.",
136
+ ],
137
+ )
138
+
139
+ # Pattern 5: direct colon simplification
140
+ m = re.search(r"(\d+)\s*:\s*(\d+)", lower)
141
+ if m and any(w in lower for w in ["simplify", "reduce", "ratio"]):
142
+ a = int(m.group(1))
143
+ b = int(m.group(2))
144
+ ra, rb = _reduce_ratio(a, b)
145
+ return SolverResult(
146
+ domain="quant",
147
+ solved=True,
148
+ topic="ratio",
149
+ answer_value=f"{ra}:{rb}",
150
+ internal_answer=f"{ra}:{rb}",
151
+ steps=[
152
+ "Find the greatest common factor of both terms.",
153
+ "Divide both sides of the ratio by that factor.",
154
+ ],
155
+ )
156
+
157
+ return None