Skip to content

Commit db1a9d3

Browse files
feat(seaborn): implement crossword-basic (#7452)
## Implementation: `crossword-basic` - python/seaborn Implements the **python/seaborn** version of `crossword-basic`. **File:** `plots/crossword-basic/implementations/python/seaborn.py` **Parent Issue:** #3805 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/26136486214)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 2c113b0 commit db1a9d3

2 files changed

Lines changed: 209 additions & 136 deletions

File tree

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,44 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
crossword-basic: Crossword Puzzle Grid
3-
Library: seaborn 0.13.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2026-01-15
3+
Library: seaborn 0.13.2 | Python 3.13.13
4+
Quality: 88/100 | Updated: 2026-05-20
55
"""
66

7+
import os
8+
79
import matplotlib.pyplot as plt
810
import numpy as np
911
import seaborn as sns
1012

1113

12-
# Set style
13-
sns.set_style("white")
14+
# Theme tokens
15+
THEME = os.getenv("ANYPLOT_THEME", "light")
16+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
17+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
18+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
19+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
20+
21+
sns.set_theme(
22+
style="ticks",
23+
rc={
24+
"figure.facecolor": PAGE_BG,
25+
"axes.facecolor": PAGE_BG,
26+
"axes.edgecolor": INK_SOFT,
27+
"axes.labelcolor": INK,
28+
"text.color": INK,
29+
"xtick.color": INK_SOFT,
30+
"ytick.color": INK_SOFT,
31+
"grid.color": INK,
32+
"grid.alpha": 0.10,
33+
"legend.facecolor": ELEVATED_BG,
34+
"legend.edgecolor": INK_SOFT,
35+
},
36+
)
1437

1538
# Data: 15x15 crossword grid with 180-degree rotational symmetry
16-
np.random.seed(42)
1739
grid_size = 15
18-
19-
# Create symmetric black cell pattern (1 = blocked, 0 = entry)
2040
grid = np.zeros((grid_size, grid_size), dtype=int)
2141

22-
# Define blocked cells for top half (will be mirrored for symmetry)
2342
blocked_positions = [
2443
(0, 4),
2544
(0, 10),
@@ -43,7 +62,6 @@
4362
(7, 7),
4463
]
4564

46-
# Apply blocked cells with 180-degree rotational symmetry
4765
for r, c in blocked_positions:
4866
grid[r, c] = 1
4967
grid[grid_size - 1 - r, grid_size - 1 - c] = 1
@@ -55,47 +73,45 @@
5573
for c in range(grid_size):
5674
if grid[r, c] == 1:
5775
continue
58-
# Check if starts across word (left edge or blocked cell to left, and has room)
5976
starts_across = (c == 0 or grid[r, c - 1] == 1) and (c < grid_size - 1 and grid[r, c + 1] == 0)
60-
# Check if starts down word (top edge or blocked cell above, and has room)
6177
starts_down = (r == 0 or grid[r - 1, c] == 1) and (r < grid_size - 1 and grid[r + 1, c] == 0)
62-
6378
if starts_across or starts_down:
6479
numbers[(r, c)] = clue_num
6580
clue_num += 1
6681

67-
# Plot using seaborn heatmap
68-
fig, ax = plt.subplots(figsize=(12, 12))
82+
# Cell colors: open cells are warm white, blocked cells near-black (data encoding)
83+
# Dark mode: use pure black for blocked cells so they contrast with #1A1A17 background
84+
cell_open = "#FFFFFF" if THEME == "light" else "#FAF8F1"
85+
cell_blocked = "#1A1A17" if THEME == "light" else "#000000"
86+
NUMBER_INK = "#1A1A17"
6987

70-
# Create color map: 0 (white cells) = white, 1 (blocked) = black
71-
cmap = sns.color_palette(["white", "#1a1a1a"])
88+
# Plot
89+
fig, ax = plt.subplots(figsize=(6, 6), dpi=400, facecolor=PAGE_BG)
7290

73-
# Plot heatmap without annotations
91+
cmap = sns.color_palette([cell_open, cell_blocked])
7492
sns.heatmap(
7593
grid,
7694
ax=ax,
7795
cmap=cmap,
7896
cbar=False,
7997
square=True,
80-
linewidths=2,
81-
linecolor="#306998",
98+
linewidths=1.0,
99+
linecolor=INK_SOFT,
82100
xticklabels=False,
83101
yticklabels=False,
84102
)
85103

86-
# Add clue numbers to appropriate cells
104+
# Add clue numbers to top-left corner of numbered cells
87105
for (r, c), num in numbers.items():
88-
# Position numbers in top-left corner of cell
89-
ax.text(c + 0.15, r + 0.25, str(num), fontsize=11, fontweight="bold", color="#306998", ha="left", va="top")
106+
ax.text(c + 0.12, r + 0.28, str(num), fontsize=9, fontweight="bold", color=NUMBER_INK, ha="left", va="top")
90107

91108
# Style
92-
ax.set_title("crossword-basic · seaborn · pyplots.ai", fontsize=24, fontweight="bold", pad=20)
109+
ax.set_title("crossword-basic · python · seaborn · anyplot.ai", fontsize=12, fontweight="medium", color=INK, pad=14)
93110

94-
# Remove axis spines and add outer border
95111
for spine in ax.spines.values():
96112
spine.set_visible(True)
97-
spine.set_color("#306998")
98-
spine.set_linewidth(3)
113+
spine.set_color(INK_SOFT)
114+
spine.set_linewidth(1.5)
99115

100116
plt.tight_layout()
101-
plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor="white")
117+
plt.savefig(f"plot-{THEME}.png", dpi=400, bbox_inches="tight", facecolor=PAGE_BG)

0 commit comments

Comments
 (0)