{"spec_id":"sudoku-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nsudoku-basic: Basic Sudoku Grid\nLibrary: letsplot 4.10.1 | Python 3.13.14\nQuality: 88/100 | Updated: 2026-06-25\n\"\"\"\n\nimport os\n\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    coord_fixed,\n    element_blank,\n    element_rect,\n    element_text,\n    geom_segment,\n    geom_text,\n    geom_tile,\n    ggplot,\n    ggsave,\n    ggsize,\n    labs,\n    layer_tooltips,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_void,\n)\n\n\nLetsPlot.setup_html()\n\n# Imprint palette theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Classic Sudoku puzzle (0 = empty cell)\ngrid = [\n    [5, 3, 0, 0, 7, 0, 0, 0, 0],\n    [6, 0, 0, 1, 9, 5, 0, 0, 0],\n    [0, 9, 8, 0, 0, 0, 0, 6, 0],\n    [8, 0, 0, 0, 6, 0, 0, 0, 3],\n    [4, 0, 0, 8, 0, 3, 0, 0, 1],\n    [7, 0, 0, 0, 2, 0, 0, 0, 6],\n    [0, 6, 0, 0, 0, 0, 2, 8, 0],\n    [0, 0, 0, 4, 1, 9, 0, 0, 5],\n    [0, 0, 0, 0, 8, 0, 0, 7, 9],\n]\n\n# Build cell data with position metadata for tooltips\nxs, ys, labels, row_nums, col_nums, box_nums, statuses = [], [], [], [], [], [], []\nfor row in range(9):\n    for col in range(9):\n        val = grid[row][col]\n        xs.append(col + 0.5)\n        ys.append(8 - row + 0.5)\n        labels.append(str(val) if val != 0 else \"\")\n        row_nums.append(row + 1)\n        col_nums.append(col + 1)\n        box_nums.append((row // 3) * 3 + (col // 3) + 1)\n        statuses.append(\"given\" if val != 0 else \"empty\")\n\ncells = {\"x\": xs, \"y\": ys, \"label\": labels, \"row\": row_nums, \"col\": col_nums, \"box\": box_nums, \"status\": statuses}\n\n# Thin grid lines (cell boundaries, skipping 3x3 box positions)\nthin_x, thin_y, thin_xend, thin_yend = [], [], [], []\nfor i in range(10):\n    if i % 3 != 0:\n        thin_x.append(i)\n        thin_y.append(0)\n        thin_xend.append(i)\n        thin_yend.append(9)\n        thin_x.append(0)\n        thin_y.append(i)\n        thin_xend.append(9)\n        thin_yend.append(i)\nthin_lines = {\"x\": thin_x, \"y\": thin_y, \"xend\": thin_xend, \"yend\": thin_yend}\n\n# Thick grid lines (3x3 box boundaries)\nthick_x, thick_y, thick_xend, thick_yend = [], [], [], []\nfor i in (0, 3, 6, 9):\n    thick_x.append(i)\n    thick_y.append(0)\n    thick_xend.append(i)\n    thick_yend.append(9)\n    thick_x.append(0)\n    thick_y.append(i)\n    thick_xend.append(9)\n    thick_yend.append(i)\nthick_lines = {\"x\": thick_x, \"y\": thick_y, \"xend\": thick_xend, \"yend\": thick_yend}\n\n# Tooltips: show cell position and box number on hover (HTML interactivity)\ncell_tooltips = layer_tooltips().line(\"Row @row, Col @col\").line(\"Box @box\").line(\"@status\")\n\nplot = (\n    ggplot()\n    + geom_tile(aes(x=\"x\", y=\"y\"), data=cells, fill=PAGE_BG, color=PAGE_BG, width=1, height=1, tooltips=cell_tooltips)\n    + geom_segment(aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"), data=thin_lines, color=INK_SOFT, size=0.4)\n    + geom_segment(aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"), data=thick_lines, color=INK, size=2.0)\n    + geom_text(aes(x=\"x\", y=\"y\", label=\"label\"), data=cells, size=9, color=INK, fontface=\"bold\")\n    + coord_fixed(ratio=1)\n    + scale_x_continuous(limits=[-0.1, 9.1], expand=[0, 0])\n    + scale_y_continuous(limits=[-0.1, 9.1], expand=[0, 0])\n    + labs(title=\"sudoku-basic · python · letsplot · anyplot.ai\")\n    + theme_void()\n    + theme(\n        plot_title=element_text(size=16, color=INK, hjust=0.5, face=\"bold\"),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        axis_title=element_blank(),\n        axis_text=element_blank(),\n        axis_ticks=element_blank(),\n        plot_margin=[40, 40, 40, 40],\n    )\n    + ggsize(600, 600)\n)\n\n# Save — scale=4 yields 2400×2400 px (canonical square canvas)\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=4)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}