The Algorithm
Each possible configuration of the Peg Solitaire (Pegsol) is a tuple made of: m × m grid
board, the
position of the cursor and whether the peg under the cursor has been selected. This tuple is
called
a state. The Pegsol Graph G = <V, E> is implicitly defined. The vertex set V is defined as all
the
possible configurations (states), and the edges E connecting two vertexes are defined by the
legal jump
actions (right, left, up, down).
Your task is to find the path leading to the best solution, i.e. leading to the vertex (state) with
the
least number of remaining pegs. A path is a sequence of actions. You are going to use
Depth First
Search to find the best solution, up to a maximum budget of expanded/explored nodes
(nodes for
which you’ve generated its children).
When the AI solver is called (Algorithm 1 ), it should explore all possible paths (sequence of
jump
actions) following a Depth First Search (DFS) strategy, until consuming the budget or until a
path
solving the game is found. Note that we do not include duplicate states in the search. If a
state was
already generated, we will not include it again in the stack (line 21 ). The algorithm should
return the
best solution found, the path leading to the least number of remaining pegs. This path will
then
be executed by the game engine.
You might have multiple paths leading to a solution. Your algorithm should consider the
possible action by scanning the board in this order: traverse coordinate x = 0,....., m first, and
then y = 0, … , m looking for a peg that can jump, and then selecting jumping actions left,
right, up or down.
Make sure you manage the memory well. When you finish running the algorithm, you have
to free all
the nodes from the memory, otherwise you will have memory leaks. You will notice that the
algorithm
can run out of memory fairly fast after expanding a few million nodes.
When you applyAction you have to create a new node, that
points to the parent,
updates the state with the action chosen,
updates the depth of the node.
updates the action used to create the node
I'm implementing this algorithm with the following code:
#include <time.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include "ai.h"
#include "utils.h"
#include "hashtable.h"
#include "stack.h"
void copy_state(state_t* dst, state_t* src){
//Copy field
memcpy( dst->field, src->field, SIZE*SIZE*sizeof(int8_t) );
dst->cursor = src->cursor;
dst->selected = src->selected;
}
/**
* Saves the path up to the node as the best solution found so far
*/
void save_solution( node_t* solution_node ){
node_t* n = solution_node;
while( n->parent != NULL ){
copy_state( &(solution[n->depth]), &(n->state) );
solution_moves[n->depth-1] = n->move;
n = n->parent;
}
solution_size = solution_node->depth;
}
node_t* create_init_node( state_t* init_state ){
node_t * new_n = (node_t *) malloc(sizeof(node_t));
new_n->parent = NULL;
new_n->depth = 0;
copy_state(&(new_n->state), init_state);
return new_n;
}
/**
* Apply an action to node n and return a new node resulting from executing the action
*/
node_t* applyAction(node_t* n, position_s* selected_peg, move_t action ){
node_t* new_node = NULL;
//printf("PASS#");
//FILL IN MISSING CODE
new_node = create_init_node( &(n->state));
new_node->parent = n;
n->depth = n->depth + 1;
execute_move_t( &(new_node->state), &(new_node->state.cursor), action );
return new_node;
}
// From here my implementation starts
/**
* Find a solution path as per algorithm description in the handout
*/
void find_solution( state_t* init_state ){
HashTable table;
int8_t x,y;
int remainingPegs;
// Choose initial capacity of PRIME NUMBER
// Specify the size of the keys and values you want to store once
ht_setup( &table, sizeof(int8_t) * SIZE * SIZE, sizeof(int8_t) * SIZE * SIZE, 16769023);
// Initialize Stack
initialize_stack();
//Add the initial node
node_t* n = create_init_node( init_state );
node_t* new_node = NULL;
//FILL IN THE GRAPH ALGORITHM
stack_push(n);
remainingPegs = num_pegs(&(n->state));
while(!is_stack_empty())
{
n = stack_top();
expanded_nodes = expanded_nodes + 1;
if(num_pegs(&(n->state)) < remainingPegs )
{
save_solution(n);
remainingPegs = num_pegs(&(n->state));
}
for (x=0;x<SIZE;x++) {
for (y=0;y<SIZE;y++) {
enum moves_e a = left;
if(can_apply(&(n->state),&(n->state.cursor),a)){
printf("World cup");
node_t* new_node = applyAction(n,&(n->state.cursor),a);
generated_nodes = generated_nodes + 1;
//printf("%d",generated_nodes);
}
a = right;
if(can_apply(&(n->state),&(n->state.cursor),a)){
printf("World cup");
node_t* new_node = applyAction(n,&(n->state.cursor),a);
generated_nodes = generated_nodes + 1;
//printf("%d",generated_nodes);
}
a = up;
if(can_apply(&(n->state),&(n->state.cursor),a)){
printf("World cup");
node_t* new_node = applyAction( n,&(n->state.cursor),a);
generated_nodes = generated_nodes + 1;
//printf("%d",generated_nodes);
}
a = down;
if(can_apply(&(n->state),&(n->state.cursor),a)){
node_t* new_node = applyAction( n,&(n->state.cursor),a);
generated_nodes = generated_nodes + 1;
//printf("%d",generated_nodes);
}
//Comment line number 134 here where segmentation fault occured
if (won(&(new_node->state)))
{
//save_solution(new_node);
//remainingPegs = num_pegs(&(new_node->state));
//free_stack();
break;
}
if(new_node->depth == 0)
{
stack_push(new_node);
}
if(expanded_nodes >= budget)
break;
}
}
}
}
And another helper methods are present in util.c are mentioned below:
#include "utils.h"
#include "layouts.h"
void execute_move_t(state_t* state, position_s* selected_peg, move_t jump) {
int8_t x = selected_peg->x;
int8_t y = selected_peg->y;
switch (jump) {
case up: //Jump up
state->field[x][y-2] = 'o';
state->field[x][y-1] = '.';
state->field[x][y-0] = '.';
state->cursor.y = y-2;
break;
case down: //Jump down
state->field[x][y+0] = '.';
state->field[x][y+1] = '.';
state->field[x][y+2] = 'o';
state->cursor.y = y+2;
break;
case left: //Jump left
state->field[x-2][y] = 'o';
state->field[x-1][y] = '.';
state->field[x-0][y] = '.';
state->cursor.x = x-2;
break;
case right: //Jump right
state->field[x+0][y] = '.';
state->field[x+1][y] = '.';
state->field[x+2][y] = 'o';
state->cursor.x = x+2;
break;
}
}
bool can_apply(state_t *board, position_s* selected_peg, move_t jump){
//printf("%d",jump);
// Can select a Peg
if ( board->field[ selected_peg->x ][ selected_peg->y ] !='o') return false;
//Determine if move is legal
switch (jump) {
case up:
//printf("Up");
if( selected_peg->y < 2) return false;
if( board->field[ selected_peg->x ][ selected_peg->y - 1 ] !='o') return false;
if( board->field[ selected_peg->x ][ selected_peg->y - 2 ] !='.') return false;
printf("Up");
break;
case down:
//printf("Down");
if( selected_peg->y > SIZE - 3 ) return false;
if( board->field[ selected_peg->x ][ selected_peg->y + 1 ] !='o') return false;
if( board->field[ selected_peg->x ][ selected_peg->y + 2 ] !='.') return false;
printf("Down");
break;
case left:
//printf("Left");
if( selected_peg->x < 2) return false;
if( board->field[ selected_peg->x - 1 ][ selected_peg->y ] !='o') return false;
if( board->field[ selected_peg->x - 2 ][ selected_peg->y ] !='.') return false;
break;
case right:
//printf("Right");
if( selected_peg->x > SIZE - 3) return false;
if( board->field[ selected_peg->x + 1 ][ selected_peg->y ] !='o') return false;
if( board->field[ selected_peg->x + 2 ][ selected_peg->y ] !='.') return false;
printf("Right");
break;
}
// Can Jump
return true;
}
bool won(state_t *board) {
int8_t x,y;
int8_t count=0;
for (x=0;x<SIZE;x++) {
for (y=0;y<SIZE;y++) {
if (board->field[x][y]=='o') {
count++;
}
// If more than one peg is left, you haven't won yet
if( count > 1) return false;
}
}
//If only one is left
return count == 1;
}
int num_pegs( state_t *board ){
int count = 0;
for (int y=0;y<SIZE;y++) {
for (int x=0;x<SIZE;x++) {
count+=board->field[x][y]=='o';
}
}
return count;
}
void rotateBoard(state_t *board) {
int8_t i,j,n=SIZE;
int8_t tmp;
for (i=0; i<n/2; i++){
for (j=i; j<n-i-1; j++){
tmp = board->field[i][j];
board->field[i][j] = board->field[j][n-i-1];
board->field[j][n-i-1] = board->field[n-i-1][n-j-1];
board->field[n-i-1][n-j-1] = board->field[n-j-1][i];
board->field[n-j-1][i] = tmp;
}
}
i = board->cursor.x;
j = board->cursor.y;
board->cursor.x = -(j-n/2)+n/2;
board->cursor.y = (i-n/2)+n/2;
}
bool select_peg(state_t *board) {
int8_t x,y,(*field)[SIZE];
bool selected;
x = board->cursor.x;
y = board->cursor.y;
field = board->field;
selected = board->selected;
if (field[x][y]!='o') return false;
board->selected = !selected;
return true;
}
bool moveUp(state_t *board) {
int8_t x,y,(*field)[SIZE];
bool selected;
x = board->cursor.x;
y = board->cursor.y;
field = board->field;
selected = board->selected;
if (selected) {
if (y<2) return false;
if (field[x][y-2]!='.') return false;
if (field[x][y-1]!='o') return false;
if (field[x][y-0]!='o') return false;
field[x][y-2] = 'o';
field[x][y-1] = '.';
field[x][y-0] = '.';
board->cursor.y = y-2;
board->selected = false;
} else {
if (y<1) return false;
if (field[x][y-1]==' ') return false;
board->cursor.y = y-1;
}
return true;
}
bool moveLeft(state_t *board) {
bool success;
rotateBoard(board);
success = moveUp(board);
rotateBoard(board);
rotateBoard(board);
rotateBoard(board);
return success;
}
bool moveDown(state_t *board) {
bool success;
rotateBoard(board);
rotateBoard(board);
success = moveUp(board);
rotateBoard(board);
rotateBoard(board);
return success;
}
bool moveRight(state_t *board) {
bool success;
rotateBoard(board);
rotateBoard(board);
rotateBoard(board);
success = moveUp(board);
rotateBoard(board);
return success;
}
int8_t validMovesUp(state_t *board) {
int8_t x,y;
int8_t count=0;
for (x=0;x<SIZE;x++) {
for (y=SIZE-1;y>1;y--) {
if (board->field[x][y]=='o') {
if (board->field[x][y-1]=='o') {
if (board->field[x][y-2]=='.') {
count++;
}
}
}
}
}
return count;
}
bool gameEndedForHuman(state_t *board) {
int8_t i,count=0;
for (i=0;i<4;i++) {
count+=validMovesUp(board);
rotateBoard(board);
}
return count==0;
}
void initialize(state_t *board, int8_t layout) {
int8_t x,y;
if( layout > NUM_LAYOUTS - 1) layout = 0;
board->cursor.x = 4;
board->cursor.y = 4;
board->selected = false;
memset(board->field,0,sizeof(board->field));
for (y=0;y<SIZE;y++) {
for (x=0;x<SIZE;x++) {
board->field[x][y]=configuration[layout][y][x*2];
}
}
}
void drawBoard(state_t *board) {
int8_t x,y,count=0;
// move cursor to home position
printf("\033[H");
for (y=0;y<SIZE;y++) {
for (x=0;x<SIZE;x++) {
count+=board->field[x][y]=='o';
}
}
printf("peg-solitaire.c %7d pegs\n",count);
printf(" \n");
for (y=0;y<SIZE;y++) {
for (x=0;x<14-SIZE;x++) {
printf(" ");
}
for (x=0;x<SIZE;x++) {
if (board->cursor.x == x && board->cursor.y == y) {
if (board->selected) {
printf("\b|\033[7m%c\033[27m|",board->field[x][y]);
} else {
printf("\033[7m%c\033[27m ",board->field[x][y]);
}
} else {
printf("%c ",board->field[x][y]);
}
}
for (x=0;x<14-SIZE;x++) {
printf(" ");
}
printf("\n");
}
printf(" \n");
printf(" arrow keys, q or enter \n");
printf("\033[A"); // one line up
}
char* action_cstr(move_t move){
switch (move) {
case up:
return "Up";
break;
case down:
return "Down";
break;
case left:
return "Left";
break;
case right:
return "Right";
break;
}
return " ";
}
void print_solution(){
for(int i=0; i< solution_size; i++)
printf(" %d - %s \n", i+1, action_cstr(solution_moves[i]));
}
void play_solution(){
for(int i=0; i <= solution_size; i++){
drawBoard(&(solution[i]));
usleep(500000);
if( i < solution_size){
//Reverse action
switch ( solution_moves[i] ) {
case up:
solution[i].cursor.y = solution[i+1].cursor.y+2;
solution[i].cursor.x = solution[i+1].cursor.x;
break;
case down:
solution[i].cursor.y = solution[i+1].cursor.y-2;
solution[i].cursor.x = solution[i+1].cursor.x;
break;
case left:
solution[i].cursor.x = solution[i+1].cursor.x+2;
solution[i].cursor.y = solution[i+1].cursor.y;
break;
case right:
solution[i].cursor.x = solution[i+1].cursor.x-2;
solution[i].cursor.y = solution[i+1].cursor.y;
break;
}
solution[i].selected = true;
drawBoard(&(solution[i]));
usleep(500000);
}
}
}
It results in a segmentation fault. Please, anyone, help me to resolve this issue.
Related
So, I'm trying to do an impletation of Sharing Suffixes WITHOUT USING UKKONNENS ALGORITHM (don't understand ukkonnens). So basicaly what I'd do is searching for a word in every node that isn't ending. However, when I try to debug it, it returns a negative value. I honestly don't know how to solve it, I made constant breakpoints so it would come out of the loop and not do as many iterations but it just keeps going.
I'm very new to C so for me this is a hard thing and I appreciate all the help.
#include "trie.h"
tree_t create_trie()
{
int i = 0;
tree_t node = (tree_t)malloc(sizeof(struct _node));
for(i = 0; i < 26; i++)
{
node->sons[i] = NULL;
}
node->ending = false;
return node;
}
void delete_trie(tree_t trie)
{
int i = 0;
for(i = 0; i < 26;i++)
{
if(trie->sons[i]!=NULL)
{
delete_trie(trie->sons[i]);
}
else
{
continue;
}
}
free(trie);
}
tree_t put_trie(tree_t trie, char* s)
{
int i = 0;
char* t = s;
tree_t aux = trie;
if(lookup_trie(trie, s))
return trie;
for(i = 0; t[i]!='\0'; i++)
{
int it = (int)((char)tolower(t[i]) - 'a'); //le index
printf("\niterator %d\n", it);
if(aux->sons[it] == NULL)
{
aux->sons[it] = create_trie();
//aux->sons[it]->s = (char *)malloc(sizeof(char*));
//printf("created tree");
}
aux = aux->sons[it];
}
aux->ending = true;
return trie;
}
bool lookup_trie(tree_t trie, char* s)
{
int i = 0;
char* t = s;
tree_t aux = trie;
for(i = 0; i<strlen(t); i++)
{
int it = (int)((char)tolower(t[i]) - 'a'); //le index
if(aux->sons[it] == NULL)
{
return false;
}
aux = aux->sons[it];
}
if(aux->ending)
{
return true;
}
return false;
}
void print_trie(tree_t trie)
{
int i = 0;
for(i = 0; i<26; i++)
{
if(trie->sons[i] == NULL)
{
continue;
}
else
{
printf("%c", ((char)(i) + 'a'));
print_trie(trie->sons[i]);
}
//print_trie(trie->sons[i])
printf("\n");
}
}
tree_t share_word(tree_t trie, tree_t auxiliar, char* s)
{
int x = 0, j = 0; //auxiliar to compare and for variable
printf("Share word debug\n");
/*if(!is_vide(trie))
return (tree_t)NULL;*/
printf("here");
printf("%s\n",s);
for(j=0; j<26; j++)
{
for(x = 0; x < strlen(s); x++)
{
int it = (int)((char)tolower(s[x]) - 'a');
printf("%d\n", it);
//if its null i'm gonna look into other nodes from the first for
if(trie->sons[j] == NULL)
{
continue;
}
if(trie->sons[j] == NULL)
{
break;
}
else if(trie->sons[it] == NULL) //might pose a problem
{
//if the node is empty, we just jump to the next iteration
if(lookup_trie(trie->sons[j], s)) //if the suffix is present, return the subtree
{
printf("Word belongs\n");
auxiliar = trie->sons[j]; //is auxiliar JUST A POINTER?
return auxiliar;
}
else //if not present, go again through the function
{
auxiliar = share_word(trie->sons[j], auxiliar, s);
}
}
else //trie->sons[it] not null
{
printf("iterator not null\n");
if(lookup_trie(trie->sons[it], s+x)) //if the word is present
{
return trie->sons[it];
}
}
}
}
return auxiliar;
}
tree_t put_word(tree_t trie, char *s)
{
int i = 0;
tree_t auxiliar = create_trie();
printf("Beggining\n");
//missing a condition so it doesnt add all the suffixes;
auxiliar = share_word(trie, auxiliar, s);
/*for(i = 0; i < strlen(s); i++)
{
int it = (int)((char)tolower(s[i]) - 'a');
auxiliar = share_word(trie, auxiliar, s + i); //should look for the suffixes;
if(auxiliar->sons[it] != NULL )
{
if(trie->sons[it] == NULL)
{
trie->sons[it] = create_trie();
trie->sons[it] = auxiliar;
return trie;
}
}
else
{
printf("Auxiliar null\n");
trie->sons[it] = create_trie(); //proceeds to the next iteration by creating the node
}
//}
trie = trie->sons[it];
}*/
return trie;
}
bool is_vide(tree_t trie)
{
int i =0;
for(i =0; i <26;i++)
{
if(trie->sons[i] != NULL)
{
return false;
}
else
{
return true;
}
}
return true;
}
bool leads_leaf(tree_t trie, char *s)
{
int i = 0;
tree_t aux = trie;
for(i = 0; i < strlen(s); i++)
{
int it = (int)((char)tolower(s[i]) - 'a');
aux = aux->sons[it];
if(i == (strlen(s) - 1) && aux->ending)
{
return true;
}
else
{
return false;
}
}
return false;
}
int main()
{
tree_t tree = create_trie();
tree = put_trie(tree, "abcd");
tree = put_word(tree, "decd");
delete_trie(tree);
return 0;
}
I tried testing putting a string in a single way (abcd) and then searching the string (decd), which would add d, e, and when it would go for c it would find the node of the first strings that leads to c -> d -> '\0'. However, it sometimes just keeps veryfing the same letter (d) and doesn't add it or it just never goes to the next (e).
I think there is a problem with the function put_word and how it calls the share suffixes multiple times.
Good evening forum members.
The following is on the agenda:
Read a sequence of coordinates (x, y, z) of spatial points from the file, ordered by distance from the point of origin (develop a separate function for calculating the distance and store this value in the data structure);
To bypass use the bottom option from right to left;
Extract from the tree all nodes whose z coordinate falls within the specified range zmin ..zmax (I decided to take from 7 to 14) and indicate their number;
To completely erase the tree, use the direct (from the root) version of the bypass from left to right;
Print the entire tree using a non-recursive function.
Please help with number 3. It is not possible to implement the deletion algorithm according to a given condition. It either does not work at all, or errors arrive (
Thanks in advance to everyone who responds
CODE:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_LEN 8
#define STACK_INIT_SIZE 20
typedef struct Tree {
int z;
int viddal;
struct Tree* left, * right;
} TREE;
typedef struct Stack {
size_t size, limit;
TREE** data;
} STACK;
int Distance(FILE* ftxt, int* vid, int* z_cord);
int CreateTreeFromFile(void);
TREE* NewNode(FILE* f, int viddal, int z);
void AddNewNode(TREE* pnew);
void PrintTreeNIZ(TREE* proot);
void iterPostorder(TREE* root);
void OutputTreeStructure(const char* title);
void ShowTree(TREE* proot, int level);
void ShowLevels(void);
int TreeHeight(TREE* proot);
void EraseTree(TREE* proot);
void DeleteSomeNodes(void);
int DeleteNode(TREE* pnew_adr);
TREE* root;
int main(){
system("chcp 1251");
if (CreateTreeFromFile() == 0)
return 0;
puts("\n Created tree: ");
PrintTreeNIZ(root);
OutputTreeStructure("of created tree");
DeleteSomeNodes();
OutputTreeStructure("of the new tree");
EraseTree(root);
root = NULL;
puts("\n Tree was deleted from DM\n\n");
return 0;
}
int Distance(FILE* ftxt, int *vid, int* z_cord) {
TREE* pel = (TREE*)malloc(sizeof(TREE));
if (feof(ftxt)) {;
return NULL;
}
else {
int x, y, z;
fscanf(ftxt, "%d%d%d", &x, &y, &z);
*z_cord = z;
*vid = sqrt(x * x + y * y + z * z);
}
}
int CreateTreeFromFile()
{
const char* fname = "Cords_1.txt";
FILE* fvoc = fopen(fname, "r");
if (fvoc == NULL) {
printf("\n\t\tCan`t open file %s...\n", fname);
return 0;
}
TREE* node;
int viddal, z;
Distance(fvoc, &viddal, &z);
while ((node = NewNode(fvoc, viddal, z)) != NULL) {
AddNewNode(node);
Distance(fvoc, &viddal, &z);
}
fclose(fvoc);
return 1;
}
TREE* NewNode(FILE* f, int viddal, int z)
{
TREE* pel;
pel = (TREE*)malloc(sizeof(TREE));
if (feof(f)) {
return NULL;
}
pel->viddal = viddal;
pel->z = z;
pel->left = pel->right = NULL;
return pel;
}
void AddNewNode(TREE* pnew) {
if (root == NULL) {
root = pnew;
return;
}
TREE* prnt = root;
do {
if (pnew->viddal == prnt->viddal) {
free(pnew);
return;
}
if (pnew->viddal < prnt->viddal) {
if (prnt->left == NULL) {
prnt->left = pnew;
return;
}
else
prnt = prnt->left;
}
else {
if (prnt->right == NULL) {
prnt->right = pnew;
return;
}
else
prnt = prnt->right;
}
} while (1);
}
void PrintTreeNIZ(TREE* proot)
{
if (proot == NULL)
return;
printf("\n Right Tree");
iterPostorder(proot->right);
printf("\n\n Left Tree");
iterPostorder(proot->left);
printf("\n\n Korin - %d", proot->viddal);
}
void OutputTreeStructure(const char* title)
{
printf("\n\n\n Structur%s:\n\n", title);
ShowLevels();
ShowTree(root, 0);
puts("\n");
}
#define TAB 7
void ShowTree(TREE* proot, int level)
{
if (proot == NULL) return;
ShowTree(proot->right, level + 1);
printf("\n%*c%d", level * TAB + 10, ' ', proot->viddal);
ShowTree(proot->left, level + 1);
}
void ShowLevels(void)
{
int lev;
printf(" Level: ");
for (lev = 1; lev <= TreeHeight(root); lev++)
printf(" %-*d", 6, lev);
printf("\n\n");
}
int TreeHeight(TREE* proot)
{
int lh, rh;
if (proot == NULL) return 0;
lh = TreeHeight(proot->left);
rh = TreeHeight(proot->right);
return lh > rh ? lh + 1 : rh + 1;
}
void EraseTree(TREE* proot)
{
if (proot == NULL)
return;
EraseTree(proot->left);
EraseTree(proot->right);
free(proot);
}
STACK* createStack() {
Stack* tmp = (Stack*)malloc(sizeof(Stack));
tmp->limit = STACK_INIT_SIZE;
tmp->size = 0;
tmp->data = (TREE**)malloc(tmp->limit * sizeof(TREE*));
return tmp;
}
void freeStack(Stack** s) {
free((*s)->data);
free(*s);
*s = NULL;
}
void push(Stack* s, TREE* item) {
if (s->size >= s->limit) {
s->limit *= 2;
s->data = (TREE**)realloc(s->data, s->limit * sizeof(TREE*));
}
s->data[s->size++] = item;
}
TREE* pop(Stack* s) {
if (s->size == 0) {
exit(7);
}
s->size--;
return s->data[s->size];
}
TREE* peek(Stack* s) {
return s->data[s->size - 1];
}
void iterPostorder(TREE* root) {
Stack* ps = createStack();
TREE* lnp = NULL;
TREE* peekn = NULL;
while (!ps->size == 0 || root != NULL) {
if (root) {
push(ps, root);
root = root->left;
}
else {
peekn = peek(ps);
if (peekn->right && lnp != peekn->right) {
root = peekn->right;
}
else {
pop(ps);
printf("\n\t Visited -> %d", peekn->viddal);
lnp = peekn;
}
}
}
freeStack(&ps);
}
// HELP WITH THAT
//--------------------------------------------------------------------------------------------
void DeleteSomeNodes(void)
{
printf("\n\t Deleting needing nods:\n");
TREE* pfind = (TREE*)malloc(sizeof(TREE));
do {
if (pfind->z >= 7 && pfind->z <= 14) {
DeleteNode(root);
printf(" Number %d was deleted from tree\n", root);
}
} while (1);
puts("\n\n");
}
#define NoSubTree 0
#define LeftSubTree -1
#define RightSubTree 1
#define TwoSubTrees 2
int DeleteNode(TREE* pnew_adr)
{
TREE* proot = root;
int subtr;
if (proot == NULL) return 0;
if (pnew_adr->viddal < proot->viddal)
return DeleteNode(proot->left);
if (pnew_adr->viddal > proot->viddal)
return DeleteNode(proot->right);
if (proot->left == NULL && proot->right == NULL)
subtr = NoSubTree;
else if (proot->left == NULL)
subtr = RightSubTree;
else if (proot->right == NULL)
subtr = LeftSubTree;
else
subtr = TwoSubTrees;
switch (subtr) {
case NoSubTree:
root = NULL; break;
case LeftSubTree:
root = proot->left; break;
case RightSubTree:
root = proot->right; break;
case TwoSubTrees:
TREE* pnew_root = proot->right, * pnew_prnt = proot;
while (pnew_root->left != NULL) {
pnew_prnt = pnew_root;
pnew_root = pnew_root->left;
}
pnew_root->left = proot->left;
if (pnew_root != proot->right) {
pnew_prnt->left = pnew_root->right;
pnew_root->right = proot->right;
}
root = pnew_root;
}
free(proot);
return 1;
}
//--------------------------------------------------------------------------------------------
I have a small program to handle a list of rabbits (name, district, participation count) stored in an array of pointers (Rabbit** iterator). I'd like to implement the following methods: add, delete and modify a rabbit, list all the rabbits or list by district.
When I compare for example the name of the rabbits in the list with strcmp() it doesn't return 0 when the names are equal. How can I solve this problem?
The Rabbit struct:
typedef struct Rabbit {
char* name;
char* district;
unsigned part_count;
} Rabbit;
The delete method:
bool delete_rabbit(char* delete_name)
{
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL && strcmp(iterator[i]->name, delete_name) == 0) {
free(iterator[i]);
iterator[i] = NULL;
count--;
return true;
}
}
return false;
}
The list by district method:
void list_by_district(char* district)
{
unsigned counter = 0;
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL && strcmp(iterator[i]->district, district) == 0) {
counter++;
printf("\n%u. Rabbit:\n", counter);
printf("Name: %s\nDistrict: %s\nParticipation count: %u\n", iterator[i]->name, iterator[i]->district, iterator[i]->part_count);
}
}
}
The modify method is similar to the delete method except it only changes the values.
The corresponding code snippets from main:
Rabbit** iterator;
unsigned size = 10, count = 0;
int main()
{
iterator = (Rabbit**)malloc(sizeof(Rabbit*) * 10);
...
do {
...
switch (input) {
case 'a':
if (count == size) iterator = allocate_more_memory();
...
iterator[count++] = add_rabbit(new_name, new_district, new_part_count);
break;
case 'd':
if (size == count + 6) iterator = allocate_less_memory();
do {
printf("Enter name to be deleted: ");
scanf("%[^\n]", delete_name);
getchar();
if (strlen(delete_name) >= 30) printf("Name only has 30 or less characters!\n");
} while (strlen(delete_name) >= 30);
if (!delete_rabbit(delete_name)) printf("\nThere's no rabbit in the list with this name.\n");
break;
...
}
} while (input != 'x');
...
free(iterator);
return 0;
}
EDIT:
The add method:
Rabbit* add_rabbit(char* new_name, char* new_district, unsigned new_part_count)
{
Rabbit* new_rabbit = (Rabbit*)malloc(sizeof(Rabbit));
if (new_rabbit) {
new_rabbit->name = (char*)malloc((strlen(new_name) + 1) * sizeof(char));
new_rabbit->district = (char*)malloc((strlen(new_district) + 1) * sizeof(char));
strcpy(new_rabbit->name, new_name);
strcpy(new_rabbit->district, district);
new_rabbit->part_count = new_part_count;
}
return new_rabbit;
}
The allocate less memory method:
Rabbit** allocate_less_memory()
{
Rabbit** new_iterator = (Rabbit**)malloc(sizeof(Rabbit*) * (size - 5));
if (new_iterator) {
unsigned counter = 0;
for (unsigned i = 0; i < size; ++i) {
if (iterator[i] != NULL) {
new_iterator[counter++] = iterator[i];
}
}
size -= 5;
free(iterator);
return new_iterator;
}
return NULL;
}
I have my priority queue working and printing as I expected it to, but the free is invalid and I'm not sure why, i'm following all the protocols for the heap that I have learned so far, but my program will not finish.
#include <stdlib.h>
#include "priority_queue.h"
struct item{
int priority;
int value;
};
typedef struct item Item;
struct priority_queue{
int size;
int capacity;
int front;
Item* data;
};
typedef struct priority_queue Priority_queue;
void priority_queue_fix_down(PRIORITY_QUEUE hQueue, int index, int size);
PRIORITY_QUEUE priority_queue_init_default(void){
Priority_queue* pQueue_ptr;
pQueue_ptr = (Priority_queue*)malloc(sizeof(Priority_queue));
if(pQueue_ptr != NULL){
pQueue_ptr->size = 0;
pQueue_ptr->capacity = 1;
pQueue_ptr->data = (Item*)malloc(sizeof(Item)*pQueue_ptr->capacity);
if (pQueue_ptr->data == NULL){
free(pQueue_ptr);
pQueue_ptr = NULL;
}
}
return pQueue_ptr;
}
Status priority_queue_insert(PRIORITY_QUEUE hQueue, int priority_level, int data_item)
{
Priority_queue* pQueue_ptr = (Priority_queue*)hQueue;
Item* temp, temp2;
//temp = (Item*)malloc(sizeof());
int i;
if (pQueue_ptr->size >= pQueue_ptr->capacity)
{
//not enough space
temp = (Item*)malloc(sizeof(Item) * 2 * pQueue_ptr->capacity);
if (temp == NULL)
{
return FAILURE;
}
for (i = 0; i < pQueue_ptr->size; i++)
{
temp[i] = pQueue_ptr->data[i];
}
pQueue_ptr->front = 0;
pQueue_ptr->capacity *= 2;
free(pQueue_ptr->data);
pQueue_ptr->data = temp;
}
i = pQueue_ptr->size;
(pQueue_ptr->data[i]).priority = priority_level;
(pQueue_ptr->data[i]).value = data_item;
int index_of_parent;
index_of_parent = (i - 1) / 2;
while (i >= 1 && ((pQueue_ptr->data[i]).priority > (pQueue_ptr->data[index_of_parent]).priority))
{
temp2 = pQueue_ptr->data[index_of_parent];
pQueue_ptr->data[index_of_parent] = pQueue_ptr->data[i];
pQueue_ptr->data[i] = temp2;
i = index_of_parent;
index_of_parent = (i - 1) / 2;
}
pQueue_ptr->size++;
// pQueue_ptr->front = 0;
// pQueue_ptr->back = pQueue_ptr->size-1;
return SUCCESS;
}
void print_heap(PRIORITY_QUEUE hQueue){
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
for(int x = 0; x<pQueue_ptr->size;x++){
printf("%d\n", pQueue_ptr->data[x].priority);
}
}
Status priority_queue_service(PRIORITY_QUEUE hQueue){
//set variables
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
Item temp;
int size, index, index_left_child, index_right_child;
if(pQueue_ptr->size == 0){
return FAILURE;
}
index = 0;
temp = pQueue_ptr->data[0];
pQueue_ptr->data[0] = pQueue_ptr->data[pQueue_ptr->size-1];
pQueue_ptr->data[size-1] = temp;
pQueue_ptr->size--;
priority_queue_fix_down(pQueue_ptr, pQueue_ptr->front, pQueue_ptr->size);
return SUCCESS;
}
int priority_queue_front(PRIORITY_QUEUE hQueue, Status* status)
{
Priority_queue* pPriority_queue = (Priority_queue*)hQueue;
if (priority_queue_is_empty(pPriority_queue))
{
if (status != NULL)
{
*status = FAILURE;
}
return 0;
}
if (status != NULL)
{
*status = SUCCESS;
}
return (pPriority_queue->data[pPriority_queue->front]).value;
}
Boolean priority_queue_is_empty(PRIORITY_QUEUE hQueue){
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
if (pQueue_ptr->size <= 0)
return TRUE;
else
return FALSE;
}
This is where I get the error when debugging, on free(pPriority_queue->data); It doesn't even reach the line below. I tried taking someone elses "service" function and it worked, but they implemented "fix down" in their service function, while I'm trying to do it outside in a separate function.
void priority_queue_destroy(PRIORITY_QUEUE* phQueue){
Priority_queue* pPriority_queue = (Priority_queue*)*phQueue;
free(pPriority_queue->data);
free(*phQueue);
// *phQueue = NULL;
return;
}
void priority_queue_fix_down(PRIORITY_QUEUE hQueue, int index, int size){
Priority_queue* pQueue_ptr = (Priority_queue*) hQueue;
Item* temp;
temp = (Item*)malloc(sizeof(Item));
if (temp == NULL)
return NULL;
//int front = priority_queue_front(pQueue_ptr, NULL);
int index_left_child = 2* index + 1;
int index_right_child = 2* index + 2;
// print_heap(pQueue_ptr);
// printf("\nsize: %d\nindex: %d\n", size, index);
// // printf("Front: %d\n", pQueue_ptr->data[0]);
// if(pQueue_ptr->data[index_left_child].priority > (pQueue_ptr->data[index]).priority){
// printf("Left child index %d\nRight child index: %d\nLeft child has highest priority of: %d\n",index_left_child, index_right_child, pQueue_ptr->data[index_left_child].priority);
// }
// else
// printf("Right child index: %d\nLeft child index %d\nRight child has highest priority of: %d\n",index_right_child, index_left_child, pQueue_ptr->data[index_right_child].priority);
if (index_left_child < size){
if (index_right_child < size && pQueue_ptr->data[index_right_child].priority > (pQueue_ptr->data[index_left_child]).priority){
if(pQueue_ptr->data[index_right_child].priority > (pQueue_ptr->data[index]).priority){
*temp = pQueue_ptr->data[index];
pQueue_ptr->data[index] = pQueue_ptr->data[index_right_child] ;
pQueue_ptr->data[index_right_child] = *temp;
priority_queue_fix_down(pQueue_ptr, index_right_child, size);
}
}
if(pQueue_ptr->data[index_left_child].priority > (pQueue_ptr->data[index]).priority){
*temp = pQueue_ptr->data[index];
pQueue_ptr->data[index] = pQueue_ptr->data[index_left_child];
pQueue_ptr->data[index_left_child] = *temp;
priority_queue_fix_down(pQueue_ptr, index_left_child, size);
}
}
}
I need to create a Robot Simulator programmed in C. The Robot has to find the Exit of a 2d labirinth using a Recursive Backtracker algorithm, i understood how does this algorithm work but i don't know how to implement it. I Think i can use a Binary Tree using Pointers but i don't know how to do this, can you try to explain it to me?
This is the program that i've created, now the Robot is entering a loop because of the method that changes direction
#ifdef __unix__
#include <unistd.h>
#elif defined _WIN32
#include <windows.h>
#define sleep(x) Sleep(1000 * x)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void goUp();
void goDown();
void goLeft();
void goRight();
typedef struct robot {
int direction;
bool is_moving;
}robot;
typedef struct room {
robot robot;
bool is_robot;
int obstacle;
}room;
room Room[20][20];
int r = 12;
int c = 10;
void generation(room matrix[20][20])
{
srand(time(NULL));
int x,i,j;
x=0;
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
matrix[i][j].is_robot=false;
x=rand()%100+1;
if(x==1||x==50||x==100)
{
matrix[i][j].obstacle=1;
}
else
{
matrix[i][j].obstacle=0;
}
}
}
}
void print_matrix(room matrix[20][20])
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
if(matrix[i][j].obstacle==0)
{
if(matrix[i][j].is_robot==true)
{
printf("I");
}
else
{
printf(" ");
}
}
else
{
if(matrix[i][j].is_robot==true)
{
printf("I");
}
else
{
printf("o");
}
}
}
printf("\n");
}
}
bool changeDirection(room Room[20][20],int i,int j)
{
if(Room[i][j].robot.direction == 1)
{
if(Room[i-1][j].obstacle == 1 || i-1 == 0)
{
if(Room[i+1][j].obstacle == 1 || i+1 == 19)
{
Room[i][j].robot.direction = 2;
return true;
}
else
{
Room[i][j].robot.direction = 4;
return true;
}
}
else
{
Room[i][j].robot.direction = 3;
return true;
}
}
if(Room[i][j].robot.direction == 2)
{
if(Room[i-1][j].obstacle == 1 || i-1 == 0)
{
if(Room[i+1][j].obstacle == 1 || i+1 == 19)
{
Room[i][j].robot.direction = 1;
return true;
}
else
{
Room[i][j].robot.direction = 4;
return true;
}
}
else
{
Room[i][j].robot.direction = 3;
return true;
}
}
if(Room[i][j].robot.direction == 3)
{
if(Room[i][j+1].obstacle == 1 || j+1 == 19)
{
if(Room[i][j-1].obstacle == 1 || j-1 == 0)
{
Room[i][j].robot.direction = 4;
return true;
}
else
{
Room[i][j].robot.direction = 2;
return true;
}
}
else
{
Room[i][j].robot.direction = 1;
return true;
}
}
if(Room[i][j].robot.direction == 4)
{
if(Room[i][j+1].obstacle == 1 || j+1 == 19)
{
if(Room[i][j-1].obstacle == 1 || j-1 == 0)
{
Room[i][j].robot.direction = 3;
return true;
}
else
{
Room[i][j].robot.direction = 2;
return true;
}
}
else
{
Room[i][j].robot.direction = 1;
return true;
}
}
}
void goRight()
{
c=c+1;
Room[r][c].robot.direction=1;
Room[r][c].is_robot=true;
Room[r][c-1].is_robot=false;
}
void goLeft()
{
c=c-1;
Room[r][c].robot.direction=2;
Room[r][c].is_robot=true;
Room[r][c+1].is_robot=false;
}
void goUp()
{
r=r-1;
Room[r][c].robot.direction=3;
Room[r][c].is_robot=true;
Room[r+1][c].is_robot=false;
}
void goDown()
{
r=r+1;
Room[r][c].robot.direction=4;
Room[r][c].is_robot=true;
Room[r-1][c].is_robot=false;
}
int main()
{
generation(Room);
Room[r][c].robot.direction = 1;
Room[r][c].robot.is_moving = true;
Room[r][c].is_robot = true;
do
{
Room[r][c].robot.is_moving = true;
if (Room[r][c].robot.direction == 1 && Room[r][c].robot.is_moving == true) // destra
{
if(Room[r][c +1].obstacle == 1 || c+1 == 19)
{
changeDirection(Room,r,c);
}
else
{
goRight();
}
}
if (Room[r][c].robot.direction == 2 && Room[r][c].robot.is_moving == true) // sinistra
{
if(Room[r][c -1].obstacle == 1 || c-1 == 0)
{
changeDirection(Room,r,c);
}
else
{
goLeft();
}
}
if (Room[r][c].robot.direction == 3 && Room[r][c].robot.is_moving == true) // su
{
if(Room[r-1][c].obstacle == 1 || r-1 == 0)
{
changeDirection(Room,r,c);
}
else
{
goUp();
}
}
if (Room[r][c].robot.direction == 4 && Room[r][c].robot.is_moving == true) // giu
{
if(Room[r+1][c].obstacle == 1 || r+1 == 19)
{
changeDirection(Room,r,c);
}
else
{
goDown();
}
}
print_matrix(Room);
sleep(0.1);
system("cls");
}
while(1);
print_matrix(Room);
}
I'm having a hard time understanding how a binary tree would be useful in finding a path in a labyrinth (maybe it's used to represent the labyrinth?) but maybe I'm blind. I would simply make a 2d int array and let 0 mean the position is blocked (there's a wall there or something) and 1 mean it's open (you can move there). The brute force backtrack procedure, going off orthogonal movement (left, right, up, down) would be:
f(x,y){
// you found the place your want to go to
if (x,y) is (destinationX,destinationY)
return true
block the position (x,y) // i.e. mark current position as visited
if there is an open spot at (x,y-1) AND f(x,y-1)
return true
if there is an open spot at (x,y+1) AND f(x,y+1)
return true
if there is an open spot at (x-1,y) AND f(x-1,y)
return true
if there is an open spot at (x+1,y) AND f(x+1,y)
return true
return false
}
Suppose you had the labyrinth looking like:
"+" is where you start ([1][1])
"-" is your destination ([3][1])
"#" is a blocked region
===========
|#|#|#|#|#|
|#|+| |#|#|
|#|#| |#|#|
|#|-| | |#|
|#|#|#|#|#|
===========
Using the above idea I have:
#include <stdio.h>
#define width 5
#define height 5
// print maze
void print(char arr[][width]){
for (int i = 0; i < 2*width+1; i++) printf("=");
printf("\n");
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
printf("|%c",arr[i][j]);
}
printf("|\n");
}
for (int i = 0; i < 2*width+1; i++) printf("=");
}
// starting from (x,y) to (destX,destY)
int path(int arr[][width],int x,int y,int destX,int destY,char toDest[][width]){
if (x==destX && y==destY) {
toDest[y][x] = '*';
print(toDest);
return 1;
}
// mark current position as visited
arr[y][x] = 0;
toDest[y][x] = '*';
// left
if (arr[y][x-1] && path(arr,x-1,y,destX,destY,toDest))
return 1;
// right
if (arr[y][x+1] && path(arr,x+1,y,destX,destY,toDest))
return 1;
// up
if (arr[y-1][x] && path(arr,x,y-1,destX,destY,toDest))
return 1;
// down
if (arr[y+1][x] && path(arr,x,y+1,destX,destY,toDest))
return 1;
return 0;
}
int main () {
// use this to store path
// and then print it out if found
char toDest[height][width] = {
{'#','#','#','#','#'},
{'#',' ',' ','#','#'},
{'#','#',' ','#','#'},
{'#',' ',' ',' ','#'},
{'#','#','#','#','#'}
};
// 0 -> position is blocked
// 1 -> position is open
int maze[height][width] = {
{0,0,0,0,0},
{0,1,1,0,0},
{0,0,1,0,0},
{0,1,1,1,0},
{0,0,0,0,0}
};
path(maze,1,1,1,3,toDest);
}
Output:
===========
|#|#|#|#|#|
|#|*|*|#|#|
|#|#|*|#|#|
|#|*|*| |#|
|#|#|#|#|#|
===========
In output the path is designated by the *s