C : Processing the columns of a 2D array - c

#include<stdio.h>
#define NUM_ROWS 3
#define NUM_COLS 5
int main(void){
int a[NUM_ROWS][NUM_COLS],(*p)[NUM_COLS], i;
for (p = &a[0],i=0; p < &a[NUM_ROWS]; p++,i++){
(*p)[i]=i;
}
printf("The value of a[0][0] is %d\n",a[0][0]); // I want 0
printf("The value of a[0][1] is %d\n",a[0][1]); // 1
printf("The value of a[0][2] is %d\n",a[0][2]); // 2
printf("The value of a[0][3] is %d\n",a[0][3]); // 3
printf("The value of a[0][4] is %d\n",a[0][4]); // 4
return 0;
}
Hi guys I'm a C novice, and I am trying to understand processing the columns of a 2D array.
I wanted output of 0,1,2,3,4 from row 0's columns but I had these results
The value of a[0][0] is 0
The value of a[0][1] is 0
The value of a[0][2] is 1
The value of a[0][3] is 0
The value of a[0][4] is -1
I tried to find what was wrong, but I failed to....
I will be grateful if someone explains what is wrong with my codes..

Your assignment in the loop is initializing the leading diagonal:
(*p)[i] = i;
To illustrate, here's an adaptation of your code that prints the whole matrix (and initializes it):
#include <stdio.h>
#include <string.h>
#define NUM_ROWS 3
#define NUM_COLS 5
int main(void)
{
int a[NUM_ROWS][NUM_COLS], (*p)[NUM_COLS], i;
/* Set all elements to -1 assuming 2's complement */
memset(a, 0xFF, sizeof(a));
for (p = &a[0], i = 0; p < &a[NUM_ROWS]; p++, i++)
{
(*p)[i] = i;
}
for (i = 0; i < NUM_ROWS; i++)
{
for (int j = 0; j < NUM_COLS; j++)
printf("%3d", a[i][j]);
putchar('\n');
}
return 0;
}
The output is:
0 -1 -1 -1 -1
-1 1 -1 -1 -1
-1 -1 2 -1 -1
Notice that the three elements on the leading diagonal are set to 0, 1, 2 and the rest are -1 as set by memset().
If you want to initialize the first row, then you simply use:
int (*p)[NUM_COLS] = &a[0];
for (int i = 0; i < NUM_COLS; i++)
(*p)[i] = i;
Or, more simply still, forget about p and use:
for (int i = 0; i < NUM_COLS; i++)
a[0][i] = i;
If you want to initialize column 0, you need:
(*p)[0] = i;
Or, again, more simply, forget about p and use:
for (int i = 0; i < NUM_ROWS; i++)
a[0][i] = i;

I think you want to write your for loop like this (based on you captions)
for the first row.
for (p = &a[0], i=0; i < NUM_COLS; i++){
(*p)[i] = i;
}
Here increasing the pointer p doesn't help for it will be incremented by a value of NUM_COLS every time due to pointer arithmetic.
Here is a second possible answer if you want to write and read the whole matrix within a single for loop
for (p = &a[0], i = 0; i < NUM_COLS * NUM_ROWS; i++) {
(*p)[i] = i;
}
Or the better solution would be to use two for loops as
for (p = &a[0], i = 0; p < &a[NUM_ROWS] ; p ++) {
int k = 0; //for the column count
for(;k < NUM_COLS; i++, k++) {
(*p)[k] = i;
}
}
Thanks for asking :)

for (p = &a[0]; p < &a[NUM_ROWS]; p++){
for(i=0;i<NUM_COLS;i++){
(*p)[i]=i;
printf("%d\n",(*p)[i]);
// I got 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
}
}
Should I write nested loop to print out all elements of 2D?
Is there a way to print out using 1 loop with processing columns of 2D array?

Related

Create a matrix with elements taken by another matrix

I have to implement a function which, given a matrix of 0s and 1s, returns a new matrix that contains the coordinates of the 1s. For example: if matrix is 3x3 and the output is:
1 0 1
0 1 1
0 0 1
New matrix will be 5x2 and the output will be:
0 0
0 2
1 1
1 2
2 2
Some advice? My method would be this:
int matrix[3][3];
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
if (matrix[i][i] == 1){
//Code i need
}
}
}
The solution really depends on the requirement:
Is it allowed to allocate result matrix with the maximum size possible (in this case 9 x 2).
If point 1 is not allowed, is it strictly required to use fixed size array (no dynamic allocation). If this is the case then may need to pass the matrix twice to allocate the right size of array.
Other solution is of course by using dynamic allocation (using malloc etc).
The simplified version of option 1 & 2 is shown below:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int matrix[3][3];
matrix[0][0] = 1;
matrix[0][1] = 0;
matrix[0][2] = 1;
matrix[1][0] = 0;
matrix[1][1] = 1;
matrix[1][2] = 1;
matrix[2][0] = 0;
matrix[2][1] = 0;
matrix[2][2] = 1;
//Solution 1 - If allowed to allocate matrix with size more than the result,
//i.e. if input is 3x3 matrix, then the maximum size of result matrix is 9 x 2
int resultMatrix1[9][2];
int usedCount1=0;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
resultMatrix1[usedCount1][0] = i;
resultMatrix1[usedCount1][1] = j;
usedCount1++;
} //end if
} //end for
} //end for
//Print the result
printf("\nSolution 1\n");
for (int i = 0; i < usedCount1; i++){
printf("%d %d\n", resultMatrix1[i][0], resultMatrix1[i][1]);
} //end for
//Solution 2 - strictly allocate matrix with size equal to the result.
//Without using dynamic allocation, meaning we need to have two passes.
//1st pass is to count the element which satisfy the criteria
int usedCount2=0;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
usedCount2++;
} //end if
} //end for
} //end for
int resultMatrix2[usedCount2][2]; //allocate the right size
int idx=0;
//2nd pass is to fill in the result matrix
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
resultMatrix2[idx][0] = i;
resultMatrix2[idx][1] = j;
idx++;
} //end if
} //end for
} //end for
//Print the result
printf("\nSolution 2\n");
for (int i = 0; i < usedCount2; i++){
printf("%d %d\n", resultMatrix2[i][0], resultMatrix2[i][1]);
} //end for
return 0;
}
Results are the same for both solution:
Solution 1
0 0
0 2
1 1
1 2
2 2
Solution 2
0 0
0 2
1 1
1 2
2 2
If matrix[i][j] == 1 what do you know about the coordinates [i,j] ? That they are the coordinates of a 1 :)
Secondly, will the input matrix always be 3x3? If not, you'll want to store the dimensions of the matrix in variables, and use theses variables for your for loops.

How to connect puzzles so that right edge has same length as left edge of another puzzle?

I have puzzles that looks like this:
=== ====
=== ===
=== ====
left edge has length from 0 to 10 000 and right also, middle part is from 1 to 10 000.
So the question is if i can build a rectangle? like first puzzle has length of left edge equal to 0 and the last puzzle has right edge of length 0 and in the middle they fit perfectly?
I am given the number of puzzle i have and their params like this:
6
1 9 2
0 3 1
0 4 1
8 9 0
2 9 0
1 5 0
and result can be any of that:
2
0 3 1
1 5 0
or
3
0 3 1
1 9 2
2 9 0
or
2
0 4 1
1 5 0
But if there is no result i have to printf("no result")
I have to do this in C, I thought about doing some tree and searching it with BFS where vertices would have edge lengths and edge would have middle length and when reached 0 i would go all way up and collect numbers but it's hard to code. So i decided to do recursion but im also stuck:
#include<stdio.h>
int main(){
int a;
scanf("%d", &a);//here i get how many puzzles i have
int tab[a][3];//array for puzzles
int result[][3];//result array
int k = 0;//this will help me track how many puzzles has my result array
for(int i = 0; i < a; i++){//upload puzzles to array
for(int j = 0; j < 3; j++){
scanf("%d", &tab[i][j]);
}
}
findx(0, a, tab, result, k);//start of recursion, because start has to be length 0
}
int findx(int x, int a, int *tab[], int *result[], int k){//i am looking for puzzle with length x on start
for(int i = 0; i < a; i++){
if(tab[a][0] == x){//there i look for puzzles with x length at start
if(tab[a][2] == 0){//if i find such puzzle i check if this is puzzle with edge length zero at the end
for(int m = 0; m < 3; m++){//this for loop add to my result array last puzzle
result[k][m] = tab[a][m];
}
return print_result(result, k);//we will return result go to print_result function
}
else{//if i have puzzle with x length on the left and this is not puzzle which ends rectangle i add this puzzle
//to my result array and again look for puzzle with x equal to end length of puzzle i found there
for(int m = 0; m < 3; m++){
result[k][m] = tab[a][m];
k += 1;
}
findx(tab[a][2], a, tab, result, k);
}
}
}
printf("no result");
}
int print_result(int *result[], int k){
printf("%d", &k);//how many puzzles i have
printf("\n");
for(int i = 0; i < k; i++){//printing puzzles...
for(int j = 0; j < 3; j++){
printf("%d ", &result[i][j]);
}
printf("\n");//...in separate lines
}
}
I have an error that result array can't look like this int result[][3] because of of [] but I don't know how many puzzles I'm gonna use so?... and I have implicit declaration for both of my functions. Guys please help, I dont know much about C and its super hard to solve this problem.
I'm not sure I understand the overall logic of the problem, but you definitely are in need of some variable sized containers for result AND tab. Arrays are fixed size and must be defined at compile time. The following should at least compile without warnings:
#include<stdio.h>
#include<stdlib.h>
void print_result(int (*result)[3], int k){
printf("%d", k);//how many puzzles i have
printf("\n");
for(int i = 0; i <= k; i++){//printing puzzles...
for(int j = 0; j < 3; j++){
printf("%d ", result[i][j]);
}
printf("\n");//...in separate lines
}
}
void findx(int x, int a, int (*tab)[3], int (*result)[3], int k){//i am looking for puzzle with length x on start
for(int i = 0; i < a; i++){
if(tab[i][0] == x){//there i look for puzzles with x length at start
if(tab[i][2] == 0){//if i find such puzzle i check if this is puzzle with edge length zero at the end
for(int m = 0; m < 3; m++){//this for loop add to my result array last puzzle
result[k][m] = tab[i][m];
}
print_result(result, k);//we will return result go to print_result function
return;
}
else{//if i have puzzle with x length on the left and this is not puzzle which ends rectangle i add this puzzle
//to my result array and again look for puzzle with x equal to end length of puzzle i found there
for(int m = 0; m < 3; m++){
result[k][m] = tab[i][m];
k += 1;
///** Increase size of result **/
//int (*newptr)[3] = realloc(result, (k+1) * sizeof(int[3]));
//if (newptr)
// result = newptr;
}
findx(tab[i][2], a, tab, result, k);
}
}
}
printf("no result\n");
}
int main(){
int a;
scanf("%d", &a);//here i get how many puzzles i have
int (*tab)[3] = malloc(a * sizeof(int[3]));//array for puzzles
int (*result)[3] = malloc(a * sizeof(int[3]));//array for puzzles
int k = 0;//this will help me track how many puzzles has my result array
for(int i = 0; i < a; i++){//upload puzzles to array
for(int j = 0; j < 3; j++){
scanf("%d", &tab[i][j]);
}
}
findx(0, a, tab, result, k);//start of recursion, because start has to be length 0
}
Note that I changed the tab and result types to (*int)[3]. Due to order of operations, we need parentheses here. Because they are variable size, they require dynamic memory allocations. In the interest of brevity and readability, I did not check the returned values of malloc or realloc. In practice, you should be checking that the returned pointer is not NULL. Because we are using dynamic memory allocations, we should also use free if you plan on doing anything else with this program. Otherwise, it doesn't really matter because exiting the program will free the resources anyway. You actually don't want to free. because we are passing a pointer by value to findx and the realloc can change the address, it may come back with a different address. Also, take note that I needed to include <stdlib.h> for the dynamic memory allocations.
Additional Issues
Your functions print_results and findx are not declared when you call them in main. Your function either need to be above main or have "function prototypes" above main.
In the printfs you do not need the &. You do not want to send the address of the variable to printf. You want to send what will actually be printed.
Now what?
The program still does not provide you with the correct results. It simply outputs 0 as the result every time. This should at least give you a starting point. By changing this line in print_results:
for(int i = 0; i < k; i++){//printing puzzles...
to
for(int i = 0; i <= k; i++){//printing puzzles...
I was at least able to output 0 0 0. This seems more correct because if k is 0, we don't loop at all.
#include<stdio.h>
void findx(int x, int a, int tab[a][3], int result[200000][3], int puzzlesinresult) { //i am looking for puzzle with length x on start
for (int i = 0; i < a; i++) {
if (tab[i][0] == x) { //there i look for puzzles with x length at start
if (tab[i][2] == 0) { //if i find such puzzle i check if this is puzzle with edge length zero at the end
for (int m = 0; m < 3; m++) { //this for loop add to my result array last puzzle
result[puzzlesinresult][m] = tab[i][m];
}
return print_result(result, puzzlesinresult); //we will return result go to print_result function
} else { //if i have puzzle with x length on the left and this is not puzzle which ends rectangle i add this puzzle
//to my result array and again look for puzzle with x equal to end length of puzzle i found there
while (result[puzzlesinresult - 1][2] != tab[i][0] && puzzlesinresult > 0) {
puzzlesinresult -= 1;
}
int isusedpuzzle = 0;
for (int j = 0; j < puzzlesinresult; j++) {
if (result[j][0] == tab[i][0] && result[j][1] == tab[i][1] && result[j][2] == tab[i][2]) {
isusedpuzzle = 1;
} else {
//pass
}
}
if (isusedpuzzle == 0) {
for (int m = 0; m < 3; m++) {
result[puzzlesinresult][m] = tab[i][m];
}
puzzlesinresult += 1;
findx(tab[i][2], a, tab, result, puzzlesinresult);
}
}
}
}
}
void print_result(int result[200000][3], int puzzlesinresult) {
printf("%d\n", puzzlesinresult + 1); //how many puzzles i have
for (int i = 0; i < puzzlesinresult + 1; i++) { //printing puzzles...
for (int j = 0; j < 3; j++) {
printf("%d ", result[i][j]);
}
printf("\n"); //...in separate lines
}
exit(0);
}
int main() {
int a;
scanf("%d", & a); //here i get how many puzzles i have
int tab[a][3]; //array for puzzles
int result[100][3]; //result array
int puzzlesinresult = 0; //this will help me track how many puzzles has my result array
for (int i = 0; i < a; i++) { //upload puzzles to array
for (int j = 0; j < 3; j++) {
scanf("%d", & tab[i][j]);
}
}
for (int i = 0; i < a; i++) { //here i delete puzzles that doesnt contribute anything like 1 x 1,2 x 2,..
if (tab[i][0] == tab[i][2] && tab[i][0] != 0) {
for (int p = i; p < a; p++) {
for (int j = 0; j < 3; j++) {
tab[p][j] = tab[p + 1][j];
}
}
}
}
findx(0, a, tab, result, puzzlesinresult); //start of recursion, because start has to be length 0
printf("NONE");
}
This returns sometimes correct result. If you can find when this program fails I would rly appreciate sharing those cases with me :)

Swap sub-arrays of a multi-dimensional array in C

I have a 50 x 50 matrix arr[50][50] and need to swap the values in the sub-array arr[0] and arr[1].
ie, the whole 50 elements in each sub-array need to be swapped.
The only way I can think of to do this is by using a loop like:
for(i=0; i<50; ++i)
{
int t = arr[0][i];
arr[0][i] = arr[1][i];
arr[1][i] = t;
}
I was wondering if there were any simpler or shorter methods? Using pointers maybe?
I tried things like
int *t = arr[0];
arr[0] = arr[1];
arr[1] = t;
but it gave error at the first line about "incompatible types when assigning to type 'int[2]' from type 'int *' ".
Then I tried pointer to an array
int (*t)[50] = arr[0];
arr[0] = arr[1];
arr[1] = t;
This time I got error at the second line about "incompatible types when assigning to type 'int[50]' from type 'int *' ".
If your matrix is implemented as arr[50][50] then the only way to physically swap two rows is to physically exchange data in memory. Your cycle is one way to do it. The rest would be just variations of that approach. You can swap matrix elements one-by-one (your cycle), you can swap the entire rows using an intermediate row-sized buffer (memcpy approach). All of them still do the same thing. There's no way around it.
If your array were implemented differently - say, a "jagged" array implemented as array of pointers to sub-arrays, then you would be able to just swap two pointers and be done with it. But in case of arr[50][50] it is not possible.
If you wish, you can just "convert" your current array into a "jagged" version by a separate row-pointer array. That row-pointer array will now become your matrix a, while the original a[50][50] will become a_data
int a_data[50][50];
int *a[50];
for (unsigned i = 0; i < 50; ++i)
a[i] = a_data[i];
/* Fill the matrix */
for (unsigned i = 0; i < 50; ++i)
for (unsigned j = 0; j < 50; ++j)
a[i][j] = rand();
/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
for (unsigned j = 0; j < 50; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
/* Swap the rows */
int *temp = a[0];
a[0] = a[1];
a[1] = temp;
/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
for (unsigned j = 0; j < 50; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
Note, that despite the physical structure of a is now different, you can still use a[i][j] syntax to work with it.
As explained in the comments, and within the other answers, in order to swap rows of an actual 2D array (as apposed to an array of pointers), you must copy/move the data from the source to target row in memory. The most straight forward way to approach this is either with a loop to copy element-by-element to temporary storage to effect the swap, or use the memory copy functions provided by the C-library (e.g. memcpy or memmove). A simple implementation using memcopy (shown with a 3x10 array for array for purposes of the example) would be:
#include <stdio.h>
#include <string.h>
enum { ROW = 3, COL = 10 };
void swaprow (int (*a)[COL], int c1, int c2);
void prna (int (*a)[COL]);
int main (void) {
int a[ROW][COL] = {{0}};
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
a[i][j] = i;
prna (a);
swaprow (a, 0, 1);
putchar ('\n');
prna (a);
return 0;
}
void swaprow (int (*a)[COL], int c1, int c2)
{
int tmp[COL];
memcpy (tmp, a[c1], COL * sizeof *tmp);
memcpy (a[c1], a[c2], COL * sizeof *a[c1]);
memcpy (a[c2], tmp, COL * sizeof *a[c2]);
}
void prna (int (*a)[COL])
{
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++)
printf ("%2d", a[i][j]);
putchar ('\n');
}
}
Example Use/Output
$ ./bin/array2d_swap_row
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
2 2 2 2 2 2 2 2 2 2
Look things over and let me know if you have any questions.
You will have to copy the data to be swapped with memcpy, I have provided sample to program to show how you can do it(ie swap arr[0] and arr[1]).
int main(void) {
// your code goes here
int t[3];
int arr[3][3]={{1,2,3},{4,5,6},{7,8,9}};
printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
memcpy(t,arr[0],sizeof(t));
memcpy(arr[0],arr[1],sizeof(t));
memcpy(arr[1],t,sizeof(t));
printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
return 0;
}

Unexpected output at a particular row for a dynamic 2D array

I was solving a programing question for displaying Pascal triangle. In the code, I have set the last element of every row equal to zero. Still, the 6th row produces the output as 50 for the last element. I'm unable to figure out the reason for this. Kindly help. The code is attached.
int ** generate(int A, int *number_of_rows) {
*number_of_rows = A;
int i,j,nc=0;
int **result = (int**)malloc(A * sizeof(int *));
for(i=0;i<A;i++)
{
nc=i+1;
result[i]=(int)malloc(nc*sizeof(int));
result[i][0]=nc;
result[i][1] = 1;
for(j=2;j<nc;j++)
{
result[i][j]=result[i-1][j]+result[i-1][j-1];
}
}
return result;
}
Edit:
The first element of every row displays the number of columns in that row.
#include <stdio.h>
#include <stdlib.h>
int ** generate(int A, int *number_of_cols) {
int **result = malloc(A * sizeof(int *));
int nc;//number of columns
for(int i = 0; i < A; ++i){
number_of_cols[i] = nc = i + 1;
result[i] = malloc(nc * sizeof(int));
result[i][0] = result[i][nc-1] = 1;
if(i > 1)
for(int j = 1; j < nc -1; ++j){
result[i][j] = result[i-1][j-1] + result[i-1][j];
}
}
return result;
}
int main(void){
int n;
scanf("%d", &n);
int *number_of_cols = malloc(n * sizeof(int));
int **pascal_triangle = generate(n, number_of_cols);
for(int i = 0; i < n; ++i){
printf("%*s", 2 * (n-i-1), "");
for(int j = 0; j < number_of_cols[i]; ++j){
printf("%4d", pascal_triangle[i][j]);
}
puts("");
free(pascal_triangle[i]);
}
free(pascal_triangle);
free(number_of_cols);
return 0;
}
I can't understand the purpose of passing the *number_of_row just to assign it the other parameter address. However, I'd split your main for loop in 2:
one to allocate all memory and another to fill it.
for(i=0;i<A;i++)
result[i]=(int)malloc((i+1)*sizeof(int));
result[0][0]=1; //in your code, result[i-1] was accessed with i=0
for(i=1;i<A;i++) {
result[i][0] = i+1;
result[i][1] = 1;
for(j=2;j<i;j++)
result[i][j] = result[i-1][j] + result[i-1][j-1]; //when j reaches the last value,
//[i-1][j] won't work! So put j<i instead.
result[i][j] = 1;
}
The rest of code was OK, check if this is what you wanted. The resulting triangle shoud be:
1
2 1
3 1 1
4 1 2 1
5 1 3 3 1
6 1 4 6 4 1 etc.

Strange C function - What is this function doing?

I encountred this function without any comment. I wonder what is this function doing? Any help?
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
What a fun problem!
Other posters are correct that it returns the index of a minimum, but it's actually more interesting than that.
If you treat the array as being circular (i.e. when you get past the end, go back to the beginning), the function returns the starting index of the minimum lexicographic subsequence.
If only one element is minimal, that element is returned. If multiple elements are minimal, we compare the next element along from each minimal element.
E.g. with an input of 10 and {0, 1, 2, 1, 1, 1, 0, 0, 1, 0}:
There are four minimal elements of 0, at indices 0, 6, 7 and 9
Of these two are followed by a 1 (the 0 and 7 elements), and two are followed by a 0 (the 6 and 9 elements). Remember that the array is circular.
0 is smaller than 1, so we only consider the 0s at 6 and 9.
Of these the sequence of 3 elements starting at 6 is '001' and the sequence from 9 is also '001', so they're still both equally minimal
Looking at the sequence of 4 elements, we have '0010' from element 6 onwards and '0012' from element 9 onwards. The sequence from 6 onwards is therefore smaller and 6 is returned. (I've checked that this is the case).
Refactored and commented code follows:
int findStartOfMinimumSubsequence(int length, char circular_array[])
{
#define AccessWithOffset(index) circular_array[(index + offset) % length]
int indicesStillConsidered[length], count_left = length, indicator[length], minIndex = 0;
for (int index = 0; index < length; index++)
{
indicesStillConsidered[index] = index;
indicator[index] = 1;
}
// Keep increasing the offset between pairs of minima, until we have eliminated all of
// them or only have one left.
for (int offset = 0; count_left >= 2; offset++)
{
// Find the index of the minimal value for the next term in the sequence,
// starting at each of the starting indicesStillConsidered
minIndex = indicesStillConsidered[0];
for (int i=0; i<count_left; i++)
minIndex = AccessWithOffset(indicesStillConsidered[i])<AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
minIndex;
// Ensure that indicator is 0 for indices that have a non-minimal next in sequence
// For minimal indicesStillConsidered[i], we make indicator 0 1+offset away from the index.
// This prevents a subsequence of the current sequence being considered, which is just an efficiency saving.
for (int i=0; i<count_left; i++){
offsetIndexToSet = AccessWithOffset(indicesStillConsidered[i])!=AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
(indicesStillConsidered[i]+offset+1)%length;
indicator[offsetIndexToSet] = 0;
}
// Copy the indices where indicator is true down to the start of the l array.
// Indicator being true means the index is a minimum and hasn't yet been eliminated.
for (int count_before=count_left, i=count_left=0; i<count_before; i++)
if (indicator[indicesStillConsidered[i]])
indicesStillConsidered[count_left++] = indicesStillConsidered[i];
}
return count_left == 1 ? indicesStillConsidered[0] : minIndex;
}
Sample uses
Hard to say, really. Contrived example: from a circular list of letters, this would return the index of the shortest subsequence that appears earlier in a dictionary than any other subsequence of the same length (assuming all the letters are lower case).
It returns the position of the smallest element within the substring of a ranging from element 0..n-1.
Test code
#include <stdio.h>
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
int main() {
printf(" test 1: %d\n", flr(4, "abcd"));
printf(" test 3: %d\n", flr(6, "10e-10"));
printf(" test 3: %d\n", flr(3, "zxyghab");
printf(" test 4: %d\n", flr(5, "bcaaa"));
printf(" test 5: %d\n", flr(7, "abcd"));
return 0;
}
This code gives following output:
[root#s1 sf]# ./a.out
test 1: 0
test 2: 3
test 3: 1
test 4: 2
test 5: 4
1. 0 is the position of `a` in the first case
2. 3 is the position of `-` in second case.
3. 1 is the position of `x` in third case.
4. 2 is the position of the second `a`.
5. 4 is the position of the `\0`
So the function returns the position of smallest element of a character pointer pointed by a and it will consider n elements. (Thats why it returned the position of x in the third case).
But when multiple smallest element available, it does not seems to be work in a predictable way, as it does not return the first occurrence, nor the last.
It should do a error checking for out of bound cases. Which may lead to problem in future.
so i'm running tests on this.
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
int main()
{
int in = 10;
char array[] = {0, 1, 1, 1, 1, 1, 0, 1, 1, 0};
int res = flr(in, array);
printf("expecting res to be 6;\tres = %d\n", res);
system("pause");
return 0;
}
output was res=9;

Resources