import fc from "fast-check"; import { describe, expect, it } from "vitest"; import { analyzeKillerCage, calculateKillerCombinations, } from "../../src/helpers"; describe("killer cage combinations", () => { it("enumerates the familiar two-cell sum 10 combinations", () => { expect(calculateKillerCombinations({ cellCount: 2, sum: 10 })).toEqual([ [1, 9], [2, 8], [3, 7], [4, 6], ]); }); it("supports allowed, required, excluded and repeated digits", () => { expect( calculateKillerCombinations({ cellCount: 3, sum: 10, allowedDigits: [1, 2, 3, 4, 5], excludedDigits: [1], requiredDigits: [5], }), ).toEqual([[2, 3, 5]]); expect( calculateKillerCombinations({ cellCount: 2, sum: 10, allowRepeats: true, }), ).toContainEqual([5, 5]); }); it("filters assignments through per-cell candidates", () => { const result = analyzeKillerCage({ cellCount: 2, sum: 10, candidates: [ [1, 2], [8, 9], ], }); expect(result.combinations).toEqual([ [1, 9], [2, 8], ]); expect(result.assignments).toEqual([ [1, 9], [2, 8], ]); expect(result.possibleByCell).toEqual([ [1, 2], [8, 9], ]); expect(result.necessaryDigits).toEqual([]); }); it("reports digits necessary in every surviving combination", () => { const result = analyzeKillerCage({ cellCount: 3, sum: 6 }); expect(result.combinations).toEqual([[1, 2, 3]]); expect(result.necessaryDigits).toEqual([1, 2, 3]); }); it("satisfies combination invariants for generated inputs", () => { fc.assert( fc.property( fc.integer({ min: 4, max: 12 }), fc.integer({ min: 1, max: 5 }), fc.integer({ min: 1, max: 60 }), (size, count, sum) => { if (count > size || sum > size * count) return; const result = calculateKillerCombinations({ size, cellCount: count, sum, }); const keys = new Set(); for (const combination of result) { expect(combination).toHaveLength(count); expect(combination.reduce((total, digit) => total + digit, 0)).toBe( sum, ); expect(combination).toEqual([...combination].sort((a, b) => a - b)); expect(new Set(combination).size).toBe(count); keys.add(combination.join(",")); } expect(keys.size).toBe(result.length); }, ), { numRuns: 100 }, ); }); });