Concentric square matrix - c

I have coding problem to write concentric square matrix (biggest number is in the middle) For example user needs to write an matrix For example:
5 5 5 5 5
5 6 6 6 5
5 6 7 6 5
5 6 6 6 5
5 5 5 5 5
My program has to output "Yes" because this is, by my program's rules, a concentric square matrix.
5 5 5 5 5
5 6 6 6 5
5 6 7 8 5
5 6 6 6 5
5 5 5 5 5
This is not a concentric square matrix because 8 is in 4th column and 3rd row.
This is my code:
#include <stdio.h>
int main() {
int mat[100][100];
int i,j;
int n;
scanf("%d",&n);
printf("Unesite matricu; ");
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&mat[i][j]);
}
}
}
I don't know how to do the rest of it so if someone can help me, I would be happy :))
Comment::
I forgot to say that only odd numbers can be the dimension of the matrix (1,3,11,27). The only final output of the program has to be "YES (if the matrix is a concentric square matrix) or "NO" (if it's not). I know how to make a concentric square matrix when the user inputs a number (for example, 4) and the matrix has 2*n-1 dimensions. And through the loops, the program automatically makes the matrix (if you know what I mean). But for my matrix, the user has to input all the elements of the matrix and the program has to check if the matrix is concentric or not.

Would you please try the following:
#include <stdio.h>
int main() {
int mat[100][100];
int ii[] = {0, 1, 0, -1}; // incremental numbers of i
int jj[] = {1, 0, -1, 0}; // incremental numbers of j
int i, j;
int n;
int u, v, w; // variables to walk on edges
int val; // value of the element
int prev; // previous value in one outer edge
int length; // length of the edge
// read matrix size and values
printf("Enter the number:\n");
scanf("%d", &n);
printf("Enter the matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
scanf("%d", &mat[i][j]);
}
}
// loop on the edges
for (u = 0; u < n / 2; u++) { // from outmost edge to inner
i = u; j = u; // index of the north west corner
val = mat[u][u]; // initial value to compare
for (v = 0; v < 4; v++) { // four sides
length = n - u * 2 - 1; // length of the edge
for (w = 0; w < length; w++) {
i += ii[v]; // one step ahead on the edge
j += jj[v]; // same as above
if (mat[i][j] != val || (u > 0 && mat[i][j] <= prev)) {
// if u == 0, skip the comparison with prev
printf("No at [%d][%d] (val=%d)\n", i, j, mat[i][j]);
return 1;
}
}
}
prev = mat[i][j];
}
// finally examine the center value (if n is odd number)
if (n % 2) {
if (mat[u][u] <= prev) {
printf("No at [%d][%d] (val=%d)\n", u, u, mat[u][u]);
return 1;
}
}
printf("Yes\n");
return 0;
}
The basic concept is to generate a series of indexes of the edge
such as:
[0, 1], [0, 2], [0, 3], [0, 4],
[1, 4], [2, 4], [3, 4], [4, 4],
[4, 3], [4, 2], [4, 1], [4, 0],
[3, 0], [2, 0], [1, 0], [0, 0]
by using the variables i, j and the arrays ii[], jj[].
The example above is the indexes for the outermost edge and go into
the inner edge in the next iteration. Then the values of the index
is compared with the other value in the same edge and the previous
value in the outer edge.
[Edit]
Here is an alternative which does not use an array other than mat[100][100]:
#include <stdio.h>
int main() {
int mat[100][100];
int i, j;
int ii, jj; // incremental values for i and j
int n;
int u, v, w; // variables to walk on edges
int val; // value of the element
int prev; // previous value in one outer edge
int length; // length of the edge
// read matrix size and values
printf("Enter the number:\n");
scanf("%d", &n);
printf("Enter the matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
scanf("%d", &mat[i][j]);
}
}
// loop on the edges
for (u = 0; u < n / 2; u++) { // from outmost edge to inner
i = u; j = u; // index of the north west corner
val = mat[u][u]; // initial value to compare
for (v = 0; v < 4; v++) { // four sides
ii = (v & 1) * ((v & 1) - (v & 2));
// assigned to {0, 1, 0, -1} in order
jj = ((v + 1) & 1) * (((v + 1) & 1) - ((v + 1) & 2));
// assigned to {1, 0, -1, 0} in order
length = n - u * 2 - 1; // length of the edge
for (w = 0; w < length; w++) {
i += ii; // one step ahead on the edge
j += jj; // same as above
if (mat[i][j] != val || (u > 0 && mat[i][j] <= prev)) {
// if u == 0, skip the comparison with prev
printf("No at [%d][%d] (val=%d)\n", i, j, mat[i][j]);
return 1;
}
}
}
prev = mat[i][j];
}
// finally examine the center value (if n is odd number)
if (n % 2) {
if (mat[u][u] <= prev) {
printf("No at [%d][%d] (val=%d)\n", u, u, mat[u][u]);
return 1;
}
}
printf("Yes\n");
return 0;
}

I created an answer using more functions than just main(). It is more verbose than what is required for your homework — it prints out the matrix it reads and diagnoses the first problem it comes across. It works with both positive and negative numbers, and with matrices with odd or even numbers of elements.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
enum { MAT_SIZE = 100 };
static int err_error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
static int err_shell(int r, int c, int a_val, int e_val)
{
printf("Element M[%d][%d] = %d vs expected value %d\n", r, c, a_val, e_val);
return 0;
}
static int check_shell(int shell, int n, int matrix[MAT_SIZE][MAT_SIZE])
{
int lb = shell;
int ub = n - shell - 1;
int val = matrix[lb][lb];
/* Check the horizontals */
for (int c = lb; c <= ub; c++)
{
if (matrix[lb][c] != val)
return err_shell(lb, c, matrix[lb][c], val);
if (matrix[ub][c] != val)
return err_shell(ub, c, matrix[ub][c], val);
}
/* Check the verticals */
for (int r = lb; r <= ub; r++)
{
if (matrix[r][lb] != val)
return err_shell(r, lb, matrix[r][lb], val);
if (matrix[r][ub] != val)
return err_shell(r, ub, matrix[r][ub], val);
}
return 1;
}
static int check_matrix(int n, int matrix[MAT_SIZE][MAT_SIZE])
{
for (int i = 0; i <= n / 2; i++)
{
if (check_shell(i, n, matrix) == 0)
return 0;
}
for (int i = 0; i < (n - 1) / 2; i++)
{
if (matrix[i][i] >= matrix[i+1][i+1])
{
printf("Shell %d has value %d but inner shell %d has value %d\n",
i, matrix[i][i], i+1, matrix[i+1][i+1]);
return 0;
}
}
return 1;
}
static int read_size(void)
{
int n;
if (scanf("%d", &n) != 1)
err_error("failed to read an integer\n");
if (n <= 0 || n > MAT_SIZE)
err_error("matrix size %d is not in the range 1..%d\n", n, MAT_SIZE);
return n;
}
static void read_matrix(int n, int matrix[n][n])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (scanf("%d", &matrix[i][j]) != 1)
err_error("failed to read M[%d][%d]\n", i, j);
}
}
}
static int max_field_width(int n, int matrix[MAT_SIZE][MAT_SIZE])
{
int min_val = matrix[0][0];
int max_val = matrix[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (matrix[i][j] < min_val)
min_val = matrix[i][j];
if (matrix[i][j] > max_val)
max_val = matrix[i][j];
}
}
int fld_width = snprintf(0, 0, "%d", max_val);
if (min_val < 0)
{
int min_width = snprintf(0, 0, "%d", min_val);
if (min_width > fld_width)
fld_width = min_width;
}
return fld_width;
}
static void print_matrix(const char *tag, int n, int matrix[MAT_SIZE][MAT_SIZE])
{
printf("%s (%d):\n", tag, n);
int w = max_field_width(n, matrix) + 1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%*d", w, matrix[i][j]);
}
putchar('\n');
}
}
int main(void)
{
int matrix[MAT_SIZE][MAT_SIZE];
int n = read_size();
read_matrix(n, matrix);
print_matrix("Input", n, matrix);
if (check_matrix(n, matrix))
printf("YES: Matrix is a valid concentric matrix\n");
else
printf("NO: Matrix is not a valid concentric matrix\n");
return 0;
}
One detail is that this code can be made to use a VLA (variable-length array) by simply replacing MAT_SIZE by n in each function definition and modifying main() to read:
static int check_shell(int shell, int n, int matrix[n][n]) { … }
static int check_matrix(int n, int matrix[n][n]) { … }
static void read_matrix(int n, int matrix[n][n]) { … }
static int max_field_width(int n, int matrix[n][n]) { … }
static void print_matrix(const char *tag, int n, int matrix[n][n]) { … }
int main(void)
{
int n = read_size();
int matrix[n][n];
read_matrix(n, matrix);
print_matrix("Input", n, matrix);
if (check_matrix(n, matrix))
printf("YES: Matrix is a valid concentric matrix\n");
else
printf("NO: Matrix is not a valid concentric matrix\n");
return 0;
}
This reads the matrix size before allocating the matrix, instead of allocating a fixed size matrix first.
The read_size() function enables this change — that input must be done separately from the main matrix scanning code.

Related

How can I fill a 2D array spirally in C? Example/problem

so I've been struggling with this example for a good hour now and I can't even begin to process how should I do this.
Write a program that, for given n and m, forms a matrix as described.
The matrix should be m x m, and it's filled "spirally" with it's
beginning in the upper left corner. The first value in the matrix is
the number n. It's repeated until the "edge" of the matrix, at which
point the number increments. After the number 9 goes 0. 0 ≤ n ≤ 9, 0 ≤
m ≤ 9
Some time ago I had made a function to display the numbers 1 to n on an odd-sized grid.
The principle was to start from the center and to shift by ;
x = 1
x box on the right
x box on the bottom
x++
x box on the left
x box at the top
x++
With this simple algorithm, you can easily imagine to maybe start from the center of your problem and decrement your value, it seems easier to start from the center.
Here is the code that illustrates the above solution, to be adapted of course for your problem, it's only a lead.
#define WE 5
void clock(int grid[WE][WE])
{
int count;
int i;
int reach;
int flag;
int tab[2] = {WE / 2, WE / 2}; //x , y
count = 0;
flag = 0;
i = 0;
reach = 1;
grid[tab[1]][tab[0]] = count;
for (int j = 0; j < WE - 1 && grid[0][WE - 1] != pow(WE, 2) - 1; j++)
for (i = 0; i < reach && grid[0][WE - 1] != pow(WE, 2) - 1; i++, reach++)
{
if(flag % 2 == 0)
{
for(int right = 0 ; right < reach ; right++, tab[0]++, count++, flag = 1)
grid[tab[1]][tab[0]] = count;
if(reach < WE - 1)
for(int bottom = 0; bottom < reach; bottom++, count++, tab[1]++)
grid[tab[1]][tab[0]] = count;
}
else
{
for(int left = 0; left < reach; left++, count++, tab[0]--, flag = 0)
grid[tab[1]][tab[0]] = count;
for(int top = 0; top < reach; top++, tab[1]--, count++)
grid[tab[1]][tab[0]] = count;
}
}
}
I finally solved it. If anybody's interested, here's how I did it:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Fills the row number "row" with the number n
int fillRow(int m, int n, int arr[m][m], int row)
{
int j;
for(j=0;j<m;j++)
{
if(arr[row][j] == -1 || arr[row][j] == n-1) arr[row][j] = n;
}
}
//Fills the column number "col" with the number n
int fillCol(int m, int n, int arr[m][m], int col)
{
int i;
for(i=0;i<m;i++)
{
if(arr[i][col] == -1 || arr[i][col] == n-1) arr[i][col] = n;
}
}
int main()
{
int n, m, i, j, r=1, c=1, row=-1, col=-1;
scanf("%d %d",&n, &m);
int arr[m][m];
//Fill array with -1 everywhere
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
arr[i][j] = -1;
}
}
//Calculate which row/column to fill (variables row/col)
//Fill row then column then row than column...
for(i=0;i<2*m;i++)
{
if(i%2==0)
{
row = (r%2==0) ? m-r/2 : r/2;
fillRow(m, n, arr, row);
n++;
r++;
}
else if(i%2==1)
{
col = (c%2==0) ? c/2-1 : m-c/2-1;
fillCol(m, n, arr, col);
n++;
c++;
}
}
//If an element is larger than 9, decrease it by 10
//Prints the elements
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
if(arr[i][j]>9) arr[i][j] -=10;
printf("%d ",arr[i][j]);
}
printf("\n");
}
return 0;
}

My sorting function gives unexpected output

I write a generalized C language program that given a sequence of numbers, sorts, even numbers in ascending order, odd numbers in descending order and places all even numbers in the initial part of an array then odd numbers.
Example: 2, 5, 1, 0, 4, 7, 9, 3, -2, 10, 20, 15
Expect: -2, 0, 2, 4, 10, 20, 15, 9, 7, 5, 3, 1
Six functions are required. The solution must be provided using only the mentioned functions.No global variables shall be declared. Use appropriate data types, return types and function arguments.
Input() – takes total number of elements and values as input from the user. Stores the values in “input” array.
SortEven() – sorts the even numbers in ascending order and stores them in an array named “even”
SortOdd() – sorts the odd numbers in descending order and stores them in an array named “odd”
Merge() – places all the even numbers in the initial part of array named “result” then odd numbers.
Display() – displays the contents of “result” array.
main() – calls the Input() module to begin the execution.
Program:
#include <stdio.h>
int main() {
input();
}
int input() {
int n;
printf("Enter The Number Of Elements You Want To Enter : ");
scanf("%d", &n);
int a[n], i, ev = 0, od = 0;
for (i = 0; i < n; i++) {
printf("Enter Number : ");
scanf("%d", &a[i]);
if (a[i] % 2 == 0) {
ev++;
} else {
od++;
}
}
sorteven(a, ev, od, n);
}
int sorteven(int a[], int ev, int od, int n) {
int i, j = 0, swap, even[ev];
for (i = 0; i < n; i++) {
if (a[i] % 2 == 0) {
even[j] = a[i];
j++;
}
}
for (i = 0; i < ev - 1; i++) {
for (j = 0; j < ev - i - 1; j++) {
if (even[j] > even[j + 1]) {
swap = even[j];
even[j] = even[j + 1];
even[j + 1] = swap;
}
}
}
sortodd(a, ev, od, n, even);
}
int sortodd(int a[], int ev, int od, int n, int even[]) {
int i, k = 0, swap, odd[od], j;
for (i = 0; i < n; i++) {
if (a[i] % 2 != 0) {
odd[k] = a[i];
k++;
}
}
for (i = 0; i < od - 1; i++) {
for (j = 0; j < od - i - 1; j++) {
if (odd[j] < odd[j + 1]) {
swap = odd[j];
odd[j] = odd[j + 1];
odd[j + 1] = swap;
}
}
}
merge(a, ev, od, n, even, odd);
}
int merge(int a[], int ev, int od, int n, int even[], int odd[]) {
int merge[n], i;
for (i = 0; i < ev; i++) {
merge[i] = even[i];
}
for (i = ev; i < n; i++) {
merge[i] = odd[i];
}
display(merge, n);
}
int display(int merge[], int n) {
int i;
printf("OUTPUT : ");
for (i = 0; i < n; i++) {
printf(" %d ", merge[i]);
}
}
When looking in the source code, the problem is located in the merge() function.
Both sorteven() and sortodd()are well implemented, but when merging both sub-arrays, the for(i=ev;i<n;i++) is not correct.
To add the odd[] array at the end of the even[] array, write:
int j;
// point to the first item of odd[]
for(i=ev,j=0;i<n;i++,j++)
{
merge[i]=odd[j];
}
Instead of:
only odd[0] to odd[od-1] are allocated and defined.
for(i=ev;i<n;i++)
{
merge[i]=odd[i];
}
Outputs of:
{ 2, 5, 1, 0, 4, 7, 9, 3, -2, 10, 20, 15 };
Are:
OUTPUT : -2 0 2 4 10 20 15 9 7 5 3 1

Reversing arrays in C

I am attempting to make a program that takes an array and reverts it backwards however the program must do this to the array in groups of three. So if the user enters the numbers 1, 2, 3, 4, 5, 6 into the array the program will then output: 3, 2, 1, 6, 5, 4.
When I run the current program I get: 3 2 1 4 5 6. If anyone could help me figure out why that would be great as I am a little confused.
Here is my code:
int * numbersProcessFour(int *x, int size)
{
int i = 0, three = 3, six = 6, nine = 9;
if (size < 4)
{
for (i; i < three; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
}else if (size > 3 && size < 7)
{
for (i; i < three; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
for (i; i < 6; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
}
else if (size > 6 && size < 10)
{
for (i; i < three; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
for (i; i < 6; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
for (i; i < 9; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
}
}
void reverse_array(int *x, int length)
{
int i, temp;
for (i = 0; i<length / 2; i++)
{
temp = x[i];
x[i] = x[length - i - 1];
x[length - i - 1] = temp;
}
}
Continuing from your comment to fluter's answer, you may be over thinking it a bit. In order to swap the 1st and 3rd element in each 3-element partition of an array, you simply need to step though the array 3-elements at a time. You need to decide how you will handle any final partial partition, but since your goal is to swap the 1st and 3rd, there is no 3rd in anything less than a full partition, so the logical choice is to ignore any final partial partition.
A variant of what you and fluter have done incorporating a swap would be:
/* reverse 1st and 3rd element in each group of 3 */
void rev3 (int *a, size_t sz)
{
if (sz < 3) return;
size_t i;
for (i = 0; i < sz; i += 3) {
if (sz - i < 3) break;
swap (&a[i], &a[i+2]);
}
}
You can put it together with:
#include <stdio.h>
void rev3 (int *a, size_t sz);
void swap (int *a, int *b);
int main (void) {
int a[] = {1,2,3,4,5,6,7,8,9};
size_t i;
rev3 (a, sizeof a/sizeof *a);
for (i = 0; i < sizeof a/sizeof *a; i++) printf (" %2d", a[i]);
putchar ('\n');
return 0;
}
void swap (int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
Example Use
When compiled and run it will give you the swap (reversal) of the 1st and 3rd elements throughout the array that you specify in your problem.
$ ./bin/revarr3
3 2 1 6 5 4 9 8 7
There is no difference whether you use a separate swap or whether you include that operation in your reversal function. There is also no need to incur the additional overheard of calling a recursive function when a procedural approach will work. Look over all the answers and compare/contrast the differing ways to accomplish your goal.
You have branches for each multiple of 3, that is inefficient. One way to solve it is you can take the array as a split by 3 smaller arrays, and reverse on them. Also, reversing an array of 3 elements is the same as swap the 1st and the 3rd element.
int i;
int temp;
for (i = 0; i < count; i += 3) {
if (i+2 >= count)
break;
temp = arr[i];
arr[i] = arr[i+2];
arr[i+2] = temp;
}
A generalized version of numberProcessFour might look like this.
int reverse_array_mod(int *input, size_t size, int mod)
{
int i, smod;
/* Error: return modulus if size cannot be divided by mod */
if(size%mod)
return size%mod;
smod = size/mod;
for(i=0; i<smod; i++)
reverse_array(input+i*mod, mod);
/* return 0 on success */
return 0;
}
Test
int main(int argc, char **argv)
{
int a[] = {0, 1, 2, 3, 4, 5};
int i, err, mod;
for(mod=1; mod<5; mod++) {
err = reverse_array_mod(a, 6, mod);
if(err) {
fprintf(stderr, "Error %d, modulus %d invalid\n", err, mod);
return err;
}
for(i=0; i<6; i++)
printf("%d\n", a[i]);
printf("\n");
}
return 0;
}
Result:
0
1
2
3
4
5
1
0
3
2
5
4
3
0
1
4
5
2
Error 2, modulus 4 invalid
try this
int *numbersProcessFour(int *x, int size) {
int i;
for(i = 0; i + 3 < size; i += 3){
reverse_array(x + i, 3);
}
if(size - i > 1)
reverse_array(x + i, size - i);
return x;
}

Count how often an int from an array appears in another array in C

I'm trying to solve an exercise that wants me to first create 2 arrays, sort them in ascending order and then count how many times a number from the first array appears in the second array. I'm almost finished. Everything seems to work perfectly fine except for one line that ruins the whole code. And I can't figure out why. I'm very new to C this is my very first exercise in this language.
Here's the code. I have commented the line that is not working:
#include <stdio.h>
void sort(int a[]) {
int i, j, l, t;
l = sizeof(a) / sizeof(a[0]);
for (i = 0; i < l + 1; i++) {
for (j = 0; j < (l - i); j++) {
if (a[j] > a[j + 1]) {
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
}
void numberOfTimes(int a[], int b[]) {
int al = sizeof(a) / sizeof(a[0]);
int bl = sizeof(b) / sizeof(b[0]);
int i, p, c = 0;
for (i = 0; i <= al; i++) {
for (p = 0; i <= bl; p++) {
if (a[i] == b[p]) {
c++; // <-------- This line doesn't work. Why?
}
}
printf("(%d, %d) ", a[i], c);
}
}
void main() {
int maxarraylen = 1000, i;
int a[maxarraylen];
int b[maxarraylen];
int v, t;
printf("Type elements of A seperated by spaces. Do not enter duplicates (type 'end' to stop): ");
while (scanf("%d", &a[i]) == 1)
i++;
scanf("%*s");
i = 0;
printf("Type elements of B seperated by spaces(type 'end' to stop): ");
while (scanf("%d", &b[i]) == 1)
i++;
scanf("%*s");
sort(a);
sort(b);
numberOfTimes(a, b);
}
The idea is that the code will first sort both arrays and then print it out in the format (n, m). n is an int from array a and m is how many times it appears in array b.
For example you enter this:
a = {3, 2 ,1}
b = {1, 3, 2, 3, 3, 2, 1}
And the code does first sort:
a = {1, 2, 3}
b = {1, 1, 2, 2, 3, 3, 3}
And then prints out how many times a number from an array a appears in b:
(1, 2) (2, 2) (3, 3)
You cannot compute the array size from a pointer received as an argument: l = sizeof(a)/sizeof(a[0]); only works if a is an array, not a pointer.
You must pass the array sizes to functions sort and numberOfTimes. In your code, the array size is not what you need, but the number of elements actually parsed for each array. You must store these numbers specifically.
Note that your sorting code is incorrect, you should not adjust j's upper bound to avoid accessing array elements beyond the end. The same is true for the numberOfTimes function. The count c must be set to 0 for each new element of a that you search in b.
Note that your code does not take advantage of the fact that a and b are sorted.
Here is a corrected version:
#include <stdio.h>
void sort(int a[], int l) {
int i, j, t;
for (i = 0; i < l; i++) {
for (j = 0; j < l - i - 1; j++) {
if (a[j] > a[j + 1]) {
t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
}
void numberOfTimes(int a[], int al, int b[], int bl) {
int i, p, c;
for (i = 0; i < al; i++) {
c = 0;
for (p = 0; p < bl; p++) {
if (a[i] == b[p]) {
c++; // <-------- This line doesn't work. Why?
}
}
printf("(%d, %d) ", a[i], c);
}
}
int main(void) {
int maxarraylen = 1000, i;
int a[maxarraylen];
int b[maxarraylen];
int al, bl, v, t;
printf("Type elements of A separated by spaces. Do not enter duplicates (type 'end' to stop): ");
for (i = 0; i < maxarraylen; i++) {
if (scanf("%d", &a[i]) != 1)
break;
}
scanf("%*s");
al = i;
printf("Type elements of B separated by spaces(type 'end' to stop): ");
for (i = 0; i < maxarraylen; i++) {
if (scanf("%d", &b[i]) != 1)
break;
}
scanf("%*s");
bl = i;
sort(a, al);
sort(b, bl);
numberOfTimes(a, al, b, bl);
return 0;
}

intersection and union of n-arrays in C

I have those functions which are making intersection/union but just of two arrays.
I need too improve them to work with n-arrays: arr = {{1,2,3},{1,5,6},...,{1,9}}.
The arrays are sorted , and their elements are unique among them.
Example (intersection):
Input: {{1,2,3,4},{2,5,4},{4,7,8}}
Output: {4}
arr1[],arr2 - arrays
m,n - length of the arrays
Intersection function:
int printIntersection(int arr1[], int arr2[], int m, int n)
{
int i = 0, j = 0;
while(i < m && j < n)
{
if(arr1[i] < arr2[j])
i++;
else if(arr2[j] < arr1[i])
j++;
else /* if arr1[i] == arr2[j] */
{
printf(" %d ", arr2[j++]);
i++;
}
}
}
and union function:
int printUnion(int arr1[], int arr2[], int m, int n)
{
int i = 0, j = 0;
while(i < m && j < n)
{
if(arr1[i] < arr2[j])
printf(" %d ", arr1[i++]);
else if(arr2[j] < arr1[i])
printf(" %d ", arr2[j++]);
else
{
printf(" %d ", arr2[j++]);
i++;
}
}
while(i < m)
printf(" %d ", arr1[i++]);
while(j < n)
printf(" %d ", arr2[j++]);
}
union(a, b, c) = union(union(a, b), c), and the same goes for intersection(). I.e. you can decompose the union or intersection of n sets into n unions or intersections of 2 sets (as NuclearGhost points out in a comment on the question). What you need to do is change your current functions so that they build up a resulting set, instead of immediately printing the result. You can then make a separate function that prints a set.
For efficiency, you want to take the union or intersection of sets that are roughly of equal size. So a divide-and-conquer approach should work alright, assuming that all input sets are likely to be of roughly equal size.
void intersection(int arr1[], int arr2[], int m, int n, int *out)
{
int i = 0, j = 0;
while(i < m && j < n)
{
if(arr1[i] < arr2[j])
i++;
else if(arr2[j] < arr1[i])
j++;
else /* if arr1[i] == arr2[j] */
{
*out++ = arr2[j++];
i++;
}
}
}
void multi_intersection(int n, int **arrays, int *lengths, int *out) {
if (n == 2) {
intersection(arrays[0], arrays[1], lengths[0], lengths[1], out);
} else if (n == 1) {
memcpy(out, arrays[0], lengths[0] * sizeof (int));
} else {
/* Allocate buffers large enough */
int *buf[2];
int len[2] = { INT_MAX, INT_MAX };
int i;
for (i = 0; i < n; ++i) {
int which = i < n / 2;
if (lengths[i] < len[which]) len[which] = lengths[i];
}
buf[0] = malloc(len[0] * sizeof (int));
buf[1] = malloc(len[1] * sizeof (int));
/* Recurse to process child subproblems */
multi_intersection(n / 2, arrays, lengths, buf[0]);
multi_intersection(n - n / 2, arrays + n / 2, lengths + n / 2, buf[1]);
/* Combine child solutions */
intersection(buf[0], buf[1], len, out);
free(buf[0]);
free(buf[1]);
}
Similar code works for multi_union(), except that the buffer lengths need to be calculated differently: the result of a union could be as large as the sum of the sizes of the inputs, rather than the minimum size of the inputs. It could probably be rewritten to do less buffer allocation. Also the recursion could be rewritten to use iteration, the same way mergesort can be written to use iteration, but the current recursive approach uses only O(log n) additional stack space anyway.
presume the max value in arrays is less than K. N is the number of arrays
int Result[K] = {0};
intersection function
//input array1
int index = 0;
for(; index < arrary1len;index++)
{
Result[array1]++;
}
.....
for(index = 0; index < K; index++)
{
if(Result[index] == N)
printf("%d",index);
}

Resources