I am working on a sudoku exercise using the backtracking algorithm using C. It prints the gameboard with the first solution it finds, however it does not stop there and continues the recursion by removing the fields of the gameboard and creates a new solution. The problem is somewhere in the solve function. Here is my approach:
#include "sudoku.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int field[SIZE][SIZE];
int initial[SIZE][SIZE];
/* Initializes the sudoku array.
* The field initial keeps the original start value for
* figuring out if a value is fixed or can be changed. */
void init(int begin[SIZE][SIZE]) {
memcpy(field, begin, SIZE * SIZE * sizeof(int));
memcpy(initial, begin, SIZE * SIZE * sizeof(int));
}
/* Retrieves the solution. NEEDED FOR AUTO-TESTING PURPOSES. */
void getResult(int result[SIZE][SIZE]){
memcpy(result, field, SIZE * SIZE * sizeof(int));
}
/* pretty prints the sudoku array */
void print() {
int row, col;
// print the first line
printf("||");
for (col = 0; col < SIZE - 1; col++) {
if (col % SQRT_SIZE == SQRT_SIZE - 1)
printf("===++");
else
printf("===+");
}
printf("===||\n");
// loop through all rows of the array
for (row = 0; row < SIZE; row++) {
// print the line with field values
for (col = 0; col < SIZE; col++) {
if (col % SQRT_SIZE == 0)
printf("|| ");
else
printf("| ");
if (field[row][col] == 0)
printf(" ");
else
printf("%d ", field[row][col]);
}
// print the separation line;
// depending on the result of the modulo operation
// print a single or double line
printf("||\n||");
if (row % SQRT_SIZE == SQRT_SIZE - 1) {
for (col = 0; col < SIZE - 1; col++) {
if (col % SQRT_SIZE == SQRT_SIZE - 1)
printf("===++");
else
printf("===+");
}
printf("===||\n");
}
else {
for (col = 0; col < SIZE - 1; col++) {
if (col % SQRT_SIZE == SQRT_SIZE - 1)
printf("---++");
else
printf("---+");
}
printf("---||\n");
}
}
}
/* Checks if the value is valid and can be set into the field.
* The function returns false if the value is already present or
* has been one of the initial values. */
int checkValueInField(int value, int row, int col) {
int i, r, c;
int squareRow;
int squareCol;
// checks for initial values
if (initial[row][col] != 0) {
if (initial[row][col] == value)
return 1;
else
return 0;
}
// check horizontally
for (i = 0; i < SIZE; i++) {
if (field[row][i] == value) return 0;
}
// check vertically
for (i = 0; i < SIZE; i++) {
if (field[i][col] == value) return 0;
}
// check square
squareRow = row / SQRT_SIZE;
squareCol = col / SQRT_SIZE;
for (r = squareRow * SQRT_SIZE; r < squareRow * SQRT_SIZE + SQRT_SIZE; r++) {
for (c = squareCol * SQRT_SIZE; c < squareCol * SQRT_SIZE + SQRT_SIZE; c++) {
if (field[r][c] == value) return 0;
}
}
return 1;
}
/* Set a value in the sudoku field if the field is empty.
* The method returns false if the field contains a fixed number. */
int setValueInField(int value, int row, int col) {
if (initial[row][col] == 0) {
field[row][col] = value;
return 1;
}
else if (initial[row][col] == value)
return 1;
return 0;
}
/* Removes a value in the sudoku field if it doesn't contain an initial value.
* The method returns false if the field contains a fixed number and cannot be
* removed. */
int removeValueFromField(int row, int col) {
if (initial[row][col] == 0) {
field[row][col] = 0;
return 1;
}
return 0;
}
/* Returns the value in the field */
int getValueFromField(int row, int col) {
return field[row][col];
}
/* Return true after a valid solution for the sudoku has been found. */
int solve(int row, int col) {
print();
bool isSet = false;
if (row == 0 && col == 0) {
for (int i = 1; i <= SIZE; i++) {
if (checkValueInField(i, row, col) && getValueFromField(row, col) == 0) {
isSet = setValueInField(i, row, col);
if (isSet) {
solve(row, col);
}
if (row == SIZE - 1 && col == SIZE - 1) {
return 1;
}
else {
removeValueFromField(row, col);
}
}
}
}
if (row == SIZE - 1 && col == SIZE - 1) {
//Here is the solution, but then it continues after returning 1
for (int r = 1; r <= SIZE; r++) {
for (int c = 1; c <= SIZE; c++) {
if (getValueFromField(r, c) != 0) {
return 1;
}
}
}
}
if (row == SIZE - 1) {
row = 0;
col = col++;
}
else {
row = row++;
}
for (int i = 1; i <= SIZE; i++) {
if (checkValueInField(i, row, col) == 1) {
isSet = setValueInField(i, row, col);
solve(row, col);
if (row == SIZE - 1 && col == SIZE == -1) {
return 1;
}
else {
removeValueFromField(row, col);
}
}
}
return 1;
}
This is my header file:
#ifndef _SUDOKU_H_
#define _SUDOKU_H_
#define SIZE 9
#define SQRT_SIZE 3
void init(int begin[SIZE][SIZE]);
void getResult(int result[SIZE][SIZE]);
void print();
int checkValueInField(int value, int row, int col);
int setValueInField(int value, int row, int col);
int removeValueFromField(int row, int col);
int getValueFromField(int row, int col);
int solve(int row, int col);
This is the initial gameboard and its solution:
int initial[SIZE][SIZE] = {
{0, 1, 0, 0, 0, 9, 0, 5, 0},
{0, 9, 0, 0, 0, 0, 4, 8, 0},
{0, 6, 0, 1, 0, 4, 0, 0, 0},
{0, 0, 5, 0, 0, 0, 9, 3, 0},
{0, 0, 0, 7, 0, 2, 0, 0, 0},
{0, 2, 1, 0, 0, 0, 8, 0, 0},
{4, 0, 0, 0, 8, 0, 6, 0, 9},
{0, 0, 0, 0, 6, 0, 5, 0, 3},
{2, 0, 0, 0, 3, 0, 0, 0, 0},
};
int expected[SIZE][SIZE] = {
{3, 1, 4, 8, 7, 9, 2, 5, 6},
{5, 9, 7, 3, 2, 6, 4, 8, 1},
{8, 6, 2, 1, 5, 4, 3, 9, 7},
{7, 4, 5, 6, 1, 8, 9, 3, 2},
{9, 3, 8, 7, 4, 2, 1, 6, 5},
{6, 2, 1, 5, 9, 3, 8, 7, 4},
{4, 7, 3, 2, 8, 5, 6, 1, 9},
{1, 8, 9, 4, 6, 7, 5, 2, 3},
{2, 5, 6, 9, 3, 1, 7, 4, 8},
};
This is my testcase:
TEST_CASE("Test2", "Sudoku")
{
int result = 0;
int actual[SIZE][SIZE];
int initial[SIZE][SIZE] = {
{0, 1, 0, 0, 0, 9, 0, 5, 0},
{0, 9, 0, 0, 0, 0, 4, 8, 0},
{0, 6, 0, 1, 0, 4, 0, 0, 0},
{0, 0, 5, 0, 0, 0, 9, 3, 0},
{0, 0, 0, 7, 0, 2, 0, 0, 0},
{0, 2, 1, 0, 0, 0, 8, 0, 0},
{4, 0, 0, 0, 8, 0, 6, 0, 9},
{0, 0, 0, 0, 6, 0, 5, 0, 3},
{2, 0, 0, 0, 3, 0, 0, 0, 0},
};
int expected[SIZE][SIZE] = {
{3, 1, 4, 8, 7, 9, 2, 5, 6},
{5, 9, 7, 3, 2, 6, 4, 8, 1},
{8, 6, 2, 1, 5, 4, 3, 9, 7},
{7, 4, 5, 6, 1, 8, 9, 3, 2},
{9, 3, 8, 7, 4, 2, 1, 6, 5},
{6, 2, 1, 5, 9, 3, 8, 7, 4},
{4, 7, 3, 2, 8, 5, 6, 1, 9},
{1, 8, 9, 4, 6, 7, 5, 2, 3},
{2, 5, 6, 9, 3, 1, 7, 4, 8},
};
init(initial);
result = solve(0,0);
getResult(actual);
INFO("Test Case: valid Sudoku board failed.");
REQUIRE(memcmp(actual, expected, sizeof(initial)) == 0);
INFO("Test Case: return value not correct.");
REQUIRE(result == 1);
}
Related
I have gotten this error a few times in my code and I've never come across it before. Sudoku is a 2d numpy array. Can anyone tell me why and how to fix it?
An example of the sudoku array would be
sudoku = np.array([[0, 2, 4, 7, 6, 3, 5, 9, 1], [3, 9, 7, 4, 5, 0, 8, 2, 6], [8, 5, 6, 9, 2, 0, 0, 4, 7], [0, 8, 9, 5, 3, 6, 7, 1, 4], [7, 3, 1, 2, 9, 4, 6, 5, 8], [6, 4, 5, 8, 1, 7, 9, 3, 2], [4, 7, 2, 3, 8, 9, 1, 6, 5], [9, 1, 8, 6, 4, 5, 2, 7, 3], [5, 6, 3, 1, 7, 2, 4, 8, 9]])
import numpy as np
import copy
global subgrids
sudoku = np.array([[0, 2, 4, 7, 6, 3, 5, 9, 1], [3, 9, 7, 4, 5, 0, 8, 2, 6], [8, 5, 6, 9, 2, 0, 0, 4, 7], [0, 8, 9, 5, 3, 6, 7, 1, 4], [7, 3, 1, 2, 9, 4, 6, 5, 8], [6, 4, 5, 8, 1, 7, 9, 3, 2], [4, 7, 2, 3, 8, 9, 1, 6, 5], [9, 1, 8, 6, 4, 5, 2, 7, 3], [5, 6, 3, 1, 7, 2, 4, 8, 9]])
ad = sudoku.tolist()
frontier = sudoku
subgrids = []
moves = [1,2,3,4,5,6,7,8,9]
columns = []
for i in range(0,9):
columns.append([row[i] for row in sudoku])
def is_possible(sudoku):
for i in range(0, 9):
for j in range(1, 10):
if np.any([ad[i].count(j) > 1] or [columns[i].count(j) > 1]):
return False
return True
sc = copy.deepcopy(ad)
for i in range(0,9,3):
for j in range(0,9,3):
subgrids.append(sc[i][j:j+3]+sc[i+1][j:j+3]+sc[i+2][j:j+3])
def get_next_zero(sudoku):
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
index = [i,j] #i is row index, j is column index
possible_values(index,subgrids)
return True
def is_solution(sudoku):
if is_possible(sudoku) == False:
return False
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
return False
return True
def possible_values(ind,grid):
possible_num = []
row = [a for a in sudoku[ind[0]]]
row = list(row)
column = []
for i in range(0,9):
column.append(sudoku[i][ind[1]])
column = list(column)
if ind[0] < 3:
if ind[1] < 3:
sub = grid[0]
elif 2 < ind[1] < 6:
sub = grid[1]
else:
sub = grid[2]
if 2 < ind[0] < 6:
if ind[1] < 3:
sub = grid[3]
elif 2 < ind[1] < 6:
sub = grid[4]
else:
sub = grid[5]
if ind[0] > 5:
if ind[1] < 3:
sub = grid[6]
elif 2 < ind[1] < 6:
sub = grid[7]
else:
sub = grid[8]
sub = list(sub)
for num in moves:
if num not in row and num not in column and num not in sub:
possible_num.append(num)
solver(possible_num, ind)
def solver(actions, where):
if len(actions) < 1:
np.delete(frontier,len(frontier)-1)
else:
for action in actions:
sudoku[where[0]][where[1]] = action
new_state = sudoku
if is_possible(new_state) == True:
np.append(frontier,new_state)
else:
np.delete(frontier,sudoku)
new_state = frontier.pop()
sudoku_solver(new_state)
def sudoku_solver(sudoku):
if is_possible(sudoku) == False:
print (np.full((9,9),-1))
elif is_solution(sudoku) == True:
print(sudoku)
else:
get_next_zero(sudoku)
sudoku_solver(sudoku)
for num in moves:
if num not in row and num not in column and num not in sub:
possible_num.append(num)
solver(possible_num, ind)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Another point in the code too
def is_solution(sudoku):
if is_possible(sudoku) == False:
return False
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
return False
return True
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Given a 2D array where each digit represents a different color, I want to be able to find out if a given node in the array is surrounded completely by one color. For example, in the 2d array below, I want to be able to confirm that the node at [3][3] is completely surrounded by the color represented by "1". Is there an existing common algorithm that accomplishes this?
{{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 2, 2, 2, 2, 1, 1, 0},
{1, 1, 1, 2, 2, 1, 1, 1},
{1, 1, 1, 2, 2, 2, 2, 1},
{1, 1, 1, 1, 1, 2, 1, 1},
{1, 1, 1, 1, 1, 1, 2, 1}}
EDIT: Sorry I am not asking about whether the target node is immediately surrounded. I am asking about whether if you move out from the target node, you can reach the edge of the array without crossing over the boundary color.
My current code is the following, but it's not quite working
let squaresChecked = []
let squareSurrounded = true
let boardSize = 15
let gameBoard = new Array(boardSize)
for(let i=0; i<gameBoard.length; i++){
gameBoard[i] = Array(boardSize).fill('white')
}
checkSurrounded(x, y, boundaryColor){
if(x >= boardSize || y >= boardSize || x < 0 || y < 0){
squareSurrounded = false
return
}
if(gameBoard[x][y] === boundaryColor){return}
if(squaresChecked.includes(x + ' ' + y)){return}
squaresChecked.push(x + ' ' + y)
checkSurrounded(x+1, y, boundaryColor)
checkSurrounded(x-1, y, boundaryColor)
checkSurrounded(x, y+1, boundaryColor)
checkSurrounded(x, y-1, boundaryColor)
}
This should check for top, left, right, bottom for given cell at row,col in 2D array if surrounded by var surroundedBy (1).
row = 2
col = 2
arr = [[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 1, 1, 0],
[1, 1, 1, 2, 2, 1, 1, 1],
[1, 1, 1, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 2, 1, 1],
[1, 1, 1, 1, 1, 1, 2, 1]]
surroundedBy = 1
if(arr[row-1][col] ===surroundedBy && arr[row+1][col] === surroundedBy && arr[row][col - 1] === surroundedBy && arr[row][col + 1] === surroundedBy) {
console.log('surrounded');
}else{
console.log('not surrounded');
}
Given this divide algorithm and sample data:
const data = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0
]
function divide(data, size) {
const result = []
for (let i = 0; i < data.length; i += size) {
const chunk = data.slice(i, i + size);
result.push(chunk)
}
if (result.length > size) {
return divide(result, size)
}
return result;
}
const result = divide(data, 5);
console.log(result)
How do you calculate the number of levels in the resulting tree? In this case of block size 5, I think there are 3 are 4 levels about, but what is the equation to use so you don't have to compute the actual tree? Basically getDepth(numItems, blockSize)?
Every recursive call reduces the input size by a factor of blocksize.
Starting with your example of 100 items. This is grouped into 20, these 20 are grouped into 4 and the algorithm ends.
The expression that capture this is log with a base of blocksize.
f(n,m) = ceil(log_base_m(n))
The depth of the example tree is
ceil(log5(99))
In general:
ceil(logchunksize(datasize-1))
I'm tyring to create a frequency counter. Basically, there's an array (testArray) with a bunch of numbers. I need to process those numbers and insert them in another array (probabilityArray). probabilityArray is also 2D array with the 1st row being the unique elements from the test array, the 2nd row being how many times a unique number occurs (Ex. probabilityArray[2][5] represents how often the number at probabilityArray[1][5] occurs). I'm having trouble exiting the rows for loop and I have no idea why.
#include <stdio.h>
#include <stdlib.h>
int histogram() {
}
int entropy() {
}
int main() {
int i, j, k, found = 0, currentPosition = 0, l = 0, x = 0, y = 0;
int testArray[10][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18 ,19, 20},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}};
int row = sizeof(testArray) / sizeof(testArray[0]);
int col = sizeof(testArray[0]) / sizeof(testArray[0][0]);
int elements = (row * col);
printf("Elements: %d\n", elements);
//printf("Rows: %d\nCols: %d\n", row, col);
int probabilityArray[3][elements];
for(x = 0; x < 3; x++) {
for(y = 0; y < elements; y++) {
//printf("X: %d\tY: %d\t", x, y);
probabilityArray[x][y] = 0;
}
//printf("\n");
}
//printf("Got here\n");
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
printf("%d\n", l);
l++;
int temp = testArray[i][j];
for (k = 0; k < currentPosition; k++) {
if (probabilityArray[1][k] == temp) {
//Element is not unique, increase occurance counter
printf("NOT UNIQUE: %d\n", temp);
probabilityArray[2][k]++;
found = 1;
break;
}
}
if (found == 0) {
//Element is unique, add it to array
printf("FOUND: %d\n", temp);
probabilityArray[1][currentPosition] = temp;
probabilityArray[2][currentPosition]++;
currentPosition++;
printf("Current Position: %d\n", currentPosition);
}
found = 0;
}
printf("I: %d\tC: %d\n", i, j);
}
for (i = 0; i < currentPosition; i++) {
probabilityArray[3][i] = (int)((probabilityArray[2][i] / elements) * 100);
}
for (i = 0; i < currentPosition; i++) {
printf("ELEMENT: %d\t\tFREQUENCY: %d\t\tPROBABILITY:%d\n", probabilityArray[1][i], probabilityArray[2][i], probabilityArray[3][i]);
}
}
Any help is appreciated!
You are using indices 1, 2, and 3, where you probably meant to use 0, 1, and 2.
Here:
if (probabilityArray[1][k] == temp) { // Should it be 0??
//Element is not unique, increase occurance counter
printf("NOT UNIQUE: %d\n", temp);
probabilityArray[2][k]++; // Should it be 1??
and here:
probabilityArray[1][currentPosition] = temp; // Should it be 0??
probabilityArray[2][currentPosition]++; // Should it be 1??
and here:
probabilityArray[3][i] = (int)((probabilityArray[2][i] / elements) * 100);
// Should it be 2 and 1 ??
and here:
printf("ELEMENT: %d\t\tFREQUENCY: %d\t\tPROBABILITY:%d\n",
probabilityArray[1][i], probabilityArray[2][i], probabilityArray[3][i]);
// Should be be 0, 1, and 2
Fixing those might fix your problems.
I haven't used C in 5-6 years, and feel that this is probably a really obvious answer.
I thought that arrays were passed by reference automatically in C, so my code below should modify the values of the array created in main() within the change function. It changes the values of the local variable within the change function, but this is not reflected afterwards in the main function.
Here is my code for my example:
int main(){
int array[3][5];
int i;
int j;\
printf("BEFORE (MAIN):\n");
for(i = 0; i < 3; i++){
for(j = 0; j < 5; j++){
array[i][j] = 1;
printf("%i, ", array[i][j]);
}
}
printf("\n\n");
change(array);
printf("\n");
printf("AFTER (MAIN):\n");
for(i = 0; i < 3; i++){
for(j = 0; j < 5; j++){
array[i][j] = 1;
printf("%i, ", array[i][j]);
}
}
printf("\n");
return 1;
}
void change(int array[][5]){
printf("PRECHANGE (CHANGE):\n");
int i;
int j;
for(i = 0; i < 3; i++){
for(j = 0; j < 5; j++){
printf("%i, ", array[i][j]);
}
}
printf("\n\n");
printf("AFTER CHANGE (CHANGE):\n");
for(i = 0; i < 3; i++){
for(j = 0; j < 5; j++){
array[i][j] = 0;
printf("%i, ", array[i][j]);
}
}
printf("\n");
}
The output is as follows:
BEFORE (MAIN):
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
PRECHANGE (CHANGE):
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
AFTER CHANGE (CHANGE):
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
AFTER (MAIN):
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
I would have thought it should be this:
BEFORE (MAIN):
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
PRECHANGE (CHANGE):
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
AFTER CHANGE (CHANGE):
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
AFTER (MAIN):
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
If you set the value to 1
printf("AFTER (MAIN):\n");
for(i = 0; i < 3; i++){
for(j = 0; j < 5; j++){
array[i][j] = 1; /* set to 1 and print afterwards */
printf("%i, ", array[i][j]);
}
}
why do you expect 0 to be printed?