How to "combine" two int arrays? - c

Hello i have a little problem trying to "mix" two string arrays, i have searched about it but i have only found how to merge them or concatenate them, but thats not what i need.
i have two int arrays like this:
int no_items = 5;
int parent1[no_items], parent2[no_items];
if the arrays contains for example:
parent1[0] = 1;
parent1[1] = 2;
parent1[2] = 3;
parent1[3] = 4;
parent1[4] = 5;
and:
parent2[0] = 5;
parent2[1] = 1;
parent2[2] = 2;
parent2[3] = 3;
parent2[4] = 4;
given a "cross" point, for example 2:
parent1 should have his 2 first elements and the rest of parent2, and parent2 should have his first 2 elements and the rest of parent1. So the result should be:
parent1: 1,2 | 5,3,4
parent2: 5,1 | 2,3,4
where "|" is the break point index and the rest of elements should not be repeated.
How can i get this kind of mixing two int arrays? Thanks you!
at the moment i have this:
for(i = 0; i < cross_point; i++)
{
sprintf(buffer, "%d,", parent1[i]);
strcat(line1, buffer);
}
for(i = 0; i < cross_point; i++)
{
sprintf(buffer, "%d,", parent2[i]);
strcat(line2, buffer);
}
but i donĀ“t know how to go further than the cross point.

int *find(int *begin, int *end, int value)
{
int *p = begin;
for ( ; p != end; ++p)
if (*p == value) break;
return p;
}
int i, j;
int output1[no_items] = {0};
int output2[no_items] = {0};
int crosspoint = 3;
memcpy(output1, parent1, crosspoint * sizeof(int));
for (i = crosspoint, j = 0; i < no_items; ++i)
{
while (find(output1, output1+i, parent2[j]) != output1+i) ++j;
output1[i] = parent2[j];
}
memcpy(output2, parent2, crosspoint * sizeof(int));
for (i = crosspoint, j = 0; i < no_items; ++i)
{
while (find(output2, output2+i, parent1[j]) != output2+i) ++j;
output2[i] = parent1[j];
}
memcpy(parent1, output1, sizeof(parent1));
memcpy(parent2, output2, sizeof(parent2));
Demo: http://ideone.com/xUt6nQ

something like this should do it if you aren't concerned about creating temporaries:
int no_items = 5;
int output1[no_items];
int output2[no_items];
for (int i = 0; i < no_items; i++){
if(i < crosspoint){
output1[i] = parent1[i];
output2[i] = parent2[i];
}else{
output1[i] = parent2[i];
output2[i] = parent1[i];
}
}
If you are concerned about temporaries you need to swap the values, the logic should be fairly similar to above.
int no_items = 5;
int temp = 0;
for (int i = 0; i < no_items; i++){
if(i < crosspoint){
/* don't need to do anything here */
}else{
temp = parent1[i];
parent1[i] = parent2[i];
parent2[i] = temp;
}
}

Related

Problem with changing numbers in an array in C

First I generate some random numbers and then i need to exchange them like I discribte in the following lines.
I tryed it iut with the for loobs.
I have to exchange the numbers of the array
Change number 1 and 2, 3 and 4,.....29 and 30
Change number 1 and 3, 4 and 7,.....27 and 30
Thank you for your Help
srand(time(NULL));
for ( i = 0; i < SIZE; i++ )
{
mainArray[i] = rand() % ( UPPERBOUND - LOWERBOUND + 1 ) + LOWERBOUND;
}
for ( i = 0; i < SIZE; i++)
{
if ( countDigitChange == 2 )
{
digitChanger1 = workArray2[i];
i++;
digitChanger2 = workArray2[i];
workArray2[i] = digitChanger1;
i--;
workArray2[i] = digitChanger2;
countDigitChange = 0;
}
countDigitChange++;
}
for ( i = 0; i < SIZE; i++)
{
if ( countDigitChange % 3 == 0 )
{
digitChanger1 = workArray3[i];
i += 2;
digitChanger2 = workArray3[i];
workArray3[i] = digitChanger1;
i += 2;
workArray3[i] = digitChanger2;
countDigitChange = 0;
}
countDigitChange++;
}
This seems much simpler:
Declare a helper function:
void swap_int(int* x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
Then in your code that needs to shuffle the array:
int i, j; // declare this up top with all your other variable declarations
// for each pair of elements swap them
for (i=0, j=1; j < SIZE; i+=2, j+=2)
{
swap_int(&mainArray[i], &mainArray[j]);
}
// swap array[0] with array[2], then swap array[3] with array[5], etc...
for (i=0, j=2; j < SIZE; i+=3, j+=3)
{
swap_int(&mainArray[i], &mainArray[j]);
}

How can I create a generic function to sort an array of structures?

I'm working on this program for my University exam. I need to sort passenger array with a sorting algorithm (I choose bubblesort due to it's simplicity).
I need to create a generic function and pass as formal parameters:
-a list of objects i want to sort;
-a sort criterion.
So I think that I'll have to create only 1 Increasing sorting function and 1 decreasing sorting function and pass them the parameters to sort by.
I already tried to pass char *file_name to function, but I think that I'm wrong.
int passengersIncreasingBubbleSort_Birthyear(passengers test[], int x) {
int i = 0, j = 0, min_idx, flag = 0;
passengers temp;
for (i = 0; i < x; i++) {
min_idx = i;
for (j = i + 1; j < x; j++) {
if (test[j].birth_date.year < test[min_idx].birth_date.year) {
min_idx = j;
}
}
temp = test[min_idx];
test[min_idx] = test[i];
test[i] = temp;
flag = 1;
}
return flag;
}
I tried this:
int passengersIncreasingBubbleSort_Birthyear(passengers test[], int x, char *value1, char *value2) {
int i = 0, j = 0, min_idx, flag = 0;
passengers temp;
for (i = 0; i < x; i++) {
min_idx = i;
for (j = i + 1; j < x; j++) {
if (value1 < value2) {
min_idx = j;
}
}
temp = test[min_idx];
test[min_idx] = test[i];
test[i] = temp;
flag = 1;
}
return flag;
}
But it doesn't work as expected.
Ok, I achieved it.
int cmpfunction_Increasing_Birthdate (const void * a, const void * b)
{
passengers *passengerA = (passengers *)a;
passengers *passengerB = (passengers *)b;
return ( passengerA->signup_date.year - passengerB->signup_date.year );
}
and this is my call:
qsort(array, x, sizeof(passengers), cmpfunction_Increasing_Birthdate);
Now the question is, how can I also compare both year, month and day? Could I do it in the same compare function?

How many numbers from first string are in other string on the different position

I do not know how to solve this problem, this function.
peg_a = how many numbers from *secret are in *guess on the same position.
Example: *secret = "1234" | *guess = "1289"| ... peg_a = 2.
peg_b = how many numbers from *secret are in *guess but on the different position.
Example: *secret = "1234" | *guess = "8912"| ... peg_b = 2.
My problem: If I have secret ... "2211" and guess "1002" ... peg_b is 4, it need to be 2 (because they are 2 same numbers in secret, but on the other position) ... how to solve this problem?
Sorry for my english and programming skills.
void get_score(char* secret, char* guess, int* peg_a, int* peg_b)
{
int i, j;
int pa, pb;
pa = pb = 0;
int lens = strlen(secret);
int leng = strlen(guess);
for(i = 0; i < lens; i++)
{
if(secret[i] == guess[i])
{
pa++;
continue;
}
for(j = 0; j < leng; j++)
{
if((secret[i] == guess[j]) && (secret[j] != guess[j]))
{
pb++;
}
}
}
*peg_a = pa;
*peg_b = pb;
}
check if the number of the "first" string is equal to the "second" string at the current index, if yes increment, else iterate the "second" string to check if the current number from the "first" string is in the "second" string, if yes, increment
void get_score(char* secret, char* guess, int* peg_a, int* peg_b){
int i, j;
int pa, pb;
pa = pb = 0;
int lens = strlen(secret);
int leng = strlen(guess);
for(i = 0; i < lens; i++){
if(secret[i] == guess[i]){
pa++;
}else{
for(j = 0; j < leng; j++){
if((secret[i] == guess[j])){
pb++;
break;
}
}
for(int k = i-1; k >= 0; k--){
if(secret[i] == secret[k]){
pb--;
}
}
}
}
*peg_a = pa;
*peg_b = pb;
}
The 3rd for is to check if the number that is now comparing is the same as one before

How to make strings stick together while radix sorting?

I have to make a program that sort strings (with exact length 7 chars) by using radix sort. I already made a function that sort each column separately. My problem is how to make the whole string move, not just one char. It's really problematic for me to see how should it work in C.
I made one array "char strings[3][8]" and "char output[3][8]" to get sorted 3 strings with exact 7 chars in each one. For example sorting these strings:
strcpy(strings[0], "kupbars");
strcpy(strings[1], "daparba");
strcpy(strings[2], "jykaxaw");
In output I get:
dakaaaa
juparbs
kypbxrw
Each column is sorted correctly but chars don't stick together. I tried many ways for 3 hours but nothing works.
My code looks like this:
void countingSort(char a[][8], char b[][8]) {
int c[123];
for (int pos = 6; pos >= 0; pos--) {
for (int i = 0; i < 123; i++)
c[i] = 0;
for (int i = 0; i < 3; i++)
c[(int)a[i][pos]]++;
for (int i = 1; i < 123; i++)
c[i] += c[i - 1];
for (int i = 2; i >= 0; i--) {
b[--c[(int)a[i][pos]]][pos] = a[i][pos];
}
}
}
(There are constants limiting string length etc. because it's easy to change it to variable - I just focused on getting this program work properly.)
Try changing the loop to move an entire string:
for (int i = 2; i >= 0; i--) {
int k = --c[(int)a[i][pos]];
for(int j = 0; j < 8; j++) {
b[k][j] = a[i][j];
}
}
You could do a circular list but it's a little overhead. I propose you to use memmove().
#include <string.h>
void array_move_forward(char array[3][8]) {
for (int i = 0; i < 3; i++) {
char tmp = array[i][6];
memmove(array[i] + 1, array[i], 6);
array[i][0] = tmp;
}
}
void array_move_rewind(char array[3][8]) {
for (int i = 0; i < 3; i++) {
char tmp = array[i][0];
memmove(array[i], array[i] + 1, 6);
array[i][6] = tmp;
}
}
A other solution would be to manipulate your string yourself and using a index, that indicate the first letter of your string.
{
char str[7];
int i = 0;
...
int j = i;
for (int k = 0; k < 7; k++) {
char tmp = str[j++ % 7];
}
}
With that you could rotate your string just with i++ or i--.
struct my_string_radix {
char str[7];
int begin;
}

Enumerating Permutations of a set of subsets

I have sets S1 = {s11,s12,s13), S2 = {s21,s22,s23) and so on till SN.I need to generate all the permutations consisting elements of S1,S2..SN.. such that there is only 1 element from each of the sets.
For eg:
S1 = {a,b,c}
S2 = {d,e,f}
S3 = {g,h,i}
My permuations would be:
{a,d,g}, {a,d,h}, {a,d,i}, {a,e,g}, {a,e,h}....
How would I go about doing it? (I could randomly go about picking up 1 from each and merging them, but that is even in my knowledge a bad idea).
For the sake of generality assume that there are 'n' elements in each set. I am looking at implementing it in C. Please note that 'N' and 'n' is not fixed.
It's just a matter of recursion. Let's assume these definitions.
const int MAXE = 1000, MAXN = 1000;
int N; // number of sets.
int num[MAXN]; // number of elements of each set.
int set[MAXN][MAXE]; // elements of each set. i-th set has elements from
// set[i][0] until set[i][num[i]-1].
int result[MAXN]; // temporary array to hold each permutation.
The function is
void permute(int i)
{
if (i == N)
{
for (int j = 0; j < N; j++)
printf("%d%c", result[j], j==N-1 ? '\n' : ' ');
}
else
{
for (int j = 0; j < num[i]; j++)
{
result[i] = set[i][j];
permute(i+1);
}
}
}
To generate the permutations, simply call permute(0);
If you know exactly how many sets there are and it's a small number one might normally do this with nested loops. If the number of sets is greater than 2 or 3, or it is variable, then a recursive algorithm starts to make sense.
And if this is homework, it's likely that implementing a recursive algorithm is the object of the entire assignment. Think about it, for each set, you can call the enumeration function recursively and have it start enumerating the next set...
If they are in a container, just iterate through each:
#include <stdio.h>
int main(void)
{
int set1[] = {1, 2, 3};
int set2[] = {4, 5, 6};
int set3[] = {7, 8, 9};
for (unsigned i = 0; i < 3; ++i)
{
for (unsigned j = 0; j < 3; ++j)
{
for (unsigned k = 0; k < 3; ++k)
{
printf("(%d, %d, %d)", set1[i], set2[j], set3[k]);
}
}
}
return 0;
}
Generic solution:
typedef struct sett
{
int* nums;
int size;
} t_set;
inline void swap(t_set *set, int a, int b)
{
int tmp = set->nums[a];
set->nums[a] = set->nums[b];
set->nums[b] = tmp;
}
void permute_set(t_set *set, int from, void func(t_set *))
{
int i;
if (from == set->size - 1) {
func(set);
return;
}
for (i = from; i < set->size; i++) {
swap(set, from, i);
permute_set(set, from + 1, func);
swap(set, i, from);
}
}
t_set* create_set(int size)
{
t_set *set = (t_set*) calloc(1, sizeof(t_set));
int i;
set->size = size;
set->nums = (int*) calloc(set->size, sizeof(int));
for(i = 0; i < set->size; i++)
set->nums[i] = i + 1;
return set;
}
void print_set(t_set *set) {
int i;
if (set) {
for (i = 0; i < set->size; i++)
printf("%d ", set->nums[i]);
printf("\n");
}
}
int main(int argc, char **argv)
{
t_set *set = create_set(4);
permute_set(set, 0, print_set);
}
This is a fairly simple iterative implementation which you should be able to adapt as necessary:
#define SETSIZE 3
#define NSETS 4
void permute(void)
{
char setofsets[NSETS][SETSIZE] = {
{ 'a', 'b', 'c'},
{ 'd', 'e', 'f'},
{ 'g', 'h', 'i'},
{ 'j', 'k', 'l'}};
char result[NSETS + 1];
int i[NSETS]; /* loop indexes, one for each set */
int j;
/* intialise loop indexes */
for (j = 0; j < NSETS; j++)
i[j] = 0;
do {
/* Construct permutation as string */
for (j = 0; j < NSETS; j++)
result[j] = setofsets[j][i[j]];
result[NSETS] = '\0';
printf("%s\n", result);
/* Increment indexes, starting from last set */
j = NSETS;
do {
j--;
i[j] = (i[j] + 1) % SETSIZE;
} while (i[j] == 0 && j > 0);
} while (j > 0 || i[j] != 0);
}
You may think about the elements of a set as values of a cycle counter. 3 sets means 3 for cycles (as in GMan answare), N sets means N (emulated) cycles:
#include <stdlib.h>
#include <stdio.h>
int set[3][2] = { {1,2}, {3,4}, {5,6} };
void print_set( int *ndx, int num_rows ){
for( int i=0; i<num_rows; i++ ) printf("%i ", set[i][ndx[i]] );
puts("");
}
int main(){
int num_cols = sizeof(set[0])/sizeof(set[0][0]);
int num_rows = sizeof(set)/sizeof(set[0]);
int *ndx = malloc( num_rows * sizeof(*ndx) );
int i=0; ndx[i] = -1;
do{
ndx[i]++; while( ++i<num_rows ) ndx[i]=0;
print_set( ndx, num_rows );
while( --i>=0 && ndx[i]>=num_cols-1 );
}while( i>=0 );
}
The most efficient method I could come up with (in C#):
string[] sets = new string[] { "abc", "def", "gh" };
int count = 1;
foreach (string set in sets)
{
count *= set.Length;
}
for (int i = 0; i < count; ++i)
{
var prev = count;
foreach (string set in sets)
{
prev = prev / set.Length;
Console.Write(set[(i / prev) % set.Length]);
Console.Write(" ");
}
Console.WriteLine();
}

Resources