{"spec_id":"sudoku-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' sudoku-basic: Basic Sudoku Grid\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 88/100 | Created: 2026-06-25\n\nlibrary(ggplot2)\nlibrary(ragg)\n\n# Theme tokens\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\n\n# Sudoku puzzle data (0 = empty cell, classic starter puzzle)\npuzzle <- matrix(c(\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), nrow = 9, ncol = 9, byrow = TRUE)\n\n# Build cell data frame: col (1=left to 9=right), y flipped so row 1 is at top\ncells       <- expand.grid(col = 1:9, row = 1:9)\ncells$value <- as.vector(t(puzzle))\ncells$label <- ifelse(cells$value == 0L, \"\", as.character(cells$value))\ncells$y     <- 10L - cells$row\nfilled      <- cells[cells$label != \"\", ]\n\n# Grid line positions\nall_pos <- seq(0.5, 9.5, by = 1)       # all 10 boundary positions (thin lines)\nbox_pos <- c(0.5, 3.5, 6.5, 9.5)       # 3x3 box boundary positions (thick lines)\n\nthin_v  <- data.frame(x = all_pos, xend = all_pos, y = 0.5,     yend = 9.5)\nthin_h  <- data.frame(x = 0.5,    xend = 9.5,      y = all_pos, yend = all_pos)\nthick_v <- data.frame(x = box_pos, xend = box_pos,  y = 0.5,    yend = 9.5)\nthick_h <- data.frame(x = 0.5,    xend = 9.5,       y = box_pos, yend = box_pos)\n\nplot_title <- \"sudoku-basic · r · ggplot2 · anyplot.ai\"\n\np <- ggplot() +\n  # Grid background fill\n  annotate(\"rect\",\n           xmin = 0.5, xmax = 9.5, ymin = 0.5, ymax = 9.5,\n           fill = PAGE_BG, color = NA) +\n  # Thin individual cell lines\n  geom_segment(data = thin_v,\n               aes(x = x, xend = xend, y = y, yend = yend),\n               color = INK_SOFT, linewidth = 0.25) +\n  geom_segment(data = thin_h,\n               aes(x = x, xend = xend, y = y, yend = yend),\n               color = INK_SOFT, linewidth = 0.25) +\n  # Thick 3x3 box boundary lines drawn on top\n  geom_segment(data = thick_v,\n               aes(x = x, xend = xend, y = y, yend = yend),\n               color = INK, linewidth = 1.5) +\n  geom_segment(data = thick_h,\n               aes(x = x, xend = xend, y = y, yend = yend),\n               color = INK, linewidth = 1.5) +\n  # Puzzle numbers centered in each cell\n  geom_text(data = filled,\n            aes(x = col, y = y, label = label),\n            color = INK, size = 8, fontface = \"bold\") +\n  # 1:1 aspect ratio, exact bounds, no expansion padding\n  coord_fixed(ratio = 1, xlim = c(0.5, 9.5), ylim = c(0.5, 9.5), expand = FALSE) +\n  labs(title = plot_title) +\n  theme_void() +\n  theme(\n    plot.background  = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background = element_rect(fill = PAGE_BG, color = NA),\n    plot.title = element_text(\n      color = INK, size = 12, hjust = 0.5, face = \"bold\",\n      margin = margin(t = 15, b = 15)\n    ),\n    plot.margin = margin(20, 40, 20, 40)\n  )\n\n# Save — square canvas: 6x6 in at 400 dpi = 2400x2400 px\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 6,\n  height   = 6,\n  units    = \"in\",\n  dpi      = 400\n)\n"}