Skip to content

Commit

Permalink
chore: add sudoku.com scraper
Browse files Browse the repository at this point in the history
  • Loading branch information
TN1ck committed May 5, 2024
1 parent 5f5aaf6 commit b8a3921
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 17 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"test-watchAll": "jest --watchAll",
"start": "vite",
"prettier:write": "prettier --write './src/**/*.ts' './src/**/*.tsx'",
"fetch-sudokus": "ts-node --project ./tsconfig.json ./scripts/fetch_sudokus.ts -l 2 -n 100",
"fetch-sudokus": "ts-node --project ./tsconfig.json ./scripts/fetch_sudokus.ts -l 6 -n 100 -p sudokuDotCom",
"generate-easy-sudokus": "ts-node --project ./tsconfig.json ./scripts/generate_sudokus.ts -d easy -n 500",
"generate-medium-sudokus": "ts-node --project ./tsconfig.json ./scripts/generate_sudokus.ts -d medium -n 500",
"generate-hard-sudokus": "ts-node --project ./tsconfig.json ./scripts/generate_sudokus.ts -d hard -n 500",
Expand Down
104 changes: 97 additions & 7 deletions scripts/fetch_sudokus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ import {Command} from "commander";
import cheerio from "cheerio";
import {writeFileSync} from "fs";
import {printSimpleSudoku} from "../src/engine/utility";
import {map} from "lodash";

const program = new Command();

async function fetchSudoku(level: number): Promise<number[][]> {
async function fetchSudokuFromWebSudoku(level: number): Promise<{sudoku: number[][]; winRate: number}> {
if (level < 1 || level > 4) {
throw new Error("Invalid level, must be between 1 and 4");
}

const response = await fetch(`https://west.websudoku.com/?level=${level}`);
if (response.status !== 200) {
throw new Error(`Failed to fetch Sudoku: ${response.statusText}`);
Expand All @@ -30,19 +35,104 @@ async function fetchSudoku(level: number): Promise<number[][]> {
throw new Error("Failed to fetch Sudoku: Empty Sudoku");
}

return sudoku;
return {sudoku, winRate: -1};
}

export async function fetchSudokuFromSudokuDotCom(level: number): Promise<{sudoku: number[][]; winRate: number}> {
if (level < 1 || level > 6) {
throw new Error("Invalid level, must be between 1 and 6");
}

const LEVEL_MAPPING: Record<number, string> = {
1: "easy",
2: "medium",
3: "hard",
4: "expert",
5: "evil",
6: "extreme",
};

const mappedLevel = LEVEL_MAPPING[level];

const response = await fetch(`https://sudoku.com/api/v2/level/${mappedLevel}`, {
headers: {
accept: "*/*",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
priority: "u=1, i",
"sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-easy-locale": "en",
"x-requested-with": "XMLHttpRequest",
},
referrer: "https://sudoku.com/",
referrerPolicy: "strict-origin-when-cross-origin",
body: null,
method: "GET",
mode: "cors",
credentials: "include",
});
if (response.status !== 200) {
throw new Error(`Failed to fetch Sudoku: ${response.statusText}`);
}

const body = (await response.json()) as {
// The sudoku is one string with 81 characters, 0-9, where 0 is empty.
mission: string;
solution: string;
win_rate: number;
id: number;
};

// Split the string into 9 strings with 9 characters each.
const sudoku: number[][] = [];
for (let i = 0; i < 9; i++) {
sudoku.push(
body.mission
.slice(i * 9, (i + 1) * 9)
.split("")
.map((cell) => parseInt(cell, 10)),
);
}

// If only empty throw error.
if (sudoku.every((row) => row.every((cell) => cell === 0))) {
console.log("Body: ", body);
throw new Error("Failed to fetch Sudoku: Empty Sudoku");
}

return {sudoku, winRate: body.win_rate};
}

program
.requiredOption("-n, --number <number>", "Number of times to fetch Sudoku")
.requiredOption("-l, --level <level>", "Difficulty level of the Sudoku (1-4)")
.requiredOption("-l, --level <level>", "Difficulty level of the Sudoku (1-6) (depends on the provider)")
.requiredOption("-p, --provider <provider>", "The provider of the Sudokus")
.action(async (options) => {
const {number, level} = options;
const sudokus: number[][][] = [];
const sudokus: Array<{sudoku: number[][]; winRate: number}> = [];

const provider = options.provider;

switch (provider) {
case "webSudoku":
console.log("Fetching Sudokus from WebSudoku");
break;
case "sudokuDotCom":
console.log("Fetching Sudokus from Sudoku.com");
break;
default:
throw new Error(`Unknown provider: ${provider}`);
}

const fetchFunction = provider === "webSudoku" ? fetchSudokuFromWebSudoku : fetchSudokuFromSudokuDotCom;

for (let i = 0; i < number; i++) {
try {
const sudoku = await fetchSudoku(level);
const sudoku = await fetchFunction(level);
sudokus.push(sudoku);
console.log(`Fetched Sudoku #${i + 1} for level ${level}`);
} catch (error) {
Expand All @@ -51,11 +141,11 @@ program
}
// Rate limiting, to avoid getting blocked
console.log(`Waiting...`);
await new Promise((resolve) => setTimeout(resolve, 5000));
await new Promise((resolve) => setTimeout(resolve, 1000));
}

const sudokusSerialized = sudokus.map((sudoku) => {
return printSimpleSudoku(sudoku);
return {sudoku: printSimpleSudoku(sudoku.sudoku), winRate: sudoku.winRate};
});

const jsonFileName = `sudokus-${level}-${number}-${new Date().getTime()}.json`;
Expand Down
6 changes: 3 additions & 3 deletions scripts/generate_sudokus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {program} from "commander";
import * as generate from "../src/engine/generate";
import * as solverAC3 from "../src/engine/solverAC3";
import {printSimpleSudoku} from "../src/engine/utility";
import {DIFFICULTY} from "../src/engine/types";
import {DIFFICULTY, SimpleSudoku} from "../src/engine/types";
import {createSeededRandom} from "../src/engine/seededRandom";

program
Expand All @@ -17,7 +17,7 @@ program
)
.parse(process.argv);

const mapping = {
const mapping: Record<string, DIFFICULTY> = {
easy: DIFFICULTY.EASY,
medium: DIFFICULTY.MEDIUM,
hard: DIFFICULTY.HARD,
Expand All @@ -29,7 +29,7 @@ const options = program.opts();
const difficulty = options.difficulty;
const sudokuDifficulty = mapping[difficulty];

function writeSudoku(sudoku) {
function writeSudoku(sudoku: SimpleSudoku) {
const iterations = solverAC3.solve(sudoku).iterations;
const printedSudoku = printSimpleSudoku(sudoku);
console.log(`write sudoku with difficulty ${iterations}\n`, printedSudoku);
Expand Down
154 changes: 149 additions & 5 deletions src/engine/__tests__/difficulties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import {solve} from "../solverAC3";
import {parseSudoku} from "../utility";
import {mean} from "lodash";

// These sudokus are from websudoku.com to test the solver / iterations count.
const SUDOKUS_WITH_DIFFICULTY: Array<{
interface SudokusWithStats {
sudokus: string[];
level: number;
averageIterations: number;
minIterations: number;
maxIterations: number;
}> = [
winRates?: number[];
}

// These sudokus are from websudoku.com to test the solver / iterations count.
const WEBSUDOKU_SUDOKUS_WITH_DIFFICULTY: SudokusWithStats[] = [
{
sudokus: [
"_71____9_\n______6__\n__3492517\n73_5____4\n_84_3_75_\n2____9_83\n3179584__\n__5______\n_2____97_",
Expand Down Expand Up @@ -444,9 +447,9 @@ const SUDOKUS_WITH_DIFFICULTY: Array<{
},
];

describe("difficulties are correctly set", () => {
describe("websudoku difficulties", () => {
// websudoku only has easy, medium, hard, evil
SUDOKUS_WITH_DIFFICULTY.forEach((s) => {
WEBSUDOKU_SUDOKUS_WITH_DIFFICULTY.forEach((s) => {
const solutions = s.sudokus.map((s, i) => {
return solve(parseSudoku(s));
});
Expand All @@ -470,3 +473,144 @@ describe("difficulties are correctly set", () => {
});
});
});

const SUDOKU_DOT_COM_SUDOKUS_WITH_DIFFICULTY: SudokusWithStats[] = [
{
sudokus: [
"2_3_569__\n_____4_1_\n_6_______\n__8______\n7_5_2_3__\n___3____9\n6_7__5__4\n_8____7__\n_9__6____",
"_______9_\n__3___7_8\n___6____5\n___59___6\n1__7_____\n85___2_4_\n__9_7____\n__83__6__\n__4___18_",
"____3___9\n_____5_6_\n_____75_8\n__6______\n32____6__\n____8__54\n_3__5____\n81_943___\n9____8___",
"_________\n9___7___3\n_2__6__5_\n_1______8\n_7__2___9\n_5_71_3__\n2____68__\n4___3___6\n___8_1___",
"____1____\n_35____4_\n__8_94_36\n6___7____\n___3_945_\n_____8___\n__9___7__\n___7__2__\n4_3__2___",
"__7__3__1\n__512__4_\n2____6___\n_____2___\n__4___9__\n5__78___6\n8__51___7\n_7_____6_\n___3_____",
"_____4_6_\n__4_3_1__\n__7_____2\n__57__92_\n_________\n_8__6____\n7______8_\n6__9_5_3_\n____4_21_",
"9___3____\n___1__5__\n_32__6_8_\n6______9_\n_79_5_8__\n4____7___\n____6___3\n_4_______\n_87__3_2_",
"9__1___4_\n_7_6__3_9\n____3__5_\n_5___1___\n________4\n1___2_9_6\n5___6_2_1\n_______3_\n__87_____",
"8___3____\n__915__2_\n_4______9\n_____8___\n7_____6__\n__429__5_\n__1__3___\n_____4_8_\n_6_81_5__",
"3__4___9_\n_______64\n8___9_1__\n_________\n_3___29__\n5___1_7__\n_7__5_3__\n_2_1__6_7\n_6__4____",
"___9_16__\n5_8______\n__76___5_\n_____4___\n______8_1\n9_6______\n__5___4__\n___7_____\n_3___9162",
"__238_64_\n5__9_____\n________3\n______1__\n__6_4_87_\n_2___6___\n__7_____1\n____3___2\n_9_8__73_",
"__74_____\n3____9___\n__8____91\n____7_8_3\n___264___\n____3___5\n______2__\n26_____3_\n_4___76__",
"3___8_9__\n___34____\n__8__56__\n5__1_4_7_\n__2__9_1_\n__3____4_\n__5__12__\n_________\n_7___8_9_",
"8316____7\n_7_______\n____2____\n______8__\n___2____5\n_8_7___96\n___1_54__\n4______7_\n9____4_61",
"56_724___\n_9___6___\n______8__\n__48__6__\n________9\n____6__5_\n___1784__\n_5__4__7_\n4_3______",
"63_1_____\n2___36_8_\n___4____6\n_9__62__7\n__7____1_\n_____4___\n8_____5__\n___3_____\n_2__97__1",
"_2759____\n_____3___\n___6__9_4\n4__1_____\n______7__\n_5_____96\n_7_9___6_\n1_5______\n9__4__3_8",
"2__9__6__\n___5__8__\n8_6_7_1__\n4____12__\n_________\n6__7____9\n_85______\n_4__5___2\n7__4____3",
"9_54__6_7\n___9_7___\n42____91_\n5_8______\n____65___\n___1_9___\n__6__38__\n____8__26\n8__2_634_",
"5___1____\n_9_4__63_\n3_____9__\n________7\n__16_____\n___19_2_5\n7________\n_8_9_41__\n2___3__4_",
"8__34__2_\n2________\n34_7____1\n_3___9__5\n___16_734\n_64____1_\n_____3_6_\n_1______2\n___25_19_",
"__47____5\n_2_____84\n__8______\n2_3_7____\n___548___\n6___2____\n19____3__\n___9___2_\n_____57__",
"_84_3____\n___6_9__1\n__3______\n__91__7__\n______4_5\n_61__4___\n_____3_84\n7__2___9_\n8________",
"_85__71_2\n__4_165__\n____5376_\n_________\n___5__871\n4____92_6\n__8_9____\n___7____5\n19_____8_",
"9____4___\n__5____6_\n_7__12__5\n___8_____\n3_____9__\n_2__75__6\n2___81_3_\n___4____1\n_8_6_____",
"_5___9_8_\n7____36_5\n____6__1_\n_______6_\n_1__3_4_9\n__2__7___\n_9__4_5_3\n1__9_____\n________8",
"8__1___7_\n_______2_\n72____9__\n_____9__6\n_____1_39\n___827___\n__1_8____\n__3___5_4\n_9_5_____",
"_64__2__8\n_____6_3_\n_1___4_5_\n_9___12__\n_4_5___8_\n_________\n6_3______\n_8_7___9_\n9__1____3",
"_45_2____\n_____1__5\n____8_3__\n21_____8_\n_7_____1_\n______693\n__19_6___\n6________\n9__3____8",
"9____84__\n4_3____5_\n____792__\n_5_____4_\n___6____1\n_________\n3_7____2_\n1____6___\n__2_45_8_",
"__2_513_9\n_____8___\n6_____2__\n___6____3\n7___35_1_\n__58_____\n_4_____7_\n___3_____\n__6_92__1",
"_1___92__\n_____75__\n_79__6_8_\n_________\n_3___1__6\n_9__2_8__\n7_5______\n_8__4_3__\n3___1__5_",
"_7_6___5_\n_________\n_9___2__1\n___4____3\n_6_9____2\n_495__1__\n4_3______\n7____63__\n_1___8__7",
"9__8_1_43\n_____9___\n4___5_1__\n7__5___61\n__5_329_4\n________5\n5__42____\n__7_8___2\n__2____86",
"83_2___41\n7________\n_____9__2\n__9____1_\n31___58__\n__73_____\n__1______\n____6_5__\n24_9___8_",
"8______4_\n3__8__56_\n__2__3___\n5_______4\n__7_6_95_\n___9____2\n2__6__83_\n________9\n_1__7____",
"5___4____\n__398_2__\n_2______7\n_____49__\n__1__7___\n8__19___6\n6______5_\n_____1___\n__832_7__",
"_1__892__\n_8___5_3_\n_9_____7_\n__6__2_4_\n__54__7__\n___97____\n_________\n__3__8_2_\n_5___4__1",
"5______36\n974______\n6_______8\n__2__6___\n___3__2_1\n_4_5_____\n__5_4__9_\n____976__\n_______7_",
"___2__8__\n1__9__3__\n83__7_6__\n4____61__\n3__7___9_\n_________\n__4_2__1_\n7__4___5_\n_28______",
"56______9\n_______8_\n1__6__45_\n___8_____\n473_5____\n_5__496__\n___7____5\n7__598___\n__5_3_974",
"_8154____\n_________\n_______84\n51_4_967_\n6__75__3_\n_7___6__9\n__6__34__\n_589___6_\n_4_1_____",
"__1____6_\n___8_____\n_73____19\n__5__2__7\n___76_58_\n7_459___6\n_6__2____\n_______78\n19___324_",
"_________\n_9__3__6_\n4__7___1_\n__23__6__\n6__5___4_\n______8_2\n__4_9__81\n2___8____\n7___1__3_",
"_9__86___\n3_______7\n56__2___3\n____3____\n_1_4_7___\n7_4_____2\n___1___4_\n______89_\n8______2_",
"___175___\n_____83__\n_____289_\n__8_6____\n_9____4_6\n_2_7_____\n7___2__5_\n_______1_\n5_1_____8",
"3________\n_6____38_\n8___7__2_\n____1_6__\n_14_____9\n_____2__7\n__56_____\n___823___\n9_67_____",
"_8_____74\n__5__7___\n_6__9____\n______1__\n9____62__\n2_1____5_\n___219___\n___5____3\n___6__8_5",
"_9__5_8__\n5____41__\n7_4______\n_1__6___2\n____4___7\n_72__9__3\n_________\n_5_3____1\n_2__9_6__",
"____61___\n3__4__8__\n_6___37__\n5__7___9_\n_4_19__2_\n6______1_\n4__9__5__\n__23___7_\n_________",
"_____3__9\n____6_4__\n1_6_____2\n_8_______\n_5__9__3_\n__4___85_\n___538___\n42_9_____\n7__4_____",
"_31_4____\n_____5_8_\n__7_____4\n96____5_1\n1_5_9___6\n____16___\n_96_2____\n___754_39\n_____94_8",
"3458_____\n8____6_3_\n_____9__8\n6_7____2_\n_____7__5\n2____39__\n4__1_____\n___7___92\n1_2_98_47",
"___425___\n___1__3__\n___9__18_\n1___7____\n__8___6_7\n__9__2___\n_______5_\n_2__9__4_\n54______1",
"3___4__7_\n__6_2____\n5__7_6__9\n__53_1_2_\n____6____\n9_____8__\n_3______2\n___4_____\n__15_7_3_",
"_4__27_31\n___8_____\n13___4___\n32__7_4__\n_5_____18\n_______5_\n6__98____\n________5\n7______6_",
"__9_1_74_\n2________\n_____4_3_\n__7___9__\n8_3__6___\n__4_2__1_\n__6__14_9\n4_____3_8\n____7____",
"_________\n__1_3_6__\n4__5__9__\n__27_____\n__94__1__\n__3__52_9\n8__6__5__\n_______27\n1____7_6_",
"73__12_9_\n____4____\n9_____5__\n__8_____6\n_1__93_5_\n___7_____\n___4___2_\n_7_5_____\n__1_278__",
"2_______8\n7___9____\n6_5_3____\n3_____6__\n__84_79__\n1__68____\n__32____1\n_5______6\n___8___4_",
"____17_5_\n______984\n_____6_7_\n_5____4__\n_1_2_3___\n7_______2\n____9____\n__4_8___5\n9_87_____",
"_________\n_7___8__5\n_2_1__9__\n4_3______\n__2_4___9\n_8___2__6\n_9___57__\n73__8_1__\n_____43__",
"__4_8_1__\n__2475__6\n3_____2__\n1_5__4___\n__6_2__3_\n_2____5_9\n4___519__\n___24__6_\n___7__4__",
"4___1_6__\n9____7_3_\n_8_2___1_\n__1_4__9_\n_______8_\n___89_7_3\n_3______5\n_9__6____\n7__5_8___",
"_9_7_____\n_____3___\n_5_____9_\n___2____9\n__6__87__\n__8_4_3_6\n_813_7___\n___5_____\n_73_2___5",
"_7___45__\n_8_______\n2_____78_\n_____9_2_\n___5____4\n9_6_____1\n__3_2____\n_12_4____\n___875___",
"__2_85__4\n____3__6_\n__421__3_\n_______52\n______31_\n9________\n8____6___\n25_4____8\n_____16__",
"____7_1__\n___56____\n_8__2__3_\n______49_\n_4_25___8\n5__9____6\n4_6______\n2________\n7__19_8__",
"9__37____\n__31___4_\n__7______\n______317\n_8____9__\n_92___4__\n____9__5_\n56___2___\n_____4__1",
"9___2__1_\n__68___7_\n_________\n______5_3\n__9__5__1\n__41___8_\n3__5_____\n7__6___9_\n2____873_",
"_6___7___\n1___8___4\n___91____\n_________\n___3___26\n47___68__\n6_5__247_\n_____81__\n__9____3_",
"_2____913\n__5____87\n___19____\n1__68__7_\n_9______2\n__4______\n_____1_2_\n8______4_\n__64_3___",
"____5___9\n_______8_\n683___4__\n______9__\n__8_7__61\n7___2___5\n_5__4____\n__9__16__\n_7___6__3",
"____9_6_5\n_8_1_6___\n_4___3_1_\n6____5__7\n_________\n__167834_\n________1\n___3_4___\n2_____4__",
"_______9_\n_97___4__\n__8_6__7_\n___987___\n_____4__1\n_____6_24\n2_____5_3\n_4__5____\n6__8_____",
"9__37____\n__31___4_\n__7______\n______317\n_8____9__\n_92___4__\n____9__5_\n56___2___\n_____4__1",
"__6_9___1\n_________\n4___2_7__\n9___4___6\n8_______5\n7___89_1_\n__42___5_\n__3_1___2\n___8_5___",
"5_8__79__\n_4____6__\n___8_324_\n6___1____\n_______2_\n__9_7____\n_2_____54\n_5_4_9___\n4______1_",
"__94____3\n4____2__6\n82_______\n__4_1_6__\n_________\n__79____5\n_78__91__\n___2__8__\n__65__7__",
"8___1____\n_3__7__91\n2___9___6\n_________\n__7_6___4\n3____2__9\n______18_\n_8___64__\n4____5__3",
"4______36\n5__9_____\n_1___6___\n___879___\n____5_41_\n____1__2_\n______8__\n_87_____1\n__9__57__",
"__76_594_\n________6\n8__1_____\n______2__\n_7__9____\n__9__453_\n_1_5__36_\n_____6__7\n__3_____2",
"__7_2___6\n5___3____\n__95_61__\n____5____\n9__4_7__3\n__1____8_\n4__6_9__7\n_____2___\n_7____3__",
"9_54__6_7\n___9_7___\n42____91_\n5_8______\n____65___\n___1_9___\n__6__38__\n____8__26\n8__2_634_",
"_6__3____\n__1_7694_\n_8_9_____\n_4___1___\n_28_9____\n______16_\n7__8_____\n______4_2\n_9__1_3__",
"_________\n_3_5___6_\n__2_8__4_\n_5__6__8_\n_1__7____\n3___2_67_\n______1_7\n1__8____4\n_4_9___3_",
"____7__45\n4_____8__\n8_1______\n_8___2___\n___59__6_\n21___4___\n5__4____3\n__2_____7\n___6___54",
"_____98_1\n_8_4_____\n6____3___\n562______\n__3____94\n__4_____7\n_______5_\n_3__6__2_\n___52_4__",
"_54_796__\n8______5_\n7___4____\n_____8__1\n__7______\n_46_1__2_\n___3__9__\n5________\n_21_8__6_",
"3458_____\n8____6_3_\n_____9__8\n6_7____2_\n_____7__5\n2____39__\n4__1_____\n___7___92\n1_2_98_47",
"_8_3___2_\n_96_7__4_\n__3_5__91\n6_______3\n_3__156__\n______254\n_____24__\n37_______\n1_97__5__",
"5___32___\n___7_____\n__4___35_\n4__6_____\n___25_9_6\n7__9__1__\n_________\n2_85___7_\n__3__9_8_",
"4_6___8__\n7__3___64\n_____49__\n__7__8_12\n3___5____\n______6__\n__1__2_47\n_2_8_____\n________9",
"_4__2_8__\n21_______\n__9__45__\n__7__96__\n__43___8_\n_________\n__8__6_7_\n_____2_1_\n7_1_9__3_",
"_7__45___\n92____1__\n__5__8__7\n______69_\n___7_____\n_1_45____\n2_____46_\n________1\n69__2__3_",
"1_____2__\n__6__3___\n3___1_94_\n__79__48_\n____8___6\n4_______2\n_5_7_____\n________8\n6___9_31_",
"_5_____2_\n__64__13_\n4___9____\n___1____2\n__8_____9\n_3__7_81_\n__39__64_\n________8\n_7___5___",
"__8_93_72\n______3__\n_1___6___\n__4___5__\n____3_8__\n6____9_43\n__7_2__94\n8__7_____\n_______5_",
],
averageIterations: 250,
level: 6,
maxIterations: 1945,
minIterations: 11,
},
];

describe("sudoku.com difficulties", () => {
// websudoku only has easy, medium, hard, evil
SUDOKU_DOT_COM_SUDOKUS_WITH_DIFFICULTY.forEach((s) => {
let solutions = s.sudokus.map((s, i) => {
return solve(parseSudoku(s));
});
it("the average number of iterations is correctly adjusted for the difficulty levels", () => {
const averageIterations = mean(solutions.map((s) => s.iterations));
const averageIterationsRounded = Math.round(averageIterations);
const expectedIterations = s.averageIterations;
expect(averageIterationsRounded).toBe(expectedIterations);
});

it("the min number of iterations is correct", () => {
const minIterations = Math.min(...solutions.map((s) => s.iterations));
const expectedIterations = s.minIterations;
expect(minIterations).toBe(expectedIterations);
});

it("the max number of iterations is correct", () => {
const maxIterations = Math.max(...solutions.map((s) => s.iterations));
const expectedIterations = s.maxIterations;
expect(maxIterations).toBe(expectedIterations);
});
});
});

// TODO: This one creates a call stack exceeded
// "_3_6__89_\n____4____\n___8__5_7\n_9_______\n_____64_5\n3____4_1_\n_6__1__3_\n__1___2__\n4___2____"
2 changes: 1 addition & 1 deletion src/engine/solverAC3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function _solveGridAC3(
iterations++;
// evil puzzles have an average of about 500, everything more than 1000 that is actually solvable
// will be too impossible for the normal user
if (iterations > 1000) {
if (iterations > 4000) {
return {
sudoku: toSimpleSudoku(grid),
iterations: Infinity,
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"include": [
"src",
"scripts",
"vite.config.ts"
]
}

0 comments on commit b8a3921

Please sign in to comment.