Skip to content

Commit ffdcbe0

Browse files
feat(plotnine): implement sudoku-basic (#5350)
## Implementation: `sudoku-basic` - python/plotnine Implements the **python/plotnine** version of `sudoku-basic`. **File:** `plots/sudoku-basic/implementations/python/plotnine.py` **Parent Issue:** #1311 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24882013321)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 7ff5dff commit ffdcbe0

2 files changed

Lines changed: 188 additions & 158 deletions

File tree

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
sudoku-basic: Basic Sudoku Grid
3-
Library: plotnine 0.15.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: plotnine 0.15.3 | Python 3.14.4
4+
Quality: 89/100 | Updated: 2026-04-24
55
"""
66

7+
import os
8+
79
import pandas as pd
810
from plotnine import (
911
aes,
1012
coord_fixed,
11-
element_blank,
13+
element_rect,
1214
element_text,
1315
geom_segment,
1416
geom_text,
@@ -20,6 +22,13 @@
2022
)
2123

2224

25+
# Theme tokens
26+
THEME = os.getenv("ANYPLOT_THEME", "light")
27+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
28+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
29+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
30+
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
31+
2332
# Data - A valid partially filled Sudoku puzzle
2433
grid = [
2534
[5, 3, 0, 0, 7, 0, 0, 0, 0],
@@ -33,67 +42,52 @@
3342
[0, 0, 0, 0, 8, 0, 0, 7, 9],
3443
]
3544

36-
# Convert grid to DataFrame for plotnine
45+
# Build cell number DataFrame
3746
cells = []
3847
for row in range(9):
3948
for col in range(9):
4049
value = grid[row][col]
41-
cells.append(
42-
{
43-
"x": col + 0.5,
44-
"y": 8.5 - row, # Flip y to have row 0 at top
45-
"value": str(value) if value != 0 else "",
46-
}
47-
)
50+
cells.append({"x": col + 0.5, "y": 8.5 - row, "value": str(value) if value != 0 else ""})
4851
df_cells = pd.DataFrame(cells)
4952

50-
# Create thin grid lines (all cell boundaries)
53+
# Thin grid lines (internal cell boundaries, skipping the 3x3 box positions)
5154
thin_lines = []
52-
for i in range(10):
53-
# Skip positions where thick lines will be drawn
55+
for i in range(1, 9):
5456
if i % 3 != 0:
55-
# Vertical lines
5657
thin_lines.append({"x": i, "xend": i, "y": 0, "yend": 9})
57-
# Horizontal lines
5858
thin_lines.append({"x": 0, "xend": 9, "y": i, "yend": i})
5959
df_thin = pd.DataFrame(thin_lines)
6060

61-
# Create thick grid lines (3x3 box boundaries)
61+
# Thick grid lines (3x3 box boundaries and outer border)
6262
thick_lines = []
6363
for i in [0, 3, 6, 9]:
64-
# Vertical lines
6564
thick_lines.append({"x": i, "xend": i, "y": 0, "yend": 9})
66-
# Horizontal lines
6765
thick_lines.append({"x": 0, "xend": 9, "y": i, "yend": i})
6866
df_thick = pd.DataFrame(thick_lines)
6967

70-
# Create tile data for cell backgrounds
71-
df_tiles = pd.DataFrame([{"x": col + 0.5, "y": row + 0.5, "fill": "white"} for row in range(9) for col in range(9)])
68+
# Cell background tiles (ensures panel fill matches theme uniformly across cells)
69+
df_tiles = pd.DataFrame([{"x": col + 0.5, "y": row + 0.5} for row in range(9) for col in range(9)])
7270

73-
# Build the plot
71+
# Plot
7472
plot = (
7573
ggplot()
76-
# Cell backgrounds
77-
+ geom_tile(data=df_tiles, mapping=aes(x="x", y="y"), fill="white", color="none", width=1, height=1)
78-
# Thin grid lines
79-
+ geom_segment(data=df_thin, mapping=aes(x="x", y="y", xend="xend", yend="yend"), color="#888888", size=0.5)
80-
# Thick grid lines for 3x3 boxes
81-
+ geom_segment(data=df_thick, mapping=aes(x="x", y="y", xend="xend", yend="yend"), color="black", size=2)
82-
# Numbers in cells
83-
+ geom_text(data=df_cells, mapping=aes(x="x", y="y", label="value"), size=28, color="black", fontweight="bold")
84-
# Title
85-
+ labs(title="sudoku-basic · plotnine · pyplots.ai")
86-
# Fixed aspect ratio
87-
+ coord_fixed(ratio=1, xlim=(0, 9), ylim=(0, 9))
88-
# Clean theme
74+
+ geom_tile(data=df_tiles, mapping=aes(x="x", y="y"), fill=PAGE_BG, color="none", width=1, height=1)
75+
+ geom_segment(
76+
data=df_thin, mapping=aes(x="x", y="y", xend="xend", yend="yend"), color=INK_MUTED, size=0.6, alpha=0.55
77+
)
78+
+ geom_segment(data=df_thick, mapping=aes(x="x", y="y", xend="xend", yend="yend"), color=INK, size=2.4)
79+
+ geom_text(data=df_cells, mapping=aes(x="x", y="y", label="value"), size=30, color=INK, fontweight="bold")
80+
+ labs(title="sudoku-basic · plotnine · anyplot.ai")
81+
+ coord_fixed(ratio=1, xlim=(-0.05, 9.05), ylim=(-0.05, 9.05))
8982
+ theme_void()
9083
+ theme(
91-
figure_size=(12, 12),
92-
plot_title=element_text(size=24, ha="center", weight="bold", margin={"b": 20}),
93-
plot_background=element_blank(),
94-
panel_background=element_blank(),
84+
figure_size=(14, 14),
85+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
86+
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
87+
plot_title=element_text(size=26, ha="center", weight="bold", color=INK, margin={"b": 24}),
88+
plot_margin=0.04,
9589
)
9690
)
9791

9892
# Save
99-
plot.save("plot.png", dpi=300, width=12, height=12, verbose=False)
93+
plot.save(f"plot-{THEME}.png", dpi=300, width=14, height=14, verbose=False)

0 commit comments

Comments
 (0)