Remove zero entries from an array in C - c

I have an array of values x = {0,0,1,2,3,0,0,7,8} and I want to remove the zero entries using C.
Attempt:
I am attempting to loop through each value in the array and check if the entry is not equal to zero. If this condition is true, then I am attempting to populate a new array with original array value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i;
int x_upd[100];
for (i = 0; i < 9; i++) {
if (x[i] != 0) {
x_upd[i] = x[i]; // if true, populate new array with value
}
}
for (i = 0; i < 9; i++) {
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
The output is not giving me the values {1,2,3,7,8} as desired. Instead, I am getting garbage values at the location where the zeros used to be.
Any advice on what I am doing wrong here? Do I need an else statement?

There is already such a function in C++. It is named remove_copy. In C such a function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
int * remove_copy(const int *in, size_t n, int *out, int value)
{
for (size_t i = 0; i != n; i++)
{
if (in[i] != value) *out++ = in[i];
}
return out;
}
int main( void )
{
int a[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int b[sizeof(a) / sizeof(*a)];
const size_t N = sizeof(a) / sizeof(*a);
int *last = remove_copy(a, N, b, 0);
for (int *first = b; first != last; ++first)
{
printf("%d ", *first);
}
putchar('\n');
return 0;
}
The program output is
1 2 3 7 8
Or the function can return the number of the copied values
size_t remove_copy(const int *in, size_t n, int *out, int value)
{
size_t m = 0;
for (size_t i = 0; i != n; i++)
{
if (in[i] != value) out[m++] = in[i];
}
return m;
}
As for your code then you need to use an additional variable that will keep the index in the destination array. For example
int m = 0;
for ( i = 0; i < sizeof( x ) / sizeof( *x ); i++ )
{
if ( x[i] != 0 )
{
x_upd[m++] = x[i]; // if true, populate new array with value
}
}
for ( i = 0; i < m; i++ )
{
printf(" Peak updated %d\t", x_upd[i] ); //
}
In fact the first loop corresponds to the second function implementation shown above.

You go through the values 0-9 once, in order, and you skip values that are 0, so you get {garbage, garbage, 1, 2, 3, garbage, garbage, 7, 8}. You'd have to keep a separate counter for the number of values that aren't 0:
int position = 0;
for(i = 0; i < 9; i++)
{
if(x[i] != 0)
{
x_upd[position] = x[i]; // if true, populate new array with value
position++;
}
}
//loop until you get to counter
for(i = 0; i < position; i++)
{
printf(" Peak updated %d\t", x_upd[i]);
}

You should use separate counter variables, otherwise you will "skip" the indexes where the original array contains zeroes when assigning to the new array.
#include <stdio.h>
int main() {
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i;
int j = 0;
int x_upd[100];
for (i = 0; i < 9; i++) {
if (x[i] != 0) {
x_upd[j++] = x[i]; // if true, populate new array with value
}
}
for (i = 0; i < j; i++) {
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}

The trick in this situation, is to use a different variable to index into your other array.
So instead of this:
x_upd[i] = x[i];
You could have another variable j that only increments when you assign a value to x_upd
x_upd[j++] = x[i];

No need to create a new array, see the working code with one array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i, n;
for (i = 0, n = 0; i<9; i++)
{
if (x[i] != 0)
{
x[n++] = x[i];
}
}
for (i = 0; i<n; i++)
{
printf("%d,", x[i]);
}
return 0;
}
OUTPUT:
1,2,3,7,8,

This
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[i] = x[i]; // if true, populate new array with value
}
}
is skipping places in the x_upd array, since i is still being incremented even when you don't insert values in your new array.
You should do this:
int j = 0;
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[j++] = x[i]; // if true, populate new array with value
}
}
Then, here
for(i=0;i<9;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
You should just count till j:
for(i=0;i<j;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}

This problem can be solved by using two indexes: one for the source array (x) and another for the destination array (x_upd), which are i and j, respectively, in the code below.
int i, j;
for(i=0,j=0; i<9; i++) {
if (!x[i]) // is x[i] zero?
continue; // then skip this element
// otherwise copy current element and update destination index
x_upd[j++] = x[i];
}
As you can see, the index j is only being updated (i.e.: incremented by one) when an element from x is being copied to x_upd, whereas the index i is being updated in each iteration of the for loop.

The problem lies here:
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[i] = x[i]; // if true, populate new array with value
}
}
and
for(i=0;i<9;i++) {
printf(" Peak updated %d\t",x_upd[i]); //
}
You need to maintain separate index for x and x_upd, since they will be of different size(x_upd wont have the '0').
Try this:
int j;
for(i=0,j=0;i<9;i++) {
if(x[i] != 0)
{
x_upd[j] = x[i]; // if true, populate new array with value
j++; // index for values inserted
}
}
and to print, use the correct count, obtained from the above code:
int k;
for(k=0;k<=j;k++) {
printf(" Peak updated %d\t",x_upd[k]); //
}

You should increment x_upd array index separately. Something like:
int y = 0;
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[y] = x[i]; // if true, populate new array with value
y++;
}
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x[] = {0,0,1,2,3,0,0,7,8};
int i;
int count = 0;
int x_upd[100];
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[count] = x[i]; // if true, populate new array with value
count++;
}
}
for(i=0;i<count;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
return 0;
}
Output
Peak updated 1 Peak updated 2 Peak updated 3 Peak updated 7 Peak updated 8

no indexes needed
int populate(int *src, int *dest, int size)
//usage: - src - source table
//src - source table
//dest - destination table
//size of the source table - source table
//Return: -1 if pointers are null, -2 if source table has zero elements, or number of non zero elements copied
{
int result = (src == NULL || dest == NULL) * -1;
// it an equivalen of:
// int result;
// if(src == NULL || dest == NULL)
// result = -1;
// else
// result = 0;
if(size == 0) result = -2;
if (!result)
{
while(size--)
if (*src)
{
*dest++ = *src;
result++;
}
src++;
}
return result;
}
int main()
{
int x[] = { 0,0,1,2,3,0,0,7,8 };
int x_upd[100];
int result = populate(x,x_upd, sizeof(x) / sizeof(x[0]))
for (int i = 0; i<result; i++)
{
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}

Related

Find longest sub-array with no repetitions

The task is to find the longest contiguous sub-array with all elements distinct.
Example Input {4, 3, 1, 3, 2, 1, 0} Output {3, 2, 1, 0}
Algorithm
Extract first sub Array (here 431)
Extract second sub Array (here 31)
Compare number of elements and keep the array with the biggest number (keep 431)
Return to 2
Problem The output is incorrect
/* Free old array and replace it by the new array
* If we only want to free old array and replace it by a new array
* Function will free old array and replace it by a new array with size equal to maximum size it can have
* Maximum size is the size of the input array
*/
int* newArray(int* oldArray,int* newArray, int sizeArray, int sizeFArray)
{
if (newArray == NULL) {
int* temp = malloc(sizeFArray * sizeof(int));
if (temp == NULL)
exit(1);
return temp;
} else {
memcpy(oldArray, newArray, sizeArray);
return oldArray;
}
printf("Error");
exit(1);
}
//int isAvailable(int* array , int size, int number) checks if number is available in array (return 0 if true, 1 if false)
//printArray(int* array, int size) is a simple function to print an array
void subArray(int* inputArray, int sizeInputArray)
{
int* candidate = malloc(sizeInputArray * sizeof(int));
if (candidate == NULL)
exit(1);
int sizeCandidate = 0;
int* newCandidate = malloc(sizeInputArray * sizeof(int));
if (newCandidate == NULL)
exit(1);
int sizeNewCandidate = 0;
//We will first fill the candidate
while (sizeCandidate < sizeInputArray && isAvailable(candidate, sizeCandidate, *(inputArray + sizeCandidate)) != 0) {
*(candidate + sizeCandidate) = *(inputArray + sizeCandidate);
sizeCandidate++;
}
int index = 1;
//Check all potential new candidates
//If new candidate holds more elements than the current candidate
//Current candidate will be replaced by new candidate
//Else we will redo the process and check using the next candidate if availble
for (int i = 1; i < sizeInputArray; i++) {
if(isAvailable(newCandidate, sizeNewCandidate, *(inputArray + i)) == 0) {
if (sizeNewCandidate > sizeCandidate) {
candidate = newArray(candidate, newCandidate, sizeNewCandidate, sizeInputArray);
newCandidate = newArray(newCandidate, NULL, 0, 0);
sizeCandidate = sizeNewCandidate;
sizeNewCandidate = 0;
i = ++index;
} else {
newCandidate = newArray(newCandidate, NULL, 0, sizeInputArray);
sizeNewCandidate = 0;
i = ++index;
}
} else {
*(newCandidate + sizeNewCandidate) = *(inputArray + i);
sizeNewCandidate++;
}
}
printArray(candidate, sizeCandidate);
}
I hope this code looks more compact and has clear comments:
#include <stdio.h>
int a[] = { 4, 3, 1, 3, 2, 1, 0 };
int check(int a[], int i, int j)
{
for (int k = i; k < j; k++)
for (int l = k + 1; l < j; l++)
if (a[k] == a[l])
return 0;
return 1;
}
int main()
{
int s = 0; // start position of the best candidate
int m = 1; // length of the best candidate
int n = sizeof(a) / sizeof(0); // length of the array
for (int i = 0; i < n; i++) { // for every start position
for (int j = i + m + 1; j <= n; j++) { // for every lengh if it more than the best one
if (check(a, i, j)) { // check if it contains repetitions
if (j - i > m) { // if no repetions
s = i; // update the candidate
m = j - i; // and length
}
}
else
break;
}
}
printf("{%d", a[s]);
for(int i = s + 1; i < s + m; ++i)
printf(", %d", a[i]);
printf("}\n");
return 0;
}
This works and gives the correct output.
I don't understand the complexity of the code.
#include <stdio.h>
int main()
{
// int x[] = { 4, 3, 1, 3, 2, 1, 0 };
int x[] = { 4, 3, 1, 3, 2, 5, 0 };
int offset;
int cur_offset = 0;
int max = 0;
int max_offset = 0;
for (int i = 1; i < sizeof(x) / sizeof(int); i++) {
for (int j = i-1; j >= cur_offset; j--) {
if (x[i] == x[j]) {
if (max <= i - j) {
max = i - j;
max_offset = j + 1;
} else if (max_offset == cur_offset) {
max = i - max_offset;
}
cur_offset = j + 1;
break;
}
}
}
if (max < sizeof(x) / sizeof(int) - cur_offset) {
max_offset = cur_offset;
max = sizeof(x) / sizeof(int) - max_offset;
}
printf("%d", x[max_offset]);
for (int i = max_offset + 1; i < max_offset + max; i++)
printf(", %d", x[i]);
printf("\n");
}

Sorting one array into another- C

So I am trying to write this function where the input parameter array will be taken and copied into another array but in a sorted way. For example: an input parameter of 3, 1, 9, 8 will copy into the target array 1, 3, 8, 9.
This is what I have so far but it only copies the smallest element in every time. I'm looking for a way to "blacklist" smallest values that are discovered in each pass.
void sort_another_array(int *param, int *target, int size){
int i, j, lowest = param[0];
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
if(param[j] < lowest){
lowest = param[j]
}
}
target[i] = lowest;
}
}
Of course I could have another array of already found lowest values but that's more unnecessary looping and checking and adds to the already terrible n^2 complexity. Is there an easier way to do this?
I'm completely new to C, so please do restrict it to simple programming concepts of logic statements, using some flag variables etc..
The probably most straight-forward way to do this is to first copy the whole array and then sort the new array in-place using a standard sorting algorithm.
However, if you want to keep the current structure, the following would be an alternative when all elements are unique:
void sort_another_array(int *param, int *target, int size) {
int i, j, past_min = INT_MAX, current_min = INT_MAX;
for (i = 0; i < size; ++i) {
for (j = 0; j < size; ++j) {
if (i == 0 || param[j] > past_min) {
if (past_min == current_min || param[j] < current_min) {
current_min = param[j];
}
}
}
target[i] = current_min;
past_min = current_min;
}
}
What this does is keeping track of the previously lowest element found (past_min). The next element to find is lowest among all elements greater than past_min. I.e., we want both param[j] > past_min and param[j] < current_min to be true. However, the first element to add to target (i.e., when i == 0) will not have a lower element before it, so we add an exception for that. Similar, the first element satisfying param[j] > past_min in a pass will not have any element to compare with so we add another exception using past_min == current_min (this is true only for the first element found in a pass).
If you have duplicates in the array, this might work:
void sort_another_array(int *param, int *target, int size) {
int j, past_min, current_min, write = 0, round_write = 0;
while (round_write != size) {
for (j = 0; j < size; ++j) {
if (round_write == 0 || param[j] > past_min) {
if (write == round_write || param[j] < current_min) {
current_min = param[j];
write = round_write;
target[write] = current_min;
++write;
} else if (param[j] == current_min) {
target[write] = current_min;
++write;
}
}
}
round_write = write;
past_min = current_min;
}
}
Basically it's the same idea, but it writes all elements of the minimum value in the same pass.
You can use a modified insertion sort algorithm to solve this problem:
#include <stdio.h>
void sort_another_array(int *param, int *target, int size)
{
for ( int i = 0; i < size; i ++ ) // do for all elements in param
{
int j = i - 1;
while ( j >= 0 && target[j] > param[i] ) // find index of element in target which is samler or equal than param[i]
{
target[j+1] = target[j]; // shift forward element of target which is greater than param[i]
j --;
}
target[j+1] = param[i]; // insert param[i] into target
}
}
#define SIZE 10
int main( void )
{
int a[SIZE] = { 9, 8, 0, 2, 1, 3, 4, 5, 7, 6 };
int b[SIZE];
sort_another_array( a, b, SIZE );
for ( int i = 0; i < SIZE; i ++ )
printf( "%2d", b[i] );
return 0;
}
The solution I am providing, has a limitation that: If there are no duplicates in the array, then this will work:
void sort_another_array(int *param, int *target, int size)
{
int i, j, lowest;
for(i = 0; i < size; i++)
{
int k = 0;
if( i > 0) // for all except first iteration
{
while(param[k] <= target[i-1]) // find the one greater than the last one added
k++;
}
lowest = param[k];
for(j = 1; j < size; j++)
{
if( ( i==0 && param[j] < lowest ) || ( i > 0 && param[j] < lowest && param[j] > target[i-1])) // for all except first iteration the min found should be greater than the last one found
{
lowest = param[j];
}
}
target[i] = lowest;
}
}

Reversing int array using recursion in C

I have learnt C language at school but I'm not good at it... And when I was trying to implement this algorithm using C language:
ReverseArray(int A[], int i, int j) {
Input: Array A, nonnegative integer indices i and j
Output: The reversal of the elements in A starting at index i and ending at j
if i < j then
swap A[i] and A[j]
ReverseArray(A, i+1, j-1)
}
I managed to code this:
int *reverseArray(int A[], int i, int j) {
int *R = NULL;
if(i < j) {
int temp = A[j];
A[j] = A[i];
A[i] = temp;
R = reverseArray(A, i+1, j-1);
return R;
} else {
return R;
}
}
But when I tried to print the original and reversed array in the main:
int main(void) {
int A[] = {1, 3, 5, 6, 8, 3, 4, 2};
int *r = reverseArray(A, 0, 7);
//This prints out the reversed array, when I intended to print the original
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
/* This was intended to print the reversed array but doesn't work
for (size_t i = 0; i < 8; i++) {
printf("%d ", r[i]);
}
*/
return 0;
}
Could anyone please explain why the commented out for loop doesn't work? And why the first for loop prints out the reversed array...
Is there any other way to get the result of reverseArray() without using *r?
I tried to malloc *r just in case that was the problem, but it still didn't work.
Thank you.
Just don't return anything. You make a reversion in place, so the resulting array is the same as the array to be reversed, and the caller knows it already.
You need to print the contents of A before you call reverseArray, not after. The reason is that you are reversing the bytes in place so the array A itself is changed by calling reverseArray.
A try from your code base and the problem description
If allowed to rewrite the Array in place, then it will work
#include<stdio.h>
void reverseArray(int A[], int i, int j) {
//int *R = NULL;
if(i < j) {
int temp = A[j];
A[j] = A[i];
A[i] = temp;
reverseArray(A, i+1, j-1);
}
}
int main(void) {
int A[] = {1, 3, 5, 6, 8, 3, 4, 2};
//This prints out original array
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
reverseArray(A, 0, 7);
// print the reversed array
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
return 0;
}
It will Output:
1 3 5 6 8 3 4 2
2 4 3 8 6 5 3 1
R is always assigned to NULL, and A is not a pointer, then you are editing the real data of the array.
if you want to reverse and create a new array, you must do something like that :
int *reverseArray(int array[], int arraySize) {
int *reversedArray = malloc(sizeof(int) * arraySize);
for ( int i = 0 ; i < arraySize ; ++i ) {
reversedArray[i] = array[arraySize - i - 1];
}
return reversedArray;
}
You can also do it in recursive way :
int *reverseArray(int inputArray[], int arrayLength ) {
int *_reverseArray (int inputArray[], int arrayLength, int *outputArray, int actual) {
if (outputArray == NULL) {
outputArray = malloc(sizeof(int) * arrayLength);
}
if (actual < arrayLength) {
outputArray[actual] = inputArray[arrayLength - actual - 1];
return _reverseArray(inputArray, arrayLength, outputArray, ++actual);
}
return outputArray;
}
return _reverseArray(inputArray, arrayLength, NULL, 0);
}
If you want to edit the original array :
void reverseArray(int array[], int arraySize)
{
for ( int i = 0 ; i < arraySize / 2 ; ++i ) {
array[i] ^= array[arraySize - i - 1];
array[arraySize - i - 1] ^= array[i];
array[i] ^= array[arraySize - i - 1];
}
}

Moving all zeros to the begining of array

I'm trying to write a function which moves all numbers from begining of array to the end of it. order should not change.
for example i have this array:
1, 2, 3, 4, 5, 0, 0, 0, 0
i want to change it to:
0, 0, 0, 0, 1, 2, 3, 4, 5
I already wrote a version of it but it can't keep the order. (array[] is original and a[] is sorted)
#include <stdio.h>
#define SIZE_MAX 20
int main()
{
int array[SIZE_MAX] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
int a[SIZE_MAX];
int i;
int p = 0;
for (i = SIZE_MAX-1; i >= 0; i--, p++)
{
a[i] = array[p];
}
for (i = 0; i < SIZE_MAX; i++)
{
printf("%d", a[i]);
}
}
One option would be to loop through the array twice, first copying over the zeros, then the rest of the values:
#include <stdio.h>
#define SIZE_MAX 10
int main()
{
int array[SIZE_MAX] = {1, 2, 0, 0, 3, 4, 5, 0, 0, 0};
int a[SIZE_MAX];
int i;
int p = 0;
for (i = 0; i < SIZE_MAX; ++i) {
if (array[i] == 0) {
a[p++] = 0;
}
}
for (i = 0; i < SIZE_MAX; ++i) {
if (array[i] != 0) {
a[p++] = array[i];
}
}
for (i = 0; i < SIZE_MAX; i++) {
printf("%d", a[i]);
}
}
I changed SIZE_MAX to 10, so that it matches the number of elements in the array.
The sentence "I'm trying to write a function which moves all numbers from beginning of array to the end of it." sounds like it should be done in place - and it turns out with this problem it is quite easy to do an in-place algorithm. Note that unlike other algorithms here, this just scans the array once, and writes the array once. Here I wrote it into a function:
void relocate_zeroes(size_t length, int *array) {
int *target = array + length - 1;
int *source = target;
for (; source >= array; source--) {
if (*source) {
*target-- = *source;
}
}
while (target >= array) {
*target-- = 0;
}
}
Basically we scan the source array once from end to beginning; and if we meet a non-zero integer, we relocate it just before the previous non-zero integer. When the whole array has been scanned, the area between the base (array) and target is filled with zeroes.
In the beginning both target and source point to the last value of the array; if the *source is not 0, we replace *target with *source; that is, if the last element is non-zero, we replace it by itself and decrease both target and source pointers; if the last element is 0, we don't copy it anywhere, only decrease the source pointer; continuing this way at the end we have copied all non-zero elements, and we can fill the remaining array elements with zeroes.
Given program:
#define SIZE_MAX 9
int main() {
int array[SIZE_MAX] = {1, 0, 2, 3, 0, 4, 0, 0, 5};
int i;
relocate_zeroes(SIZE_MAX, array);
for (i = 0; i < SIZE_MAX; i++) {
printf("%d ", array[i]);
}
}
The output will be
0 0 0 0 1 2 3 4 5
If the 2-array version is required, then this is easy to modify for that too:
void relocate_zeroes(size_t length, int *source_array, int *target_array) {
int *target = target_array + length - 1;
int *source = source_array + length - 1;
for (; source >= source_array; source--) {
if (*source) {
*target-- = *source;
}
}
while (target >= target_array) {
*target-- = 0;
}
}
If you need all the 0 at the beginning and rest of the numbers in same order try this :
#include <stdio.h>
#define SIZE_MAX 9
int main()
{
int array[SIZE_MAX] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
int a[SIZE_MAX];
int i;
int temp[SIZE_MAX];
int ind1=0,ind2=0;
// separating all the 0's and store it at the beginning
for (i = 0; i < SIZE_MAX; i++)
{
if(array[i]==0)
a[ind1++]=0;
else
temp[ind2++]=array[i];
}
// storing rest of the numbers in order
for (i = 0; i < ind2; i++)
{
a[ind1++]=temp[i];
}
for (i = 0; i < SIZE_MAX; i++)
{
printf("%d", a[i]);
}
}
NOTE:
first i stored all the 0's in the result array and in the meantime all the non zero value are being stored in temp array.
later, i just merged the temp array to the result array.
Integer fullArray[] = { 1, 10, 20, 0, 59, 63, 0, 88, 0 };
for (int i = 0; i <= fullArray.length - 1; i++) {
if (fullArray[i] == 0 && i > 0) {
int temp = fullArray[i - 1];
if (temp != 0) {
fullArray[i - 1] = 0;
fullArray[i] = temp;
i = -1;
}
}
}
System.out.println(Arrays.asList(fullArray).toString());
Here is an in-place method using swap()
#include <stdio.h>
#define SIZE_MAX 20
swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
moveZerosLeft(int length, int *array)
{
int i = 0;
int cur = length - 1;
for( i = length - 1; i >= 0; --i)
if(array[i] != 0)
{
swap(&array[i], &array[cur--]);
}
}
int main()
{
int array[SIZE_MAX] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
int i;
int length = 9;
moveZerosLeft(length, array);
// display the result
for(i = 0; i < length; i++)
{
printf("%d ", array[i]);
}
}
We scan from the right of the array to the left. When we see a non-zero value, we swap it with a zero which we saw previously.
This method requires only 1 scan of the array.
public class Demo{
public static void moveZeros() {
int[] num = {1, 0, 0 , 6, 7, 0};
int temp=-1;
for (int i = 0; i < num.length;i++)
{
if(num[i]!=0)
{
++temp;
if(num[temp] ==0){
int val = num[i];
num[i]=num[temp];
num[temp]=val;
}
else
{
num[temp]=num[i];
}
}
}
}
public static void main(String args[])
{
Demo.moveZeros();
}
}

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