I am creating a function which can compare two arrays. It returns 1 when they are the same and return 0 when they are not.
It required the program run as linear time, so i cannot use a for-for loop to compare it. Any suggestions for me?
Examples of arrays for which scrambled should return 1:
a = {10,15,20}, b = {10,15,20}
a = {1,2,3,4,5}, b = {5,3,4,2,1}
a = {}, b = {} (i.e. len = 0)
a = {2,1,3,4,5}, b = {1,2,4,3,5}
Examples of arrays for which scrambled should return 0:
a = {1,1}, b = {1,2}
a = {10,15,20}, b = {10,15,21}
a = {1,2,3,4,5}, b = {5,3,4,2,2}
If you can specify a maximum value for the array elements, you can compare them in linear time pretty easily, by just looping through each one and counting the values which are present, like so:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_ARRAY_VALUE 100
bool compare_arrays(int * arr1, size_t arr1_size,
int * arr2, size_t arr2_size)
{
/* Set up array to count elements */
int * table = calloc(MAX_ARRAY_VALUE + 1, sizeof * table);
if ( !table ) {
perror("couldn't allocate memory");
exit(EXIT_FAILURE);
}
/* Increment index if element is present in first array... */
for ( size_t i = 0; i < arr1_size; ++i ) {
table[arr1[i]]++;
}
/* ...and decrement index if element is present in second array. */
for ( size_t i = 0; i < arr2_size; ++i ) {
table[arr2[i]]--;
}
/* If any elements in array are not zero, then arrays are not equal */
for ( size_t i = 0; i < MAX_ARRAY_VALUE + 1; ++i ) {
if ( table[i] ) {
free(table);
return false;
}
}
free(table);
return true;
}
int main(void) {
int a1[] = {10, 20, 30, 10};
int a2[] = {20, 10, 10, 30};
int a3[] = {1, 4, 5};
int a4[] = {1, 3, 5};
if ( compare_arrays(a1, 4, a2, 4) ) {
puts("a1 and a2 are equal"); /* Should print */
}
else {
puts("a1 and a2 are not equal"); /* Should not print */
}
if ( compare_arrays(a3, 3, a4, 3) ) {
puts("a3 and a4 are equal"); /* Should not print */
}
else {
puts("a3 and a4 are not equal"); /* Should print */
}
if ( compare_arrays(a1, 4, a4, 3) ) {
puts("a1 and a4 are equal"); /* Should not print */
}
else {
puts("a1 and a4 are not equal"); /* Should print */
}
return 0;
}
which outputs:
paul#horus:~/src/sandbox$ ./lincmp
a1 and a2 are equal
a3 and a4 are not equal
a1 and a4 are not equal
paul#horus:~/src/sandbox$
Without specifying the maximum value, you can loop through each array and find the maximum. It'll still be linear time, but without an upper bound you might end up with a huge index table.
Because the comparison of the two arrays is independent of the order of the elements, both must be sorted before they can be compared. Because of this, you can't do this in linear time. The best you can do is O(n log n), as that is the best order of most sorting algorithms.
My C is pretty rusty so the may be some memory problem with the script below. However, the basic task is to sort the 2 arrays, compare them element by element. If they all match, scramble should return 1, other it's 0.
The script below works with GCC, haven't tested it with any other compiler. It compares arrays of equal length. The case of unequal length is left for the OP as an minor exercise.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare_ints(const void * a , const void * b)
{
const int * ia = (const int *)a;
const int * ib = (const int *)b;
return *ia > *ib;
}
int scramble(const int * a, const int * b, unsigned int len)
{
int * sorted_a = malloc(len * sizeof(int));
int * sorted_b = malloc(len * sizeof(int));
memcpy(sorted_a, a, len * sizeof(int));
memcpy(sorted_b, b, len * sizeof(int));
qsort(sorted_a, len, sizeof(int), compare_ints);
qsort(sorted_b, len, sizeof(int), compare_ints);
for (int i = 0; i < len; i++)
{
if (sorted_a[i] != sorted_b[i])
{
free(sorted_a);
free(sorted_b);
return 0;
}
}
free(sorted_a);
free(sorted_b);
return 1;
}
int main (int argc, char const *argv[])
{
int a[3] = {20, 10, 15};
int b[3] = {10, 15, 20};
int is_equal = scramble(a, b, 3);
printf("is_equal = %i\n", is_equal);
return 0;
}
FYI: you can't do it in linear time. qsort has O(n log n).
At a certain extent, you can obtain the sum of all the hashed values of the first array, and compare it to the sum of the hashed values of the second array. It'll work, but I don't know precise it is.
Here is my attempt, all my tests have given positive results so far :
#include <stdio.h>
unsigned int hash(unsigned int x) {
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x);
return x;
}
int compareArrays(int *arr1, int *arr2, int size) {
if (size == 0) return 1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
for (int i = 0; i < size; ++i) {
sum1 += hash(arr1[i]);
}
for (int i = 0; i < size; ++i)
sum2 += hash(arr2[i]) ;
return sum1 == sum2;
}
int main(void) {
int a[] = {1,2,3,4,5,6,7,8,255};
int b[] = {1,2,3,4,5,6,7,8,9};
int size = 9;
printf("Are they the same? %s.\n", compareArrays(a, b, size) ? "yes" : "no");
return 0;
}
You can use memcmp function with this format:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
For example;
/* memcmp example */
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer1[] = "abcde";
char buffer2[] = "abcde";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
return 0;
}
output is:
'abcde' is same as 'abcde'.
Related
I wish to sort a second array as per the first array. e.g.
first = {1,8,7,2,4}
second = {9,7,2,10,3}
I want first to be unchanged and second to be sorted in the same relative order as the first. i.e. the lowest value is at index 0, the second lowest value is at index 3, third lowest value is at index 4 etc etc
second = {2,10,9,3,7}
I have already tried some code for the following
#include <stdio.h>
typedef struct
{
int num;
int pos;
}ArrType;
ArrType arrA[5] = {{1,0},{8,1},{7,2},{2,3},{4,4}};
ArrType arrB[5] = {{9,0},{7,1},{2,2},{10,3},{3,4}};;
int cmparr(const void *a, const void *b)
{
ArrType *tmpa, *tmpb;
tmpa = (ArrType*) a;
tmpb = (ArrType*) b;
return(arrA[tmpa->pos].num - arrA[tmpb->pos].num);
}
int main(void)
{
int i;
qsort(arrB,5, sizeof(ArrType), cmparr);
for (i=0; i<5; i++)
{
printf ("%d ",arrB[i].num);
}
return (0);
}
The actual output is
9 10 3 2 7
I am open to a different data structure, but arrB should only be sorted one time.
I have seen some solutions for this in C++, Javascipt and other languages. But there is not a solution in C.
Edit - These arrays would be quite large in the final program. I am looking for a single sorting operation. i.e. single call to qsort
You need to create the meta-data that matches the desired ordering (i.e an array of indexes). Then apply that meta-data to the second array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int first[] = {1,8,7,2,4};
int second[] = {9,7,2,10,3};
int compare(const void * a, const void * b);
int binary_search(int array[], int min, int max, int target);
void print_array(int * array, int c);
int main()
{
int idx;
int c = sizeof(first)/sizeof(int);
int * sorted = NULL;
int * indexes = NULL;
int * result = NULL;
if (NULL == (sorted = malloc(sizeof(first)))) {
return -1;
}
memcpy(sorted, first, sizeof(first));
if (NULL == (indexes = malloc(sizeof(first)))) {
free(sorted);
return -1;
}
memset(indexes, -1, sizeof(first));
if (NULL == (result = malloc(sizeof(second)))) {
free(sorted);
free(indexes);
return -1;
}
memset(result, -1, sizeof(second));
// 1st: Sort the reference array
qsort (sorted, c, sizeof(int), compare);
// 2nd: Record the position of each sorted element in the original array (this is your meta-data)
for (idx=0; idx<c; idx++) {
indexes[idx] = binary_search(sorted, 0, c, first[idx]);
}
// 3rd sort the target array
memcpy(sorted, second, sizeof(second));
qsort (sorted, c, sizeof(int), compare);
// 4th apply the stored positions to the sorted target array
for (idx = 0; idx < c; idx++) {
result[idx] = sorted[indexes[idx]];
}
print_array(result, c);
free(result);
free(indexes);
free(sorted);
return 0;
}
int compare(const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int binary_search(int array[], int min, int max, int target)
{
int mid;
while (min <= max)
{
mid = min + (max - min)/2;
if (target > array[mid])
min = mid + 1;
else if (target < array[mid])
max = mid - 1;
else
return mid;
}
return -1;
}
void print_array(int * array, int c)
{
for(int i = 0; i < c; i++) {
printf("%d ", array[i]);
}
printf("\n");
}
Demo
Here is my approach, it uses qsort twice and arrC contains the result.
#include <stdio.h>
typedef struct
{
int num;
int pos;
}ArrType;
ArrType arrA[5] = {{1,0},{8,1},{7,2},{2,3},{4,4}};
int arrB[5] = {9,7,2,10,3};;
int arrC[5];
int cmpInt(const void *a, const void *b)
{
return(*a - *b);
}
int cmp(const void *a, const void *b)
{
ArrType *tmpa, *tmpb;
tmpa = (ArrType*) a;
tmpb = (ArrType*) b;
return(tmpa->num - tmpb->num);
}
int main(void)
{
int i;
qsort(arrA,5, sizeof(ArrType), cmp);
qsort(arrB,5, sizeof(ArrType), cmpInt);
for (i=0; i<5; i++)
{
arrC[arrA[i].pos] = arrB[i];
}
return (0);
}
Since C doesn't have a lambda compare (which could be used to sort an array of indexes according to first[]), the code below sorts an array of pointers ap[] to the elements of first[] using qsort(). Using pointers eliminates the need to pass an array name as a parameter for the compare function, which in turn allows the compare function to work with qsort(). The expression (ap[i]-first) converts a pointer into an index. Next second[] is sorted, also using qsort(). Then ap[] is used as a set of ranks to reorder second[] in place and in O(n) time.
To explain reorder by rank versus reorder by index:
dst[rank[i]] = src[i]; /* reorder by rank */
dst[i] = src[index[i]]; /* reorder by index */
Example code:
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
/* compare for ptr to integer */
int cmppi(const void *p0, const void *p1){
return (*(int *)p0 - *(int *)p1);
}
/* compare for ptr to ptr to integer */
int cmpppi(const void *p0, const void *p1){
return (**(int **)p0 - **(int **)p1);
}
int main()
{
int first[] = {1, 8, 7, 2, 4};
int second[] = {9, 7, 2,10, 3};
int **ap; /* array of pointers */
int *tmpp;
int tmpi;
size_t i, j;
/* allocate and generate array of pointers to first[] */
ap = (int **)malloc(sizeof(first)/sizeof(first[0])*sizeof(int *));
for(i = 0; i < sizeof(first)/sizeof(first[0]); i++)
ap[i] = &first[i];
/* sort ap */
qsort(ap, sizeof(first)/sizeof(first[0]), sizeof(int *), cmpppi);
/* sort second */
qsort(second, sizeof(second)/sizeof(second[0]), sizeof(int), cmppi);
/* reorder ap and second in place using ap as rank (O(n) time) */
for (i = 0; i < sizeof(second) / sizeof(second[0]); i++){
while(i != (j = ap[i] - first)){
tmpp = ap[i]; /* swap(ap[i], ap[j]) */
ap[i] = ap[j];
ap[j] = tmpp;
tmpi = second[i]; /* swap(second[i], second[j] */
second[i] = second[j];
second[j] = tmpi;
}
}
/* display second[] */
for (i = 0; i < sizeof(second) / sizeof(second[0]); i++)
printf("%3d", second[i]);
printf("\n");
free(ap);
return 0;
}
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.
I encountered the following question in an interview.
Complete this function to return a reversed array without modifying the function signature or the original array. Note that static data types should not be used here at all.
Assume the arrayLength is a power of 2. i.e 2^n. -> I think this is the trick here.
int* reverse(int *array, int arrayLength){
}
Please help.
Note that I could not really think of a solution to the problem. The interviewer hinted at using 2^n for the puspose, but i could not really think of the solution.
How about this:
int* reverse(int *array, int arrayLength){
if (arrayLength==1) {
int* out=(int*)malloc(sizeof(int));
out[0] = array[0];
return out;
}
int* left = reverse(array+arrayLength/2, arrayLength-arrayLength/2);
int* right = reverse(array,arrayLength/2);
int* out = (int*)realloc(left, sizeof(int)*arrayLength);
memcpy(out+arrayLength/2, right, sizeof(int)*(arrayLength/2));
free(right);
return out;
}
Agree with OP the the hint is "2^n". As with many recursive functions: divide and conquer.
This routine first deals with errant paramters and the simple lengths. Next, divide the length in half and reverse each half. Form the result by concatenating the reversed left and right sub-arrays. First, right, then left.
Usual clean-up follows
#include <string.h>
#include <stdlib.h>
int* reverse(int *array, int arrayLength) {
// Check parameters
if (array == NULL || arrayLength < 0) {
; // TBD HandleBadParameters();
}
// Allocate space for result, not much to do if length <= 1
int *y = malloc(arrayLength * sizeof *y);
if (y == NULL) {
; // TBD HandleOOM();
}
if (arrayLength <= 1) {
memcpy(y, array, arrayLength * sizeof *y);
return y;
}
// Find reverse of the two halves
int halflength = arrayLength / 2;
int *left = reverse(array, halflength);
int *right = reverse(&array[halflength], halflength);
// Append them to the result - in reverse order
memcpy(y, right, halflength * sizeof *y);
memcpy(&y[halflength], left, halflength * sizeof *y);
// Clean-up and return
free(right);
free(left);
return y;
}
int* reverse(int *array, int arrayLength){
if(arrayLength == 0) return array;
int* ret = (int*)malloc(arrayLength*sizeof(int));
for(int i=0;i<arrayLength;i++) ret[i] = array[arrayLength-1-i];
return reverse(ret, 0); // technically recursive
}
Here it is (and works):
int *reverse(int *array, int arrayLength)
{
if (arrayLength > 1) {
int i, n = arrayLength >> 1;
int *m = calloc(n, sizeof(int));
memcpy(m, array, n*sizeof(int));
memcpy(array, array + n, n*sizeof(int));
memcpy(array + n, m, n*sizeof(int));
free(m);
reverse(array, n);
reverse(array+n, n);
} /* for */
return array;
} /* reverse */
it can be done without temporary storage, but you have to iterate a little.
int *reverse(int *a, int al)
{
if (al > 1) {
int i, a1 = al >> 1;
for (i = 0; i < a1; i++) {
int temp = a[i];
a[i] = a[i + a1];
a[i + a1] = temp;
} /* for */
reverse(a, a1);
reverse(a+a1, a1);
} /* for */
return a;
} /* reverse */
but, it would be nicer just to exchange from the boundaries to the middle and do it completely iterative.
int *reverse(int *array, int arrayLength)
{
int a, b;
for (a = 0, b = arrayLength-1; a < b; a++, b--) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
} /* for */
return array;
} /* reverse */
And just for the ones who asked for a non selfmodifying array, this all-inefficient form:
int *reverse(int *array, int arrayLength)
{
int *a1, *a2;
int *res;
if (arrayLength > 1) {
int l = arrayLength >> 1;
a1 = reverse(array, l);
a2 = reverse(array + l, l);
res = calloc(arrayLength, sizeof(int));
memcpy(res, a2, l*sizeof(int));
memcpy(res+l, a1, l*sizeof(int));
free(a1);
free(a2);
} else {
/* we return always memory alloc'd with malloc() so we have to do this. */
res = malloc(sizeof(int));
*res = array[0];
} /* if */
return res;
} /* reverse */
Well, here's one sneaky way, and it doesn't care what length the array is. Note: I'm assuming you can't introduce a new function, it has to be done all within the existing function
if the length is postive, it allocates memory and makes a copy, then calls reverse again with a negative length and the copy, then if the function is called with a negative length, it reverses the first and last inplace, then recursively calls by moving to the next in the array and shrinks the length till there is nothing left to reverse and then the recursive function unwinds
int* reverse(int *array, int arrayLength){
int* result;
if(arrayLength > 0)
{
result =(int*) malloc((sizeof(int)*arrayLength));
memcpy(result, array, sizeof(int)*arrayLength);
reverse(result, -arrayLength);
return result;
}
else if(arrayLength < -1)
{
int end = (-arrayLength)-1;
int temp = array[end];
array[end] = array[0];
array[0] = temp;
return reverse(array+1, arrayLength+2);
}
return array;
}
Considering that arrayLength is always a power of 2. we will apply the function to the two parts of the array then concat them in the reverse way.
Finaly if the array has only one element, we simply return other array with the same element.
int* reverse(int *array, int arrayLength){
int * newArray = NULL;
if(arrayLength == 1){
newArray = (int *)malloc(sizeof(int));
*newArray = array[0];
} else if(arrayLength == 2){
newArray = (int *)malloc(2 * sizeof(int));
newArray[0] = array[1];
newArray[1] = array[0];
} else {
// apply to first half
int * first = reverse(array, arrayLength / 2);
// apply to second half
int * second = reverse(array + arrayLength / 2, arrayLength / 2);
// allocate space
newArray = (int *) malloc(arrayLength * sizeof(int));
// copy parts in reverse way
memcpy(newArray, second, arrayLength / 2 * sizeof(int));
memcpy(newArray + arrayLength / 2, first, arrayLength / 2 * sizeof(int));
// free allocated space for parts
free(first);
free(second);
}
return newArray;
}
I'll give it a shot.
Knowing that the array is of length 2^n means that it can be safely halved. We call the function recursively on each half until length is 2. At this point we swap the two integers. Think { 2,1,4,3,6,5,8,7 }. When we come back from that, each half is then merged opposite of where it came from ( { 4,3,2,1,8,7,6,5} ). Rinse and repeat.
#include <stdio.h>
#include <stdlib.h>
int * reverse( int* arr, int length )
{
if ( length == 1 )
{
int *result = malloc( sizeof( arr[0] ) );
result[0] = arr[0];
return result;
}
int * result = 0;
if ( length == 2 )
{
result = malloc( sizeof( arr[0] ) * 2 );
result[0] = arr[1];
result[1] = arr[0];
}
else
{
int half_length = length / 2;
// named correctly
int * right = reverse( arr, half_length );
int * left = reverse( arr + half_length, half_length );
result = malloc( sizeof( arr[0] ) * length );
for ( int i = 0; i < half_length; ++i )
{
result[i] = left[i];
result[ i + half_length ] = right[i];
}
free( right );
free( left );
}
return result;
}
int main( void )
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int length = 8;
int *reversed = reverse( arr, length );
for ( int i = 0; i < length; ++i )
{
printf( "%d %d\n", arr[i], reversed[i] );
}
free( reversed );
return 0;
}
for all integer arrays with more than 2 elements.
The basic idea is to swap elements from both ends untill the number of elements remaining is 1.
int* reverse_array(int* array, int arrayLength)
{
if(arrayLength <2)
{
return NULL;
}
else
{
int *array1 = NULL;
int *array2 = NULL;
array1 = malloc(arrayLength*sizeof(int));
memcpy(array1,array,arrayLength*sizeof(int));
/*swap the start and end*/
swap(array1,(array1+arrayLength-1));
/* swap the next pair */
array2 = reverse_array(array1+1,arrayLength-2);
memcpy(array1+1,array2,(arrayLength-2)*sizeof(int));
if(array2!= NULL)
{
free(array2);
}
return array1;
}
}
I have an array let's say A[5], the 5 elements are 5,4,1,2,3. Now I sort these arrays in ascending order. so the resulting array will now be 1,2,3,4,5. I use qsort() function of stdlib.h to sort this. The question is how can I get the indices of the original array with respect to my new array. originally my indices were 0,1,2,3,4 for corresponding values of 5,4,1,2,3 and now the indices have changed to 2,3,4,1,0. How can I get these indices efficiently in C? Thank you in advance(please write the code if possible)
There is also a method as follows under limited conditions.
#include <stdio.h>
int main(void){
int data[] ={ 5,4,1,2,3 }; //Without duplication, The number of limited range.
int size = sizeof(data)/sizeof(*data);
int keys[size];
int i;
printf("data :\n");
for(i=0;i<size;i++){
printf("%d ",data[i]);
}
for(i=0;i<size;i++){
keys[data[i]-1]=i;
}
printf("\n\ndata\tindex\n");
for(i=0;i<size;i++){
printf("%d\t%d\n", data[keys[i]], keys[i]);
}
return 0;
}
/* result sample
data :
5 4 1 2 3
data index
1 2
2 3
3 4
4 1
5 0
*/
How to sort an array of index #Kerrek is as proposed.
#include <stdio.h>
#include <stdlib.h>
int *array;
int cmp(const void *a, const void *b){
int ia = *(int *)a;
int ib = *(int *)b;
return array[ia] < array[ib] ? -1 : array[ia] > array[ib];
}
int main(void){
int data[] ={ 5,4,1,2,3 };
int size = sizeof(data)/sizeof(*data);
int index[size];//use malloc to large size array
int i;
for(i=0;i<size;i++){
index[i] = i;
}
array = data;
qsort(index, size, sizeof(*index), cmp);
printf("\n\ndata\tindex\n");
for(i=0;i<size;i++){
printf("%d\t%d\n", data[index[i]], index[i]);
}
return 0;
}
Take a 2D array. Store the numbers is first column and then corressponding indexes in second column. You can write your comparator function as:
int compare ( const void *pa, const void *pb )
{
const int *a = pa;
const int *b = pb;
if(a[0] == b[0])
return a[1] - b[1];
else
return a[0] - b[0];
}
Call to qsort should be:
qsort(array, n, sizeof array[0], compare); // n is representing rows
See the Live Demo
Based on Kerrek SB's brilliant idea I made an implementation that works for any array type by providing its element size and a comparator function for that type.
_Thread_local uint8_t *array_to_order;
_Thread_local size_t elem_size_to_order;
_Thread_local int (*cmp_for_ordering)(const void *, const void *);
int cmp_array_entry(const size_t *a, const size_t *b)
{
return cmp_for_ordering(&array_to_order[*a * elem_size_to_order], &array_to_order[*b * elem_size_to_order]);
}
size_t *make_order_index_array(void *array, size_t *order, size_t elem_count, size_t elem_size, int (*cmp)(const void *, const void *))
{
// If order is provided by the caller it should have suitable contents, such as when updating an order
// Initialise the order array if not already provided
if (order == NULL)
{
order = calloc(elem_count, sizeof(size_t));
// Initialise the order array to the unsorted indices
for (size_t i=0; i < elem_count; i++)
order[i] = i;
}
// Globals used by the comparison function to order the array
array_to_order = array;
elem_size_to_order = elem_size;
cmp_for_ordering = cmp;
// Order the order array
qsort(order, elem_count, sizeof(size_t), cmp_array_entry);
return order;
}
_Thread_local is something that we should be able to take for granted for writing such code when we're forced to use globals but should worry about thread safety. Mine is defined with the following macros:
#if defined(_MSC_VER) && !defined(_Thread_local)
#define _Thread_local __declspec(thread)
#endif
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define _Thread_local __thread
#endif
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && (((__GNUC__ << 8) | __GNUC_MINOR__) < ((4 << 8) | 9))
#define _Thread_local __thread
#endif
#include <limits.h>
#include <stdio.h>
#define SIZE 5
int* sortArrayNKeepIndices(int arr[], int arrSize){
static int indexArr[SIZE];
int arr2[arrSize];
for (int i = 0; i < arrSize; i++) {
indexArr[i] = 0;
arr2[i] = arr[i];
}
int min = 0, temp = 0;
for (int i = 0; i < arrSize ; i++)
{
min = i; // record the position of the smallest
for (int j = i + 1; j < arrSize; j++)
{
// update min when finding a smaller element
if (arr[j] < arr[min])
min = j;
}
// put the smallest element at position i
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
} // array sorting ends here
int ctr = 0;
while ( ctr < arrSize) {
min = 0; // restart from first element
for (int j = 0; j < arrSize; j++)
{
if (arr2[j] == INT_MAX) continue; // ignore already marked as minimum indices
// update min when finding a smaller element
if (arr2[j] < arr2[min])
min = j;
}
indexArr[ctr] = min; // updating indexArr with the index of the next minimum
arr2[min] = INT_MAX; // marking minimum element to be ignored next time
ctr++;
} //keeping track of previous indices of the array elements ends here
return indexArr;
} // function sortArrayKeepIndices ends here
int main () {
int arr[SIZE] = {16, 15, 12, 10, 13};
int* ptr = sortArrayNKeepIndices(arr, SIZE);
for (int dex = 0; dex < SIZE; dex++){
printf("%d (%d, %d)\t", arr[dex], * (ptr + dex), dex);}
}
// output will be 10 (3, 0) 12 (2, 1) 13 (4, 2) 15 (1, 3) 16 (0, 4)
// element (old index, new index)
How can I include the elements of array X and Y in to array total in C language ?
can you please show with an example.
X = (float*) malloc(4);
Y = (float*) malloc(4);
total = (float*) malloc(8);
for (i = 0; i < 4; i++)
{
h_x[i] = 1;
h_y[i] = 2;
}
//How can I make 'total' have both the arrays x and y
//for example I would like the following to print out
// 1, 1, 1, 1, 2, 2, 2, 2
for (i = 0; i < 8; i++)
printf("%.1f, ", total[i]);
Your existing code is allocating the wrong amount of memory because it doesn't take sizeof(float) into account at all.
Other than that, you can append one array to the other with memcpy:
float x[4] = { 1, 1, 1, 1 };
float y[4] = { 2, 2, 2, 2 };
float* total = malloc(8 * sizeof(float)); // array to hold the result
memcpy(total, x, 4 * sizeof(float)); // copy 4 floats from x to total[0]...total[3]
memcpy(total + 4, y, 4 * sizeof(float)); // copy 4 floats from y to total[4]...total[7]
for (i = 0; i < 4; i++)
{
total[i] =h_x[i] = 1;
total[i+4]=h_y[i] = 2;
}
A way to concatenate two C arrays when you know their size.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define ARRAY_CONCAT(TYPE, A, An, B, Bn) \
(TYPE *)array_concat((const void *)(A), (An), (const void *)(B), (Bn), sizeof(TYPE));
void *array_concat(const void *a, size_t an,
const void *b, size_t bn, size_t s)
{
char *p = malloc(s * (an + bn));
memcpy(p, a, an*s);
memcpy(p + an*s, b, bn*s);
return p;
}
// testing
const int a[] = { 1, 1, 1, 1 };
const int b[] = { 2, 2, 2, 2 };
int main(void)
{
unsigned int i;
int *total = ARRAY_CONCAT(int, a, 4, b, 4);
for(i = 0; i < 8; i++)
printf("%d\n", total[i]);
free(total);
return EXIT_SUCCCESS;
}
I thought I'd add this because I've found it necessary in the past to append values to a C array (like NSMutableArray in Objective-C). This code manages a C float array and appends values to it:
static float *arr;
static int length;
void appendFloat(float);
int main(int argc, const char * argv[]) {
float val = 0.1f;
appendFloat(val);
return 0;
}
void appendFloat(float val) {
/*
* How to manage a mutable C float array
*/
// Create temp array
float *temp = malloc(sizeof(float) * length + 1);
if (length > 0 && arr != NULL) {
// Copy value of arr into temp if arr has values
memccpy(temp, arr, length, sizeof(float));
// Free origional arr
free(arr);
}
// Length += 1
length++;
// Append the value
temp[length] = val;
// Set value of temp to arr
arr = temp;
}
may be this is simple.
#include <stdio.h>
int main()
{
int i,j,k,n,m,total,a[30],b[30],c[60];
//getting array a
printf("enter size of array A:");
scanf("%d",&n);
printf("enter %d elements \n",n);
for(i=0;i<n;++i)
{scanf("%d",&a[i]);}
//getting aaray b
printf("enter size of array b:");
scanf("%d",&m);
printf("enter %d elements \n",m);
for(j=0;j<m;++j)
{scanf("%d",&b[j]);}
total=m+n;
i=0,j=0;
//concating starts
for(i=0;i<n;++i)
{
c[i]=a[i];
}
for(j=0;j<m;++j,++n)
{
c[n]=b[j];
}
printf("printing c\n");
for(k=0;k<total;++k)
{printf("%d\n",c[k]);}
}
Here a solution to concatenate two or more statically-allocated arrays. Statically-allocated arrays are array whose length is defined at compile time. The sizeof operator returns the size (in bytes) of these arrays:
char Static[16]; // A statically allocated array
int n = sizeof(Static_array); // n1 == 16
We can use the operator sizeof to build a set of macros that will concatenate two or more arrays, and possibly returns the total array length.
Our macros:
#include <string.h>
#define cat(z, a) *((uint8_t *)memcpy(&(z), &(a), sizeof(a)) + sizeof(a))
#define cat1(z, a) cat((z),(a))
#define cat2(z, a, b) cat1(cat((z),(a)),b)
#define cat3(z, a, b...) cat2(cat((z),(a)),b)
#define cat4(z, a, b...) cat3(cat((z),(a)),b)
#define cat5(z, a, b...) cat4(cat((z),(a)),b)
// ... add more as necessary
#define catn(n, z, a ...) (&cat ## n((z), a) - (uint8_t *)&(z)) // Returns total length
An example of use:
char One[1] = { 0x11 };
char Two[2] = { 0x22, 0x22 };
char Three[3] = { 0x33, 0x33, 0x33 };
char Four[4] = { 0x44, 0x44, 0x44, 0x44 };
char All[10];
unsigned nAll = catn(4, All, One, Two, Three, Four);
However, thanks to the way we defined our macros, we can concatenate any type of objects as long as sizeof returns their size. For instance:
char One = 0x11; // A byte
char Two[2] = { 0x22, 0x22 }; // An array of two byte
char Three[] = "33"; // A string ! 3rd byte = '\x00'
struct {
char a[2];
short b;
} Four = { .a = { 0x44, 0x44}, .b = 0x4444 }; // A structure
void * Eight = &One; // A 64-bit pointer
char All[18];
unsigned nAll = catn(5, All, One, Two, Three, Four, Eight);
Using constant literals, one can also these macros to concatenate constants, results from functions, or even constant arrays:
// Here we concatenate a constant, a function result, and a constant array
cat2(All,(char){0x11},(unsigned){some_fct()},((uint8_t[4]){1,2,3,4}));
i like the answer from jon. In my case i had to use a static solution.
So if you are forced to not use dynamic memory allocation:
int arr1[5] = {11,2,33,45,5};
int arr2[3] = {16,73,80};
int final_arr[8];
memcpy(final_arr, arr1, 5 * sizeof(int));
memcpy(&final_arr[5], arr2, 3 * sizeof(int));
for(int i=0; i<(sizeof(final_arr)/sizeof(final_arr[0]));i++){
printf("final_arr: %i\n", final_arr[i]);
}
Why not use simple logic like this?
#include<stdio.h>
#define N 5
#define M (N * 2)
int main()
{
int a[N], b[N], c[M], i, index = 0;
printf("Enter %d integer numbers, for first array\n", N);
for(i = 0; i < N; i++)
scanf("%d", &a[i]);
printf("Enter %d integer numbers, for second array\n", N);
for(i = 0; i < N; i++)
scanf("%d", &b[i]);
printf("\nMerging a[%d] and b[%d] to form c[%d] ..\n", N, N, M);
for(i = 0; i < N; i++)
c[index++] = a[i];
for(i = 0; i < N; i++)
c[index++] = b[i];
printf("\nElements of c[%d] is ..\n", M);
for(i = 0; i < M; i++)
printf("%d\n", c[i]);
return 0;
}
Resultant array size must be equal to the size of array a and b.
Source: C Program To Concatenate Two Arrays