sudoku-pro 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +13 -6
  2. package/package.json +5 -2
  3. package/sudoku-pro.js +185 -141
package/README.md CHANGED
@@ -22,7 +22,13 @@ npm run hard
22
22
 
23
23
  ```javascript
24
24
  // Import the module
25
- const { generateSudoku, printSudoku, solveSudoku } = require("sudoku-pro");
25
+ const {
26
+ generateSudoku,
27
+ printSudoku,
28
+ solveSudoku,
29
+ getHint,
30
+ waitForHint,
31
+ } = require("sudoku-pro");
26
32
 
27
33
  // Get the difficulty level
28
34
  const args = process.argv.slice(2);
@@ -30,16 +36,17 @@ const args = process.argv.slice(2);
30
36
  const difficulty = args[0]; // Get the difficulty level from command line arguments
31
37
 
32
38
  // Generate a Sudoku puzzle
33
- const sudoku = generateSudoku(difficulty);
39
+ const { sudoku, solvedSudoku } = generateSudoku(difficulty);
34
40
 
35
41
  // Print the puzzle
36
42
  printSudoku(sudoku);
37
43
 
38
- // Solve the puzzle
39
- solveSudoku(sudoku);
44
+ // Function to wait for user input for hint or complete solution
45
+ waitForHint(sudoku, solvedSudoku);
40
46
 
41
- // Print the solved puzzle
42
- printSudoku(sudoku);
47
+ // This script will continue running until the user chooses to exit
43
48
 
44
49
  process.exit();
45
50
  ```
51
+
52
+ Now, in addition to generating and solving Sudoku puzzles, users can also request hints or print the complete solution while the script is running.
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "sudoku-pro",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "sudoku-pro humbly presents itself as your go-to toolkit for generating, solving, and printing Sudoku puzzles spanning different difficulty levels. Powered by the reliable backtracking algorithm, it aspires to offer enthusiasts and learners alike a simple yet effective platform to engage with Sudoku puzzles. With Sudoku-Pro, embark on a journey of brain-teasing challenges or delve into educational endeavors with ease. This humble interface aims to make Sudoku puzzle creation and enjoyment accessible to all, ensuring a delightful experience for users of varying skill levels. Join us in exploring the possibilities of Sudoku puzzles while we humbly accompany you on your puzzle-solving adventures.",
5
+ "changelog": {
6
+ "1.0.6": "generateSudoku, printSudoku, solveSudoku",
7
+ "1.0.7": "getHint function added"
8
+ },
5
9
  "main": "sudoku-pro.js",
6
10
  "repository": {
7
11
  "type": "git",
@@ -32,7 +36,6 @@
32
36
  "Puzzle",
33
37
  "Puzzle Game",
34
38
  "Game",
35
- "Numbers Game",
36
39
  "Board Game",
37
40
  "Logic Game",
38
41
  "Numbers Game",
package/sudoku-pro.js CHANGED
@@ -1,185 +1,229 @@
1
+ const readline = require("readline");
2
+
1
3
  // Get the difficulty level
2
4
  const args = process.argv.slice(2);
3
5
 
4
6
  function shuffle(array) {
5
- // Fisher-Yates shuffle algorithm
6
- for (let i = array.length - 1; i > 0; i--) {
7
- const j = Math.floor(Math.random() * (i + 1));
8
- [array[i], array[j]] = [array[j], array[i]];
9
- }
10
- return array;
7
+ // Fisher-Yates shuffle algorithm
8
+ for (let i = array.length - 1; i > 0; i--) {
9
+ const j = Math.floor(Math.random() * (i + 1));
10
+ [array[i], array[j]] = [array[j], array[i]];
11
+ }
12
+ return array;
11
13
  }
12
14
 
13
15
  function generateSudoku(difficulty) {
14
- const sudoku = Array.from({ length: 9 }, () => Array(9).fill(0));
15
-
16
- // Fill the diagonal blocks (3x3 sub-grids) with valid numbers
17
- for (let i = 0; i < 9; i += 3) {
18
- const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
19
- shuffle(nums);
20
- for (let j = 0; j < 3; j++) {
21
- for (let k = 0; k < 3; k++) {
22
- sudoku[i + j][i + k] = nums.pop();
23
- }
24
- }
16
+ const sudoku = Array.from({ length: 9 }, () => Array(9).fill(0));
17
+
18
+ // Fill the diagonal blocks (3x3 sub-grids) with valid numbers
19
+ for (let i = 0; i < 9; i += 3) {
20
+ const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
21
+ shuffle(nums);
22
+ for (let j = 0; j < 3; j++) {
23
+ for (let k = 0; k < 3; k++) {
24
+ sudoku[i + j][i + k] = nums.pop();
25
+ }
25
26
  }
26
-
27
- // Solve the puzzle
28
- solveSudoku(sudoku);
29
-
30
- // Determine the number of cells to remove based on difficulty level
31
- let numToRemove;
32
- if (difficulty === 'e') {
33
- numToRemove = Math.floor(Math.random() * 20) + 20; // Easy difficulty
34
- } else if (difficulty === 'm') {
35
- numToRemove = Math.floor(Math.random() * 25) + 40; // Medium difficulty
36
- } else if (difficulty === 'h') {
37
- numToRemove = Math.floor(Math.random() * 30) + 55; // Hard difficulty
27
+ }
28
+
29
+ // Solve the puzzle
30
+ const solvedSudoku = JSON.parse(JSON.stringify(sudoku)); // Create a deep copy for later use
31
+ solveSudoku(solvedSudoku);
32
+
33
+ // Determine the number of cells to remove based on difficulty level
34
+ let numToRemove;
35
+ if (difficulty === "e") {
36
+ numToRemove = Math.floor(Math.random() * 20) + 20; // Easy difficulty
37
+ } else if (difficulty === "m") {
38
+ numToRemove = Math.floor(Math.random() * 25) + 40; // Medium difficulty
39
+ } else if (difficulty === "h") {
40
+ numToRemove = Math.floor(Math.random() * 30) + 55; // Hard difficulty
41
+ } else {
42
+ throw new Error(
43
+ 'Invalid difficulty level. Please use "e" for easy, "m" for medium, or "h" for hard.'
44
+ );
45
+ }
46
+
47
+ // Create a copy of the solved Sudoku to remove cells from
48
+ const sudokuCopy = JSON.parse(JSON.stringify(solvedSudoku));
49
+
50
+ // Remove some numbers to create the puzzle
51
+ for (let i = 0; i < numToRemove; i++) {
52
+ const row = Math.floor(Math.random() * 9);
53
+ const col = Math.floor(Math.random() * 9);
54
+ if (sudokuCopy[row][col] !== 0) {
55
+ sudokuCopy[row][col] = 0;
38
56
  } else {
39
- throw new Error('Invalid difficulty level. Please use "e" for easy, "m" for medium, or "h" for hard.');
40
- }
41
-
42
- // Remove some numbers to create the puzzle
43
- for (let i = 0; i < numToRemove; i++) {
44
- const row = Math.floor(Math.random() * 9);
45
- const col = Math.floor(Math.random() * 9);
46
- if (sudoku[row][col] !== 0) {
47
- sudoku[row][col] = 0;
48
- } else {
49
- i--; // Try again if the cell is already empty
50
- }
57
+ i--; // Try again if the cell is already empty
51
58
  }
59
+ }
52
60
 
53
- return sudoku;
61
+ return { sudoku: sudokuCopy, solvedSudoku };
54
62
  }
55
63
 
56
64
  function solveSudoku(sudoku) {
57
- const emptyCell = findEmptyCell(sudoku);
58
- if (!emptyCell) {
59
- return true; // Puzzle solved successfully
65
+ const emptyCell = findEmptyCell(sudoku);
66
+ if (!emptyCell) {
67
+ return true; // Puzzle solved successfully
68
+ }
69
+
70
+ const [row, col] = emptyCell;
71
+ for (let num = 1; num <= 9; num++) {
72
+ if (isValidMove(sudoku, row, col, num)) {
73
+ sudoku[row][col] = num;
74
+ if (solveSudoku(sudoku)) {
75
+ return true;
76
+ }
77
+ sudoku[row][col] = 0; // Undo the assignment
60
78
  }
79
+ }
61
80
 
62
- const [row, col] = emptyCell;
63
- for (let num = 1; num <= 9; num++) {
64
- if (isValidMove(sudoku, row, col, num)) {
65
- sudoku[row][col] = num;
66
- if (solveSudoku(sudoku)) {
67
- return true;
68
- }
69
- sudoku[row][col] = 0; // Undo the assignment
70
- }
71
- }
72
-
73
- return false; // No solution found, backtrack
81
+ return false; // No solution found, backtrack
74
82
  }
75
83
 
76
84
  function findEmptyCell(sudoku) {
77
- // Function to find an empty cell in the Sudoku grid
78
- for (let row = 0; row < 9; row++) {
79
- for (let col = 0; col < 9; col++) {
80
- if (sudoku[row][col] === 0) {
81
- return [row, col];
82
- }
83
- }
85
+ // Function to find an empty cell in the Sudoku grid
86
+ for (let row = 0; row < 9; row++) {
87
+ for (let col = 0; col < 9; col++) {
88
+ if (sudoku[row][col] === 0) {
89
+ return [row, col];
90
+ }
84
91
  }
85
- return null; // No empty cell found
92
+ }
93
+ return null; // No empty cell found
86
94
  }
87
95
 
88
96
  function isValidMove(sudoku, row, col, num) {
89
- // Check if assigning num to the cell at (row, col) is a valid move
90
- // Check row
91
- for (let i = 0; i < 9; i++) {
92
- if (sudoku[row][i] === num) {
93
- return false; // Number already exists in the row
94
- }
97
+ // Check if assigning num to the cell at (row, col) is a valid move
98
+ // Check row
99
+ for (let i = 0; i < 9; i++) {
100
+ if (sudoku[row][i] === num) {
101
+ return false; // Number already exists in the row
95
102
  }
103
+ }
96
104
 
97
- // Check column
98
- for (let i = 0; i < 9; i++) {
99
- if (sudoku[i][col] === num) {
100
- return false; // Number already exists in the column
101
- }
105
+ // Check column
106
+ for (let i = 0; i < 9; i++) {
107
+ if (sudoku[i][col] === num) {
108
+ return false; // Number already exists in the column
102
109
  }
103
-
104
- // Check 3x3 subgrid
105
- const startRow = Math.floor(row / 3) * 3;
106
- const startCol = Math.floor(col / 3) * 3;
107
- for (let i = 0; i < 3; i++) {
108
- for (let j = 0; j < 3; j++) {
109
- if (sudoku[startRow + i][startCol + j] === num) {
110
- return false; // Number already exists in the subgrid
111
- }
112
- }
110
+ }
111
+
112
+ // Check 3x3 subgrid
113
+ const startRow = Math.floor(row / 3) * 3;
114
+ const startCol = Math.floor(col / 3) * 3;
115
+ for (let i = 0; i < 3; i++) {
116
+ for (let j = 0; j < 3; j++) {
117
+ if (sudoku[startRow + i][startCol + j] === num) {
118
+ return false; // Number already exists in the subgrid
119
+ }
113
120
  }
121
+ }
114
122
 
115
- return true; // Valid move
123
+ return true; // Valid move
116
124
  }
117
125
 
118
126
  function printSudoku(sudoku) {
119
- console.log("Sudoku Puzzle:");
120
- console.log("-------------------------");
121
- sudoku.forEach((row, rowIndex) => {
122
- if (rowIndex % 3 === 0 && rowIndex !== 0) {
123
- console.log("------|-------|-------");
124
- }
125
- row.forEach((cell, cellIndex) => {
126
- if (cellIndex % 3 === 0 && cellIndex !== 0) {
127
- process.stdout.write("| ");
128
- }
129
- process.stdout.write(String(cell || '.') + ' ');
130
- if (cellIndex === 8) {
131
- console.log();
132
- }
133
- });
127
+ console.log("Sudoku Puzzle:");
128
+ console.log("-------------------------");
129
+ sudoku.forEach((row, rowIndex) => {
130
+ if (rowIndex % 3 === 0 && rowIndex !== 0) {
131
+ console.log("------|-------|-------");
132
+ }
133
+ row.forEach((cell, cellIndex) => {
134
+ if (cellIndex % 3 === 0 && cellIndex !== 0) {
135
+ process.stdout.write("| ");
136
+ }
137
+ process.stdout.write(String(cell || ".") + " ");
138
+ if (cellIndex === 8) {
139
+ console.log();
140
+ }
134
141
  });
135
- console.log("-------------------------");
142
+ });
143
+ console.log("-------------------------");
136
144
  }
137
145
 
138
146
  function printSudokuWithAnswers(sudoku) {
139
- console.log("Sudoku Puzzle with Answers:");
140
- console.log("-------------------------");
141
- sudoku.forEach((row, rowIndex) => {
142
- if (rowIndex % 3 === 0 && rowIndex !== 0) {
143
- console.log("------|-------|-------");
144
- }
145
- row.forEach((cell, cellIndex) => {
146
- if (cellIndex % 3 === 0 && cellIndex !== 0) {
147
- process.stdout.write("| ");
148
- }
149
- process.stdout.write(String(cell) + ' ');
150
- if (cellIndex === 8) {
151
- console.log();
152
- }
153
- });
147
+ console.log("Sudoku Puzzle with Answers:");
148
+ console.log("-------------------------");
149
+ sudoku.forEach((row, rowIndex) => {
150
+ if (rowIndex % 3 === 0 && rowIndex !== 0) {
151
+ console.log("------|-------|-------");
152
+ }
153
+ row.forEach((cell, cellIndex) => {
154
+ if (cellIndex % 3 === 0 && cellIndex !== 0) {
155
+ process.stdout.write("| ");
156
+ }
157
+ process.stdout.write(String(cell) + " ");
158
+ if (cellIndex === 8) {
159
+ console.log();
160
+ }
154
161
  });
155
- console.log("-------------------------");
156
- // set flag to true and clear interval
157
- sudokuPrinted = true;
158
- clearInterval(intervalId);
162
+ });
163
+ console.log("-------------------------");
159
164
  }
160
165
 
161
- const difficulty = args[0]; // Get the difficulty level from command line arguments
162
-
163
- let sudokuPrinted = false;
166
+ function getHint(sudoku, solvedSudoku) {
167
+ const emptyCells = [];
168
+ for (let i = 0; i < 9; i++) {
169
+ for (let j = 0; j < 9; j++) {
170
+ if (sudoku[i][j] === 0) {
171
+ emptyCells.push([i, j]);
172
+ }
173
+ }
174
+ }
175
+ if (emptyCells.length === 0) {
176
+ console.log("No empty cells left to provide a hint.");
177
+ return;
178
+ }
179
+ const randomIndex = Math.floor(Math.random() * emptyCells.length);
180
+ const [row, col] = emptyCells[randomIndex];
181
+ sudoku[row][col] = solvedSudoku[row][col];
182
+ console.log(
183
+ `Hint: The number at row ${row + 1}, column ${col + 1} is ${
184
+ solvedSudoku[row][col]
185
+ }`
186
+ );
187
+ }
164
188
 
165
- // Set interval to run every 5 seconds
166
- const intervalId = setInterval(() => {
167
- // Check if sudokuPrinted is true
168
- if (sudokuPrinted) {
169
- // If sudokuPrinted is true, clear the interval
170
- clearInterval(intervalId);
171
- } else {
172
- // If sudokuPrinted is false, continue executing
173
- const sudoku = generateSudoku(difficulty);
189
+ function waitForHint(sudoku, solvedSudoku) {
190
+ const rl = readline.createInterface({
191
+ input: process.stdin,
192
+ output: process.stdout,
193
+ });
194
+
195
+ rl.question(
196
+ "Press 'h' for a hint or 'c' for the complete solution: ",
197
+ (answer) => {
198
+ if (answer.trim().toLowerCase() === "h") {
199
+ getHint(sudoku, solvedSudoku);
174
200
  printSudoku(sudoku);
175
- solveSudoku(sudoku); // Solve the generated puzzle
176
- printSudokuWithAnswers(sudoku);
201
+ } else if (answer.trim().toLowerCase() === "c") {
202
+ printSudokuWithAnswers(solvedSudoku);
203
+ process.exit();
204
+ } else {
205
+ console.log(
206
+ "Invalid input. Please press 'h' for a hint or 'c' for the complete solution."
207
+ );
208
+ }
209
+ rl.close();
210
+ waitForHint(sudoku, solvedSudoku); // Ask again for hint or complete solution
177
211
  }
178
- }, 5000);
212
+ );
213
+ }
214
+
215
+ const difficulty = args[0]; // Get the difficulty level from command line arguments
216
+
217
+ const { sudoku, solvedSudoku } = generateSudoku(difficulty);
218
+ printSudoku(sudoku);
219
+
220
+ waitForHint(sudoku, solvedSudoku);
179
221
 
180
222
  module.exports = {
181
- generateSudoku,
182
- printSudoku,
183
- solveSudoku,
184
- printSudokuWithAnswers
223
+ generateSudoku,
224
+ printSudoku,
225
+ solveSudoku,
226
+ printSudokuWithAnswers,
227
+ getHint,
228
+ waitForHint,
185
229
  };