I want to check if three matrices A,B,C with same dimensions are permutations of each other(contain same elements with the same number of repetitions in every 2d array) and return 1 if they are and 0 if they are not. My code does not work properly; in this case it returns 1 1 1 1 instead of 1 0 1 0. I hope that you could help me with this.
#include <stdio.h>
#define MAX 100
int permutation (double A[100][100], double B[100][100], double C[100][100], int M, int N){
int i,j,x,y,true;
for(i=0;i<M;i++)
for(j=0;j<N;j++){
true=1;
for(x=0;x<M-i && true;x++)
for(y=0;y<N-j && true;y++)
if(A[i+x][j+y]!=B[i+x][j+y] || A[i+x][j+y]!=C[i+x][j+y])
true=0;
if(true) return 1;
}
return 0;
}
int main(){
double A[100][100] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
double B[100][100] = { {4, 1, 9}, {7, 8, 3}, {6, 2, 5} };
double C[100][100] = { {8, 4, 6}, {5, 2, 1}, {7, 9, 3} };
printf("%d ", permutation(A, B, C, 3, 3) );
C[2][2] = 1;
printf("%d ", permutation(A, B, C, 3, 3) );
C[1][2] = 3;
printf("%d ", permutation(A, B, C, 3, 3) );
B[2][2] = 10;
printf("%d ", permutation(A, B, C, 3, 3) );
}
I have edited this to remove my first attempt which worked for this particular example, but did not work in general (as pointed out in the comments, thanks). I will leave my second option.
My preferred solution is quite different than what you're currently doing so it might not be what you want, but in general I like the idea of simply sorting and doing a straight comparison.
// A comparison function to work with qsort from stdlib.h
// Like the original code, this checks for actual inequality, but when dealing with doubles you might want to look into using DBL_EPSILON from float.h
int doublecomp(const void *v1, const void *v2) {
double d1 = *(double *)v1;
double d2 = *(double *)v2;
if (d1 > d2) {
return 1;
}
if (d1 < d2) {
return -1;
}
return 0;
}
int permutation (double A[100][100], double B[100][100], double C[100][100], int M, int N) {
double ap[M*N]; // Assuming you have room on the stack for these. If M and N are expected to be large, put this on the heap instead
double bp[M*N];
double cp[M*N];
for (int i = 0; i < M; ++i) {
memcpy(ap + i * N, A[i], N * sizeof(ap[0]));
memcpy(bp + i * N, B[i], N * sizeof(bp[0]));
memcpy(cp + i * N, C[i], N * sizeof(cp[0]));
}
qsort(ap, M*N, sizeof(ap[0]), doublecomp);
qsort(bp, M*N, sizeof(bp[0]), doublecomp);
qsort(cp, M*N, sizeof(cp[0]), doublecomp);
return !(memcmp(ap, bp, M*N*sizeof(ap[0])) || memcmp(ap, cp, M*N*sizeof(ap[0])));
}
I find this nice to read. It handles arbitrary double values (you can adjust the comparison function based on your actual requirements, e.g. use DBL_EPSILON). And, assuming you might possibly have arbitrary doubles, this is probably as efficient as building some mapping for a histogram.
You could start by defining a function comparing the frequencies of the integers from two matrices.
bool is_permutation(int m1[][NUM_COLS], int m2[][NUM_COLS], int n)
{
int i, j, num1, num2;
int m1_counts[MAX_NUM] = {0};
int m2_counts[MAX_NUM] = {0};
for (i = 0; i < n; i++)
for (j = 0; j < NUM_COLS; j++) {
num1 = m1[i][j];
num2 = m2[i][j];
if (0 <= num1 && num1 < MAX_NUM &&
0 <= num2 && num2 < MAX_NUM) {
m1_counts[num1]++;
m2_counts[num2]++;
} else {
fprintf(stderr, "Error: out of bounds");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < MAX_NUM; i++)
if (m1_counts[i] != m2_counts[i])
return false;
return true;
}
Using this approach you have a choice of either extending the function to include more matrices in its parameters. A simpler, yet less performant approach would be to just combine the results of multiple comparisons, which can be done with a macro.
#define ARE_PERMUTATIONS(m1, m2, m3, n) \
(is_permutation((m1), (m2), (n)) && \
is_permutation((m1), (m3), (n)) && \
is_permutation((m2), (m3), (n)))
Printing the results can be handled in a similar way.
#define PRINT_ARE_PERMUTATIONS(m1, m2, m3, n) \
printf(#m1 ", " #m2 ", and " #m3 " %s permutations\n", \
ARE_PERMUTATIONS((m1), (m2), (m3), (n)) ? \
"are" : "are not")
All that need be added to the main function are the following lines.
PRINT_ARE_PERMUTATIONS(m1, m2, m3, NUM_COLS);
m3[2][2] = 1;
PRINT_ARE_PERMUTATIONS(m1, m2, m3, NUM_COLS);
m3[1][2] = 3;
PRINT_ARE_PERMUTATIONS(m1, m2, m3, NUM_COLS);
m2[2][2] = 10;
PRINT_ARE_PERMUTATIONS(m1, m2, m3, NUM_COLS);
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
array a1 = [1, 2, 3, 4, 5, 8];
array a2 = [1, 4, 5];
array a3 = a1 - a2; /* [2, 3, 8] */
array a4 = a2 - a1; /* print -None */
Here array would be the type my program uses to represent a struct which is used as a container. The rest of it is pseudo code, of course I'm not creating the arrays like that nor subtracting.
The simplest solution I can think of involves nested loops. any idea to solve an efficient way to solve this problem?
You want set difference. If both arrays are sorted, and contain no duplicates, you can iterate through both simultaneously:in linear time.
Whenever you encounter an element b in list B greater than the current element a of A, you can be sure that B does not contain a (or it would not be sorted). Then a is in A and not B, so it is in your output. Proceed to the next element of A, and compare it to the first element of B greater than the previous a, which is your current b. If b < a, it is also less than any remaining element of a, so you can advance to the next element of b. If you do encounter a == b, it is not in the set difference, so compare the next elements of both lists. If you reach the end of B first, add all remaining elements of A. When you reach the end of A, stop.
You can sort a list and remove duplicates in O(n log n) time, or faster if you can radix sort.
Sample Code
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
void print_set( const size_t asize, const int a[asize] )
{
const ptrdiff_t n = (ptrdiff_t)asize;
assert(n >= 0);
putchar('{');
if (n > 0) {
printf( "%d", a[0] );
for ( ptrdiff_t i = 1; i < n; ++i )
printf( ", %d", a[i] );
}
putchar('}');
fflush(stdout);
return;
}
size_t setdiff( const size_t asize, const int a[asize],
const size_t bsize, const int b[bsize],
const size_t csize, int c[csize] )
/* Calculates c = a - b, where a, b and c are sets. Returns the number of
* elements in c. The destination array c must be large enough to hold the
* result (asize elements are always enough). All sets must be sorted and
* contain no duplicates (checked at runtime).
*/
{
ptrdiff_t i = 0, j = 0, k = 0;
const ptrdiff_t m = (ptrdiff_t)asize;
const ptrdiff_t n = (ptrdiff_t)bsize;
const ptrdiff_t p = (ptrdiff_t)csize;
assert(m >= 0);
assert(n >= 0);
assert(p >= 0);
while ( i < m ) {
if ( j == n || a[i] < b[j] ) {
assert( k < p );
c[k++] = a[i++];
assert( i == m || a[i] > a[i-1]);
} else if ( a[i] > b[j] ) {
++j;
assert( j == n || b[j] > b[j-1]);
} else {
assert( a[i] == b[j] );
++i;
assert( i == m || a[i] > a[i-1]);
++j;
assert( j == n || b[j] > b[j-1]);
}
}
return (size_t)k;
}
int main(void)
{
static const int a[] = {1, 2, 3, 4, 5, 6};
static const size_t m = sizeof(a)/sizeof(a[0]);
static const int b[] = {1, 4, 5};
static const size_t n = sizeof(b)/sizeof(b[0]);
int c[6] = {0};
static const size_t p = sizeof(c)/sizeof(c[0]);
print_set( m, a );
printf(" - ");
print_set( n, b );
printf(" = ");
const size_t q = setdiff( m, a, n, b, p, c );
print_set( q, c );
printf(".\n");
print_set( n, b );
printf(" - ");
print_set( m, a );
printf(" = ");
const size_t r = setdiff( n, b, m, a, p, c );
print_set( r, c );
printf(".\n");
return EXIT_SUCCESS;
}
Assuming the two arrays are sorted, as in your examples, you should be able to locate common elements optimally using bsearch. I've provided an example, but in the future please make an effort to write your own C code in the future, then I/we might be able to help you better!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(void const *x, void const *y) {
return memcmp(x, y, sizeof (int)); // XXX: This might not be what you expect for negative values!
}
size_t difference(void *dest, size_t dest_size, void const *x, size_t x_size, void const *y, size_t y_size, size_t size, int (*compare)(void const *, void const *)) {
typedef unsigned char item[size];
item const *a = x, *b = y;
item *d = dest;
size_t cursor = 0, d_size = 0;
for (size_t x = 0; x < x_size; x++) {
item *ptr = bsearch(a + x, b + cursor, y_size - cursor, size, compare);
if (ptr) {
cursor = ptr - b;
}
else {
memcpy(d[d_size++], a[x], sizeof (item));
}
}
return d_size;
}
void print(char *name, int array[], size_t array_size) {
printf("%s: %s", name, array_size ? "" : "NONE\n");
for (size_t x = 0; x < array_size; x++, putchar(x < array_size ? ',' : '\n')) {
printf("%d", array[x]);
}
}
int main(void) {
int a[] = { 1, 2, 3, 4, 5, 8 },
b[] = { 1, 4, 5 },
c[sizeof a / sizeof *a],
d[sizeof a / sizeof *a];
size_t c_size = difference(c, sizeof c / sizeof *c,
a, sizeof a / sizeof *a,
b, sizeof b / sizeof *b,
sizeof (int), compare);
size_t d_size = difference(d, sizeof d / sizeof *d,
b, sizeof b / sizeof *b,
a, sizeof a / sizeof *a,
sizeof (int), compare);
print("c", c, c_size);
print("d", d, d_size);
}
First, you will obviously need a find function:
int find(int val, const int* a, int na)
{
int i;
for (i = 0; i < na; ++i)
{
if (val == a[i])
return i;
}
return -1;
}
The diff function become quite trivial, assuming you have an allocated array for the result. r should be able to hold at least na elements.
int diff(int* r, const int* a, int na, const int* b, int nb)
{
// returns the number of elenment in resulting set.
// on output r contains the elements from a that are not found in b
// expects r to provide enough room for na elements
int i, nr;
nr = 0;
for (i = 0; i < na; ++i)
{
if (find(a[i], b, nb) < 0)
{
r[nr++] = a[i];
}
}
return nr;
}
I know that in a sense, this is still a nested loop. But it is much more readable. Plus, you've gained a generic find() function that you can use elsewhere in your code.
I thought the difference of two sets was not as you describe, but defined as A with intersection of A and B removed. i.e. If a value is found several times in A, but only once in B, only one element of A is removed from the result set. For this case, you'd need a remove function.
int remove(int at, int* a, int na)
{
// removes first occurence of val in a.
// returns the number of elements in a after remove op.
if (0 <= at && at < na)
{
memmove(&a[at], &a[at + 1], sizeof(int) * (na - (at + 1)));
return na - 1;
}
return na;
}
The diff when elements are not unique is not much more complex, we'll loop on b.
int difference(int* r, const int* a, int na, const int* b, int nb)
{
// returns elements from a, minus set b.
// handles non-unique cases, so this is the true difference or a-b
// returns the number of elements in resulting set
int nr, found;
memcpy(r, a, na * sizeof(int));
nr = na;
for (i = 0; i < nb; ++i)
{
found = find(b[i], r, nr);
if (found >= 0)
{
nr = remove(found, r, nr);
}
}
return nr;
}
I did not try to compile these, so there might be some typos, but it should be fairly close..
Edit: These algorithms have a complexity of O(N^2), so by sorting a (or b) and using a binary search, you could get them down to 1) O(2NlogN) 2) O(3NlogN), which is not bad, since you'd only need to change the find() function to implement optimization.
Given two arrays containing integers, figure out whether or not three consecutive integers are present in both arrays.
For example: A = [1, 4, 5, 7, 2] and B = [3, 1, 4, 5, 9] will result in "true" / 1 because [1, 4, 5] is present in both arrays.
My solution to this task is present below, but I feel like there must be a more optimized solution than this.
int consecutiveInts(int *a, int sizeA, int *b, int sizeB){
int i, j;
// Iterate over every integer in array b for every integer in array a.
for (i = 0 ; i < sizeA - 2 ; i++){
for (j = 0 ; j < sizeB - 2 ; j++){
if (a[i] == b[j] && a[i + 1] == b[j + 1] && a[i + 2] == b[j + 2])
return 1;
}
}
return 0;
}
For small arrays, OP approach is OK. For array lengths m,n it has O(m*n) run time.
An alternate makes 2 value arrays, sorts them and then looks for a common element. It has O(m*log2(m) + n*log2(n)) run time. Certainly faster with large arrays than OP's code.
typedef struct {
int i[3];
} int3;
void Init3(int3 *i3, const int *i, size_t n) {
while (n--) {
i3[n].i[0] = i[n];
i3[n].i[1] = i[n + 1];
i3[n].i[2] = i[n + 2];
}
}
int fcmp(const void *a, const void *b) {
return memcmp(a, b, sizeof (int3));
}
bool Pattern3(const int *a, size_t size_a, const int *b, size_t size_b) {
if (size_a < 3 || size_b < 3) return false;
int3 a3[size_a - 2];
Init3(a3, a, size_a - 2);
qsort(a3, size_a - 2, sizeof *a3, fcmp);
int3 b3[size_b - 2];
Init3(b3, b, size_b - 2);
qsort(b3, size_b - 2, sizeof *b3, fcmp);
while (size_a && size_b) {
int cmp = fcmp(&a[size_a - 1], &b[size_b - 1]);
if (cmp == 0) return true;
if (cmp > 0) size_a--;
else size_b--;
}
return false;
}
int main() {
int A[] = { 1, 4, 5, 7, 2 };
int B[] = { 3, 1, 4, 5, 9 };
printf("%d\n", Pattern3(A, sizeof A / sizeof *A, B, sizeof B / sizeof *B));
}
An alternative would use a bsearch() rather than form the 2nd int3 b3[]/qsort().
I think I cannot be wrong by sayin that declaring i and j outside of the loop is useless and not optimized.
Something like :
for (unsigned i = 0; i < sizeA - 2; i++) // i will only exist inside the loop
Would be a little better.
I use unsigned type because it is a habit I have taken when using an iterating variable. I think this is a matter which, if you are interested and not already informed, you could learn from by reading this topic.
Not sure it optimizes running speed, but I notice that in case there are repeated numbers you don't need to check them over and over again.
For example three sequential elements in the first array are all 1. After checking a[i] and seeing it's a mismatch you can skip directly to a[i + 3] without comparing a[i + 1] or a[i + 2] (they are also a mismatch).
The management of this condition, particularly if it's a short sequence of repeats, may not improve running time. You have to measure.
With code changes that do not affect the order of complexity, any candidate improvements need profiling (tests that measure the performance) to verify.
The following is still a O(n*m), yet with reduced coefficient as it can step through b[] faster if a[] has repeated values that also exist in b[]. This speeds the inner b[] loop where the majority of time is consumed.
Look at the a[] pattern for distinct values to so j may be advanced faster.
Example:
#define x 0
bool Pattern3(const int *a, size_t size_a, const int *b, size_t size_b) {
static const unsigned char deltas[2][2][2][2] = { //
// What type of pattern is a[0], a[1], a[2]?
{ { { 1, 1 }, // X Y Z
{ 1, 1 } }, // X Y Y
{ { 1, 2 }, // X Y X
{ x, x } } }, // not possible
{ { { 2, 1 }, // X X Y
{ x, x } }, // not possible
{ { x, x }, // not possible
{ 2, 3 } } } }; // X X X
for (unsigned i = 0; i + 2 < size_a; i++) {
const unsigned char *delta23 = deltas[a[0] == a[1]][a[0] == a[2]][a[1] == a[2]];
for (unsigned j = 0; j + 2 < size_b;) {
if (a[0] != b[j]) {
j++;
} else if (a[0 + 1] != b[j + 1]) {
j += delta23[0];
} else if (a[0 + 2] != b[j + 2]) {
j += delta23[1];
} else {
return true;
}
}
a++;
}
return false;
}
Other minor changes which may help.
In the above, swap a,b when size_a > size_b.
Use const as lesser compilers can optimized on that.
// int consecutiveInts(int *a, int sizeA, int *b, int sizeB){
int consecutiveInts(const int *a, int sizeA, const int *b, int sizeB){
Iterate from 2. Adjust indexing accordingly.
for (i = 2 ; i < sizeA ; i++){
...
try using the following loop
for(int i=0;i<A.length;i++)
{
for(int j=0;j<A.length;j++)
{
if(A[i]==B[j])
{
count=count+1; //It checks how many times equal elements have been found
//ensure to declare and initialize int count=0;
}
}
}
if(count>=3)
System.out.println("true");
Followed this method (pdf) to implement a recursive solution, but I think it is buggy. I have exactly implemented it as described in the pdf file.
The output of the code below is wrong. It shows the target locations. The target array contains bit representation of the numbers that should be added to get the sum.
Placing the binary[i] = 1 in else if condition fixes the problem, but it doesn’t make sense.
Is it possible to clarify what is the right solution?
#define SIZE(a) sizeof(a)/sizeof(a[0])
int binary[100];
void foo(int target, int i, int sum, int *a, int size) {
binary[i] = 1;
if (target == sum+a[i]) {
int j;
for (j=0;j<size;j++)
printf("%d\n", binary[j]);
return;
} else if ((i+1 < size) && (sum + a[i] < target)) {
foo(target, i+1, sum + a[i], a, size);
}
if ((i+1 < size) && (sum +a[i+1] <= target)) {
binary[i] = 0;
foo(target, i+1, sum, a, size);
}
}
int main()
{
int i, target =10,a[] = {1, 2, 3, 5, 100};
foo(target, 0, 0, a, SIZE(a));
}
Current output: 0 1 1 1 1
Expected output: 0 1 1 1 0
#include <stdio.h>
#define SIZE(a) sizeof(a)/sizeof(a[0])
int binary[100];
void show(int* p, int size) {
int j;
for (j = 0; j < size; j++)
printf("%d\n", p[j]);
}
void foo(int target, int i, int sum, int *a, int size) {
if (sum == target) {
// solution found
show(binary, size);
} else if (sum < target && i < size) {
// try both branches
// 1. current value used
binary[i] = 1;
foo(target, i + 1, sum + a[i], a, size);
// 2. current value skipped
binary[i] = 0;
foo(target, i + 1, sum, a, size);
} else {
// no solution on this path
}
}
int main() {
int target = 10;
int a[] = {1, 2, 3, 5, 100};
foo(target, 0, 0, a, SIZE(a));
}
Explanation:
Let's speak only about i, sum and binary because everything else is constant from this algorithm's perspective.
Our aim is to select individual elements from a whose sum is equal to target. When we reach this situation we are done and our only work is to show the solution.
The algorithm can proceed only if our current sum is still below the target, and we haven't reached the end of a yet.
There are always two possibilities: Use the current element or skip it. Both are investigated recursively.
The procedure must leave zero in the appropriate position of binary, otherwise it would provide misleading results at various levels of backtracking. For this reason the use branch is investigated first.
FROM HERE
Given a value N, if we want to make change for N cents, and we have
infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how
many ways can we make the change? The order of coins doesn’t matter.
For example, for N = 4 and S = {1,2,3}, there are four solutions:
{1,1,1,1},{1,1,2},{2,2},{1,3}. So output should be 4. For N = 10 and S
= {2, 5, 3, 6}, there are five solutions: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} and {5,5}. So the output should be 5.
Recursive solution. (Can someone please help me understand how to calculate time complexity of this solution)
How to solve T(M,N) = T(M,N-1) + T(M-1,N)
int count( int S[], int m, int n )
{
if (n == 0)
return 1;
if (n < 0)
return 0;
if (m <=0 && n >= 1)
return 0;
return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
int main()
{
int i, j;
int arr[] = {1, 2, 3};
int m = sizeof(arr)/sizeof(arr[0]);
printf("%d ", count(arr, m, 4));
getchar(); return 0;
}
I have a Java method that multiplies 2 matrices. I have tried to port the same method in C without success.
Here is my attempt to write a method that should multiply 2 matrices in C:
float **multiply(int m1, int n1, float Xy1[], int m2, int n2, float Xy2[]) {
int i, j, k;
float **result = allocate_mem_mtrx(m1, n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
At this line
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
I receive the error:
subscripted value is neither array nor pointer nor vector
Clearly my syntax is wrong, but I haven't understood how I should fix this line of code, to solve my problem.
In my main I have:
float matrix1[3][2] = {{0, 1}, {3, 4}, {6, 7}};
float matrix2[2][3] = {{5, 1, 2}, {3, 4, 5}};
with the actual signature I invoke the method in this way:
multiply(3, 2, &matrix1, 2, 3, &matrix2);
My original Java method
public static int[][] multiply(int[][] Xy1, int[][] Xy2) {
int rowsInXy1 = Xy1.length;
int columnsInXy1 = Xy1[0].length; // same as rows in B
int columnsInXy2 = Xy2.length;
int[][] result = new int[rowsInXy1][columnsInXy2];
for (int i = 0; i < rowsInXy1; i++) {
for (int j = 0; j < columnsInXy2; j++) {
for (int k = 0; k < columnsInXy1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
You have float Xy1[]
but you treat it as 2D
Xy1[i][k]
Same for Xy2.
You should change float Xy1[] to float** Xy1.
Also another thing, in your loop I feel that you are sure that result 2D array is initialized in your function that says allocate. If that functions just mallocs the array, then this array will have garbage inside.
For more.
[EDIT]
Also I see in one other answer that they cast what malloc returns. Ouch!
Do not cast the return value of malloc in C.
[EDIT.2]
SO, you could something like this:
#include <stdlib.h>
// We return the pointer
float **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
float **table;
table = malloc(N*sizeof(float *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(float) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
// do not forget to FREE what multiply returns
float **multiply(int m1, int n1, float** Xy1,int m2, int n2, float** Xy2) {
int i,j,k;
float **result = get(m1,n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
// this line is correct, the prototype of the function
// was not OK
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
int main(void) {
float** A = get(5, 5); // arrays declared as double pointers
float** B = get(5, 5);
float** C = get(5, 5);
C = multiply(5, 5, A, 5, 5, B);
// free2Darray function defined below
free2Darray(A, 5);
free2Darray(B, 5);
free2Darray(C, 5);
return 0;
}
[EDIT.3]
Another way, if you now the columns apriori, which you probably don't as your function implies, you could do that:
#include <stdlib.h>
#include <stdio.h>
// We return the pointer
float **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
float **table;
table = malloc(N*sizeof(float *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(float) );
return table;
}
float **multiply(int m1, int n1, float Xy1[][2],int m2, int n2, float Xy2[][2]) {
int i,j,k;
float **result = get(m1,n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
int main() {
float matrix1[2][2] = {{0, 1}, {3, 4}};
float matrix2[2][2] = {{0, 1}, {3, 4}};
float** C;
C = multiply(2, 2, matrix1, 2, 2, matrix2);
free2Darray(C, 2);
printf("ok\n");
return 0;
}
I got the get() function from my pseudo-site.
float Xy1[]
is not a two dimensional array, so to write
Xy1[i][k]
is an error.
In C you can use a pointer to pointer notation:
float** multiply( int m1, int n1, float** Xy1,int m2, int n2, float** Xy2) {
//...
}
or you can take advantage of the variable-length array feature in the C language and write
functions that can take multidimensional arrays of varying sizes:
float** multiply( int m1, int n1, float Xy1[m1][n1],
int m2, int n2, float Xy2[m2][n2]) {
float **result, i, j;
result = malloc( m1 * sizeof *result); // remember to free this memory
for( i = 0; i < m1; ++i)
result[i] = malloc( n2 * sizeof float);
//... I don't continue since there seems to be an issue with your indices
// however now you can use result this way:
// result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j]; i, j, k integers
return result;
}
In C++ use a std::vector< std::vector<float> >:
typedef std::vector<std::vector<float> > array; // shorten notation
array multiply( const array& Xy1, const array& Xy2) {
//...
}
In addition
int[][] result = new int[rowsInXy1][columnsInXy2];
is not correct way to create two dimensional array. Such array is an array of pointers and correct way to create this is:
C
int **a, i;
a = malloc( rowsInXy1 * sizeof *a);
for( i = 0; i < rowsInXy1; ++i)
a[i] = malloc( columnsInXy2 * sizeof int);
C++
int** result = new int*[rowsInXy1];
for( int i = 0; i < rowsInXy1; ++i)
result[i] = new int[columnsInXy2];
I see you have already chosen a solution but here is some additional info about arrays in C.
In C there is no equivalent of Java's int[][] type. Java array storage also includes storage of how many items are in the array. However, C's array storage is purely the values in the array contiguous in memory; and you have to keep track of the size either as compile-time constants, or by storing a variable that holds the length.
Further; originally in C, arrays (using the [] syntax) had to have their size known at compile-time. There is an optional feature called variable-length array which means that the array size can be specified at runtime -- however the size can't be changed once the array is created. The major compiler vendors all support VLA, I think.
The VLA uses contiguous storage, however it is not possible to return one via a function's return value. But you can "return" them using an "out" parameter.
It's probably going to turn into a jumble if your code sometimes uses VLAs and sometimes uses dynamically-allocated arrays of pointers.
Another point: in both cases you have to store both array dimensions separately from the array, so that's 3 variables to pass around for each matrix. I'd like to suggest wrapping all of this up in a struct. Since VLAs can't live in a struct, and the compiler might not support them anyway, your best bet may be to use the dynamic allocation version.
Even though we are in C, if you are planning to do more than just a throwaway program, my recommendation would be to use an object-oriented approach for the matrix. Here's an example framework (where all Matrices are to have the Matrix be dynamically allocated, as well as the cells):
// Matrix.h
typedef struct
{
size_t y_dim, x_dim;
float **cells;
} Matrix;
Matrix *matrix_construct(size_t y_dim, size_t x_dim);
void matrix_free(Matrix *m); // frees m as well as cells
void matrix_assign(Matrix *dst, Matrix const *src); // may re-size dst
void matrix_set_values(Matrix *dst, float *row_major);
bool matrix_is_equal(Matrix const *m1, Matrix const *m2);
typedef Matrix *MatrixBinaryOperator(Matrix const *m1, Matrix const *m2);
MatrixBinaryOperator matrix_multiply;
Example usage:
float mat1_array[3][2] = {{0, 1}, {3, 4}, {6, 7}};
float mat2_array[2][3] = {{5, 1, 2}, {3, 4, 5}};
Matrix *mat1 = matrix_construct(3, 2);
Matrix *mat2 = matrix_construct(2, 3);
matrix_set_values(mat1, (float *)&mat1_array);
matrix_set_values(mat2, (float *)&mat2_array);
Matrix *mat3 = matrix_multiply(mat1, mat2);
matrix_free(mat1);
matrix_free(mat2);
matrix_free(mat3);
See it working - disclaimer: this code doesn't check for malloc failure and I have only done the most basic testing; and a lot of optimization is possible.