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

Create solver_probability.py

Browse files
Files changed (1) hide show
  1. solver_probability.py +155 -0
solver_probability.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from math import comb, perm
5
+ from typing import Optional, List
6
+
7
+ from models import SolverResult
8
+
9
+
10
+ def _nums(text: str) -> List[int]:
11
+ return [int(x) for x in re.findall(r"-?\d+", text)]
12
+
13
+
14
+ def solve_probability(text: str) -> Optional[SolverResult]:
15
+ lower = (text or "").lower()
16
+
17
+ prob_words = [
18
+ "probability", "chance", "likely", "dice", "die", "coin", "cards",
19
+ "card", "deck", "random", "at random", "marble", "ball", "urn",
20
+ "without replacement", "with replacement"
21
+ ]
22
+ if not any(w in lower for w in prob_words):
23
+ return None
24
+
25
+ nums = _nums(lower)
26
+
27
+ # Pattern 1: simple favorable / total
28
+ m = re.search(
29
+ r"probability.*?(\d+).*?out of.*?(\d+)",
30
+ lower,
31
+ )
32
+ if m:
33
+ fav = int(m.group(1))
34
+ total = int(m.group(2))
35
+ if total == 0:
36
+ return None
37
+ result = fav / total
38
+ return SolverResult(
39
+ domain="quant",
40
+ solved=True,
41
+ topic="probability",
42
+ answer_value=f"{result:g}",
43
+ internal_answer=f"{result:g}",
44
+ steps=[
45
+ "Use probability = favorable outcomes ÷ total outcomes.",
46
+ ],
47
+ )
48
+
49
+ # Pattern 2: one die
50
+ if ("die" in lower or "dice" in lower) and "even" in lower:
51
+ result = 3 / 6
52
+ return SolverResult(
53
+ domain="quant",
54
+ solved=True,
55
+ topic="probability",
56
+ answer_value=f"{result:g}",
57
+ internal_answer=f"{result:g}",
58
+ steps=[
59
+ "A fair die has 6 equally likely outcomes.",
60
+ "Even outcomes are 2, 4, and 6, so there are 3 favorable outcomes.",
61
+ "Probability = 3/6.",
62
+ ],
63
+ )
64
+
65
+ if ("coin" in lower) and ("head" in lower or "heads" in lower):
66
+ # one fair coin if not otherwise specified
67
+ if "twice" not in lower and "two" not in lower:
68
+ result = 1 / 2
69
+ return SolverResult(
70
+ domain="quant",
71
+ solved=True,
72
+ topic="probability",
73
+ answer_value=f"{result:g}",
74
+ internal_answer=f"{result:g}",
75
+ steps=[
76
+ "A fair coin has 2 equally likely outcomes.",
77
+ "Heads is 1 favorable outcome out of 2.",
78
+ ],
79
+ )
80
+
81
+ # Pattern 3: at least one head in n fair tosses
82
+ m = re.search(r"(?:coin.*?tossed|toss.*?coin).*?(\d+)\s+times", lower)
83
+ if m and "at least one head" in lower:
84
+ n = int(m.group(1))
85
+ result = 1 - (1 / 2) ** n
86
+ return SolverResult(
87
+ domain="quant",
88
+ solved=True,
89
+ topic="probability",
90
+ answer_value=f"{result:g}",
91
+ internal_answer=f"{result:g}",
92
+ steps=[
93
+ "Use the complement: at least one head = 1 − P(no heads).",
94
+ "For a fair coin, P(no heads in n tosses) = (1/2)^n.",
95
+ ],
96
+ )
97
+
98
+ # Pattern 4: drawing one item from a set
99
+ if any(w in lower for w in ["marble", "ball", "urn", "bag"]) and len(nums) >= 2:
100
+ if any(w in lower for w in ["red", "blue", "green", "white", "black"]):
101
+ total = sum(nums[:-1]) if "total" not in lower else nums[-1]
102
+ # conservative: if exactly 2 nums, assume favorable then total
103
+ if len(nums) == 2:
104
+ favorable, total = nums[0], nums[1]
105
+ else:
106
+ favorable = nums[0]
107
+ if total == 0:
108
+ total = sum(nums)
109
+ if total == 0:
110
+ return None
111
+ result = favorable / total
112
+ return SolverResult(
113
+ domain="quant",
114
+ solved=True,
115
+ topic="probability",
116
+ answer_value=f"{result:g}",
117
+ internal_answer=f"{result:g}",
118
+ steps=[
119
+ "Probability = number of favorable items ÷ total number of items.",
120
+ ],
121
+ )
122
+
123
+ # Pattern 5: combinations-based probability
124
+ # Example: choose 2 from 5 red and 3 blue, both red
125
+ m = re.search(
126
+ r"(\d+)\s+red.*?(\d+)\s+blue.*?choose\s+(\d+).*?both red",
127
+ lower,
128
+ )
129
+ if m:
130
+ red = int(m.group(1))
131
+ blue = int(m.group(2))
132
+ choose_n = int(m.group(3))
133
+ total = red + blue
134
+ if choose_n != 2 or total < 2 or red < 2:
135
+ return None
136
+ result = comb(red, 2) / comb(total, 2)
137
+ return SolverResult(
138
+ domain="quant",
139
+ solved=True,
140
+ topic="probability",
141
+ answer_value=f"{result:g}",
142
+ internal_answer=f"{result:g}",
143
+ steps=[
144
+ "Count favorable selections.",
145
+ "Count total possible selections.",
146
+ "Probability = favorable ÷ total.",
147
+ ],
148
+ )
149
+
150
+ # Pattern 6: at least / exactly from combinations
151
+ if "exactly" in lower and "probability" in lower and len(nums) >= 4:
152
+ # too ambiguous, skip unless explicit structure is added later
153
+ return None
154
+
155
+ return None