2828 "ErdosProblems" ,
2929)
3030
31- # Matches the category annotation line immediately before a main theorem.
32- # Captures the status word ("open" or "solved") and the problem number.
33- # The main theorem is `erdos_{N}` possibly followed by a suffix like `_statement`,
34- # but NOT containing a dot (which indicates a variant).
31+ # Matches the category annotation line immediately before any erdos theorem.
32+ # Captures the category, the problem number, and the full theorem name suffix.
33+ # Used to find all theorems for a given problem number.
3534CATEGORY_THEN_THEOREM = re .compile (
3635 r"@\[category research (open|solved|formally solved[^]]*),.*\]\s*\n"
37- r"theorem erdos_(\d+)\w*[\s:] " ,
36+ r"theorem erdos_(\d+)([\w.]*)\s " ,
3837 re .MULTILINE ,
3938)
4039
@@ -84,8 +83,18 @@ def lean_category(cat):
8483 return "solved"
8584
8685
86+ def is_variant (suffix ):
87+ """Check if a theorem name suffix indicates a variant (not a main part)."""
88+ return ".variants." in suffix
89+
90+
8791def scan_lean_files ():
88- """Return dict mapping problem number (str) -> 'open', 'solved', or 'formally solved'."""
92+ """Return dict mapping problem number (str) -> 'open', 'solved', or 'formally solved'.
93+
94+ For multi-part problems (no single `erdos_{N}` theorem), collects all
95+ non-variant theorems. The problem is 'open' if any part is open,
96+ 'formally solved' if all parts are formally solved, and 'solved' otherwise.
97+ """
8998 result = {}
9099 for fname in os .listdir (ERDOS_DIR ):
91100 if not fname .endswith (".lean" ):
@@ -96,11 +105,35 @@ def scan_lean_files():
96105 filepath = os .path .join (ERDOS_DIR , fname )
97106 with open (filepath ) as f :
98107 content = f .read ()
99- # Find the main theorem's category (first match for this problem number)
108+
109+ # Collect all non-variant theorem categories for this problem number
110+ main_categories = []
111+ has_exact_main = False
112+ exact_main_cat = None
100113 for m in CATEGORY_THEN_THEOREM .finditer (content ):
101- if m .group (2 ) == file_number :
102- result [file_number ] = lean_category (m .group (1 ))
103- break
114+ if m .group (2 ) != file_number :
115+ continue
116+ suffix = m .group (3 ) # e.g. "", "_cycles", ".parts.i", ".variants.foo"
117+ cat = lean_category (m .group (1 ))
118+ if suffix == "" or suffix == ":" :
119+ # Exact match: `erdos_{N}` with no suffix
120+ has_exact_main = True
121+ exact_main_cat = cat
122+ elif not is_variant (suffix ):
123+ main_categories .append (cat )
124+
125+ if has_exact_main :
126+ # Single main theorem exists — use its category directly
127+ result [file_number ] = exact_main_cat
128+ elif main_categories :
129+ # Multi-part problem: open if any part is open
130+ if "open" in main_categories :
131+ result [file_number ] = "open"
132+ elif all (c == "formally solved" for c in main_categories ):
133+ result [file_number ] = "formally solved"
134+ else :
135+ result [file_number ] = "solved"
136+
104137 return result
105138
106139
0 commit comments