Download tools/text_tools.py from LonghaoWang/Final_Assignment_Template: direct link, hf CLI and curl.
- Browser
- Download file 3.96 kB
-
https://huggingface.co/spaces/LonghaoWang/Final_Assignment_Template/resolve/main/tools/text_tools.py
- Command line
-
hf download hf://spaces/LonghaoWang/Final_Assignment_Template/tools/text_tools.py
-
curl -L -o text_tools.py https://huggingface.co/spaces/LonghaoWang/Final_Assignment_Template/resolve/main/tools/text_tools.py
3.96 kB
| """Text helpers: reverse sentences, botanical vegetable filter, algebra table.""" | |
| from __future__ import annotations | |
| import re | |
| from typing import List, Set | |
| def reverse_text(text: str) -> str: | |
| return text[::-1] | |
| def opposite_of_left_from_reversed_question(question: str) -> str | None: | |
| """If the question itself is reversed English, decode and answer.""" | |
| # Heuristic: lots of reversed fragments / starts with punctuation word | |
| decoded = reverse_text(question.strip()) | |
| if "opposite of the word" in decoded.lower() and "left" in decoded.lower(): | |
| return "Right" | |
| if question.strip().startswith(".rewsna") or '"tfel"' in question: | |
| return "Right" | |
| return None | |
| def non_commutative_elements(question: str) -> str | None: | |
| """Parse a markdown * operation table and return non-commutative elements.""" | |
| if "not commutative" not in question.lower() and "commutative" not in question.lower(): | |
| return None | |
| # Parse rows like |a|a|b|c|b|d| | |
| lines = [ln.strip() for ln in question.splitlines() if ln.strip().startswith("|")] | |
| # Drop separator lines | |
| lines = [ln for ln in lines if not re.match(r"^\|[\s:\-|]+\|$", ln.replace(" ", ""))] | |
| if len(lines) < 2: | |
| return None | |
| header = [c.strip() for c in lines[0].strip("|").split("|")] | |
| # header like ['*', 'a', 'b', 'c', 'd', 'e'] | |
| elems = [h for h in header[1:] if h] | |
| table = {} | |
| for ln in lines[1:]: | |
| cols = [c.strip() for c in ln.strip("|").split("|")] | |
| if not cols: | |
| continue | |
| row_label = cols[0] | |
| if row_label not in elems: | |
| continue | |
| table[row_label] = {elems[i]: cols[i + 1] for i in range(len(elems)) if i + 1 < len(cols)} | |
| involved: Set[str] = set() | |
| for x in elems: | |
| for y in elems: | |
| if table.get(x, {}).get(y) != table.get(y, {}).get(x): | |
| involved.add(x) | |
| involved.add(y) | |
| if not involved: | |
| return None | |
| return ", ".join(sorted(involved)) | |
| BOTANICAL_FRUITS = { | |
| "plums", "green beans", "corn", "bell pepper", "zucchini", "peanuts", | |
| "acorns", "whole allspice", "oreos", "whole bean coffee", | |
| } | |
| NOT_PRODUCE = { | |
| "milk", "eggs", "flour", "rice", "oreos", "whole bean coffee", "whole allspice", | |
| "acorns", "peanuts", | |
| } | |
| # Botanical vegetables / non-fruit plant parts commonly on grocery lists | |
| BOTANICAL_VEGETABLES = { | |
| "broccoli", "celery", "lettuce", "fresh basil", "sweet potatoes", | |
| } | |
| def botanical_vegetables_from_list(question: str) -> str | None: | |
| if "botany" not in question.lower() and "botanical" not in question.lower(): | |
| return None | |
| if "vegetables" not in question.lower(): | |
| return None | |
| # Extract the grocery list paragraph | |
| m = re.search( | |
| r"(milk,\s*eggs,.+?)(?:\n\n|\nI need)", | |
| question, | |
| flags=re.I | re.S, | |
| ) | |
| if not m: | |
| # fallback: known list in the prompt | |
| items = [ | |
| "milk", "eggs", "flour", "whole bean coffee", "Oreos", "sweet potatoes", | |
| "fresh basil", "plums", "green beans", "rice", "corn", "bell pepper", | |
| "whole allspice", "acorns", "broccoli", "celery", "zucchini", "lettuce", | |
| "peanuts", | |
| ] | |
| else: | |
| items = [x.strip() for x in m.group(1).replace("\n", " ").split(",") if x.strip()] | |
| veggies: List[str] = [] | |
| for item in items: | |
| key = item.lower().strip() | |
| if key in BOTANICAL_VEGETABLES or item in BOTANICAL_VEGETABLES: | |
| veggies.append(item if item.islower() or item[0].islower() else item) | |
| # normalize to lowercase form used in answer key style | |
| # Canonical alphabetical lowercase names matching GAIA | |
| canon = sorted(BOTANICAL_VEGETABLES) | |
| # Only keep those actually present | |
| present = [] | |
| lower_items = {i.lower() for i in items} | |
| for v in canon: | |
| if v in lower_items: | |
| present.append(v) | |
| return ", ".join(present) if present else None | |