Skip to content

Commit cee85ee

Browse files
committed
Initial prototype
1 parent f6ce32c commit cee85ee

7 files changed

Lines changed: 186 additions & 0 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Contributing
2+
3+
Thanks for helping improve the table!
4+
5+
## Quickstart (editing via GitHub UI)
6+
7+
1. Open `data/problems.yaml`.
8+
2. Click **Edit** and add an entry. Use the template below.
9+
3. Run checks locally if you can (`scripts/validate.py`), or rely on CI.
10+
4. Open a Pull Request. CI will validate the format and the README freshness.
11+
12+
### Entry template
13+
14+
```yaml
15+
- id: "kissing-number-3d" # lowercase, hyphens
16+
name: "Kissing Number in 3D"
17+
area: "Discrete geometry"
18+
status:
19+
state: "solved"
20+
last_update: "2025-08-31"
21+
note: "24 spheres; solved historically by Schütte–van der Waerden."
22+
statements:
23+
short: "Max number of unit spheres tangent to a given one in ℝ^3."
24+
references:
25+
oeis: []
26+
urls:
27+
- "https://en.wikipedia.org/wiki/Kissing_number_problem"
28+
tags: ["sphere packing", "geometry"]

‎README.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,24 @@
11
# erdosproblems
22
A community database for the problems on the erdosproblems.com site
3+
4+
**Canonical data:** `data/problems.yaml` (YAML)
5+
**Rendered view:** table below (auto-generated)
6+
7+
- To propose changes, open a PR editing `data/problems.yaml`.
8+
- See **CONTRIBUTING.md** for guidelines and field definitions.
9+
10+
## Table
11+
12+
<!-- TABLE:START -->
13+
| ID | Prize | Status | OEIS | Tags |
14+
|---|---|---|---|---|
15+
| [1](https://www.erdosproblems.com/1) | $500 | open | [A276661](https://oeis.org/A276661) | number theory, additive combinatorics |
16+
| [2](https://www.erdosproblems.com/2) | — | solved | N/A | number theory, covering systems |
17+
<!-- TABLE:END -->
18+
19+
---
20+
21+
### Notes
22+
23+
- **Status** values: `open`, `solved`, `partial`, `retired`.
24+
- OEIS codes must look like `A123456` and will auto-link.

‎data/problems.yaml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
- number: "1"
2+
prize: "$500"
3+
status:
4+
state: "open" # open | solved | partial | retired
5+
last_update: "2025-08-31"
6+
oeis: ["A276661"]
7+
tags: ["number theory", "additive combinatorics"]
8+
9+
- number: "2"
10+
status:
11+
state: "solved"
12+
last_update: "2025-08-31"
13+
oeis: ["N/A"]
14+
tags: ["number theory", "covering systems"]

‎requirements.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
PyYAML==6.0.2
2+
jsonschema==4.23.0

‎schema/problems.schema.json‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"title": "Erdos problems table",
4+
"type": "array",
5+
"items": {
6+
"type": "object",
7+
"required": ["number", "status"],
8+
"properties": {
9+
"number": { "type": "string", "pattern": "^[0-9\\-]+$" },
10+
"prize": { "type": "string" },
11+
"status": {
12+
"type": "object",
13+
"required": ["state"],
14+
"properties": {
15+
"state": { "type": "string", "enum": ["open", "solved", "partial", "retired"] },
16+
"last_update": { "type": "string", "format": "date" },
17+
"note": { "type": "string" }
18+
}
19+
},
20+
"oeis": {
21+
"type": "array",
22+
"items": { "type": "string" }
23+
},
24+
"tags": {
25+
"type": "array",
26+
"items": { "type": "string" },
27+
"uniqueItems": true
28+
}
29+
},
30+
"additionalProperties": false
31+
},
32+
"uniqueItems": true
33+
}

‎scripts/generate_readme.py‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from pathlib import Path
2+
import re
3+
import yaml
4+
5+
ROOT = Path(__file__).resolve().parents[1]
6+
data_path = ROOT / "data" / "problems.yaml"
7+
readme_path = ROOT / "README.md"
8+
9+
START = "<!-- TABLE:START -->"
10+
END = "<!-- TABLE:END -->"
11+
12+
def num_link(num):
13+
return f"[{num}](https://www.erdosproblems.com/{num})"
14+
15+
def md_link(text, url):
16+
return f"[{text}]({url})"
17+
18+
def oeis_link(code: str) -> str:
19+
# only link if it's a genuine OEIS identifier like "A123456"
20+
if re.fullmatch(r"A\d{6}", code):
21+
return f"[{code}](https://oeis.org/{code})"
22+
else:
23+
return code # e.g. "N/A" or any other placeholder
24+
25+
def build_table(rows):
26+
header = "| ID | Prize | Status | OEIS | Tags |\n|---|---|---|---|---|"
27+
lines = [header]
28+
for r in rows:
29+
oeis = ", ".join(oeis_link(s) for s in r.get("oeis", [])) or "—"
30+
tags = ", ".join(s for s in r.get("tags", [])) or "—"
31+
status = r["status"]["state"]
32+
rid = num_link(r["number"])
33+
prize = r.get("prize", "—")
34+
lines.append(f"| {rid} | {prize} | {status} | {oeis} | {tags} |")
35+
return "\n".join(lines)
36+
37+
def insert_between_markers(content, payload):
38+
pattern = re.compile(
39+
rf"({re.escape(START)})(.*)({re.escape(END)})",
40+
flags=re.DOTALL
41+
)
42+
repl = rf"\1\n{payload}\n\3"
43+
return re.sub(pattern, repl, content)
44+
45+
rows = yaml.safe_load(data_path.read_text(encoding="utf-8"))
46+
rows = sorted(rows, key=lambda r: r["number"].lower())
47+
table_md = build_table(rows)
48+
49+
readme = readme_path.read_text(encoding="utf-8")
50+
new_readme = insert_between_markers(readme, table_md)
51+
if new_readme != readme:
52+
readme_path.write_text(new_readme, encoding="utf-8")
53+
print("README updated.")
54+
else:
55+
print("README already up-to-date.")

‎scripts/validate.py‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import sys, json
2+
from pathlib import Path
3+
4+
import yaml
5+
from jsonschema import validate, Draft202012Validator
6+
7+
ROOT = Path(__file__).resolve().parents[1]
8+
data_path = ROOT / "data" / "problems.yaml"
9+
schema_path = ROOT / "schema" / "problems.schema.json"
10+
11+
data = yaml.safe_load(data_path.read_text(encoding="utf-8"))
12+
schema = json.loads(schema_path.read_text(encoding="utf-8"))
13+
14+
# Schema validation
15+
v = Draft202012Validator(schema)
16+
errors = sorted(v.iter_errors(data), key=lambda e: e.path)
17+
if errors:
18+
for e in errors:
19+
loc = "/".join([str(p) for p in e.path])
20+
print(f"[schema] {loc}: {e.message}")
21+
sys.exit(1)
22+
23+
# Extra: ensure unique IDs
24+
ids = set()
25+
for row in data:
26+
i = row["number"]
27+
if i in ids:
28+
print(f"[data] duplicate id: {i}")
29+
sys.exit(1)
30+
ids.add(i)
31+
32+
print("Validation OK.")

0 commit comments

Comments
 (0)