File size: 2,987 Bytes
f55fed4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import re
from typing import Optional


BOTANICAL_VEGETABLES = {
    "asparagus",
    "beet",
    "beets",
    "broccoli",
    "cabbage",
    "carrot",
    "carrots",
    "cauliflower",
    "celery",
    "fresh basil",
    "lettuce",
    "onion",
    "onions",
    "potato",
    "potatoes",
    "spinach",
    "sweet potato",
    "sweet potatoes",
}


def _normalized(text: str) -> str:
    return re.sub(r"\s+", " ", text or "").strip()


def _solve_reversed_instruction(question: str) -> Optional[str]:
    reversed_question = question[::-1].lower()
    if "opposite of the word" in reversed_question and "left" in reversed_question:
        return "Right"
    return None


def _parse_markdown_table(question: str) -> tuple[list[str], list[list[str]]]:
    rows = []
    for raw_line in question.splitlines():
        line = raw_line.strip()
        if not line.startswith("|") or not line.endswith("|"):
            continue
        cells = [cell.strip() for cell in line.strip("|").split("|")]
        if all(set(cell) <= {"-"} for cell in cells if cell):
            continue
        rows.append(cells)

    if len(rows) < 2:
        return [], []

    headers = rows[0][1:]
    body = rows[1:]
    return headers, body


def _solve_noncommutative_elements(question: str) -> Optional[str]:
    q = question.lower()
    if "commutative" not in q or "|" not in question:
        return None

    headers, body = _parse_markdown_table(question)
    if not headers or not body:
        return None

    table = {}
    for row in body:
        if len(row) < len(headers) + 1:
            continue
        row_key = row[0]
        table[row_key] = dict(zip(headers, row[1: len(headers) + 1]))

    involved = set()
    for left in headers:
        for right in headers:
            left_result = table.get(left, {}).get(right)
            right_result = table.get(right, {}).get(left)
            if left_result is not None and right_result is not None and left_result != right_result:
                involved.add(left)
                involved.add(right)

    if not involved:
        return None

    return ", ".join(sorted(involved))


def _solve_botanical_vegetables(question: str) -> Optional[str]:
    q = question.lower()
    if "vegetable" not in q or "alphabetize" not in q:
        return None

    candidates = []
    after_colon = question.split(":")[-1]
    for item in re.split(r",|\n|;", after_colon):
        item = item.strip().strip(".").lower()
        if item in BOTANICAL_VEGETABLES:
            candidates.append(item)

    if not candidates:
        return None

    return ", ".join(sorted(dict.fromkeys(candidates)))


def try_programmatic_answer(question: str) -> Optional[str]:
    question = question or ""

    for solver in (
        _solve_reversed_instruction,
        _solve_noncommutative_elements,
        _solve_botanical_vegetables,
    ):
        answer = solver(question)
        if answer is not None:
            return answer

    return None