feat: add initial project scaffolding with Makefile, C sources, web UI, and documentation
Add Makefile with build targets for sudoku solver, generator, and coverage reporting. Include NOTES.md explaining sudoku difficulty factors and solving techniques. Add README.md with puzzle examples and generator output. Implement app.js with Grid and Grid2 classes for rendering puzzle data in the browser. Add box.c with functions for box indexing, grid-to-array conversion, and box value extraction. Include footer.h with terminal size detection, cursor positioning, and footer display utilities. Add index.html with CSS grid layout and script loading for the web interface. Include rlib.h as a large utility header library.
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
#ifndef SUDOKU_H
|
||||
#define SUDOKU_H
|
||||
|
||||
#include "rlib.h"
|
||||
#include "rsolve.h"
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ANSII_BLUE_BG "\033[34m"
|
||||
#define ANSII_RED_BG "\033[31m"
|
||||
#define ANSII_GREEN_BG "\033[32m"
|
||||
#define ANSII_CLEAR "\033[0m"
|
||||
|
||||
#define N 9
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void draw_cell(int c)
|
||||
{
|
||||
if (c > 0 && c <= 3)
|
||||
{
|
||||
printf("%s", ANSII_BLUE_BG);
|
||||
}
|
||||
else if (c > 0 && c <= 6)
|
||||
{
|
||||
printf("%s", ANSII_GREEN_BG);
|
||||
}
|
||||
else if (c > 0 && c <= 9)
|
||||
{
|
||||
printf("%s", ANSII_RED_BG);
|
||||
}
|
||||
if(c){
|
||||
printf("%s%d ", c > 9 ? "" :" ", c );
|
||||
}else{
|
||||
printf(" 0 ");
|
||||
}
|
||||
printf("%s", ANSII_CLEAR);
|
||||
}
|
||||
|
||||
char * grid_to_string(int grid[N][N]){
|
||||
static char result[1024];
|
||||
result[0] = 0;
|
||||
for (int row = 0; row < N; row++) {
|
||||
for (int col = 0; col < N; col++) {
|
||||
char chunk[4];
|
||||
chunk[0] = 0;
|
||||
sprintf(chunk,"%d ",grid[row][col]);
|
||||
strcat(result,chunk);
|
||||
}
|
||||
strcat(result,"\n");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void print_grid(int grid[N][N],bool clear) {
|
||||
if(clear)
|
||||
printf("\033[2J\033[H");
|
||||
for (int row = 0; row < N; row++) {
|
||||
for (int col = 0; col < N; col++) {
|
||||
draw_cell(grid[row][col]);
|
||||
///printf("%d ", grid[row][col]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int count_neighbors2(int grid[N][N],int row, int col){
|
||||
// Check row
|
||||
int num = -1;
|
||||
int neighbors = 0;
|
||||
for (int x = 0; x < N; x++) {
|
||||
if(grid[row][x])
|
||||
neighbors++;
|
||||
if (grid[row][x] == num) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check column
|
||||
for (int x = 0; x < N; x++) {
|
||||
if(grid[x][col])
|
||||
neighbors++;
|
||||
if (grid[x][col] == num) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check box
|
||||
int startRow = row - row % (N / 3), startCol = col - col % (N / 3);
|
||||
for (int i = 0; i < N / 3; i++) {
|
||||
for (int j = 0; j < N / 3; j++) {
|
||||
if(grid[i + startRow][j + startCol])
|
||||
neighbors++;
|
||||
if (grid[i + startRow][j + startCol] == num) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
int is_safe(int grid[N][N], int row, int col, int num) {
|
||||
//if(count_neighbors(grid, row,col) < 4)
|
||||
// return false;
|
||||
// Check row
|
||||
for (int x = 0; x < N; x++) {
|
||||
if (grid[row][x] == num) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check column
|
||||
for (int x = 0; x < N; x++) {
|
||||
if (grid[x][col] == num) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check box
|
||||
int startRow = row - row % (N / 3), startCol = col - col % (N / 3);
|
||||
for (int i = 0; i < N / 3; i++) {
|
||||
for (int j = 0; j < N / 3; j++) {
|
||||
if (grid[i + startRow][j + startCol] == num) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void grid_reset(int * grid){
|
||||
memset(grid,0,N*N*sizeof(int));
|
||||
}
|
||||
int * grid_copy(int * grid){
|
||||
int * new_grid = malloc(N*N*sizeof(int));
|
||||
memcpy(new_grid,grid,N*N*sizeof(int));
|
||||
return new_grid;
|
||||
}
|
||||
|
||||
int * grid_new(){
|
||||
return (int *)calloc(sizeof(int),N*N);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool empty_spot_is_available(int grid[N][N]){
|
||||
for (unsigned int row = 0; row < N; row++) {
|
||||
for (unsigned int col = 0; col < N; col++) {
|
||||
if (grid[row][col] == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long long _solve(int grid[N][N], unsigned long long *attempts, bool draw){
|
||||
(*attempts)++;
|
||||
unsigned int row, col;
|
||||
if(!get_easiest_cell(grid,&row,&col)){
|
||||
//print_grid(grid, false);
|
||||
return *attempts;
|
||||
}
|
||||
for(int num = 1; num < N + 1; num++){
|
||||
if(is_safe(grid,row,col,num)){
|
||||
grid[row][col] = num;
|
||||
//print_grid(grid,true);
|
||||
if(_solve(grid,attempts,draw))
|
||||
{
|
||||
return *attempts;
|
||||
}
|
||||
grid[row][col] = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int _solve2(int grid[N][N], unsigned long long * attempts, bool draw) {
|
||||
(*attempts)++;
|
||||
unsigned int row, col;
|
||||
bool emptySpot = false;
|
||||
|
||||
for (row = 0; row < N; row++) {
|
||||
for (col = 0; col < N; col++) {
|
||||
if (grid[row][col] == 0) {
|
||||
// if(count_neighbors(grid,row,col) == 8){
|
||||
|
||||
// print_grid(grid,true);
|
||||
// printf("Found neighbors\n");
|
||||
// exit(0);
|
||||
//}
|
||||
emptySpot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emptySpot) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!emptySpot)
|
||||
return true;
|
||||
/*
|
||||
if (!empty_spot_is_available(grid)) {
|
||||
return true;
|
||||
}*/
|
||||
|
||||
for (int num = 1; num <= 9; num++) {
|
||||
//unsigned int * easy_row = calloc(sizeof(int),1);
|
||||
//unsigned int * easy_col = calloc(sizeof(int), 1);
|
||||
//if(get_easiest_cell(grid,easy_row,easy_col)){
|
||||
// row = *easy_row;
|
||||
// free(easy_row);
|
||||
// col = *easy_col;
|
||||
// free(easy_col);
|
||||
|
||||
//}
|
||||
if (is_safe(grid, row, col, num)) {
|
||||
grid[row][col] = num;
|
||||
if(draw)
|
||||
print_grid(grid,true);
|
||||
|
||||
if (_solve2(grid,attempts,draw)) {
|
||||
return *attempts;
|
||||
}
|
||||
|
||||
grid[row][col] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
unsigned int solve2(int grid[N][N], bool draw){
|
||||
unsigned long long attempts = 0;
|
||||
return _solve(grid,&attempts, draw);
|
||||
}
|
||||
|
||||
unsigned int solve(int grid[N][N],bool draw) {
|
||||
unsigned long long attempts = 0;
|
||||
return _solve2(grid,&attempts, draw);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user