shifting a sequence of numbers in C? - c

I have a question about some trying to wrap around a sequence of numbers that I'm trying to shift in the C programming language. The first value that is found in the sequence of numbers I calculate via a loop gets thrown out in the end. Here is what the code looks like right now:
numbers[d] = numbers[x];
for (d = y-1; d >=0; d --){
numbers[d] = numbers[(d - 1) % y];
printf(" numbers[d] = %d \n", numbers[d]);
}
Here are the numbers[x] I calculated from my previous loop:
1, 17, 3, 15, 14, 6, 12, 8, 10
Here is what the numbers[d] currently looks like:
17, 3, 15, 14, 6, 12, 8, 10, 10
...and here is what it should look like:
17, 3, 15, 14, 6, 12, 8, 10, 1
It seems like it doesn't wrap the 1 around to the end. Is there a conditional that I am missing in my loop? Thanks!

Let's analyze your for loop, minus the printf statement.
for (d = y-1; d >=0; d --){
numbers[d] = numbers[(d - 1) % y];
}
Before you start the loop, you have the following values in numbers.
1, 17, 3, 15, 14, 6, 12, 8, 10
The value of y is 9.
In the first iteration of the loop, d = 8. (d-1)%y = 7. You replace the value of number[8] by number[7]. The array becomes:
1, 17, 3, 15, 14, 6, 12, 8, 8
In the next iteration of the loop, d = 7. (d-1)%y = 6. You replace the value of number[7] by number[6]. The array becomes:
1, 17, 3, 15, 14, 6, 12, 12, 8
When you reach the iteration where d=1, (d-1)%y = 0. You replace the value of number[1] by number[0]. The array becomes:
1, 1, 17, 3, 15, 14, 6, 12, 8
In the next iteration, d=0, (d-1)%y = -1. The statement
numbers[d] = numbers[(d - 1) % y];
is equivalent to
numbers[0] = numbers[-1];
This certainly leads to undefined behavior but it doesn't explain the other numbers in your output. Maybe the output that you posted corresponds to a different block of code.
I think the answer by #JonathanLeffler gives a solution to your algorithmic problem. I won't repeat that here.

Code
#include <stdio.h>
static const int debug = 0;
static void dump_array(const char *tag, int n, const int array[n])
{
printf("%s (%d)", tag, n);
for (int i = 0; i < n; i++)
printf("%3d", array[i]);
putchar('\n');
}
static void rot1u(int n, int numbers[n])
{
int v = numbers[n-1];
for (int d = n - 1; d >= 0; d--)
{
numbers[d] = numbers[(n + d - 1) % n];
if (debug)
printf(" numbers[%d] = %d\n", d, numbers[d]);
}
numbers[0] = v;
dump_array("Up After: ", n, numbers);
}
static void rot1d(int n, int numbers[n])
{
int v = numbers[0];
for (int d = 0; d < n; d++)
{
numbers[d] = numbers[(d + 1) % n];
if (debug)
printf(" numbers[%d] = %d\n", d, numbers[d]);
}
numbers[n-1] = v;
dump_array("Dn After: ", n, numbers);
}
int main(void)
{
int numbers[] = { 1, 17, 3, 15, 14, 6, 12, 8, 10 };
enum { N_NUMBERS = sizeof(numbers) / sizeof(numbers[0]) };
dump_array("-- Before:", N_NUMBERS, numbers);
rot1u(N_NUMBERS, numbers);
rot1d(N_NUMBERS, numbers);
rot1d(N_NUMBERS, numbers);
rot1d(N_NUMBERS, numbers);
rot1u(N_NUMBERS, numbers);
rot1u(N_NUMBERS, numbers);
return 0;
}
Example output
-- Before: (9) 1 17 3 15 14 6 12 8 10
Up After: (9) 10 1 17 3 15 14 6 12 8
Dn After: (9) 1 17 3 15 14 6 12 8 10
Dn After: (9) 17 3 15 14 6 12 8 10 1
Dn After: (9) 3 15 14 6 12 8 10 1 17
Up After: (9) 17 3 15 14 6 12 8 10 1
Up After: (9) 1 17 3 15 14 6 12 8 10

You need to save the element(s) which should be rotated to the the other side before the loop, and only put it into its proper place (theem into their proper places) afterwards.

#include <stdio.h>
#include <time.h>
#define METHOD 2
#define MAX_SKIERS 20
int starting_lineup[MAX_SKIERS+1];
int main(void)
{
int i, num_skiers = 20;
srand(time(NULL));
int pos1, pos2, temp;
for (i = 0; i <= num_skiers; i++)
starting_lineup[i] = i;
for (i = 0; i < num_skiers*2; i++) {
// Generate two random positions
pos1 = rand() % num_skiers + 1;
pos2 = rand() % num_skiers + 1;
// Swap the skiers at the two positions
temp = starting_lineup[pos1];
starting_lineup[pos1] = starting_lineup[pos2];
starting_lineup[pos2] = temp;
}
printf("The starting lineup (first to last):\n");
for (i = 1; i <= num_skiers; i++)
printf("%s%d", (i == 1 ? "" : ", "), starting_lineup[i]);
putchar('\n');
return 0;
}

Related

How to make parameter of double dimension arrangement to use in function

#include <stdio.h>
void Turn(int(*ptr)[4], int length, int vertical)
{
int arr[100][100] = { 0, };
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
arr[i][j] = *(*(ptr + (vertical - j - 1)) + i);
}
}
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
*(*(ptr + i) + j) = arr[i][j];
}
}
}
int main(void)
{
int BY[4][4] = {
1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16,
};
int length = sizeof(BY[0]) / sizeof(int);
int vertical = (sizeof(BY) / sizeof(int)) / length;
Turn(BY, length, vertical);
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
printf("%d ", BY[i][j]);
}
printf("\n");
}
return 0;
}
I wrote a function named Turn to rotate a 2D array right (a 90 degree rotation). I wanted to make this function to turn every array that has same vertical range and length. But I can't hand over
(I used google translate, I don't know how to describe it) parameter of a 2D array.
I first used void Turn(int(*ptr)[] ....)
but it didn't work. So I couldn't help using
int (*ptr)[4] in this function.
How can I make a parameter of a 2D array that can be used with any 2D array?
Using the C99 variable length array (VLA) feature make the problem easy. C11 makes support for VLAs optional, but the implementation must define __STDC_NO_VLA__ to show that it doesn't support VLAs.
Here's one version of the code. I've renamed your Turn() function (which turns the matrix 90° right into TurnR() and added a TurnL() function which turns the matrix 90° left. Because the code handles non-square matrices, the output matrix is separate from the input matrix. (You can simplify the code slightly if you only want to work with square matrices.)
#include <stdio.h>
static void TurnR(size_t rows, size_t cols, int matrix[rows][cols], int result[cols][rows])
{
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
result[c][rows - 1 - r] = matrix[r][c];
}
}
static void TurnL(size_t rows, size_t cols, int matrix[rows][cols], int result[cols][rows])
{
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
result[cols - 1 - c][r] = matrix[r][c];
}
}
static void Print(const char *tag, size_t rows, size_t cols, int matrix[rows][cols])
{
printf("%s (%zux%zu):\n", tag, rows, cols);
for (size_t r = 0; r < rows; r++)
{
const char *pad = "";
for (size_t c = 0; c < cols; c++)
{
printf("%s%3d", pad, matrix[r][c]);
pad = " ";
}
putchar('\n');
}
}
int main(void)
{
int BY[4][4] = {
{ 1, 2, 3, 4, },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12, },
{ 13, 14, 15, 16, },
};
int out[4][4];
Print("before", 4, 4, BY);
TurnR(4, 4, BY, out);
Print("right", 4, 4, out);
TurnL(4, 4, BY, out);
Print("left", 4, 4, out);
int m4x6[4][6] =
{
{ 1, 2, 3, 4, 5, 6, },
{ 7, 8, 9, 10, 11, 12, },
{ 13, 14, 15, 16, 17, 18, },
{ 19, 20, 21, 22, 23, 24, },
};
int m6x4[6][4];
Print("before", 4, 6, m4x6);
TurnR(4, 6, m4x6, m6x4);
Print("right", 6, 4, m6x4);
TurnL(4, 6, m4x6, m6x4);
Print("left", 6, 4, m6x4);
int m5x3[5][3] =
{
{ 1, 2, 3, },
{ 4, 5, 6, },
{ 7, 8, 9, },
{ 10, 11, 12, },
{ 13, 14, 15, },
};
int m3x5[3][5];
Print("before", 5, 3, m5x3);
TurnR(5, 3, m5x3, m3x5);
Print("right", 3, 5, m3x5);
TurnL(5, 3, m5x3, m3x5);
Print("left", 3, 5, m3x5);
TurnL(3, 5, m3x5, m5x3);
Print("doubleL", 5, 3, m5x3);
return 0;
}
And sample output is:
before (4x4):
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
right (4x4):
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
left (4x4):
4 8 12 16
3 7 11 15
2 6 10 14
1 5 9 13
before (4x6):
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
right (6x4):
19 13 7 1
20 14 8 2
21 15 9 3
22 16 10 4
23 17 11 5
24 18 12 6
left (6x4):
6 12 18 24
5 11 17 23
4 10 16 22
3 9 15 21
2 8 14 20
1 7 13 19
before (5x3):
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
right (3x5):
13 10 7 4 1
14 11 8 5 2
15 12 9 6 3
left (3x5):
3 6 9 12 15
2 5 8 11 14
1 4 7 10 13
doubleL (5x3):
15 14 13
12 11 10
9 8 7
6 5 4
3 2 1
I wouldn't dream of writing the code using the *(ptr + index) notation, especially with the double subscripts; it is just too error prone and hard to read (a nightmare, indeed!).

How to rearrange a two dimensional array

I want to assign the values in one array to another, but in a different
order. For example the original array would be:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
And the desired array is:
8 11 14 3 6 16 19
9 12 1 4 7 17 20
10 13 2 5 15 18 21
How would I do this? In the code below I moved a selected row to the center, then assigned each array individually. I can't figure out a better way.
int main()
{
int decide, i, j, k;
int save[3][7];
int shuffle[3][7];
int arr[3][7] = {
{1, 2, 3, 4, 5, 6, 7},
{8, 9, 10, 11, 12, 13, 14},
{15, 16, 17, 18, 19, 20, 21}
};
printf("Select a number between 1 and 21\n\n0-GroupA (1 - 7))\n1-GroupB ( 8 - 14)\n2-GroupC (15 - 21)\n\n");
for(k = 0 ; k < 1 ; ++k)
{
printf("Select which group the number falls into:");
scanf("%d", &decide);
for(j = 0 ; j < 7 ; ++j)
{/*moves selected row to middle row of array*/
save[0][j] = arr[1][j];
arr[1][j] = arr[decide][j];
arr[decide][j] = save[0][j];
}
/*this is a horrible method*/
shuffle[0][0] = arr[0][0];
shuffle[1][0] = arr[0][1];
shuffle[2][0] = arr[0][2];
shuffle[0][1] = arr[0][3];
shuffle[1][1] = arr[0][4];
shuffle[2][1] = arr[0][5];
shuffle[0][2] = arr[0][6];
shuffle[1][2] = arr[1][0];
shuffle[2][2] = arr[1][1];
shuffle[0][3] = arr[1][2];
shuffle[1][3] = arr[1][3];
shuffle[2][3] = arr[1][4];
shuffle[0][4] = arr[1][5];
shuffle[1][4] = arr[1][6];
shuffle[2][4] = arr[2][0];
shuffle[0][5] = arr[2][1];
shuffle[1][5] = arr[2][2];
shuffle[2][5] = arr[2][3];
shuffle[0][6] = arr[2][4];
shuffle[1][6] = arr[2][5];
shuffle[2][6] = arr[2][6];
}
like this ?
#include <stdio.h>
#define ROWS 3
#define COLS 7
int main(void){
int arr[ROWS][COLS] = {
{1, 2, 3, 4, 5, 6, 7},
{8, 9, 10, 11, 12, 13, 14},
{15, 16, 17, 18, 19, 20, 21}
};
int result[ROWS][COLS];
int order[ROWS] = {1, 0, 2};
int n = sizeof(arr)/sizeof(**arr);//number of elements
int r = 0, c = 0, i = 0, j = 0;
while(n--){
result[r++][c] = arr[order[i]][j++];
if(r == ROWS){
r = 0;
c += 1;
}
if(j == COLS){
j = 0;
i += 1;
}
}
//check print
for(r = 0; r < ROWS; ++r){
for(c = 0; c < COLS; ++c)
printf("%-2d ", result[r][c]);
puts("");
}
}
The transposition part can be done like this:
#include <stdio.h>
typedef struct Sequence2D
{
int idx_slow;
int idx_fast;
int max_slow;
int max_fast;
} Sequence2D;
static inline void next2D(Sequence2D *seq)
{
if (++seq->idx_fast == seq->max_fast)
{
seq->idx_fast = 0;
if (++seq->idx_slow == seq->max_slow)
seq->idx_slow = 0;
}
}
static inline void dump2D(const char *tag, int rows, int cols, int data[rows][cols])
{
printf("%s:\n", tag);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
printf("%3d", data[r][c]);
putchar('\n');
}
}
enum { ROWS = 3, COLS = 7 };
int main(void)
{
int src[ROWS][COLS] =
{
{ 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19, 20, 21 },
};
int dst[ROWS][COLS];
Sequence2D dst2D = { 0, 0, COLS, ROWS };
Sequence2D src2D = { 0, 0, ROWS, COLS };
dump2D("Source", ROWS, COLS, src);
for (int i = 0; i < ROWS * COLS; i++)
{
dst[dst2D.idx_fast][dst2D.idx_slow] = src[src2D.idx_slow][src2D.idx_fast];
printf("dst[%d][%d] = src[%d][%d] = %d\n",
dst2D.idx_fast, dst2D.idx_slow,
src2D.idx_slow, src2D.idx_fast,
dst[dst2D.idx_fast][dst2D.idx_slow]);
next2D(&dst2D);
next2D(&src2D);
}
dump2D("Target", ROWS, COLS, dst);
return 0;
}
The Sequence2D structure plus the next2D() function cycle through array indexes, changing the fast index on each call of next2D() and the slow index when necessary. This saves you writing out the sequence of 21 assignments, and immediately scales to other shapes without requiring much extra work on your part. Indeed, it would not take much to handle all the sizes as run-time inputs instead of compile-time constants.
The output of this code is:
Source:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
dst[0][0] = src[0][0] = 1
dst[1][0] = src[0][1] = 2
dst[2][0] = src[0][2] = 3
dst[0][1] = src[0][3] = 4
dst[1][1] = src[0][4] = 5
dst[2][1] = src[0][5] = 6
dst[0][2] = src[0][6] = 7
dst[1][2] = src[1][0] = 8
dst[2][2] = src[1][1] = 9
dst[0][3] = src[1][2] = 10
dst[1][3] = src[1][3] = 11
dst[2][3] = src[1][4] = 12
dst[0][4] = src[1][5] = 13
dst[1][4] = src[1][6] = 14
dst[2][4] = src[2][0] = 15
dst[0][5] = src[2][1] = 16
dst[1][5] = src[2][2] = 17
dst[2][5] = src[2][3] = 18
dst[0][6] = src[2][4] = 19
dst[1][6] = src[2][5] = 20
dst[2][6] = src[2][6] = 21
Target:
1 4 7 10 13 16 19
2 5 8 11 14 17 20
3 6 9 12 15 18 21
If you rearrange the initial matrix (src) according to whatever arcane rules you're using before you copy the 'transpose' of src into the result (dst), then you should be able to get the result you desire.
As noted, the code can be generalized rather easily using C99 and variable-length arrays:
#include <assert.h>
#include <stdio.h>
typedef struct Sequence2D
{
int idx_slow;
int idx_fast;
int max_slow;
int max_fast;
} Sequence2D;
static inline void next2D(Sequence2D *seq)
{
if (++seq->idx_fast == seq->max_fast)
{
seq->idx_fast = 0;
if (++seq->idx_slow == seq->max_slow)
seq->idx_slow = 0;
}
}
static inline void dump2D(const char *tag, int rows, int cols, int data[rows][cols])
{
printf("%s:\n", tag);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
printf("%3d", data[r][c]);
putchar('\n');
}
}
static void transpose(int rows, int cols)
{
assert(rows * cols < 1000000);
int src[rows][cols];
int dst[rows][cols];
Sequence2D dst2D = { 0, 0, cols, rows };
Sequence2D src2D = { 0, 0, rows, cols };
int cells = rows * cols;
for (int i = 0; i < cells; i++)
{
src[src2D.idx_slow][src2D.idx_fast] = i;
next2D(&src2D);
}
/* src2D is back to its initial state! */
dump2D("Source", rows, cols, src);
for (int i = 0; i < cells; i++)
{
dst[dst2D.idx_fast][dst2D.idx_slow] = src[src2D.idx_slow][src2D.idx_fast];
printf("dst[%d][%d] = src[%d][%d] = %d\n",
dst2D.idx_fast, dst2D.idx_slow,
src2D.idx_slow, src2D.idx_fast,
dst[dst2D.idx_fast][dst2D.idx_slow]);
next2D(&dst2D);
next2D(&src2D);
}
dump2D("Target", rows, cols, dst);
}
int main(void)
{
transpose(3, 7);
transpose(9, 4);
return 0;
}
The first section of the output is the same as before; the 9x4 part looks like:
Source:
0 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 31
32 33 34 35
dst[0][0] = src[0][0] = 0
dst[1][0] = src[0][1] = 1
dst[2][0] = src[0][2] = 2
dst[3][0] = src[0][3] = 3
dst[4][0] = src[1][0] = 4
dst[5][0] = src[1][1] = 5
dst[6][0] = src[1][2] = 6
dst[7][0] = src[1][3] = 7
dst[8][0] = src[2][0] = 8
dst[0][1] = src[2][1] = 9
dst[1][1] = src[2][2] = 10
dst[2][1] = src[2][3] = 11
dst[3][1] = src[3][0] = 12
dst[4][1] = src[3][1] = 13
dst[5][1] = src[3][2] = 14
dst[6][1] = src[3][3] = 15
dst[7][1] = src[4][0] = 16
dst[8][1] = src[4][1] = 17
dst[0][2] = src[4][2] = 18
dst[1][2] = src[4][3] = 19
dst[2][2] = src[5][0] = 20
dst[3][2] = src[5][1] = 21
dst[4][2] = src[5][2] = 22
dst[5][2] = src[5][3] = 23
dst[6][2] = src[6][0] = 24
dst[7][2] = src[6][1] = 25
dst[8][2] = src[6][2] = 26
dst[0][3] = src[6][3] = 27
dst[1][3] = src[7][0] = 28
dst[2][3] = src[7][1] = 29
dst[3][3] = src[7][2] = 30
dst[4][3] = src[7][3] = 31
dst[5][3] = src[8][0] = 32
dst[6][3] = src[8][1] = 33
dst[7][3] = src[8][2] = 34
dst[8][3] = src[8][3] = 35
Target:
0 9 18 27
1 10 19 28
2 11 20 29
3 12 21 30
4 13 22 31
5 14 23 32
6 15 24 33
7 16 25 34
8 17 26 35
You can't transpose a matrix in place. That is to say, it is not possible to write a function which will take a matrix and modify it so that it is its transpose, without creating a temporary matrix of equal size. At least without some very fancy programming.
Now your task isn't exactly the transpose, but it seems to be very similar. So I wouldn't expect there to be a nice, in place solution. You must simply create a temporary, apply the mapping from input to temporary, and write the values back.
What might help is this.
/* swap two rows of a matrix */
void swaprows(int *mtx, int width, int height, int rowa, int rowb)
{
int i;
for(i=0;i<width;i++)
{
int temp = mtx[rowa*width+i];
mtx[rowa*width+i] = mtx[rowb*width+i];
mtx[rowa*width+i] = temp;
}
}
/* transpose a matrix */
int transpose(int *mtx, int width, int height)
{
int *tmtx = malloc(width*height*sizeof(int));
if(!tmtx)
return -1;
for(y=0;y<width;y++)
for(x=0;x<height;x++)
tmtx[y*height+x] = mtx[x*width+y];
mempy(mtx, tmtx, width * height * sizeof(int));
free(tmtx);
}
/* your logic */
int arr[3][7] = {
{1, 2, 3, 4, 5, 6, 7},
{8, 9, 10, 11, 12, 13, 14},
{15, 16, 17, 18, 19, 20, 21}
};
swaprows((int *) arr, 7, 3, 0, 1);
transpose(int *) arr, 7, 3);
This seems to be what you are trying to do.

How does this foo function works?

This C program will take the value stored in the variable a and print them one by one.
#include <stdio.h>
void foo(int n, int sum)
{
int k = 0, j = 0;
if (n == 0)
return;
k = n % 10;
j = n / 10;
sum = sum + k;
foo (j, sum);
printf ("%d, ", k);
}
int main ()
{
int a = 2048, sum = 0;
foo (a, sum);
printf("\n");
return 0;
}
Output:
2, 0, 4, 8,
When the function foo executes:
1) For the first time: n = 2048, k = 8, j = 204, sum = 8
2) For the second time: n = 204, k = 4, j = 20, sum = 12
3) For the third time: n = 20, k = 0, j = 2, sum = 12
4) For the fourth time: n = 2, k = 2, j = 0, sum = 14
If I replace the line (present in the foo function):
printf ("%d, ", k);
with this:
printf ("%d | %d, ", k, sum);
Output:
2 | 14, 0 | 12, 4 | 12, 8 | 8,
Can someone please explain how this program works:
1) How it's printing value stored in a?
2) And in this order: 2, 0, 4, 8, ?
3) Why is the value of sum is changing when we're printing values of k?
4) What would happen when n become 0?
You are calling the function foo on a.
That is the order since you are printing AFTER you are processing the rest of the number. Try moving the call to printf before the call to foo in foo and see if you get anything different.
sum is changing because you are doing sum = sum + k and passing it to all the future calls.
When n eventually becomes 0 due to repeated divisions, the last call to foo starts returning and following them all the previous calls start returning after printing the digit they had extracted using n % 10

Submatrix extraction from matrix with loop tiling

I have the following matrix 4x4:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
and I want extract and store (in some news variables) the four following submatrix 2x2:
[1 2
5 6]
[3 4
7 8]
[9 10
13 14]
[11 12
15 16]
It's like the "Rect" (http://docs.opencv.org/java/org/opencv/core/Rect.html) function of openCV, but I don'want to use OpenCV.
I have to use a parallelizing compiler and so I would like to do the extraction of the submatrix with a famous loop transformation present in literature: "loop tiling" (also knows as "loop blocking" or "loop unroll and jam" or "loop stripmine and interchange"). - (http://en.wikipedia.org/wiki/Loop_tiling)
Is it possible?
Is it possible?
Of course …
int n = 4;
int matrix[4][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int submatrixes[n/2*n/2][2][2];
int i, j, x, y, z;
for (z = i = 0; i < n; i += 2)
for (j = 0; j < n; j += 2, ++z)
for (x = 0; x < 2; x++)
for (y = 0; y < 2; y++)
submatrixes[z][x][y] = matrix[i+x][j+y];

Given a sorted array, output all triplets <a,b,c> such that a-b = c

Given a sorted array, output all triplets such that a-b = c.
The code I tried so far is as below; but there are following test cases-
-12 = -7 - 5
-12 = 3 - 15
-7 = -4 - 3
-7 = 3 - 10
-7 = 9 - 16
-4 = 5 - 9
3 = -4 - -7
5 = -7 - -12
5 = 15 - 10
10 = 3 - -7
10 = 15 - 5
15 = 3 - (-12)
16 = 9 - (-7)
while my program prints only-
-12 = -7 - 5
-7 = -4 - 3
-12 = 3 - 15
-7 = 3 - 10
-4 = 5 - 9
-7 = 9 - 16
5 = 15 - 10
means only the abs difference! Any suggestion ll be great help!
void binder(int*a, int n) {
int i;
for (i = 0; i < n; i++) {
int current = a[i];
int left = 0;
int right = n-1;
while (left < right) {
if ( left == i ) {
left++;
continue;
}
if (right == i) {
right--;
continue;
}
if (a[left] + a[right] < current) {
left++;
} else if (a[left] + a[right] > current) {
right--;
} else {
printf("\n %d = %d - %d",a[left],current, a[right]);
left++;
right--;
}
}
}
}
int main() {
int a[] = {-12, -7, -4, 0, 3, 5, 9, 10, 15, 16};
binder(a, 10);
return 0;
}
It seems as though the test case is also missing a triplet:
9 = 5 - (-4)
Try changing your printing from:
printf("\n %d = %d - %d",a[left],current, a[right]);
to:
printf("\n %d = %d - %d",a[left],current, a[right]);
printf("\n %d = %d - %d",a[right],current, a[left]);
This solution is O(n^3), but it should work.
void binder(int*a, int n)
{
for(int left = 0; left < n; left++)
{
for(int right = 0; right < n; right++)
{
for(int result = 0; result < n; result++)
{
if(left != right && left != result && result != right && a[left] - a[right] == a[result])
printf("\n %d = %d - %d", a[result], a[left], a[right]);
}
}
}
}
How about something like this:
HashTable table;
for b = 0 to n-1:
for c = 0 to n-1:
table[b + c] = <b, c>
end for
end for
for a = 0 to n-1:
if table[a] exists and (<b, c> in table[a] where b != a and c != a) then:
output <a, b, c>
end if
end for
So, if we consider "a=b+c", for each (b, c) pair of values, we place that in a hash table, associating it with the (b, c) pair [O(n^2)].
Then, we go through the array again and if a value appears in the hash table, and the associated pairs are for different indices, then we've found a new entry (rearranging the terms back into "a-b=c"). This step is O(n), resulting in a O(n^2) solution overall.
I think we can see this question as a variation on the "find pairs of values in an array that sum up to S, for a fixed S" problem.
If they are sorted, (and as Hanning pointed out, a-b=c is the same as a=b+c) you can start with the smallest b and c, and add them, and this should lead to the smallest a. Now while increasing b or c, a can only get bigger too, so you should have never to look back.
If you make a table of b's and c's and their sum (which should be one of the a's):
c\ b:-12 3 4 5 7 10 15 16
-12: -24, -19, -9, -7, -3, -2, 3, 4
-7: -9, -4, 6, 8, 12, 13, 18,
3: -8, -3, 7, 9, 13, 14, 19,
5: -7, -2, 8, 10, 14, 15,
9: -5, 0, 10, 12, 16,
10: -2, 3, 13, 15,
15: 3, 8, 18,
16: 4, 9, 19,
you see, that I omited the values on the lower right, because the previous value (from left) already exceeded the maximum a (15), so a higher value can't match.
Of course, for such a small number of equations, you waste much more time thinking about optimization, than you gain from omitting superfluous calculations. For much bigger sets of values, it might be useful, to optimize.
you have missed one more iteration/loop in your code. since you are using brute force strategy so analysis say that it will take O(n^3) space and you code's time complexity seems O(n^2).
here is the case which will help you to understand.
you check for :
a = b-c
and you skip the check for :
c = b-a

Resources