clone

a daily shikaku puzzle for phones: one seeded puzzle per date, solved by dragging rectangles

main
rect.run / tests / lib / shikaku / generator_test.ts
generator_test.ts 2.6K
1import { assert, assertEquals, assertNotEquals } from "@std/assert";23import {4 createPuzzleFromDailySeed,5 createSeededRng,6 generatePuzzleFromSeed,7} from "@/lib/shikaku/generator.ts";89Deno.test("createSeededRng is deterministic for the same string seed", () => {10 const rngA = createSeededRng("2026-04-16");11 const rngB = createSeededRng("2026-04-16");1213 const valuesA = [rngA(), rngA(), rngA(), rngA()];14 const valuesB = [rngB(), rngB(), rngB(), rngB()];1516 assertEquals(valuesA, valuesB);17});1819Deno.test("generatePuzzleFromSeed returns stable puzzles for the same seed", () => {20 const puzzleA = generatePuzzleFromSeed("2026-04-16");21 const puzzleB = generatePuzzleFromSeed("2026-04-16");22 const puzzleC = generatePuzzleFromSeed("2026-04-17");2324 assertEquals(puzzleA, puzzleB);25 assertNotEquals(puzzleA.givens, puzzleC.givens);26});2728Deno.test("generated puzzle covers the full board and respects clue area invariants", () => {29 const puzzle = generatePuzzleFromSeed("2026-04-16", {30 width: 8,31 height: 8,32 maxRectSize: 8,33 });3435 assertEquals(puzzle.width, 8);36 assertEquals(puzzle.height, 8);37 assert(puzzle.givens.length > 0);38 assertEquals(puzzle.solution?.length, puzzle.givens.length);3940 const covered = new Set<string>();41 let totalArea = 0;4243 for (const rectangle of puzzle.solution ?? []) {44 totalArea += rectangle.width * rectangle.height;4546 const matchingGiven = puzzle.givens.find((given) =>47 given.id === rectangle.clueId && given.value === rectangle.value &&48 given.row >= rectangle.row &&49 given.row < rectangle.row + rectangle.height &&50 given.col >= rectangle.col && given.col < rectangle.col + rectangle.width51 );52 assert(53 matchingGiven,54 `missing matching clue for rectangle ${JSON.stringify(rectangle)}`,55 );5657 for (58 let row = rectangle.row;59 row < rectangle.row + rectangle.height;60 row++61 ) {62 for (63 let col = rectangle.col;64 col < rectangle.col + rectangle.width;65 col++66 ) {67 const key = `${row},${col}`;68 assert(!covered.has(key), `cell ${key} covered more than once`);69 covered.add(key);70 }71 }72 }7374 assertEquals(totalArea, puzzle.width * puzzle.height);75 assertEquals(covered.size, puzzle.width * puzzle.height);76});7778Deno.test("createPuzzleFromDailySeed exposes date and streak-based ids", () => {79 const puzzle = createPuzzleFromDailySeed("2026-04-16", 3);8081 assertEquals(puzzle.date, "2026-04-16");82 assertEquals(puzzle.streakIndex, 3);83 assertEquals(puzzle.id, "daily-2026-04-16-3");84 assertEquals(puzzle.seed, "2026-04-16:3");85});