Making edge on Ice Sliding puzzle path finding - c

[My apology for the title, I just specified the problem I encountered on this puzzle.
I'm making a path finding method with the least distance travelled, depending on the number of asterisks encountered.
The rules of the game is simple, traversing from A to B, but I can only move in a straight line and cannot stop moving in that direction until you hit an asterisk (or the B), as if they were sliding across every zero.
Example, the photo shows the shortest path from A to B with 23 as the total distance travelled.
]1
The first idea that appeared on my mind is making an adjacency matrix, initially, which I have my code here:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main()
{
FILE *hehehe = fopen("input.txt","r");
//==========================ADJACENCY MATRIX INITIALIZATION=======================================//
int row, column, i, j;
fscanf(hehehe,"%d",&row);
fscanf(hehehe,"%d",&column);
char c;
c = fgetc(hehehe);
int matrix[row][column];
c = fgetc(hehehe);
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
if (c == '*'){
matrix[i][j] = 1;
c = fgetc(hehehe);
}
else if (c == 'A')
{
matrix[i][j] = 2;
c = fgetc(hehehe);
}
else if (c == 'B')
{
matrix[i][j] = 3;
c = fgetc(hehehe);
}
else{
matrix[i][j] = 0;
c = fgetc(hehehe);
}
if (c == '\n'){c = fgetc(hehehe);}
}
}
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
//if (matrix[i][j] == 1) printf("*");
//else printf(" ");
printf("%d ",matrix[i][j]);
}
printf("\n");
}
fclose(hehehe);
}
Any idea or suggestion for continuing for making of edge in every straight line in the photo is high appreciated. Thank you for any help in advance.

In this case, I think a matrix is overdoing it. Because you cannot make a move while sliding, you only need a directed graph.
There are a few things to keep in mind while making your algorithm:
Stopping points are the goal, or any space adjacent to a wall/asterisk.
A vertex should store two values; direction, and location.
For each asterisk or obstacle, add adjacent spaces to the list of vertices (if they don't exist in your graph yet). They only require one direction.
For each B, add a vertex with all possible directions. (Or one vertex for each direction, depending on whether that makes it easier).
For each vertex, find the closest vertex in the direction stored. Draw an edge between both vertices (if it does not already exist).
Run an appropriate search algorithm. If distance matters, use Dijkstra's. If it doesn't, use Breadth-first. If there are special scoring rules, consider A*.
Because your search space doesn't seem so large, I haven't fully optimized the algorithm. This is why I mention checking that vertices and edges aren't already added. Optimizing these is possible, and I can help with that if you need, but if-statements aren't costly enough to warrant premature optimization. Because your search space is easy to simplify, Breadth-first and Dijkstra's algorithm are absolutely perfect; they find the shortest path and their performance cost is nowhere near as high as putting them on a 2D grid.
If you're not sure of how to make your data structures, here's the way I'd approach it.
1.
Graph Structures
Direction // x and y tuple/variable, integer, or string
Point // x and y tuple/variable. Note that you can use this as direction too
Vertex
- Point
- Map < Direction, Edge > // each direction is linked to another vertex
// maps in C can be made with two arrays
// a vertex for each direction may be easier
Edge
- Vertex // you can store both vertices, but you only need to store the one being moved to.
// without OOP, reuse a simple struct before making it complex
Graph
- Vertices // array of vertex
// each vertex stores its edges; the graph doesn't need to
2.
Pathfinder Structures
Node
- Parent // a link to the previous node
// trace the links back to construct a path
- Depth // last node's depth + 1
- Vertex // the vertex hit by the pathfinder
Path
- Nodes // while parent is not null
// add a node to this list
// then read it backward

Related

Backtracking maze in C, with obstacles

I need to solve a maze using backtracking method.
My maze has 0 listed as a wall, 1 listed as an empty cell, 2 is for visited, 3 for dragon.
Dragons are basically obstacles that I can go through BUT I need to choose the path with the LEAST dragons.
So far I can solve the maze and mark a path, but I can't seem to think of a relatively simple way of finding the path with the least dragons.
Do note we just started coding with C in my uni (so far I've only done java/bash/a bit of python), so I'm really new to C and algorithms in general.
Code is below.
#include <stdio.h>
#define IMPOSSIBLE (N*N+1)
int counter=0;
enum {WALL,EMPTY,VISITED,DRAGON,N};
int printMaze(int maze[N][N])
{
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
printf("%d ",maze[i][j]);
}
printf("\n");
}
}
int solveMaze(int maze[N][N], int i, int j)
{
if (maze[i][j] == WALL){ return 0; } // If [i][j] are currently a wall (0).
if (maze[i][j] == VISITED) { return 0; } // If [i][j] are currently a mark (2).
if (maze[i][j] == DRAGON) { counter++; }
maze[i][j] = VISITED; // Mark current spot with (2).
if (i==N-1 && j==N-1) { return 1; } // reached the end (N-1,N-1) - (3,3) incase N is 4.
if ( ((i < N-1) && solveMaze(maze,i+1,j)) || ((i > 0) && solveMaze(maze,i-1,j)) || ((j < N-1) && solveMaze(maze,i,j+1)) || ((j > 0) && solveMaze(maze,i,j-1)) ) { // checking index-out-bounds + recursively going around the maze
return 1;
}
maze[i][j] = EMPTY;
return 0;
}
int main() {
int maze[N][N] = { {1,1,3,3},
{3,0,1,1},
{3,0,0,1},
{1,3,3,1} };
int solved = solveMaze(maze, 0, 0);
if (solved)
{
printMaze(maze);
printf("Amount of dragons passed through in the maze: %d\n",counter);
}
else
{
printf("No solution, %d\n",IMPOSSIBLE);
}
}
I tried creating a counter that counts the amount of dragons on the way, but I guess I'm not fluent enough in recursions to make it go in every available path and choose the best one.
You seem to understand the idea of recursively traversing the tree with backtracking. The issue is that you need to find not just a path, but the one with the least cost -- that is, the fewest dragons. That means that in general, you can't stop with the first path you find. You need to keep going until you can be sure that there's no better path.
Here's one way to do it:
Maintain a variable to track the number of dragons along the best path discovered so far. Initialize it to something larger than the value that can appear along any path -- your IMPOSSIBLE, for example, or INT_MAX. This is separate from the number of dragons so far encountered along the path you are currently exploring.
Perform a recursive traversal much like you are already doing, except
Fix the example code's problems with restoring state (node contents and counter value) when you backtrack out of a dragon node.
Stop exploring any given path when the number of dragons encountered along it equals the number along the best path discovered so far.
In light of the previous, you can be certain that whenever you discover a path that reaches the exit, that path has fewer dragons than the best path previously discovered, if any. Update the variable tracking the best number of dragons accordingly. Note that this does not necessarily end the search, but it may reduce the search space that remains to be explored.
A way to solve this is to imagine the maze as a 3 dimensional graph instead of 2D. You have the triplet (i, j, number_of_dragons) define the nodes of the graph. Note that this may in extreme case mean the number of nodes are N^4. Thus you will need an array with size [N][N][N*N] to store if the given node is visited (note that dragons and walls can still be stored in a [N][N] array). To get the minimal path from source to target, simply iterate over the the values of [target.x][target.y][i] and return the minimum i for which you have visited the node.
I can suggest a better solution using min path graph algorithm like Dijkstra, but it seems this is out of scope for the question.

Finding the diameter of m-ary tree - C

I have to analyze an m-ary tree in C - using namely BFS.
There are some requirements I don't succeed to implement for a while:
1. Find the diameter of the tree.
2. Given two vertices in the tree - find the shortest simple path between them.
As for 1 - I went through the topics in Stack - and have seen some implementations (not in C unfortunately) which are not very clear to me... Some way of calculating the diameter by using BFS twice, starting from a random vertex... I'm not sure if the second BFS has to "remember" the visited array from the first BFS.
As for 2 - I really don't know how to approach to that, but I believe I can use somehow BFS here.
Moreover, I have to implement these two requirements in O(n^2) time complexity.
Besides that, I have to find the maximal and minimal heights of the tree.
As for the maximal height - I have implemented BFS (not sure it's absolutely correct) which to my understanding, deals with this maximal height.
As for the minimal height - I have no idea how to find it.
Here are my vertex struct and BFS implementations:
typedef struct Vertex {
size_t key;
size_t amountOfNeighbors; // The current amount of neighbors
size_t capacity; // The capacity of the neighbors (It's updating during run-time)
struct Vertex* parent;
struct Vertex** neighbors; // The possible parent and children of a vertex
} Vertex;
Vertex* bfs(Vertex* allVertices, size_t numOfVertices, Vertex* startVertex, size_t* pathDistance) {
if (startVertex -> neighbors == NULL) { // In case we have only one vertex in the graph
*pathDistance = 0;
return startVertex;
}
Queue* q = (Queue*)malloc((sizeof(size_t) * numOfVertices));
int* visited = (int*)malloc(sizeof(int) * numOfVertices);
for (size_t i = 0; i < numOfVertices; i++) {
visited[i] = 0; // Mark all the vertices as unvisited
}
size_t lastVertex = 0; // Actually indicates the furthermost vertex from startVertex
*pathDistance = 0; // The number of edges between lastVertex and startVertex
enqueue(q, startVertex->key);
visited[startVertex->key] = 1; // Mark as visited
while (!queueIsEmpty(q)) {
unsigned int currentVertex = dequeue(q); // The key of the current vertex
Vertex* s = &allVertices[currentVertex];
size_t currentAmountOfNeighbors = 0; // Detects the number of processed neighbors of the current vertex
for (Vertex **child = s->neighbors; currentAmountOfNeighbors < s->amountOfNeighbors; currentAmountOfNeighbors++) {
if (!visited[(*(child))->key]) {
visited[(*(child))->key] = 1;
enqueue(q, (*(child))->key);
child++; // TODO Validate it's a correct use of memory!
}
}
*pathDistance += 1; // Another layer passed
lastVertex = peekQueue(q);
}
Vertex* furtherMostVertexFromS = &allVertices[lastVertex];
free(q);
q = NULL;
return furtherMostVertexFromS;
}
My difficulties and wondering are in bold and any help with some of them will be appreciated.
Firstly, questions of this nature are more appropriate to the CS Stack Exchange, but I'll try to help regardless
For your first question(finding the diameter), note that the longest path of the tree must begin(or end) with the deepest node in the tree(which is a leaf). BFS helps you find the depths of all nodes, and thus help you find the deepest node. Can you figure from there how to find the end of said path? Hint: Think about the procedure for finding the deepest node of a graph.
There seems to be a misunderstanding on your part about how BFS works: Note that the point of keeping track of visited nodes, is to avoid crossing through back-edges - that is, to avoid cycles - which aren't possible in a tree.
But hypothetically, even if you do maintain such a 'visited' array (e,g if you want your algorithm to handle cyclic graphs), why would it be shared between different BFS invocations?
As for the second question: BFS finds the distances between nodes in the graph and the starting node(also called 'depth' when called from root). In particular, these are the shortest paths(on an unweighted graph)
The answer to the rest of your bolded questions are also related, the key takeway is that in an acylic, unweighted graph - BFS lets you find the shortest path/minimal distance from the starting node (consult an algorithms textbook for more details on that)

Generating a connected graph and checking if it has eulerian cycle

So, I wanted to have some fun with graphs and now it's driving me crazy.
First, I generate a connected graph with a given number of edges. This is the easy part, which became my curse. Basically, it works as intended, but the results I'm getting are quite bizarre (well, maybe they're not, and I'm the issue here). The algorithm for generating the graph is fairly simple.
I have two arrays, one of them is filled with numbers from 0 to n - 1, and the other is empty.
At the beginning I shuffle the first one move its last element to the empty one.
Then, in a loop, I'm creating an edge between the last element of the first array and a random element from the second one and after that I, again, move the last element from the first array to the other one.
After that part is done, I have to create random edges between the vertexes until I get as many as I need. This is, again, very easy. I just random two numbers in the range from 0 to n - 1 and if there is no edge between these vertexes, I create one.
This is the code:
void generate(int n, double d) {
initMatrix(n); // <- creates an adjacency matrix n x n, filled with 0s
int *array1 = malloc(n * sizeof(int));
int *array2 = malloc(n * sizeof(int));
int j = n - 1, k = 0;
for (int i = 0; i < n; ++i) {
array1[i] = i;
array2[i] = 0;
}
shuffle(array1, 0, n); // <- Fisher-Yates shuffle
array2[k++] = array1[j--];
int edges = d * n * (n - 1) * .5;
if (edges % 2) {
++edges;
}
while (j >= 0) {
int r = rand() % k;
createEdge(array1[j], array2[r]);
array2[k++] = array1[j--];
--edges;
}
free(array1);
free(array2);
while (edges) {
int a = rand() % n;
int b = rand() % n;
if (a == b || checkEdge(a, b)) {
continue;
}
createEdge(a, b);
--edges;
}
}
Now, if I print it out, it's a fine graph. Then I want to find a Hammiltonian cycle. This part works. Then I get to my bane - Eulerian cycle. What's the problem?
Well, first I check if all vertexes are even. And they are not. Always. Every single time, unless I choose to generate a complete graph.
I now feel destroyed by my own code. Is something wrong? Or is it supposed to be like this? I knew that Eulerian circuits would be rare, but not that rare. Please, help.
Let's analyze the probability for having euleran cycle, and for simplicity - let's do it for all graphs with n vertices, no matter number of edges.
Given a graph G of size n, choose one arbitrary vertex. The probability of it's degree being even is roughly 1/2 (assuming for each u1,u2, P((v,u1) exists) = P((v,u2) exists)).
Now, remove v from G, and create a new graph G' with n-1 vertices, and without all edges connected to v.
Similarly, for any arbitrary vertex v' in G' - if (v,v') was an edge on G', we need d(v') to be odd. Otherwise, we need d(v') to be even (both in G'). Either way, probability of it is still roughly ~1/2. (independent from previous degree of v).
....
For the ith round, let #(v) be the number of discarded edges until reaching the current graph that are connected to v. If #(v) is odd, the probability of its current degree being odd is ~1/2, and if #(v) is even, the probability of its current degree being even is also ~1/2, and we remain with current probability of ~1/2
We can now understand how it works, and make a recurrence formula for the probability of the graph being eulerian cyclic:
P(n) ~= 1/2*P(n-1)
P(1) = 1
This is going to give us P(n) ~= 2^-n, which is very unlikely for reasonable n.
Note, 1/2 is just a rough estimation (and is correct when n->infinity), probability is in fact a bit higher, but it is still exponential in -n - which makes it very unlikely for reasonable size graphs.

Can't delete snake's tail according to his head's movement

EDIT #1.
Now i see that my functions doesnt work with this game so please forget them.
Still haven't found a solution, saw some documentation about Queue's as fjf2002 mentioned but it's way too complex to me at this momment. Tried to make a snake[20] array to store coordinates by 2 {1, 1, 1, 2} would be: Head (1,1) Tail (1,2) on the map. Still can't figure how to move it around the map and make the tail follow the head. My mind is blank after trying everything and getting frustrated by my lack of experience. Im not allowed to use anything beyond two-dimensional arrays. Meaning that no structs, no queues, no stacks... This is supposed to be done without using those and profesor says that is more easier than i think. (Dont post that i should ask him for the solution as he keeps saying the same without answering my questions). Any idea would help me greatly...------------------------------------------------------------------------------------------------------------------------------------
im using VisualStudio 2013 and programming in C language.
Was looking for a solution in the past 2 days and found nothing over internet to help me. Saw dozens of different snake games in english and spanish but i can't understand them due to zero explaining of their programs or due to my lack of experience.
Tried everything of my knowledge without success and i can't really come up with a solution by my own.
I have:
-Function to generate the map.
-Function to move the snake:
COORD cxy;
#define posicion(x,y) {(cxy.X)= (x);(cxy.Y)= (y); SetConsoleCursorPosition((GetStdHandle(STD_OUTPUT_HANDLE)), (cxy) );}
int tablero[20][20], posx = 0, posy = 0;
void movimientoSnake(){
int m = 1, k = 0, tail = 3;
char dir = 'd';
do{
if (kbhit()){
dir = getch();
if (dir == 'w'){
m = 0;
k = -1;
}
if(dir == 's'){
m = 0;
k = 1;
}
if (dir == 'a'){
m = -1;
k = 0;
}
if (dir == 'd'){
m = 1;
k = 0;
}
}
else{
Sleep(500);
posicion(posx += m, posy += k);
printf("%d", 1);
posicion(posx - tail, posy);
printf("%d", 0);
}
} while (2 > 1);
*The snake moves OK according to wasd keys, and it leaves a trail with 1's (map is full of 0's).
*It moves based on position: position(x,y) of the map (moves there) printf("%d", 1); (prints an 1). for example
The main problem is when i want to delete the trail when i move down, delete the last position while at the same time im printing the new one ahead.
If possible i would like a solution without too much complex (using too many libraries) as by now i only know:
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
I tried to store coordinates on arrays as i saw in almost 90% of snake games out there but i dont understand the concept so i ended up with a bunch of tries without success.
Any ideas?
Thank you very much in advance.
So let us summarize:
Knowing only the coordinates of the head of the snake, how to determine the coordinates of the tail?
Since the snake may have several turns, there is no straight forward way.
I tried to store coordinates on arrays as i saw in almost 90% of snake games out there
Seems to be the only solution.
but i dont understand the concept
You should store the positions occupied by the snake in an array. You have to keep track which array elements are currently occupied, where the head and where the tail is stored.
Or you use the above as an already implemented product: a data structure that allows easy access to first and last element. Read
about http://en.wikipedia.org/wiki/FIFO , http://www.cplusplus.com/reference/queue/queue/ .

Linear algorithm to fill a contour

I am trying to make an algorithm that will fill a contour in linear complexity. I know such an algorithm exists. I've read somewhere that it has to do with the number of crossings, but there is a special case that I haven't had great luck in solving yet.
So far I have tried using the following algorithm. Note that I can't access previous elements (to the left) because they will/may be overwritten:
for (int y = blob->miny; y < blob->maxy; ++y)
{
int NumberOfBorderCrossings = 0;
unsigned int NextElem = 0;
unsigned int NextNextElem = 0;
for (int x = blob->minx-1; x < blob->maxx-1; ++x)
{
NextElem = CV_IMAGE_ELEM(labelimg,unsigned int,y,x+1);
NextNextElem = CV_IMAGE_ELEM(labelimg,unsigned int,y,x+2);
if (CV_IMAGE_ELEM(labelimg,unsigned int,y,x) != label)
{
if (NextElem == label && NextNextElem != label)
++NumberOfBorderCrossings;
else
if (NumberOfBorderCrossings%2)
CV_IMAGE_ELEM(labelimg,unsigned int,y,x) = label;
}
}
}
The result I get is the following. The input is to the right (all non-black pixels must be copied), and the erroneous output is to the left. Note again that I only have the contour of the image to the right (not rendered).
It appears that you're looking for a general Polygon filling algorithm. Your line crossing counting algorithm will break where it hits single points and horizontal and vertical lines. Have a look at Quickfill for a possible alternative.

Resources