Sort 2 arrays in C by a joint logic - c

Given two arrays
a = [1,3,2,8,5,6]
b = [4,3,2,5,1,2]
I would like to sort them in "one pass" where the "logic" involves the two arrays, meaning:
if
int sortBySum(index i, index j){
if (a[i]+b[i] > a[j]+b[j]){
return 1;
}
return -1;
}
The output of the two arrays will be
a = [2,1,3,5,6,8]
b = [2,4,3,1,2,5]
Because the original arrays sum is a+b=[5,6,4,13,6,8]

When a task is about sorting, qsort is - in most cases - your friend.
But qsort can only sort one array. So you need to copy the elements from array a and b into an array of structs containing the data from a and b. Then use qsort and then copy the data back.
Like:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
} common_data;
// Compare function for qsort
int cmp(const void *p1, const void *p2)
{
common_data* pa = (common_data*)p1;
common_data* pb = (common_data*)p2;
return ((pa->a + pa->b) - (pb->a + pb->b));
}
int main(void)
{
int a[] = {1,3,2,8,5,6};
int b[] = {4,3,2,5,1,2};
size_t sz = sizeof(a)/sizeof(a[0]);
common_data carr[sz];
// Copy to common array
for (size_t i = 0; i < sz; ++i)
{
carr[i].a = a[i];
carr[i].b = b[i];
}
// Sort common array
qsort(carr, sz, sizeof(carr[0]), cmp);
// Copy to back to original array
for (size_t i = 0; i < sz; ++i)
{
a[i] = carr[i].a;
b[i] = carr[i].b;
}
// Print array a
for (size_t i = 0; i < sz; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
// Print array b
for (size_t i = 0; i < sz; ++i)
{
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
Output:
2 1 3 5 6 8
2 4 3 1 2 5

A primitive approach can look the following way.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a[] = { 1, 3, 2, 8, 5, 6 };
int b[] = { 4, 3, 2, 5, 1, 2 };
const size_t N = sizeof( a ) / sizeof( *a );
printf( "a: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
printf( "b: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", b[i] );
}
putchar( '\n' );
putchar( '\n' );
for ( size_t n = N, last; !( n < 2 ); n = last )
{
for ( size_t i = last = 1; i < n; i++ )
{
if ( a[i] + b[i] < a[i-1] + b[i-1] )
{
int tmp = a[i];
a[i] = a[i-1];
a[i-1] = tmp;
tmp = b[i];
b[i] = b[i-1];
b[i-1] = tmp;
last = i;
}
}
}
printf( "a: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
printf( "b: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", b[i] );
}
putchar( '\n' );
putchar( '\n' );
return 0;
}
The program output is
a: 1 3 2 8 5 6
b: 4 3 2 5 1 2
a: 2 1 3 5 6 8
b: 2 4 3 1 2 5
The code that sorts the arrays using the method bubble sort can be moved in a separate function.

Related

I want to insert in a vector multiple values in a location

When I create a vector , let's say size of 5 , elements are 1,2,3,4,5 and I want to add at the location( for example index 2) the numbers 200 and 300 , the vector should look like 1 ,2 ,200,300,3,4,5.
#include <stdio.h>
#include <stdlib.h>
int main(){
int v[] ={1,2,3,4,5,6,7};
int n = sizeof(v)/sizeof(int);
int location,element;
printf("Enter location:");
scanf("%d",&location);
printf("Enter element:");
scanf("%d",&element);
for(int i = n - 1; i >= location;i--){
v[i + 1] = v[i];
}
v[location] = element;
for(int i = 0; i <= n;i++){
printf("%d ",v[i]);
}
}
You need to loop like this
for(;;){
int location,element;
printf("Enter location:");
scanf("%d",&location);
if(location == -1)
break;
printf("Enter element:");
scanf("%d",&element);
for(int i = n - 1; i >= location;i--){
v[i + 1] = v[i];
}
v[location] = element;
}
BUT you code is severely broken, you are adding to a vector thats of fixed size. you cannot do that
In this code
for (int i = n - 1; i >= location; i--) {
v[i + 1] = v[i];
}
n is the count of number of elements, so on the first loop you do
v[n] = v[n-1]
ie
v[7] = v[6]
well v[7] is off the end of the array (array indexes are 0 to 6) Thats very bad
You declared a fixed size array
int v[] ={1,2,3,4,5,6,7};
You can not enlarge it.
Thus this loop
for(int i = 0; i <= n;i++){
printf("%d ",v[i]);
}
invokes undefined behavior due to using the index with the value n that is outside the valid range of indices [0, n) for the source array.
You need to allocate the array dynamically and when you are going to add one more element you will need to reallocate the array.
Here is a demonstration program.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main( void )
{
size_t n = 7;
int *v = malloc( n * sizeof( int ) );
memcpy( v, ( int [7] ){ 1, 2, 3, 4, 5, 6, 7 }, n * sizeof( int ) );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", v[i] );
}
putchar( '\n' );
size_t location = 0;
printf( "Enter location: " );
scanf( "%zu", &location );
if ( n < location ) location = n;
int element = 0;
printf( "Enter element: " );
scanf( "%d",&element );
int *tmp = realloc( v, ( n + 1 ) * sizeof( int ) );
if ( tmp != NULL )
{
v = tmp;
memmove( v + location + 1, v + location, ( n - location ) * sizeof( int ) );
v[location] = element;
++n;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", v[i] );
}
putchar( '\n' );
free( v );
}
The program output might look like
1 2 3 4 5 6 7
Enter location: 2
Enter element: 200
1 2 200 3 4 5 6 7

Copying an unsorted C array into another while avoiding duplicates

Hello everyone and thanks for your time.
For exercise, I wanted to write a program which copies all elements from an array to another array but without the duplicates. The only condition is that I cannot change the original array - so no sorting.
I tried making a function which checks if the current element of array1 is found in the array we copy to (array2). If no, we then copy the element to the second array and increase the size by one.
However, it does not work:
If I have
int array1[15] = {3,2,4,7,9,1,4,6,7,0,1,2,3,4,5};
int array2[15];
array2 should contain the following numbers: 3,2,4,7,9,1,6,0,5
But my output is as follows: 3,2,4,7,9,1,6
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int already_exists(int array2[], int size_arr2, int element)
{
int i;
for(i=0; i<size_arr2; i++)
{
if(array2[i] == element)
return 1;
}
return 0;
}
int main()
{
int array1[15] = {3,2,4,7,9,1,4,6,7,0,1,2,3,4,5};
int array2[15];
int i;
int size_arr2=0;
for(i=0; i<9; i++)
{
int element = array1[i];
if(already_exists(array2, size_arr2, element) == 1)
continue;
else
{
array2[size_arr2] = element;
size_arr2++;
}
}
for(i=0; i<size_arr2; i++)
{
printf("%d, ", array2[i]);
}
return 0;
}
You have a typo in the for loop
for(i=0; i<9; i++)
The array array1 contains 15 elements. So the loop should look like
for ( i = 0; i < 15; i++ )
The reason of the error is that you are using "magic numbers" instead of named constants.
Nevertheless the program in whole is inefficient because the function already_exists is called for each element of the array array1. At least you could declare it as an inline function.
Moreover it should be declared like
int already_exists( const int array2[], size_t size_arr2, int element );
Instead of this function it is better to write a function that performs the full operation.
Here is a demonstrative program.
#include <stdio.h>
size_t copy_unique( const int a1[], size_t n1, int a2[] )
{
size_t n2 = 0;
for ( size_t i = 0; i < n1; i++ )
{
size_t j = 0;
while ( j < n2 && a2[j] != a1[i] ) j++;
if ( j == n2 ) a2[n2++] = a1[i];
}
return n2;
}
int main(void)
{
enum { N = 15 };
int array1[N] = { 3, 2, 4, 7, 9, 1, 4, 6, 7, 0, 1, 2, 3, 4, 5 };
int array2[N];
for ( size_t i = 0; i < N; i++ ) printf( "%d ", array1[i] );
putchar( '\n' );
size_t n2 = copy_unique( array1, N, array2 );
for ( size_t i = 0; i < n2; i++ ) printf( "%d ", array2[i] );
putchar( '\n' );
return 0;
}
Its output is
3 2 4 7 9 1 4 6 7 0 1 2 3 4 5
3 2 4 7 9 1 6 0 5

Sorting array only with while and if

I get a message when I try to run the program. Why?
Segmentation fault
my code:
#include <stdio.h>
void sort_array(int *arr, int s);
int main() {
int arrx[] = { 6, 3, 6, 8, 4, 2, 5, 7 };
sort_array(arrx, 8);
for (int r = 0; r < 8; r++) {
printf("index[%d] = %d\n", r, arrx[r]);
}
return(0);
}
sort_array(int *arr, int s) {
int i, x, temp_x, temp;
x = 0;
i = s-1;
while (x < s) {
temp_x = x;
while (i >= 0) {
if (arr[x] > arr[i]) {
temp = arr[x];
arr[x] = arr[i];
arr[i] = temp;
x++;
}
i++;
}
x = temp_x + 1;
i = x;
}
}
I think that the problem is in the if statement.
What do you think? Why does it happen? I think that I use in positive way with the pointer to the array.
Thank you!
This loop in your program
while (i >= 0) {
//...
i++;
}
does not make sense because i is increased unconditionly.
The program can look the following way
#include <stdio.h>
void bubble_sort( int a[], size_t n )
{
while ( !( n < 2 ) )
{
size_t i = 0, last = 1;
while ( ++i < n )
{
if ( a[i] < a[i-1] )
{
int tmp = a[i];
a[i] = a[i-1];
a[i-1] = tmp;
last = i;
}
}
n = last;
}
}
int main( void )
{
int a[] = { 6, 3, 6, 8, 4, 2, 5, 7 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
bubble_sort( a, N );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
return 0;
}
The program output is
6 3 6 8 4 2 5 7
2 3 4 5 6 6 7 8
If you want that the sorting function had only one while loop then you can implement it the following way
void bubble_sort( int a[], size_t n )
{
size_t i = 0;
while ( ++i < n )
{
if ( a[i] < a[i-1] )
{
int tmp = a[i];
a[i] = a[i-1];
a[i-1] = tmp;
i = 0;
}
}
}
In your inner loop, you increment i beyond the size of the array. Your algorithm should require you to decrement i instead, but I am not sure this would be enough to fix the sorting algorithm.
You should first try to implement Bubble sort with a single while loop where you compare adjacent items and step back whenever you swap them.

How to remove neighbouring duplicate in array using recursion?

I have made the following function that will remove the neighboring duplicate. How to implement it using recursion??
example 1,1,5,4,7,7,9,9,8 will result to 1, 5, 4, 7, 9, 8
void remove() {
int arr[9]={1,1,5,4,7,7,9,9,8};
int newarr[9];
int counter=0;
for(int i = 0; i < 9; i++) {
if(arr[i] == arr[i + 1]) {
newarr[counter] = arr[i];
i += 1;
counter++;
} else {
newarr[counter] = arr[i];
counter++;
}
}
for(int z = 0; z < counter; z++){
printf("%d ", newarr[z]);
}
}
First of all your program has undefined behaviour because it tries to access memory beyond the array in the loop when i is equal to 8.
for(int i = 0; i < 9; i++) {
if(arr[i] == arr[i + 1]) {
^^^^^^
The element with index equal to 9 (arr[8 + 1]) does not exist.
Moreover the logic is wrong. You are incrementing i twice when arr[i] is equal to arr[i+1]
for(int i = 0; i < 9; i++) {
^^^^
if(arr[i] == arr[i + 1]) {
newarr[counter] = arr[i];
i += 1;
^^^^^^
counter++;
} else {
but the next element with index arr[i+2] also can be equal to arr[i]. So the same value will be written at least twice in the destination array.
Try for example to apply your program to an array like this
int arr[] = { 1, 1, 1, 1, 1, 1 };
So you need to rewrite your program entirely.:)
As for the recursive function then it can look the following way
#include <stdio.h>
int * unique( const int *a, size_t n, int *b )
{
if ( n == 0 ) return b;
if ( n == 1 || a[0] != a[1] ) *b++ = *a;
return unique( a + 1, n - 1, b );
}
int main( void )
{
int a[] = { 1, 1, 5, 4, 7, 7, 9, 9, 8 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
int b[N];
int *last = unique( a, N, b );
for ( int *first = b; first != last; ++first ) printf( "%d ", *first );
printf( "\n" );
}
Its output is
1 1 5 4 7 7 9 9 8
1 5 4 7 9 8
If you compiler does not support the C99 STandard then the program can look like
#include <stdio.h>
int * unique( const int *a, size_t n, int *b )
{
if ( n == 0 ) return b;
if ( n == 1 || a[0] != a[1] ) *b++ = *a;
return unique( a + 1, n - 1, b );
}
#define N 9
int main( void )
{
int a[N] = { 1, 1, 5, 4, 7, 7, 9, 9, 8 };
int b[N];
size_t i;
int *first, *last;
for ( i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
last = unique( a, N, b );
for ( first = b; first != last; ++first ) printf( "%d ", *first );
printf( "\n" );
}

Finding minimum difference between a pair of integers

Given the set of unsorted integers, how to find every pair of integers which have minimum difference. There are 3 samples as described below:
a = random.sample (range(-200,200), 5)
b = random.sample (range(-1000, 1000), 25)
c = random.sample (range(-2000, 2000), 50)
The expected output should be something like:
List A = [-85, -154, -33, 192, -160]
Minimum pairs for list A:
(-160, -154)
Catch! :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Pair
{
size_t first;
size_t second;
};
struct Pair minimum_difference( const int a[], size_t n )
{
struct Pair p = { 0 };
if ( 1 < n )
{
p.first = 0;
p.second = 1;
for ( size_t i = 0; i < n - 1; i++ )
{
for ( size_t j = i + 1; j < n; j++ )
{
// printf( "%d %d %llu\n", a[i], a[j],
// ( unsigned long long )abs( a[i] - a[j] ) );
if ( ( unsigned long long )abs( a[i] - a[j] ) <
( unsigned long long )abs( a[p.first] - a[p.second] ) )
{
p.first = i;
p.second = j;
}
}
}
}
return p;
}
int main(void)
{
const size_t N = 5;
const int UPPER_BOUND = 40 * N;
int a[N];
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
a[i] = rand() % ( 2 * UPPER_BOUND ) - UPPER_BOUND;
}
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
struct Pair p = minimum_difference( a, N );
printf( "(%d, %d)\n", a[p.first], a[p.second] );
return 0;
}
The program output might look loke
119 9 -193 21 -43
(9, 21)
This prpgram finds only the first pair with the minimum difference. If there are several pairs with the minimum difference when you have to allocate dynamically an array of pairs. Of course the function will be changed.
The other approach is to use a sort-copy algorithm by using an additional array. And then traverse this array calculating the difference.

Resources