So I am trying to improve my sudoku validator and test it's performance, I wanted to know that how I can reassign threads, I changed up the code a bit but when I am specifying the number of threads, it is only scanning that many items in the sudoku
Enter the size of Sudoku (4, 9, 16, etc.): 4
Enter the number of threads: 2
Thread 1 checks row 1 and is valid.
Thread 2 checks column 1 and is valid.
Sudoku is valid.
The total time taken is 278.00 microseconds.
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <math.h>
#define MAX_SIZE 64
int sudoku[MAX_SIZE][MAX_SIZE];
// Function to check if a number can be placed at a given position
int is_valid(int row, int col, int num, int size) {
// Check row
for (int i = 0; i < size; i++) {
if (i != col && sudoku[row][i] == num) {
return 0;
}
}
// Check column
for (int i = 0; i < size; i++) {
if (i != row && sudoku[i][col] == num) {
return 0;
}
}
// Check subgrid
int subgrid_size = (int)sqrt(size);
int start_row = row - row % subgrid_size;
int start_col = col - col % subgrid_size;
for (int i = start_row; i < start_row + subgrid_size; i++) {
for (int j = start_col; j < start_col + subgrid_size; j++) {
if (i != row && j != col && sudoku[i][j] == num) {
return 0;
}
}
}
return 1;
}
// Function to solve the Sudoku using backtracking
int solve_sudoku(int row, int col, int size) {
if (row == size) {
return 1;
}
if (col == size) {
return solve_sudoku(row + 1, 0, size);
}
if (sudoku[row][col] != 0) {
return solve_sudoku(row, col + 1, size);
}
for (int num = 1; num <= size; num++) {
if (is_valid(row, col, num, size)) {
sudoku[row][col] = num;
if (solve_sudoku(row, col + 1, size)) {
return 1;
}
sudoku[row][col] = 0;
}
}
return 0;
}
// Struct to pass arguments to thread function
typedef struct {
int thread_id;
int start;
int end;
int size;
int valid;
} ThreadArgs;
// Thread function to check validity of rows, columns, and subgrids
void *thread_function(void *args) {
ThreadArgs *thread_args = (ThreadArgs *)args;
int local_valid = 1;
// Check rows
if (thread_args->thread_id <= thread_args->size) {
int row = thread_args->thread_id - 1;
for (int j = 0; j < thread_args->size; j++) {
if (!is_valid(row, j, sudoku[row][j], thread_args->size)) {
local_valid = 0;
break;
}
}
// Print row validation message
if (local_valid) {
printf("Thread %d checks row %d and is valid.\n", thread_args->thread_id, thread_args->thread_id);
} else {
printf("Thread %d checks row %d and is invalid.\n", thread_args->thread_id, thread_args->thread_id);
}
}
// Check columns
if (thread_args->thread_id > thread_args->size && thread_args->thread_id <= 2 * thread_args->size) {
int col = thread_args->thread_id - 1 - thread_args->size;
for (int i = 0; i < thread_args->size; i++) {
if (!is_valid(i, col, sudoku[i][col], thread_args->size)) {
local_valid = 0;
break;
}
}
// Print column validation message
if (local_valid) {
printf("Thread %d checks column %d and is valid.\n", thread_args->thread_id, thread_args->thread_id - thread_args->size);
} else {
printf("Thread %d checks column %d and is invalid.\n", thread_args->thread_id, thread_args->thread_id - thread_args->size);
}
}
// Check subgrids
if (thread_args->thread_id > 2 * thread_args->size && thread_args->thread_id <= 3 * thread_args->size) {
int subgrid_size = (int)sqrt(thread_args->size);
int subgrid_num = thread_args->thread_id - 2 * thread_args->size;
int start_row = ((subgrid_num - 1) / subgrid_size) * subgrid_size;
int start_col = ((subgrid_num - 1) % subgrid_size) * subgrid_size;
for (int i = start_row; i < start_row + subgrid_size; i++) {
for (int j = start_col; j < start_col + subgrid_size; j++) {
if (!is_valid(i, j, sudoku[i][j], thread_args->size)) {
local_valid = 0;
break;
}
}
}
// Print subgrid validation message
if (local_valid) {
printf("Thread %d checks subgrid %d and is valid.\n", thread_args->thread_id, subgrid_num);
} else {
printf("Thread %d checks subgrid %d and is invalid.\n", thread_args->thread_id, subgrid_num);
}
}
// Update overall validity (only thread 1)
if (thread_args->thread_id == 1) {
thread_args->valid = local_valid;
}
pthread_exit(NULL);
}
int main() {
int size, K;
printf("Enter the size of Sudoku (4, 9, 16, etc.): ");
scanf("%d", &size);
if (size > MAX_SIZE || (int)sqrt(size) != sqrt(size)) {
printf("Sudoku size must be a square number less than or equal to 64.\n");
return 1;
}
printf("Enter the number of threads: ");
scanf("%d", &K);
if (K < 1) {
printf("Number of threads must be at least 1.\n");
return 1;
}
FILE *file = fopen("input.tex", "r");
if (file == NULL) {
printf("Error opening file.\n");
return 1;
}
fscanf(file, "%d", &size);
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
fscanf(file, "%d", &sudoku[i][j]);
}
}
fclose(file);
clock_t start, end;
double cpu_time_used;
start = clock();
int valid = 1;
// Array to hold pthread IDs
pthread_t threads[K];
// Array to hold thread arguments
ThreadArgs thread_args[K];
// Create and execute threads
for (int i = 0; i < K; i++) {
thread_args[i].thread_id = i + 1;
thread_args[i].start = i * size / K + 1;
thread_args[i].end = (i + 1) * size / K;
thread_args[i].size = size;
thread_args[i].valid = 1;
int rc = pthread_create(&threads[i], NULL, thread_function, (void *)&thread_args[i]);
if (rc) {
printf("Error: Unable to create thread %d.\n", i + 1);
exit(-1);
}
}
// Join threads
for (int i = 0; i < K; i++) {
pthread_join(threads[i], NULL);
if (!thread_args[i].valid) {
valid = 0;
}
}
if (valid) {
printf("Sudoku is valid.\n");
} else {
printf("Sudoku is invalid.\n");
}
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
double microseconds = cpu_time_used * 1000000;
printf("The total time taken is %.2f microseconds.\n", microseconds);
return 0;
}
I want it to reassign the thread to scanning something else, like once thread 1 is done scanning row 1, it should get reassigned to row 2 or col 2, or smth.