Longest Path: Recursive Backtracking with Constraints in C - c

I was recently assigned a problem, which boils down to finding the longest path in a given matrix, where two cells are adjacent iff the neighboring value is less than the present cell. I've been tearing my hair out trying to figure it out, so I would be extremely grateful for any help. However, as I said, this is a homework assignment, so suggestions and hints are very welcome (but try not to make it too easy for me).
Here's the latest version of my code:
#include <stdio.h>
int isValid(int i, int j, int rows, int cols) {
if (i < 0 || i >= rows || j < 0 || j >= cols)
return 0;
return 1;
}
void printpath(int path[1000][2]) {
int i = 0;
while (path[i][0] != -1) {
printf("(%d, %d) ", path[i][0], path[i][1]);
i++;
}
}
void print_array_path(int path[1000][2], int array[100][100]) {
int i = 0;
while (path[i][0] != -1) {
printf("%d -> ", array[path[i][0]][path[i][1]]);
i++;
}
}
int path_length(int path[1000][2]) {
int i = 0, s = 0;
while ( path[i][0] != -1) {
s++;
i++;
}
return s-1;
}
void add_path(int path[1000][2], int u, int v) {
int i = 0;
while (path[i][0] != -1) {
i++;
}
path[i][0] = u; // row
path[i][1] = v; // column
}
int last_i(int path[1000][2], int s) {
int v;
v = path[s][0];
//path[i-2][0] = -1;
return v;
}
int last_j(int path[1000][2], int s) {
int u;
u = path[s][1];
//path[i-2][1] = -1;
return u;
}
int c1[4] = {1, 0, -1, 0};
int c2[4] = {0, 1, 0, -1};
int dfs(int visited[100][100], int array[100][100], int i, int j, int rows, int cols, int path[1000][2], int length) {
// 1. Take the current visited, along with the previous vertex, to create a unique
// list of visited vertices.
// 2. For every direction, check if it is valid. If valid, do dfs(visited, current, choice)
// 3. If all four directions are checked, with no valid choice, report the solution.
int s;
for (s=0; s<4; s++) {
if ( isValid(i+c1[s], j+c2[s], rows, cols) && !(visited[i+c1[s]][j+c2[s]]) && (array[i][j] < array[i+c1[s]][j+c2[s]]) ) {
// TODO visited.add(current)
visited[i][j] = 1;
add_path(path, i+c1[s], j+c2[s]);
//printf("%d -> ", array[i+c1[s]][j+c2[s]]);
//printpath(path);
length += 1;
dfs( visited, array, i+c1[s], j+c2[s], rows, cols, path, length);
} else if (s==3) {
//visited[i+c1[s]][j+c2[s]] = 0;
//printf("end at %d, %d\n", i, j);
if ( (last_i(path, i) == i) && (last_i(path, j) == j) ){
printf("%d ", length);
print_array_path(path, array);
printf("\n");
continue;
}
length -= 1;
dfs(visited, array, last_i(path, i-1), last_j(path, i-1), rows, cols, path, length);
return path[i][0];
}
}
}
int main() {
int array[100][100];
int rows, columns;
scanf("%d", &rows);
scanf("%d", &columns);
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
scanf("%d", &array[i][j]);
}
}
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
printf("%d ", array[i][j]);
}
printf("\n");
}
int visited[100][100];
for (i=0; i<rows; i++) {
for (j=0; j<columns; j++) {
visited[i][j] = 0;
}
}
int path[1000][2];
for (i=0; i<1000; i++) {
for (j=0; j<2; j++) {
path[i][j] = -1;
}
}
path[0][1] = 0;
path[0][0] = 0;
int length = 0;
dfs(visited, array, 0, 0, rows, columns, path, length);
}
Basically, it first collects an inputted matrix, and starts at the first cell (once I get the whole thing working, it would move through every cell), calls a search function, checks to see if a neighboring cell is valid, then calls the search again. If all four directions have been checked, it backtracks. The current path is tracking in a list path. My problem seems to mostly be in the backtracking part. However, I'm not sure how to move forward. This code barely compiles at the moment, as I've been trying so many different things. At this point, I'd like to catch my breath and really understand what I'm trying to do.
Earlier on, I tried generating an adjacency list, and constructing paths from that, but the backtracking option seemed more promising. A typical input looks like this:
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
To express a 5x5 matrix. The expected output would be 25 (25->24-> ... 2->1). Please let me know if any other info would be helpful. Any advice / tips would be greatly appreciated! Thanks.
EDIT: The original problem was reversed (i.e two cells are adj iff the neighbor has a strictly lower value. The two problems are equivalent, right?)
EDIT 2: I made some changes to the code, and I think I'm a bit closer. It now gives this output:
3 1 -> 16 -> 17 -> 24 -> 25 ->
3 1 -> 16 -> 17 -> 24 -> 25 ->
4 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 ->
9 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 ->
10 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 ->
8 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 ->
17 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 ->
20 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 ->
21 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 ->
21 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 ->
19 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
19 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
13 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
12 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
11 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
9 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
8 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
7 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
8 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
7 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
5 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
4 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
2 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
1 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
I replaced the above code to reflect those changes. It seems very close, but not quite the right answer, namely, the path seems to be found but the lengths are not correct.

The main problem of the current code is trackback.
It is necessary to return the environment after executing the function.
Specific modification example:
#include <stdio.h>
#include <stdbool.h>
#define MAX_LEN 1000
#define SIZE 100
#define EOP -1 //End Of Path
typedef struct pos {
int r, c;//rows, columns
} Pos;
Pos EPOS = { EOP, EOP};
bool isValidPos(Pos pos, int rows, int cols) {
return 0 <= pos.r && pos.r < rows && 0 <= pos.c && pos.c < cols;
}
bool isVisited(Pos pos, bool visited[SIZE][SIZE]){
return visited[pos.r][pos.c];
}
/* unused
void printPos(Pos pos){
printf("(%d, %d)", pos.r, pos.c);
}
void printpath(Pos path[]){
while(path->r != EOP)
printPos(*path++);
}
int path_length(Pos path[]) {
int i = 0;
while((path++)->r != EOP)
++i;
return i;
}
void add_path(Pos path[], Pos pos) {
while (path->r != EOP)
++path;
*path = pos;
path[1] = EPOS;
}
*/
int valueOf(Pos pos, int array[SIZE][SIZE]){
return array[pos.r][pos.c];
}
void print_path(Pos path[], int array[SIZE][SIZE]){
while(path->r != EOP)
printf("%d -> ", valueOf(*path++, array));
}
const Pos rpos[] = {{1,0},{0,1},{-1,0},{0,-1}};//relative position
void dfs(bool visited[SIZE][SIZE], int array[SIZE][SIZE], Pos pos, int rows, int cols, Pos path[], int length){
visited[pos.r][pos.c] = true;
int value = valueOf(pos, array);
bool CantAddPath = true;
for (int s = 0; s < sizeof(rpos)/sizeof(*rpos); s++){
Pos movePos = { .r = pos.r + rpos[s].r, .c = pos.c + rpos[s].c};
if(!isValidPos(movePos, rows, cols) || isVisited(movePos, visited) || value >= valueOf(movePos, array))
continue;
CantAddPath = false;
path[length++] = pos;//add_path(path, pos);length++;
dfs(visited, array, movePos, rows, cols, path, length);
path[--length] = EPOS;
}
if(CantAddPath){
printf("%d ", length+1);//+1: current (last) postion
print_path(path, array);
printf("%d\n", value);//value of current (last) position
}
visited[pos.r][pos.c] = false;
}
int main(void) {
int array[SIZE][SIZE];
int rows, columns;
scanf("%d", &rows);
scanf("%d", &columns);
int i, j;
for(i = 0; i < rows; i++)
for(j = 0; j < columns; j++)
scanf("%d", &array[i][j]);
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++)
printf("%2d ", array[i][j]);
printf("\n");
}
bool visited[SIZE][SIZE] = {{ false }};
Pos path[MAX_LEN];
for (i = 0; i < MAX_LEN; i++){
path[i] = EPOS;
}
Pos start = { 0, 0 };
//path[0] = start;//Mismatch with `int length = 0;`
int length = 0;
dfs(visited, array, start, rows, columns, path, length);
}

Related

Shuffle array several times without repeating pairs

I have a list of names, for example:
"Alice", "Bob", "Steve", "Kate", "Jane", "John", "Vic", "Dan", "Robert"
They call each other in a circle chain:
"Alice" -> "Bob" -> "Steve" -> "Kate" -> "Jane" -> "John" -> "Vic" -> "Dan" -> "Robert" -> "Alice"
I need an algorithm which will print several chains where in the result every person should have a call with all other persons without repeats. So if Vic called Dan and John called Vic yestarday all of them should have another persons in today call.
Your task can be achieved by the following MiniZinc model:
include "circuit.mzn";
int: n = 9; % number of participants
int: rounds = 4;
set of int: N = 1..n;
set of int: Rounds = 1..rounds;
% decision variables
array[N, Rounds] of var N: x;
predicate is_chain(array[N] of var N: c) =
circuit(c);
predicate is_talking_to(N: p1, N: p2, Rounds: r) =
(x[p1, r] == p2) \/
(x[p2, r] == p1);
constraint forall(r in Rounds) (circuit([x[p, r] | p in N]));
constraint forall(r1 in Rounds, r2 in r1+1..rounds, p1 in N, p2 in p1+1..n)
(is_talking_to(p1, p2, r1) -> not is_talking_to(p1, p2, r2));
function string: show_chain(array[N] of var N: c) =
join(" -> ", [ "\(c[p])" | p in N ]) ++ " -> \(c[1])\n";
output [ show_chain([fix(x[p, r]) | p in N]) | r in Rounds ];
Example output:
7 -> 5 -> 2 -> 9 -> 8 -> 4 -> 3 -> 6 -> 1 -> 7
4 -> 8 -> 9 -> 7 -> 1 -> 5 -> 2 -> 3 -> 6 -> 4
6 -> 9 -> 1 -> 3 -> 7 -> 2 -> 8 -> 4 -> 5 -> 6
2 -> 4 -> 6 -> 5 -> 3 -> 7 -> 9 -> 1 -> 8 -> 2
For more than four rounds, no solution was found.
The model interpretes to "have a call" as symmetric "speaking to eachother". It does not matter, who is initiating a call.

AWK array seems to empty itself?

I am trying to learn awk by solving code puzzles. I am trying to read several "grids" of integers (representing bingo boards as per https://adventofcode.com/2021/day/4) into a three-dimensional awk array. An example "grid" can look like this:
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
And there are several of these in a longer input file. After reading each line into an array rows I am attempting to organize the numbers into this multi dimensional array called boards. Here is my example code:
{
b = 0
for (i in rows) {
split(rows[i], nums, " ")
for (j in nums) {
r = i % 5
n = j - 1
boards[b][r][n] = nums[j]
print b, r, n, nums[j], boards[b][r][n]
}
if (i%5==0)
++b
}
print boards[0][1][1]
}
Notice the debug printout print b, r, n, nums[j], boards[b][r][n] which indeed outputs the correct values for boards[b][r][n] on that row:
0 0 0 22 22
0 0 1 13 13
0 0 2 17 17
Etc. This seems to verify that the multi dimensional array gets written properly. Yet on the final line of the example code, the output is instead empty. I have tried using the form boards[b, r, n] for the array as well with the exact same result. Obviously there's something I'm not quite understanding here. Any help is appreciated. Full code for reproducibility:
# === ex.txt ===
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7
# === solve.awk ===
BEGIN {
r = 0
}
{
if (NR == 1)
split($0, draws, "")
else if (NR != 2 && (NR-3)%6 != 5)
rows[r++] = $0
}
END {
b = 0
for (i in rows) {
split(rows[i], nums, " ")
for (j in nums) {
r = i % 5
n = j - 1
boards[b][r][n] = nums[j]
print b, r, n, nums[j], boards[b][r][n]
}
if (i%5==0)
++b
}
print boards[0][1][1]
}
I run this with awk -f solve.awk ex.txt. awk --version outputs GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0-p13, GNU MP 6.2.1) as its first line. Thank you!
You are incrementing b at the end of the first iteration of your for (i in rows) loop because i == 0 ==> i%5 == 0, while you want to do it at the end of the 5th iteration. Try if (i%5 == 4) ++b.
Note that as you use GNU awk you could simplify all this. When the record separator (RS) is the empty string the records are separated by empty lines (one record per board):
$ awk -v RS='' '
NR>1 {
a[NR-2][1]; split($0, a[NR-2]);
}
END {
for(b in a) for(r in a[b])
boards[b][int((r-1)/5)][(r-1)%5] = a[b][r];
for(b in boards) for(r in boards[b]) for(n in boards[b][r])
print b, r, n, boards[b][r][n]
}' ex.txt
0 0 0 22
0 0 1 13
0 0 2 17
0 0 3 11
0 0 4 0
0 1 0 8
...

C code implementing bubble sort for linked list isn't working

I am trying to apply bubble sort on linklist. for that I have implemented my own list but the code isn't working as it somehow isn't printing any value when all of the linklist values are printed.
The course I was writing code for required me to write everything from scratch. I wrote a bubble sort function which isn't working as it should, It is somehow tempering the root due to which I am not able to print all of the values of the linklist.
I also tried to print string "values swapped" to understand how many times is the loop running, turns out it is running the number of times it should run. but doing something due to which I can't print the values from the root.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <stdbool.h>
typedef struct Node
{
int value;
struct Node *next;
} Node;
Node *insert(Node *root, int val)
{
Node *new = (Node *)malloc(sizeof(Node));
new->value = val;
new->next = NULL;
if (root == NULL)
{
root = new;
return root;
}
while (root->next != NULL)
{
root = root->next;
}
root->next = new;
return NULL;
}
void swap(Node *n1, Node *n2)
{
int temp = n1->value;
n1->value = n2->value;
n2->value = temp;
}
void print(Node *root)
{
if (root == NULL)
return;
printf("%d ", root->value);
print(root->next);
}
void bubbleSort(Node *root)
{
bool toSwap = true;
Node *trav = root;
while (toSwap)
{
toSwap = false;
while (trav != NULL)
{
if (trav->value > trav->next->value)
{
swap(trav, trav->next);
printf("Values Swapped \n");
toSwap = true;
}
trav = trav->next;
}
}
}
int main(void)
{
Node *root = NULL;
root = insert(root, 4);
insert(root, 1);
insert(root, 5);
insert(root, 3);
bubbleSort(root);
print(root);
return 0;
}
Your code runs in O(n) time, since trav moves forward at every iteration and the algorithm terminates when trav has reached the end of the list. However, Bubble Sort is a O(n^2) time algorithm.
You need to use two pointers. Let's call the second pointer trav_2. The first pointer (trav) simply acts as a counter to make sure that the second pointer (trav_2) iterates through the list performing the necessary swaps n times. If you replace your while loop with the following logic, it should work fine:
while (trav!=NULL)
{
toSwap = false;
Node *trav_2 = root;
while (trav_2 != NULL && trav_2->next!=NULL)
{
if (trav_2->value > trav_2->next->value)
{
swap(trav_2, trav_2->next);
printf("Values Swapped \n");
toSwap = true;
}
trav_2 = trav_2->next;
}
trav = trav->next;
}
I have also fixed some pointer dereferencing errors you had in your code (the ones others have mentioned). However, fixing them wasn't enough. The logic was flawed too.
Fixing the existing code has already been done by Harsh. I'm going to show you how this is done by pure pointer juggling rather than swapping datum across nodes. Normally that is the purpose of this exercise. Imagine an enormous data payload held within each node that makes it obtrusive to copy. You don't have to if you just jostle the pointers to rearrange the list.
For each enumeration the "largest" element will bubble to the end. it is pruned from there and pushed on to the head of a new list. When the algorithm is done one of two things will have transpired:
We ran out of nodes. OR
We ejected early due to noswap-optimization.
The first of these is trivial. We already have all the nodes and they're already sorted. The latter complicates things because we still have two sorted lists: one is the list of items we've pruned thus far as we push-built our sorted result, the other is the remaining list that we detected as already-sorted and ejected the sorting loop. Fortunately, due to the manner in which we tracked the last node pointer in remaining source list, it makes linking them easy and we'll have our final result.
Finally, because root can change, the algorithm requires the new root be returned from the function. That, in turn, requires a change in main. This is not specific to the aforementioned algorithm. It would have to be done regardless as a separate, but important, bug fix.
The sorting implementation appears below:
Node *bubbleSort(Node *root)
{
Node *result = NULL;
Node **pp;
bool swapped = (root != NULL);
while (swapped)
{
// reset swap state
swapped = false;
pp = &root;
while (*pp && (*pp)->next)
{
// compare the two node values
if ((*pp)->next->value < (*pp)->value)
{
Node *p = *pp;
*pp = (*pp)->next;
p->next = (*pp)->next;
(*pp)->next = p;
swapped = true;
}
pp = &(*pp)->next;
}
// pp holds the address of the pointer pointing to
// the last node in the source list. So, we...
// 1. prune off the end node.
// 2. terminate the source list
// 3. push the pruned node on to the front of
// the result list where it belongs.
Node *p = *pp;
*pp = NULL;
p->next = result;
result = p;
// TODO: fun thing here. print both lists (result and root)
}
// the above loop could have exited early, leaving root
// holding the sorted low half of the list. the *last*
// pointer in that list is addressed by pp, so we can
// just link the rest of the list we already pruned to
// that end and we're done.
*pp = result;
return root;
}
The change in main is likewise below:
int main(void)
{
Node *root = insert(root, 4);
insert(root, 1);
insert(root, 5);
insert(root, 3);
root = bubbleSort(root);
print(root);
return 0;
}
And finally, the result:
1 3 4 5
Worth noting: bubble-sort is already dreadful enough. It is a terrible fit for nearly all sorting purposes, and especially for linked lists, where the ideal sorting mechanic would be merge-sort. But for academic purposes it makes for an interesting exercise, especially if you embrace the challenge of doing it exclusively with pointer jostling; not datum swapping.
An Interesting View
Modifying the code to do the following:
Generate a random shuffle of the sequence 1...30
Do the sort as shown above, but print the source and result lists after each iteration.
the results show how the pruning, pushing, and final fix up happen. The original shuffled list is:
11 28 16 6 12 23 13 1 20 14 27 3 2 7 21 4 8 30 19 15 22 17 26 29 24 9
Printing each list (the remaining source list and the result we're building), the outcome looks like this:
root: 11 16 6 12 23 13 1 20 14 27 3 2 7 21 4 8 28 19 15 22 17 26 29 24 9 5 18 25 10
result: 30
root: 11 6 12 16 13 1 20 14 23 3 2 7 21 4 8 27 19 15 22 17 26 28 24 9 5 18 25 10
result: 29 30
root: 6 11 12 13 1 16 14 20 3 2 7 21 4 8 23 19 15 22 17 26 27 24 9 5 18 25 10
result: 28 29 30
root: 6 11 12 1 13 14 16 3 2 7 20 4 8 21 19 15 22 17 23 26 24 9 5 18 25 10
result: 27 28 29 30
root: 6 11 1 12 13 14 3 2 7 16 4 8 20 19 15 21 17 22 23 24 9 5 18 25 10
result: 26 27 28 29 30
root: 6 1 11 12 13 3 2 7 14 4 8 16 19 15 20 17 21 22 23 9 5 18 24 10
result: 25 26 27 28 29 30
root: 1 6 11 12 3 2 7 13 4 8 14 16 15 19 17 20 21 22 9 5 18 23 10
result: 24 25 26 27 28 29 30
root: 1 6 11 3 2 7 12 4 8 13 14 15 16 17 19 20 21 9 5 18 22 10
result: 23 24 25 26 27 28 29 30
root: 1 6 3 2 7 11 4 8 12 13 14 15 16 17 19 20 9 5 18 21 10
result: 22 23 24 25 26 27 28 29 30
root: 1 3 2 6 7 4 8 11 12 13 14 15 16 17 19 9 5 18 20 10
result: 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 6 4 7 8 11 12 13 14 15 16 17 9 5 18 19 10
result: 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 11 12 13 14 15 16 9 5 17 18 10
result: 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 11 12 13 14 15 9 5 16 17 10
result: 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 11 12 13 14 9 5 15 16 10
result: 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 11 12 13 9 5 14 15 10
result: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 11 12 9 5 13 14 10
result: 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 11 9 5 12 13 10
result: 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 9 5 11 12 10
result: 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 8 5 9 11 10
result: 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 7 5 8 9 10
result: 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 6 5 7 8 9
result: 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 5 6 7 8
result: 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
root: 1 2 3 4 5 6 7
result: 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
The final result is as expected:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Change your inner while loop to this:
while (trav != NULL && trav->next != NULL) {
if (trav->value > trav->next->value) {
printf("Swapping values %d %d\n", trav->value, trav->next->value);
swap(trav, trav->next);
toSwap = true;
}
trav = trav->next;
}
It corrects the NULL pointer dereferencement.
You'll see why it doesn't work by clearly showing what is being swapped.
That being said, you should rather do what is mentioned in the second comment.

Create matrix of some repeating numbers

EN = 10;
etable = [1,2,3,4,5,6;
4,5,6,7,8,9;
7,8,9,10,11,12;
10,11,12,13,14,15;
13,14,15,16,17,18;
16,17,18,19,20,21;
19,20,21,22,23,24;
22,23,24,25,26,27;
25,26,27,28,29,30;
28,29,30,31,32,33];
Is it possible to make a for loop in which I just change the EN value and it automatically creates etable? Because I have to make EN 50 so it'll not be good to write 50 lines in etable.
I tried in this way:
EN = 10;
c = 1:EN;
nodes = zeros(size(c',1),2);
for i = 1:length(c)
nodes(i,1) = i;
nodes(i,2) = i+1;
end
etable = zeros(size(c',1),6);
for i = 1:size(nodes,1)
etable(i,1) = 2*nodes(i,1)-1;
etable(i,2) = 2*nodes(i,1);
etable(i,3) = 2*nodes(i,1)+1;
etable(i,4) = 2*nodes(i,2);
etable(i,5) = 2*nodes(i,2)+1;
etable(i,6) = 2*nodes(i,2)+2;
end
You can use implicit expansion implicitly (introduced in MATLAB R2016b) or explicitly by using MATLAB's bsxfun to create that matrix:
% Parameters
EN = 10;
n = 6;
step = 3;
% Matrix (implict expansion, MATLAB >= R2016b)
etable = (0:step:EN*step-1).' + (1:n)
% Matrix (bsxfun, MATLAB < R2016b)
etable_legacy = bsxfun(#plus, (0:step:EN*step-1).', (1:n))
For the given parameter set, the outputs are:
etable =
1 2 3 4 5 6
4 5 6 7 8 9
7 8 9 10 11 12
10 11 12 13 14 15
13 14 15 16 17 18
16 17 18 19 20 21
19 20 21 22 23 24
22 23 24 25 26 27
25 26 27 28 29 30
28 29 30 31 32 33
etable_legacy =
1 2 3 4 5 6
4 5 6 7 8 9
7 8 9 10 11 12
10 11 12 13 14 15
13 14 15 16 17 18
16 17 18 19 20 21
19 20 21 22 23 24
22 23 24 25 26 27
25 26 27 28 29 30
28 29 30 31 32 33
You can change EN (number of rows), the "number of columns" n and/or the "step between rows" step.
Hope that helps.

Loop text to match character count between two linked list in C

I have this text that I want to loop to match the count of my elements in a linked list.
char myBaseArray[] = "close your eyes ";
I have this linked list made of int (0 and 1) like this :
linkedListOne = 1 -> 0 -> 0 -> 0 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 0 -> 0 -> 0
I want to make a second linked list with the same number of 0's and 1's and loop through my base array for text. In other words, 1's and 0's are letters but I want to keep the blanks with my base array.
Example 1 :
linkedListOne = 1 -> 0 (2 elements in my list)
linkedListTwo = c -> l (2 letters)
Example 2 :
linkedListOne = 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 (20 elements in my list)
linkedListTwo = c -> l -> o -> s -> e ->(blank)-> y -> o -> u -> r ->(blank)-> e -> y -> e -> s ->(blank)->c -> l -> o -> s -> e->(blank)->y -> o(20 letters)
As you can see blank does not count as a 0 or 1.
The example 2 is more complex because I have to add blank spaces in my linked list so when I print it, it will output :
close your eyes close yo
Another output with a very long list could be :
close your eyes close your eyes close your eyes close your eyes close your eyes
My linked list are working just fine and I have implemented a count function so I know the numbers of 1's and 0's. I am not sure on how to loop through my base array to match that count.
I ended doing this :
int i=0;
int j=0;
while(i != LETTER_COUNT)
{
char c = myBaseArray[j % myBaseArray_LENGTH];
if(c == ' '){
linkedListTwo = add(linkedListTwo, c);
j++;
}
else{
linkedListTwo= add(linkedListTwo, c);
j++;
i++;
}
}

Resources