# Simple MATH answer grader used identically for every arm (last \boxed{}, string normalization, then exact SymPy check of simple numbers). import re def last_boxed(t): i = t.rfind('\\boxed') if i < 0: i = t.rfind('\\fbox') if i < 0: return None j = t.find('{', i) if j < 0: return None d = 0 for k in range(j, len(t)): if t[k] == '{': d += 1 elif t[k] == '}': d -= 1 if d == 0: return t[j+1:k] return None def norm(s): if s is None: return None s = s.strip() s = re.sub(r'\\text\{\s*([^{}]*)\}', r'\1', s) for a, b in [('\\left', ''), ('\\right', ''), ('\\!', ''), ('\\,', ''), ('\\;', ''), ('\\ ', ''), ('dfrac', 'frac'), ('tfrac', 'frac'), ('^\\circ', ''), ('^{\\circ}', ''), ('\\%', ''), ('%', ''), ('\\$', ''), ('$', ''), ('\\displaystyle', '')]: s = s.replace(a, b) s = re.sub(r'\s+', '', s).rstrip('.') s = re.sub(r'^[a-z]=', '', s) s = re.sub(r'\\frac(\d)(\d)', r'\\frac{\1}{\2}', s) s = re.sub(r'\\sqrt(\d)', r'\\sqrt{\1}', s) if re.fullmatch(r'-?\d{1,3}(,\d{3})+', s): s = s.replace(',', '') s = re.sub(r'(\d)\.0+$', r'\1', s) return s def num(s): m = re.fullmatch(r'(-?)\\frac\{(-?\d+)\}\{(\d+)\}', s) if m: return (-1 if m.group(1) else 1) * int(m.group(2)) / int(m.group(3)) try: return float(s) except: return None def correct(text, gold): p, g = norm(last_boxed(text)), norm(gold) if p is None: return False if p == g: return True a, b = num(p), num(g) return a is not None and b is not None and abs(a - b) < 1e-9