Skip to content

Commit ae28fe0

Browse files
committed
sudoku: casual explainer added
1 parent 624fba6 commit ae28fe0

File tree

1 file changed

+103
-15
lines changed

1 file changed

+103
-15
lines changed

projects/sudoku/main.py

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import random
1212
from pathlib import Path
1313
from datetime import datetime
14-
from typing import List, Union
14+
from typing import List, Union, Callable
1515

1616
## Installed package imports
1717
import requests
@@ -44,12 +44,77 @@
4444
DEFAULT_FONT = "standard"
4545

4646

47+
def generate_problem_casual(problem_markdown: str) -> str:
48+
if OPENAI_API_KEY == "":
49+
print("[*] OpenAI API Key not found. Exiting ...")
50+
return ""
51+
52+
prompt = f"""
53+
You are a friendly storyteller and teacher, explaining competitive programming problems in a simple, relaxing way —
54+
something light enough for a reader to enjoy before bed when their brain is only at 10-20% power.
55+
56+
Given the following Codeforces problem statement (in markdown format), produce a casual explanation that feels
57+
like a conversation, not a lecture. Your response should be written in **plain markdown** with a soft, easy-to-read style.
58+
59+
Please include:
60+
61+
---
62+
63+
## 1. Gentle Storytelling Summary
64+
- Retell the problem in very simple words, like explaining to a friend.
65+
- Use small metaphors or analogies if it helps (e.g., “Imagine you’re sorting candies”).
66+
- Avoid heavy math terms unless absolutely necessary.
67+
68+
## 2. The Core Idea
69+
- What is the problem *really* asking for?
70+
- Describe it in everyday terms, focusing on the main trick or decision.
71+
72+
## 3. How You Might Think About Solving It
73+
- Give a casual sketch of how one might approach it, without going too deep into technical jargon.
74+
- Mention the key observation in plain English.
75+
- Include one or two “good to know” hints, but keep it lightweight.
76+
77+
## 4. A Cozy Closing Thought
78+
- End with a friendly note: encouragement, a fun analogy, or how this problem connects to daily life.
79+
- The tone should feel relaxing and supportive.
80+
81+
---
82+
83+
### Problem Statement:
84+
85+
{problem_markdown}
86+
87+
---
88+
89+
Formatting rules:
90+
- Do not use technical section headers like "algorithms", "system design", etc.
91+
- Keep it warm, casual, and low-pressure.
92+
- Avoid overwhelming lists or references.
93+
- Imagine the reader is tired but curious, and just wants to end the day with a little mental puzzle explained gently.
94+
"""
95+
96+
response = client.chat.completions.create(
97+
model="gpt-4o-mini",
98+
messages=[
99+
{
100+
"role": "system",
101+
"content": "You are a friendly teacher and storyteller. Always keep things simple, warm, and casual, with a tone that makes the reader feel at ease.",
102+
},
103+
{"role": "user", "content": prompt},
104+
],
105+
temperature=0.7,
106+
max_tokens=2000,
107+
n=1,
108+
)
109+
110+
return response.choices[0].message.content.strip()
111+
112+
47113
def generate_problem_analysis(problem_markdown: str) -> str:
48114
if OPENAI_API_KEY == "":
49115
print("[*] OpenAI API Key not found. Exiting ...")
50116
return ""
51117

52-
print("[*] OpenAI API Key found.")
53118
prompt = f"""
54119
You are an expert competitive programming instructor and system architect with a talent for clear, insightful explanations.
55120
@@ -161,7 +226,10 @@ def example_algorithm(data):
161226
response = client.chat.completions.create(
162227
model="gpt-4o-mini",
163228
messages=[
164-
{"role": "system", "content": "You are an expert competitive programming instructor and system architect. Provide highly detailed, structured, research-style responses with actionable insights, references, and clear learning roadmaps."},
229+
{
230+
"role": "system",
231+
"content": "You are an expert competitive programming instructor and system architect. Provide highly detailed, structured, research-style responses with actionable insights, references, and clear learning roadmaps.",
232+
},
165233
{"role": "user", "content": prompt},
166234
],
167235
temperature=0.2,
@@ -239,6 +307,29 @@ def requests_get(url: str) -> requests.Response:
239307
return requests.get(url, verify=PROXY)
240308

241309

310+
def append_analysis(
311+
md_text: str,
312+
generator_fn: Callable[[str], str],
313+
label: str,
314+
) -> str:
315+
"""
316+
Apply a given analysis generator function (like generate_problem_analysis
317+
or generate_problem_casual), format the result, and append to md_text.
318+
"""
319+
generated = mdformat.text(generator_fn(md_text).strip()).replace("**", "__")
320+
321+
md_text = (
322+
f"{md_text}\n"
323+
"______________________________________________________________________\n\n"
324+
f"```markdown\n{get_art_formatted_text(label)}```\n\n"
325+
"______________________________________________________________________\n"
326+
f"\n{generated}\n"
327+
)
328+
329+
# fix strange unicode issues
330+
return md_text.replace(" ", " ").replace("’", "'").strip() + "\n"
331+
332+
242333
def get_art_formatted_text(text: str) -> str:
243334
result, _, _ = art.text2art(
244335
text,
@@ -341,21 +432,18 @@ def fetch_problem_statement(
341432
f"{extracted_samples}"
342433
)
343434
md_text = mdformat.text(md_text, options={"wrap": 80})
344-
art_formatted_text_for_title = get_art_formatted_text((title.split(".")[1]).replace(' ', ' '))
345-
md_text = f"# Problem\n\n```markdown\n{art_formatted_text_for_title}```\n\n" f"{md_text}"
346-
generated_problem_analysis = mdformat.text(
347-
generate_problem_analysis(md_text).strip()
348-
).replace("**", "__")
435+
art_formatted_text_for_title = get_art_formatted_text(
436+
(title.split(".")[1]).replace(" ", " ")
437+
)
349438
md_text = (
350-
f"{md_text}\n"
351-
"______________________________________________________________________\n\n"
352-
f"```markdown\n{get_art_formatted_text('OpenAI Analysis')}```\n\n"
353-
"______________________________________________________________________\n"
354-
f"\n{generated_problem_analysis}\n"
439+
f"# Problem\n\n```markdown\n{art_formatted_text_for_title}```\n\n" f"{md_text}"
355440
)
356441

357-
# strange unicode character in output -- skipping
358-
md_text = md_text.replace(' ', ' ').replace('’', '\'').strip() + "\n"
442+
for generator_fn, label in [
443+
(generate_problem_analysis, "OpenAI Analysis"),
444+
(generate_problem_casual, "Casual Analysis"),
445+
]:
446+
md_text = append_analysis(md_text, generator_fn, label)
359447

360448
# Save locally
361449
save_problem_markdown(problem_name, index, md_text, problem_rating, contest_id)

0 commit comments

Comments
 (0)