Recursive shortest path finding in C - c

I want to make a program that finds the shortest path from 0x0 to the mxn point recursively and change the values of the path to '-'. '1' values in the matrix means path and '0' means wall, and I can go in all directions.
I'm very fresh, so please try to explain the details as much you can.
int startRow = 0, startColumn = 0;
char fun(char arr[][3]);
int main()
{
char matrix[3][3] = { {1,0,1},{1,1,0},{0,1,1} };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
fun(matrix);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
return 0;
}
char fun(char arr[][3])
{
if (arr[startColumn][startRow+1] != 0)
{
arr[startColumn][startRow + 1] = '-';
return fun(arr[startColumn][startRow + 1]);
}
else
{
startRow = 0;
return fun(arr[startColumn + 1][startRow]);
}
}
The output should be like this:

Shortest path in an unweighted graph like this is typically best done with a breadth-first search, which is implemented iteratively using a queue data structure to store search state, rather than a depth-first search using a stack (such as the call stack and recursion).
If you use a stack, a search that happens to hit the goal node isn't necessarily shortest, because the path isn't extended methodically one level at a time as in BFS. Rather, the DFS explores all the way to a terminal state as soon as possible, then begins to backtrack and explore other terminal paths. None of these paths have the shortness guarantee of BFS.
The consequence of this is that with a naive recursive implementation, you will need to explore all paths before you can claim you've found the shortest one. But if your grids are small or have few paths as appears to be the case here, this shouldn't be a problem.
If you do need to optimize yet maintain the recursion, see the canonical thread Performing Breadth First Search recursively. But going forward I'll assume we're doing DFS.
The other concern is that when the graph has cycles, you need to be able to keep track of visited nodes to avoid an infinite loop. Since you seem to not mind changing characters in your grid, it should suffice that you'll never try to re-visit a cell marked '-' and you'll undo any '-' mark at the end of a recursive call in case you find a faster path to that cell in the future.
As a C-specific aside, it's best not to write function headers like char fun(char arr[][3]). The name is unclear, as is the return value, and the parameter is hard-coded to be exactly 3 columns wide. It's unrealistic to expect a client calling the function from a library to go in and edit the source code every time they want to use a different grid. Even if they did, they'd be prohibited from calling this function on multiple grid sizes in the same program. That size should be dynamic. Also, the function relies on global state, int startRow = 0, startColumn = 0; which is not thread-safe and very prone to errors. Pass all state as parameters, or at least only read global constants.
Here's a proof of concept that could still use some clean-up (repeated code, hardcoded literals). Basically, run a standard DFS to get the length of the shortest path, then run it again to populate the first path that fulfills the minimum length requirement: very much a brute-force approach.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ensure(bool predicate, const char *msg, unsigned int line) {
if (!predicate) {
fprintf(stderr, "%s:%d: %s\n", __FILE__, line, msg);
exit(1);
}
}
void print_grid(size_t rows, size_t cols, char **grid) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%c", grid[i][j]);
}
puts("");
}
}
void find_shortest_path_recursive(
int path_length,
int *shortest_path_length,
int y,
int x,
size_t rows,
size_t cols,
char **grid
) {
if (y < 0 || x < 0 || y >= rows ||
x >= cols || grid[y][x] != '1') {
return;
}
else if (y == rows - 1 && x == cols - 1 &&
(*shortest_path_length < 0 ||
path_length < *shortest_path_length)) {
*shortest_path_length = path_length + 1;
}
grid[y][x] = '-';
const static int dirs[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
for (int i = 0; i < 4; i++) {
find_shortest_path_recursive(
path_length + 1,
shortest_path_length,
y + dirs[i][0],
x + dirs[i][1],
rows,
cols,
grid
);
}
grid[y][x] = '1';
}
bool set_shortest_path_recursive(
int path_length,
int shortest_path_length,
int y,
int x,
size_t rows,
size_t cols,
char **grid
) {
if (y < 0 || x < 0 || y >= rows ||
x >= cols || grid[y][x] != '1') {
return false;
}
grid[y][x] = '-';
if (y == rows - 1 && x == cols - 1 &&
path_length + 1 == shortest_path_length) {
return true;
}
const static int dirs[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
for (int i = 0; i < 4; i++) {
if (set_shortest_path_recursive(
path_length + 1,
shortest_path_length,
y + dirs[i][0],
x + dirs[i][1],
rows,
cols,
grid
)) {
return true;
}
}
grid[y][x] = '1';
return false;
}
int set_shortest_path(size_t rows, size_t cols, char **grid) {
int shortest_path_length = -1;
find_shortest_path_recursive(
0, &shortest_path_length, 0, 0, rows, cols, grid
);
set_shortest_path_recursive(
0, shortest_path_length, 0, 0, rows, cols, grid
);
return shortest_path_length;
}
int main(void) {
size_t rows = 8;
size_t cols = 8;
char src_grid[8][8] = {
"10011110",
"10001011",
"11111010",
"00100010",
"00110110",
"11100010",
"10011110",
"11110011",
};
char **grid = malloc(sizeof(*grid) * rows);
ensure(grid, "malloc failed", __LINE__);
for (int i = 0; i < rows; i++) {
grid[i] = malloc(sizeof(grid[i]) * cols);
ensure(grid[i], "malloc failed", __LINE__);
memcpy(grid[i], src_grid[i], cols);
}
int shortest_path_length = set_shortest_path(rows, cols, grid);
print_grid(rows, cols, grid);
printf("shortest path length: %d\n", shortest_path_length);
return 0;
}
Output:
-001---0
-000-0-1
-----0-0
001000-0
001101-0
111000-0
100111-0
111100--
shortest path length: 19

Related

Is there a better way to solve the problem of city linked by roads?

I have been working on a problem I solved but I'm not sure if it is the best way to do it.
I m working in windows 10 with visual studio. I know I'm using a c++ compiler but the code needs to be in C.
The problem:
On mars surface there are N city connected by M roads, humans want to destroy roads, but only strategic roads. A road is strategic if and only if without that road a pair of cities is no longer connected. Because humans are going to destroy some roads they are constructing Q new road.
Input:
a .txt file, on the first line there are 3 number N, M, Q, the following M line are the link on mars surface, the next Q lines contains the roads martians are going to build.
input.txt
5 4 2
5 1
3 2
2 5
4 2
1 2
5 3
Output:
Q line which contain the number of strategic roads after adding each line.
output example:
2
1
I tought to create a dynamic array and add a city if it is connected with another city in the array, if at the the end of the loop 2 city are not in the array the road which links those two city is not strategic.
#include<assert.h>
#include<stdio.h>
#include<malloc.h>
#define MAX_LINKS (250000)
typedef struct {
int a;
int b;
} link_t;
int N, M, Q, L, i;
link_t links[MAX_LINKS];
int find(int, int*, int);
bool strategic(link_t);
int main() {
freopen("input.txt", "r", stdin);
assert(scanf("%d%d%d", &N, &M, &Q)==3);
for (i = 0; i < M; ++i) {
assert(scanf("%d%d", &links[i].a, &links[i].b)==2);
++L;
}
int strategic_roads;
for (i = 0; i < Q; ++i) {
assert(scanf("%d%d", &links[M + i].a, &links[M + i].b) == 2);
++L;
strategic_roads = 0;
for (int j = 0; j < L; ++j) {
if (strategic(links[j])) {
++strategic_roads;
}
}
printf("%d\n", strategic_roads);
}
}
int find(int val, int* array, int size) {
for (int i = 0; i < size; ++i) {
if (array[i] == val) {
return i;
}
}
return -1;
}
bool strategic(link_t link) {
int counter = 1, size = 1, *arr;
int find_a = 0, find_b = 0;
arr = (int*)malloc(size * sizeof(int));
arr[0] = link.a;
bool still_working;
do {
still_working = false;
for (int i = 0; i < L; ++i) {
if ((links[i].a == link.a && links[i].b == link.b) || (links[i].a == link.b && links[i].b == link.a)) {
continue;
}
find_a = find(links[i].a, arr, size);
find_b = find(links[i].b, arr, size);
if (find_a < 0 && find_b >= 0) {
++size;
arr = (int*) realloc(arr, size * sizeof(int));
arr[counter] = links[i].a;
++counter;
still_working = true;
}
else if (find_a >= 0 && find_b < 0) {
++size;
arr = (int*)realloc(arr, size * sizeof(int));
arr[counter] = links[i].b;
++counter;
still_working = true;
}
}
} while (still_working);
return (find(link.b, arr, size) < 0);
}
Do you know another better way to solve it?

Numbers falling down a matrix

I have a N*N matrix full of elements. With a function I can destroy some elements so that they leave an empty space that can be occupied by numbers falling from above. An example of the process:
[1][3][4][5] [1][ ][4][5] [ ][ ][ ][5]
[3][3][3][0]-->[ ][ ][ ][0]-->[ ][ ][4][0]
[3][0][2][1]-->[ ][0][2][1]-->[1][0][2][1]
[2][4][5][3] [2][4][5][3] [2][4][5][3]
In this example only the numbers 1 and 4 fell down. Also when a column is completely empty those filled on the left must move right.
I want to create a function void gravity (game_t * p).
game_t in defined:
typedef struct game{
int n; /*n*n matrix */
int h; /* numbers on matrix go from 0 to h-1*/
int ** board; /*the actual matrix*/
} game_t
I can't think of a good strategy to solve this problem, can you please help me?
edit: this is what I wrote so far:
void gravity(game_t *p) {
int i, j, k;
for (k = 0; k < p->n - 1; k++) {
for (i = p->n - 2; i = 0; i--) {
for (j = p->n - 1; i = 0; i--) {
if (p->board[i - 1][j] == EMPTY) {
p->board[i - 1][j] = p->board[i][j];
p->board[i][j] = EMPTY;
}
}
}
return;
}
This one I wrote doesn't seem very efficient, maybe it should be recursive. For each element of the matrix from the second to last row going right to left I check if the element below is empty and move it there. However I have to check the matrix multiple times (k) because some elements may have to move more than once. `
Ok, as expected: "I know you will not do it, but please provide a minimal reproducible example." Yet again people ask a question and are not even interested in letting others solve their problem. The function you provided doesn't even compile...
Anyway, a solution is provided here along with all the code required to test it. It would have taken much less effort if you just had written all of this in the question with the non working gravity() function.
For the future readers , check out how the allocation done with a single malloc() and some casting, which allows to free everything with a single call to free(). It would be even better to use a single pointer to the data instead of the double pointer, but I understand that teachers around the world still favor the double pointer version. Also the game_set() function is interesting because it's a variadic function.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdarg.h>
const int EMPTY = INT_MIN;
typedef struct game {
int n; /*n*n matrix */
int h; /* numbers on matrix go from 0 to h-1*/
int **board; /*the actual matrix*/
} game_t;
game_t *game_construct(game_t *g, int n, int h)
{
assert(n > 0);
g->n = n;
g->h = h;
g->board = malloc(n * sizeof(int*) + n * n * sizeof(int));
g->board[0] = (int*)((char*)g->board + n * sizeof(int*));
for (int i = 1; i < n; ++i) {
g->board[i] = g->board[i - 1] + n;
}
return g;
}
game_t* game_destruct(game_t* g)
{
free(g->board);
return g;
}
void game_set(game_t* g, ...)
{
va_list argptr;
va_start(argptr, g);
for (int r = 0; r < g->n; ++r) {
for (int c = 0; c < g->n; ++c) {
g->board[r][c] = va_arg(argptr, int);
}
}
}
void game_print(game_t *g)
{
for (int r = 0; r < g->n; ++r) {
for (int c = 0; c < g->n; ++c) {
if (g->board[r][c] == EMPTY) {
printf("[ ]");
}
else {
printf("[%d]", g->board[r][c]);
}
}
printf("\n");
}
printf("\n");
}
void gravity(game_t *g)
{
for (int c = 0; c < g->n; ++c) {
int rf = g->n - 1;
for (int r = rf; r >= 0; --r) {
if (g->board[r][c] != EMPTY) {
g->board[rf--][c] = g->board[r][c];
}
}
while (rf >= 0) {
g->board[rf--][c] = EMPTY;
}
}
}
int main(void)
{
game_t g;
game_construct(&g, 4, 9);
game_set(&g,
1, 3, 4, 5,
3, 3, 3, 0,
3, 0, 2, 1,
2, 4, 5, 3);
game_print(&g);
game_set(&g,
1, EMPTY, 4, 5,
EMPTY, EMPTY, EMPTY, 0,
EMPTY, 0, 2, 1,
2, 4, 5, 3);
game_print(&g);
gravity(&g);
game_print(&g);
game_destruct(&g);
return 0;
}

Brute force algorithm causes undefined behaviour

I have to create a program for an assignment that solves a sudoku puzzle. User needs to enter the name of a binary file (NOT a true binary file, it just has a .bin extension, it can be opened with notepad, notepad++ etc. as well) that contains numbers. Those numbers represent coordinates on the puzzle as well as the number contained in those coordinates e.g 432 means 4th row 3rd column contains number 2. After filling out the puzzle i need to solve it and print it on screen. After executing the program it crashed, so I decided to use MSVC 2017 debugger which is among the best according to some developers to find and fix the bug. Here is my code:
Sudoku.c
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
#include "sudokulib.h"
#define MALLOC_ERROR 0xFF
#define FILE_NOT_FOUND 0xFFF
#define ROWS 9
#define COLUMNS 9
int main(int argc, char ** argv)
{
char **matrix;
int i, args;
int row, column, num;
FILE * fp;
char * filename;
char * importedData;
matrix = (char **)malloc(ROWS * sizeof(char *));
if (!matrix)
exit(MALLOC_ERROR);
for (i = 0; i<ROWS; ++i)
{
matrix[i] = (char *)malloc(COLUMNS * sizeof(char));
if (!matrix[i])
exit(MALLOC_ERROR);
}
initSudoku(matrix);
printf ("Give me the name of data file: ");
filename = (char *)malloc(100 * sizeof(char));
if (!filename)
exit(MALLOC_ERROR);
scanf("%99s", filename);
fp = fopen(filename, "rb");
if (!fp)
{
printf ("File not found\n");
exit(FILE_NOT_FOUND);
}
importedData = (char *)malloc(sizeof(char)*ROWS*COLUMNS * 3);
if (!importedData)
exit (MALLOC_ERROR);
args = fread(importedData, 1, 243, fp);
i = 0;
while (importedData[i] != ' ' && importedData[i + 1] != ' ' && importedData[i + 2] != ' ' && importedData[i] >= '1' && importedData[i + 1] >= '1' && importedData[i + 2] >= '1' && importedData[i] <= '9' && importedData[i + 1] <= '9' && importedData[i + 2] <= '9' && i < 243)
{
row = importedData[i] - '0' - 1; /* Convert from ascii code to number */
column = importedData[i + 1] - '0' - 1;
num = importedData[i + 2] - '0';
matrix[row][column] = num;
i = i + 3;
}
printf("Sudoku after importing data:\n\n");
printSudoku(matrix);
system("pause");
if (solvePuzzle(matrix))
{
printSudoku(matrix);
}
else
printf ("Puzzle has no solution\n");
fclose(fp);
free(filename);
for (i = 0; i<9; ++i)
{
free(matrix[i]);
}
free(matrix);
return 0;
}
Sudokulib.h
#pragma once
#include <stdlib.h>
#include <stdio.h>
/* Function Prototypes Begin Here */
void printSudoku(char **);
void initSudoku(char **);
int checkRow(char **, int, int);
int checkCol(char **, int, int);
int check3x3(char **, int, int, int);
int checkIfEmpty(char **, int*, int*);
int solvePuzzle (char **);
/* Function Prototypes End Here */
void printSudoku(char ** Mat)
{
int i, j;
for (i = 0; i<9; ++i)
{
printf ("-------------------\n");
printf("|");
for (j = 0; j<9; ++j)
{
printf("%d|", Mat[i][j]);
}
printf("\n");
}
printf ("-------------------\n");
}
void initSudoku(char ** Mat)
{
int i, j;
for (i = 0; i<9; ++i)
for (j = 0; j<9; ++j)
Mat[i][j] = 0;
}
int checkRow (char ** Mat, int row, int num) // if row is free returns 1 else returns 0
{
int col;
for (col = 0; col < 9; col++)
{
if (Mat[row][col] == num)
{
return 0;
}
}
return 1;
}
int checkCol (char ** Mat, int col, int num) // if column is free returns 1 else returns 0
{
int row;
for (row = 0; row < 9; row++)
{
if (Mat[row][col] == num)
{
return 0;
}
}
return 1;
}
int check3x3 (char ** Mat, int row, int col, int num) // if number doesnt exist in the 3x3 grid returns 1 else returns 0
{
row = (row / 3) * 3; // set to first row in the grid
col = (col / 3) * 3; // set to first col in the grid
int i;
int j;
for (i = 0; i < 3; i++) // grid is 3x3
{
for (j = 0; j < 3; j++)
{
if (Mat[row + i][col + j] == num)
{
return 0;
}
}
}
return 1;
}
int isValid (char ** Mat, int row, int col, int num)
{
return (checkRow(Mat, row, num) && checkCol(Mat, col, num) && check3x3(Mat, row, col, num));
}
int checkIfPuzzleSolved (char ** Mat, int *row, int *col) // if function finds a box empty (puzzle not solved) returns 0 else returns 1
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
printf("ROW: %d COL: %d\n",*row,*col);
if (Mat[*row][*col] == 0)
{
return 0;
}
}
}
return 1;
}
int solvePuzzle (char ** Mat)
{
int row;
int col;
if (checkIfPuzzleSolved(Mat, &row, &col))
{
return 1;
}
int num;
for (num = 1; num <= 9; num++)
{
//if (checkRow (Mat,row,num) && checkCol (Mat,col,num) && check3x3 (Mat,row,col,num))
if (isValid(Mat, row, col, num))
{
Mat[row][col] = num;
if (solvePuzzle(Mat))
return 1;
Mat[row][col] = 0;
}
}
return 0;
}
The debugger found a bug at this function:
int checkIfPuzzleSolved (char ** Mat, int *row, int *col) // if function finds a box empty (puzzle not solved) returns 0 else returns 1
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
printf("ROW: %d COL: %d\n",*row,*col);
if (Mat[*row][*col] == 0) /* DEBUGGER ERROR CODE 0xC0000005: Access violation reading location 0xCDCA247C
{
return 0;
}
}
}
return 1;
}
Two things that confused me:
1) I don't understand the reason solvePuzzle gets stuck brute forcing the first box in the puzzle (1st row 1st column). It seems that checkIfPuzzleSolved thinks that the first box is empty (containing 0), even though using printSudoku I can see the algorithm modifying that box toggles its value between 3 and 4 and obviously 0 != 3 and 0 != 4.
2) In checkIfPuzzleSolved, printf prints on screen row and column number and it constantly produces the following result:
ROW: 0 COL: 0
ROW: 0 COL: 0
ROW: 0 COL: -858993460
Also double checked this with the debugger and the values are indeed those mentioned.
My train of thought was the following:
1) Use checkIfEmpty to determine if a box of the puzzle contained 0, that would mean that the puzzle would not be solved yet. Row and col variables are sent into the function by reference, so when function finds an empty box and returns, row and col would save the coordinates of the empty box.
2) In the loop, call checkRow, checkCol and check3x3 to check if a number can be put into the desired box without breaking the sudoku rules. isValid is there for readability purposes.
3) Call solvePuzzle recursively until the puzzle is solved, meanwhile if a number is wrong, reset it to 0.
I have tried everything i could think of to solve this problem, wasting hours reading again and again my code to find a logical error, but everything seems okay. Any ideas?
EDIT: On request of Michael Beer, here is a sample binary file:
data.bin
142156177191216228257289311329364375418422441484534546562579625663682698739743787794824855883896917933951968
*row++; parses as *(row++);, which is equivalent to just row++. You're incrementing the pointer, not the counter.
– melpomene
I see. So am I incrementing the pointer by sizeof(int) and not increasing the value that it refers to by 1? If so what is the correct way of writing "increment the value of the address you are pointing to by 1" regarding the syntax?
(*row)++ or ++(*row) or ++*row or *row += 1.
– melpomene

Is there a way to iterate over order?

How can one iterate through order of execution?
I am developing a piece of software that have several steps to compute over some data, and i was thinking in may changing the order of those steps pragmatically so i can check what would be the best order for some data.
Let me exemplify: I have let's say 3 steps (it's actually more):
stepA(data);
stepB(data);
stepC(data);
And I want a contraption that allow me to walk thought every permutation of those steps and then check results. Something like that:
data = originalData; i=0;
while (someMagic(&data,[stepA,stepB,stepC],i++)){
checkResults(data);
data = originalData;
}
then someMagic execute A,B then C on i==0. A, C then B on i==1. B, A then C on i==2 and so on.
You can use function pointers, maybe something like the following:
typedef void (*func)(void *data);
int someMagic(void *data, func *func_list, int i) {
switch (i) {
case 0:
func_list[0](data);
func_list[1](data);
func_list[2](data);
break;
case 1:
func_list[0](data);
func_list[2](data);
func_list[1](data);
break;
case 2:
func_list[1](data);
func_list[0](data);
func_list[2](data);
break;
default: return 0;
}
return 1;
}
func steps[3] = {
stepA,
stepB,
stepC
}
while (someMagic(&data, steps, i++)) {
....
}
The key is to find a way to iterate over the set of permutations of the [0, n[ integer interval.
A permutation (in the mathematical meaning) can be seen as a bijection of [0, n[ into itself and can be represented by the image of this permutation, applied to [0, n[.
for example, consider the permutation of [0, 3[:
0 -> 1
1 -> 2
2 -> 0
it can be seen as the tuple (1, 2, 0), which in C, translate naturally to the array of integers permutation = (int []){1, 2, 0};.
Suppose you have an array of function pointers steps, then for each permutation, you'll then want to call steps[permutation[i]], for each value of i in [0, n[.
The following code implements this algorithm:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void stepA(int data) { printf("%d: %s\n", data, __func__); }
static void stepB(int data) { printf("%d: %s\n", data, __func__); }
static void stepC(int data) { printf("%d: %s\n", data, __func__); }
static void (* const steps[])(int) = {stepA, stepB, stepC,};
static int fact(int n) { return n == 0 ? 1 : fact(n - 1) * n; }
static int compare_int(const void *pa, const void *pb)
{
return *(const int *)pa - *(const int *)pb;
}
static void get_next_permutation(int tab[], size_t n)
{
int tmp;
unsigned i;
unsigned j;
unsigned k;
/* to find the next permutation in the lexicographic order
* source: question 4 (in french, sorry ^^) of
* https://liris.cnrs.fr/~aparreau/Teaching/INF233/TP2-permutation.pdf
. */
/* 1. find the biggest index i for which tab[i] < tab[i+1] */
for (k = 0; k < n - 1; k++)
if (tab[k] < tab[k + 1])
i = k;
/* 2. Find the index j of the smallest element, bigger than tab[i],
* located after i */
j = i + 1;
for (k = i + 1; k < n; k++)
if (tab[k] > tab[i] && tab[k] < tab[j])
j = k;
/* 3. Swap the elements of index i and j */
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
/* 4. Sort the array in ascending order, after index i */
qsort(tab + i + 1, n - (i + 1), sizeof(*tab), compare_int);
}
int main(void)
{
int n = sizeof(steps) / sizeof(*steps);
int j;
int i;
int permutation[n];
int f = fact(n);
/* first permutation is identity */
for (i = 0; i < n; i++)
permutation[i] = i;
for (j = 0; j < f; j++) {
for (i = 0; i < n; i++)
steps[permutation[i]](i);
if (j != f - 1)
get_next_permutation(permutation, n);
}
return EXIT_SUCCESS;
}
The outer loop in main, indexed by j, iterates over all the n! permutations, while the inner one, indexed by i, iterates overs the n steps.
The get_next_permutation modifies the permutation array in place, to obtain the next permutation in the lexicographical order.
Note that it doesn't work when the permutation in input is the last one (n - 1, ..., 1, 0), hence the if (j != f - 1) test.
One could enhance it to detect this case (i isn't set) and to put the first permutation (0, 1, ..., n - 1) into the permutation array.
The code can be compiled with:
gcc main.c -o main -Wall -Wextra -Werror -O0 -g3
And I strongly suggest using valgrind as a way to detect off-by-one errors.
EDIT: I just realized I didn't answer the OP's question precisely. The someMagic() function would allow a direct access to the i-th permutation, while my algorithm only allows to compute the successor in the lexicographic order. But if the aim is to iterate on all the permutations, it will work fine. Otherwise, maybe an answer like this one should match the requirement.
I've come to a solution that is simple enough:
void stepA(STRUCT_NAME *data);
void stepB(STRUCT_NAME *data);
void stepC(STRUCT_NAME *data);
typedef void (*check)(STRUCT_NAME *data);
void swap(check *x, check *y) {
check temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(check *a, int l, int r,STRUCT_NAME *data) {
int i, j = 0, score;
HAND_T *copy, *copy2, *best_order = NULL;
if (l == r) {
j = 0;
while (j <= r) a[j++](data);
} else {
for (i = l; i <= r; i++) {
swap((a + l), (a + i));
permute(a, l + 1, r, data);
swap((a + l), (a + i));
}
}
}
check checks[3] = {
stepA,
stepB,
stepC,
};
int main(void){
...
permute(checks,0,2,data)
}

sort and remove duplicates from int array in c

I am learning C and came over the topic of sorting. I wrote a comp() function in and used qsort to sort an array of int. Now for the next task I need to remove the duplicates from the array.
Is it possible to sort and remove duplicates at the same time?
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int indexes[10] = { 0, 98, 45, 65, 45, 98, 78, 56, 65, 45 };
int comp(const void * elem1, const void * elem2) {
int f = *((int*) elem1);
int s = *((int*) elem2);
if (f > s) {
return 1;
}
if (f < s) {
return -1;
}
return 0;
}
void printIndexArray() {
int i = 0;
for (i = 0; i < 10; i++) {
printf("i is %d\n", indexes[i]);
}
}
int main() {
qsort(indexes, sizeof(indexes) / sizeof(int), sizeof(int), comp);
printIndexArray();
return 0;
}
Since your numbers are already sorted, removing dupes is easy. In C++, it's even built in as std::unique:
http://en.cppreference.com/w/cpp/algorithm/unique
Assuming you want to do it yourself, you can do it the same way unique does it:
int* unique (int* first, int* last)
{
if (first==last) return last;
int* result = first;
while (++first != last)
{
if (!(*result == *first))
*(++result)=*first;
}
return ++result;
}
Yes
This can be achieved by mergesort. If both left and right are the same just merge the one value
That's the code that removes the duplicates using mergesort. This snippet of code does the removing work:
else if(a[p1] == a[p2])
{
merged[p] = a[p1];
p1++;
p2++;
}
That's the iterative merge sort while the recursive version would be easier.
#include <stdio.h>
#include <stdlib.h>
#define min(a,b) (((a) < (b)) ? (a) : (b))
int indexes[10] = { 0, 98, 45, 65, 45, 98, 78, 56, 65, 45 };
void merge(int *a, int s, int m, int e)
{
int p1 = s;
int p2 = m + 1;
int * merged = (int*)malloc(sizeof(int) * (e - s + 1));
int p = 0;
while(p1 < m + 1 && p2 < e + 1)
{
if(a[p1] > a[p2])
{
merged[p] = a[p2];
p2++;
}
else if(a[p1] == a[p2])
{
merged[p] = a[p1];
p1++;
p2++;
}
else
{
merged[p] = a[p1];
p1++;
}
p++;
}
while(p1 < m + 1)
{
merged[p++] = a[p1++];
}
while(p2 < e + 1)
merged[p++] = a[p2++];
int i;
for(i = 0;i < (e -s+1); i++)
{
a[s + i] = merged[i];
}
free(merged);
}
void merge_sort(int *a, int n)
{
int width;
for(width = 1; width < n; width = 2 * width)
{
int i;
for(i = 0; i < n; i = i + 2 * width)
{
merge(a, i, min(i + width - 1, n - 1), min(i + 2 * width - 1, n - 1) );
}
}
}
void printIndexArray()
{
int i = 0;
for(i = 0; i < 10; i++)
{
printf("i is %d\n", indexes[i]);
}
}
int main()
{
merge_sort(indexes, sizeof(indexes) / sizeof(int) );
printIndexArray();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int indexes[10] = { 0, 98, 45, 65, 45, 98, 78, 56, 65, 45 };
size_t undup(int array[], size_t len)
{
size_t src,dst;
if (!len) return 0;
for (src=dst=1; src < len; src++) {
if (array[dst-1] == array[src]) continue;
array[dst++] = array[src];
}
return dst;
}
int comp(const void * elem1, const void * elem2) {
int f = *((int*) elem1);
int s = *((int*) elem2);
if (f > s) return 1;
if (f < s) return -1;
return 0;
}
void printIndexArray(size_t len) {
size_t i = 0;
for (i = 0; i < len; i++) {
printf("array[%zu] is %d\n", i, indexes[i]);
}
}
int main() {
size_t len = 10;
printf("Before sort\n" );
printIndexArray(len);
qsort(indexes, sizeof indexes / sizeof indexes[0], sizeof indexes[0], comp);
printf("After sort\n" );
printIndexArray(len);
len = undup(indexes,10);
printf("After undup\n" );
printIndexArray(len);
return 0;
}
The short answer is: yes.
The long answer is: it is always possible, but the complexity to do it depends heavily on the algorithm you use.
The more complex algorithms like quick-sort, slow-sort, bucket-sort, and straight-radix-sort do not lend themselves to such an enhancement, because they rely on the data being in a consecutive array, that can implicitly be split into subarrays. So, when you detect a duplicate, you cannot easily take it out. Again, it is possible, but certainly not a problem for beginners.
The less complex in-place algorithms like bubble-sort, insertion-sort, and shell-sort make it relatively easy: you can just replace one of the duplicates you detect with a sentinel value that sorts greater than all legal values, and let it rise to the top. After that, you just need to scoop off the cream of sentinel values and you are done.
The algorithms that really lend themselves to removing duplicates, are the ones that use intermediate arrays that grow/shrink in the process; in these cases you can just shrink or skip growing one of these intermediate arrays when you detect a duplicate. Candidates are merge-sort and heap-sort.
Note, however, that it is more prudent to just sort the array, and eliminate duplicates in a second, separate step. Why? Because eliminating duplicates adds complexity to the inner loop of the sorting algorithm, which is of O(n*log(n)) in most relevant cases. But eliminating duplicates from a sorted array is an O(n) operation, making the split operation faster than the fused one.

Resources