Pangram verdict · v3.3
We believe that this text is a mix of AI and human-written content.
AI likelihood · overall
MixedArticle text · 1,190 words · 11 segments analyzed
Zen sand gardens are often intended for meditation, whether to look at or while maintaining it by raking the sand into the prescribed patterns which are formed by the tines of the rake yielding parallel lines (like |||). Such a chore might be tedious, but there is also a great deal of satisfaction to restoring an esthetic order from chaos, and raking sand seems like one of those things, like popping bubblewrap, which can be oddly satisfying—I recall the lifeguards at my summer camp seeming to rather enjoy the task of raking the beach in front of their office every day and not allowing any campers to do so. Puzzle-solving is also often described as being ‘meditative’ and ‘oddly satisfying’, even when it looks a lot like a tedious chore. So for those of us who do not live at a Zen temple, can we make a Zen sand garden puzzle?This page turns the original 2023 sketch into a full design.
Where the sketch speculated (would “mirror raking” be too restrictive? could a neural net rank solutions by beauty? how should difficulty be raised?), we answer with a solver and measurements; where it left gaps (what exactly makes a garden hard, what the worlds are, how levels are generated, what the player touches), we fill them. The title is Samon (砂紋, “sand crest”), the term for the patterns themselves.1Appendix: Code and Data Every file behind this page: the solvers, the experiments, the level generator, the prototype's source and its tests, this edition's build script and test, the poems, and the data they wrote. The code, the logs and the poems are shown below; the data, the figures' sources and the campaign cache are listed, and everything is in the download.
Download all 223 files as one .zip (1.8 MB; SHA-256 b60754f3fba988794a433d5d8c43cdf4a3160a07b05de806d7b1a664828b74d4).
Start with src/zgsolve.c (exact search), src/zg.py (the rules, the solver driver and a brute-force checker), src/zcp.py (CP-SAT par proofs), src/grader.py (the deductive grader), and src/verify_doc.py, which re-derives every number in the document. The build and test commands are in the guide below. Not included: this page itself and the prototype's two pages, which standalone/build_standalone.py and proto/build.py write.
Code behind the numbers and figures in the Samon design document (2026-10-03, revised 2026-10-04), and the playable prototype.
The single-file edition of the document carries this whole tree in its appendix: the code is shown there, and every file is in the .zip it offers (all but the three generated pages, which the build scripts write).
Build cd src && gcc -O3 -march=native -Wall -Wextra -o zgsolve zgsolve.c pip install ortools cairosvg playwright # CP-SAT optimiser; SVG→PNG for figures; browser test of the prototype playwright install chromium pip install beautifulsoup4 # (and pandoc) for the single-file edition # ffmpeg with libmp3lame, for sound/make_sound_bundle.py (the recordings; see sound/README.md) Paths: the scripts use absolute paths under /home/claude/zen/ (the directory this tree was developed in).
To run from wherever this tree is unpacked, rewrite them once, from the top of the tree: grep --recursive --files-with-matches --exclude=README.md /home/claude/zen . | xargs sed --in-place "s|/home/claude/zen|$PWD|g" Files src/zgsolve.c: exact DFS solver (counts/enumerates rakings; turn & U-turn histograms; branch-and-bound min turns). Rules: one stroke ending at the gate; optional ripple rings, wave bands / ichimatsu, given grooves, pebbles (shape: S = straight through, B = turn), no-U-turn (nohairpin 1), wide rake (nohairpin 2 + endcells), fixed rake start (two gates: end, and endside, the wall the side gate is in, so that a bend in its cell counts as a turn), the abbot’s finished sand (R: not walkable, and not a pivot for the wide rake). stream 1 prints every solution (used to export all par rakings). src/zg.py: garden model (text symbols: . sand, # stone, O ripple stone, h/v wave bands, =/| ichimatsu blocks; clues = grooves, marks = pebbles), solver driver, rule checker, brute-force enumerator. src/zcp.py: independent CP-SAT model (AddCircuit + dummy node) for par proofs and cross-checks. src/grader.py: tiered deductive solver used to grade difficulty. src/gen.py, clues.py, levels.py, search*.py: layout sampling, greedy groove and pebble selection, level searches. src/exp_marks.py, fig_pebbles.py: pebbles vs grooves on the same gardens (writes out/marks_vs_grooves.json), and the pebbles figure. src/render.py, final_figs.py: figure rendering (writes fig/final/*.png|svg, out/facts.json). src/final_tables.py, exp_*.py: the tables and statistics quoted in the document. src/verify_doc.py: re-derives every number quoted in the document (C solver + CP-SAT); prints OK/BAD. src/test_crosscheck.py, xc_stats.py, xc_cpsat*.py: solver validation (brute force; CP-SAT; OEIS A145157/A145156).
src/test_marks.py, test_grader_marks.py: pebbles: C solver vs brute force vs CP-SAT; soundness of the grader’s pebble rules.
src/garden_sampler.py: the garden-like stone sampler (odd-numbered, asymmetric groups of one- to three-cell stones; ripple stones, wave bands, closed rings, side gates, ichimatsu layouts). src/exp_sampler.py compares its yields with single-cell stones (writes out/sampler_yields.json). src/campaign.py: generates the campaign (7 worlds, 148 gardens): generated gardens per world from the sampler and the pipeline’s filters, plus the hand-made and searched teaching gardens and the contrasting pairs; each world’s main path is the template (introduction, two applications, trap, combinations, calm garden, capstone; roles assigned by measurement; 72 gardens in all), and the rest of its gardens are optional extras (76); writes out/campaign.json and out/campaign_stats.json (per-spec candidates and the pairs are cached in out/campaign_cache/).
src/pairs.py: searches for the contrasting pairs that introduce each rule (the same small garden before and after one change: a ripple stone, a band or the wide rake that breaks every par raking of the first; one groove that leaves one raking; pebbles in place of grooves; a side gate that leaves one of two wide-rake rakings). src/exp_continuity.py: how many of the par rakings rewarded in worlds 1–3 turn back in open sand (writes out/continuity.json). src/test_side_pivot.py: rechecks the side gate’s turn counting and finished sand (no pivot) in the C solver against brute force (small gardens) and CP-SAT (medium); logs in out/test_side_pivot_seed*.log. src/hints.py: the abbot’s first observation for generated gardens: the provable fact that most changes the plan (free gardens: true of every par raking, and missed by the most near-misses; strict gardens: about the unique raking, and lowering the grade the most), with the cells the abbot points at; trap scores for the template’s ordering. src/export_proto.py: exports the campaign to out/proto_gardens.json, re-deriving each garden’s raking count (exact solver), par (CP-SAT), every par raking (for the in-page hints), and an intended raking (asserted valid and at par), with its first hint (authored, or from hints.py), its role, whether it is an extra, its pair, and whether the monk demonstrates it first; writes the hints’ measured effect to out/hint_stats.json. src/seed_garden_names.py, out/garden_names.json: garden names follow layouts (a registry keyed by the garden’s rows, gates and clues), so a garden keeps its name, and its poem, when the campaign is regenerated or reordered. poems/samon-poems.json: the poems, one per garden and one for the practice garden: Japanese text, working translation (and its credit), poet, collection, the page each text was checked against, notes, the short source shown in the game, and why each poem goes with its garden. poems/astra-samon-poem-selection.json is GPT-6 Astra’s original selection for the 136-garden campaign (with its unused candidates); poems/pass2_replacements.py and poems/pass3_astra_review.py are the second and third curation passes (25 swaps and 4 translation repairs, logged in the JSON’s about.revisions); poems/originals-brainstorm.md holds original candidates for three gardens, not used.