I had this question to solve:
Find the length of increasing subarrays in the given array and print length of each segment in a new line
Here's what I have done so far:
#include <stdio.h>
int main(){
int c = 0;
int a[] = {1, 3, 2, 4, 5, 7};
for (int i = 0; i < 6; i++) {
if (a[i] > a[i-1]) {
c++;
}
else {
printf("%d\n", c);
c=1;
}
}
return 0;
}
My expected answer is:
2
4
but I am getting only 2, on increasing i to 7, I am getting correct answer, am I doing something wrong in traversing the array because the length is 6 and i<6 should have given the correct answer
Apologies in advance if the question is too trivial, just getting started.
It's simple. Because you have included in this line:
if (a[i] > a[i-1])
i starts with a 0 but a[-1] doesn't exist.
To fix your code:
#include <stdio.h>
int main(void){
int c = 0;
int a[] = {1, 3, 2, 4, 5, 7};
for (int i = 1; i < 6; i++) {
if (a[i] > a[i-1])
c++;
else {
printf("%d\n", c);
c=1;
}
}
return 0;
}
It is possible to do it with a single printf in the loop if you loop over all values from 0 to the array length, and treat the first and last iterations as special cases:
#include <stdio.h>
int main(void){
int c = 0;
int a[] = {1, 3, 2, 4, 5, 7};
const int len = sizeof a / sizeof a[0];
for (int i = 0; i <= len; i++) {
if (i < len && (i == 0 || a[i] > a[i-1])) {
c++;
} else {
printf("%d\n", c);
c = 1;
}
}
return 0;
}
The i < len makes sure that the code does not access a[len], which is out of bounds. When i equals len the code reaches the else part to print the length of the final segment.
The i == 0 makes sure that the code does not access a[-1], which is out of bounds, but we want it to increment c for the first entry in the array.
The code can be simplified a bit by initializing c = 1 and starting the loop at i = 1. By doing that, the first element of the array has already been accounted for:
#include <stdio.h>
int main(void){
int c = 1;
int a[] = {1, 3, 2, 4, 5, 7};
const int len = sizeof a / sizeof a[0];
for (int i = 1; i <= len; i++) {
if (i < len && a[i] > a[i-1]) {
c++;
} else {
printf("%d\n", c);
c = 1;
}
}
return 0;
}
The code will run slightly faster if the code inside the loop is simplified as much as possible, eliminating the i < len test inside the loop, and terminating the loop when i reaches len (i.e. continue the loop if i < len), but that will require the length of the final segment to be printed separately after the for loop has terminated:
#include <stdio.h>
int main(void){
int c = 1;
int a[] = {1, 3, 2, 4, 5, 7};
const int len = sizeof a / sizeof a[0];
for (int i = 1; i < len; i++) {
if (a[i] > a[i-1]) {
c++;
} else {
printf("%d\n", c);
c = 1;
}
}
printf("%d\n", c);
return 0;
}
If there is a requirement for the code to work when the overall sequence has zero length, then the final printf would print the wrong value 1. That could be dealt with either by setting c to 0 when len is 0, or by skipping the final printf if len is 0. (It depends whether you want to print anything at all when the overall sequence has zero length.)
Related
Currently I am trying to solve this task: Two arrays of five integers each are given. Find the lowest number in the first array that is not in the second array.
It seems to me that if the user enters such integers in the first array:
0 1 2 3 4
And the integers of the second array:
0 2 3 4 5
The lowest integer, according to the condition of the task, will be 1, because it is not in the second array.
So here is my code:
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "Rus");
int arr1[5]; //initialize arrays
int arr2[5];
printf("Enter integers\n");
for (int i = 0; i < 5; i++) {
int element;
scanf_s("%d", &element);
arr1[i] = element;
}
printf("Enter integers\n");
for (int i = 0; i < 5; i++) {
int element;
scanf_s("%d", &element);
arr2[i] = element;
}
int min1 = arr1[0];
int min2 = arr2[0];
for (int i = 0; i < 5; i++) { // algorithm for finding the minimum number of an array 1
if (min1 > arr1[i]) {
min1 = arr1[i];
}
if (min2 > arr2[i]) {
min2 = arr2[i];
}
}
}
Well, the code is very clear, but here's how to make this check, if the first array input 0 1 2 3 4 and the second 0 2 3 4 5 then how to remove this zero.
There are some issues ...
We don't care about the min value for arr2--only for arr1
We must scan all arr2 values for a match to the current/candidate value of arr1
There are some special cases we must handle
Normally, if we're just looking for the min value in arr1 (e.g. arr2 is not a factor), we can do [as you've done]:
int min1 = arr1[0];
And, we could start indexing into arr1 from 1 in the for loop.
But, this fails if:
arr1[0] is the min value in arr1 and that value is in arr2
arr1 and arr2 have identical values [even if they are in a different order].
So, we need an extra [boolean] value to denote whether the min1 value is valid. And, we must start indexing in the for loop from 0.
Here is the refactored code. It is annotated:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#define A1MAX 5
#define A2MAX 5
int
main(void)
{
setlocale(LC_ALL, "Rus");
// define arrays
int arr1[A1MAX];
int arr2[A2MAX];
printf("Enter integers\n");
for (int i = 0; i < A1MAX; i++) {
if (scanf("%d", &arr1[i]) != 1) {
printf("missing arr1[%d] -- %s\n",i,strerror(errno));
return 2;
}
}
printf("Enter integers\n");
for (int i = 0; i < A2MAX; i++) {
if (scanf("%d", &arr2[i]) != 1) {
printf("missing arr2[%d] -- %s\n",i,strerror(errno));
return 3;
}
}
int nomin = 1;
int min1 = arr1[0];
// check all values in arr1
for (int i = 0; i < A1MAX; i++) {
// current value we're going to test
int val = arr1[i];
// check value if it's a _new_ minimum or we do _not_ yet have a minimum
if ((val < min1) || nomin) {
// scan all elements of arr2, looking for a match to the current
// arr1 value
int match = 0;
for (int j = 0; j < A2MAX; j++) {
match = (val == arr2[j]);
if (match)
break;
}
// if the current value is _not_ in arr2, we have a new minimum
if (! match) {
min1 = val;
nomin = 0;
}
}
}
if (nomin)
printf("there are no elements in arr1 that are not in arr2\n");
else
printf("the minimum element in arr1 not in arr2 is: %d\n",min1);
return nomin;
}
Things get complicated with code tries to maintain multiple indexes into multiple arrays... Things are simplified if you re-use code and break out functions (that can test user input, too)...
#include <stdio.h>
void fill( int arr[], size_t sz ) { // Get user input (with checking)
printf("Enter integers\n");
for( size_t i = 0; i < sz; i++ )
if( scanf( "%d", &arr[i] ) != 1 ) {
fprintf( stderr, "scanf failure\n" );
exit(1);
}
}
// Search for a value in an array. Return index if found, or size if not found
size_t hunt( int val, int arr[], size_t sz ) {
for( size_t i = 0; i < sz; i++ )
if( val == arr[i] )
return i;
return sz;
}
int main() {
#if 0 // Normal with user entry
int arr1[5], arr2[5];
size_t a1sz = sizeof arr1/sizeof arr1[0];
size_t a2sz = sizeof arr2/sizeof arr2[0];
fill( arr1, a1sz );
fill( arr2, a2sz );
#else // less tedious with compile time init of data
int arr1[] = { 0, 1, 2, 3, 4 };
int arr2[] = { 0, 2, 3, 4, 5 };
size_t a1sz = sizeof arr1/sizeof arr1[0];
size_t a2sz = sizeof arr2/sizeof arr2[0];
#endif
size_t gotOne = 0;
for( size_t i = 0; i < a1sz; i++ ) {
// don't bother testing values if got a candidate and value is larger
if( gotOne && arr1[i] >= arr1[ gotOne ] ) continue;
// following is TRUE when not found...
if( hunt( arr1[i], arr2, a2sz ) == a2sz )
gotOne = i + 1;
}
if( gotOne )
printf( "Smallest in arr1 not in arr2 = %u\n", arr1[ gotOne - 1 ] );
else
puts( "No such value matching criteria" );
return 0;
}
Smallest in arr1 not in arr2 = 1
Algorithm
The naive approach to this, and one that works very well for small datasets, is to nest a couple of loops. This approach grows in time complexity very fast. O(m*n) where m is the length of the first array and n is the length of the second array.
Fortunately, we can approach this in a way that does not involve nested loops. This assumes both arrays contain only unique values. If they have duplicates, removing those duplicates would be a necessary step before the below can be performed.
Let's start with a couple of simple arrays:
int foo[] = {1, 4, 7, 9, 2};
int bar[] = {4, 1, 6, 7, 3};
Let's combine them into another array. This is a linear operation.
{1, 4, 7, 9, 2, 4, 1, 6, 7, 3}
Let's then use qsort to sort them. This operation is typically O(n*log n).
{1, 1, 2, 3, 4, 4, 6, 7, 7, 9}
Now, we can do a linear loop over these and find the unique elements. These are the ones present in one but not both of the arrays.
{2, 3, 6, 9}
But this doesn't tell us which is in the first array. That sounds like a nested loop issue. Instead, though, let's combine that with the first array.
{1, 4, 7, 9, 2, 2, 3, 6, 9}
And we'll sort this.
{1, 2, 2, 3, 4, 6, 7, 9, 9}
Now we'll scan for the first repeated number.
2
An implementation
Note: Does not check for malloc errors.
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
int c = *(const int *)a;
int d = *(const int *)b;
if (c == d) return 0;
else if (c < d) return -1;
else return 1;
}
int min_not_in_2nd_array(int *result, int *arr1, size_t m, int *arr2, size_t n) {
int *temp = malloc(sizeof(int) * (m + n));
//if (!temp) return 0;
for (size_t i = 0; i < m; ++i) temp[i] = arr1[i];
for (size_t i = 0; i < n; ++i) temp[m+i] = arr2[i];
qsort(temp, m+n, sizeof(int), cmp);
int *uniques = malloc(sizeof(int) * (m + n));
//if (!uniques) return 0;
size_t n_uniques = 0;
int cur = temp[0] - 1;
size_t cur_count = 0;
for (size_t i = 0; i < m+n; ++i) {
if (i == m+n-1 && temp[i] != temp[i-1]) {
uniques[n_uniques++] = temp[i];
}
else if (temp[i] != cur) {
if (cur_count == 1) uniques[n_uniques++] = cur;
cur = temp[i];
cur_count = 1;
}
else {
cur_count++;
}
}
//for (size_t i = 0; i < n_uniques; ++i) printf("%d ", uniques[i]);
//printf("\n");
int *temp2 = malloc(sizeof(int) * (m + n_uniques));
// if (!temp2) return 0;
for (size_t i = 0; i < m; ++i) temp2[i] = arr1[i];
for (size_t i = 0; i < n_uniques; ++i) temp2[m+i] = uniques[i];
qsort(temp2, m+n_uniques, sizeof(int), cmp);
int found = 0;
for (size_t i = 0; i < m+n_uniques-1; ++i) {
if (temp2[i] == temp2[i+1]) {
*result = temp2[i];
found = 1;
break;
}
}
free(temp);
free(uniques);
free(temp2);
return found;
}
int main(void) {
int foo[] = {1, 4, 7, 9, 2};
int bar[] = {4, 1, 6, 7, 3};
int baz;
if (min_not_in_2nd_array(&baz, foo, sizeof(foo)/sizeof(*foo),
bar, sizeof(bar)/sizeof(*bar))) {
printf("Min not in 2nd array is %d\n", baz);
}
else {
printf("All elements shared.\n");
}
return 0;
}
I have written a code for randomly printing a number from 1 to 10 without any repetition, but it isn't working properly sometimes I get the number that is already written.
In short, I'm trying to print numbers from 1-10 randomly with no repetition.
Here is my code :
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
main() {
int no = 0, repeat[100] = { 0 }, i = 0, x = 0, j = 0;
srand(time(NULL));
while (true) {
no = (rand() % 10) + 1;
for (i = 0; i < 100; i++) {
if (no != repeat[i]) {
x = 1;
} else if (no == repeat[i]) {
x = 0;
}
}
if (x == 1) {
repeat[j] = no;
printf("\n%d", repeat[i]);
j = j + 1;
}
getch();
}
}
Don't use rand() to generate the numbers directly, instead fill a sequential array, and then use rand() to shuffle the array, e.g.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/** shuffle integer array of size 'n'
* (using fisher-yates method)
*/
void shuffle (int *a, int n)
{
int i, tmp;
while (n-- > 1) {
i = rand() % (n + 1);
tmp = a[i];
a[i] = a[n];
a[n] = tmp;
}
}
int main (void) {
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
srand (time(NULL));
shuffle (arr, 10);
for (int i = 0; i < 10; i++)
printf (" %d", arr[i]);
putchar ('\n');
}
By shuffling the array and swapping random elements within it, you eliminate all possibility of a duplicate number.
Example Use/Output
$ ./bin/shuffle_arr
3 10 7 8 4 5 6 9 1 2
#include <stdio.h>
#define N1 1
#define N2 10
void main() {
int len = N2 - N1 + 1, i, r, temp;
int num[len];
//Fill array with numbers
for (temp = 0, i = N1; temp < len; i++, temp++)
num[temp] = i;
srand(time(NULL));
for (i = len - 1; i > 0; i--) {
r = rand() % i; //pop random number
//swaping
temp = num[i];
num[i] = num[r];
num[r] = temp;
}
/*Random Numbers are stored in Array*/
//print that array
for (i = 0; i < len; i++)
printf("%d\n", num[i]);
}
How to separate the even position number of an array from the odd position number in C.
Example
int arr[]= {2,3,4,5,6,7,8,9,1};
int odd[]= {2,4,6,8,1};
int even[] = {3,5,7,9};
Use % to get the remainder. If the remainder is nonzero, then the index is odd, otherwise even. But index starts from 0 and not 1, thus the first element's index is 0 and is even. if you want to sort according to that (seems to be you do), add 1 to index.
#include <stdio.h>
int main() {
int arr[] = {2, 3, 4, 5, 6, 7, 8, 9, 1}; // our array
const size_t max_size = sizeof(arr) / sizeof(arr[0]);
int odd[max_size];
size_t odd_cnt = 0;
int even[max_size];
size_t even_cnt = 0;
for (size_t i = 0; i != max_size; ++i) {
if ((i + 1) % 2) { // if (i + 1) % 2 is nonzero, i + 1 is odd
odd[odd_cnt++] = arr[i];
} else {
even[even_cnt++] = arr[i];
}
}
for (size_t i = 0; i != odd_cnt; ++i) {
printf("%d ", odd[i]);
}
printf("\n");
for (size_t i = 0; i != even_cnt; ++i) {
printf("%d ", even[i]);
}
printf("\n");
return 0;
}
I want to iterate through any array starting at an index that's close to the middle, go to the end then go to the beginning.As an example:
#include <stdio.h>
int main(){
int a[]= {1, 2, 3, 4, 5, 6, 7,};
int i = 0;
for (i = 2; i < 6; i++){
if (i == 6){
i = 0;
}
printf("%d\n", a[i]);
}
return 0;
}
How can I "reassign" the index to be zero when it reaches the end (index 6)
Here is a simple write-up. Not tested so adjust as needed. The idea is have the counter start at 0 and add the value of start each time using modulus to make it relative.
int a[]= {1, 2, 3, 4, 5, 6, 7};
int length = sizeof(a)/sizeof(a[0]);
int start = length/2;
for (int i = 0; i < length; i++)
{
printf("%d\n", a[(i+start)%length]);
}
And props to #SouravGhosh for pointing out modulus in the comments before I got this answer up.
If I well understood the question you want two for loops, one starting from the middle of your array and going to the end of the array and the second starting from the middle (minus one) and decreasing to the beginning of the array.
This is the code you can use, it is quite easy and works fine for me:
#include <stdio.h>
int main() {
int a[] = { 1, 2, 3, 4, 5, 6, 7, };
int max = (int)(sizeof(a)/sizeof(a[0]));
int middle = (int)(max / 2);
int i;
for (i = middle; i < max ; i++) {
printf("%d\n", a[i]);
}
for (i = middle - 1; i >= 0; i--) {
printf("%d\n", a[i]);
}
}
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();
}
}