Unexpected return value in this C program - c

I wrote a C program to find the difference in indices of the largest even number and the smallest even number in an array(here 0 is considered as an even number and from the testcases it definitely didn't look like the array should be sorted). It will return a value or No if the array has one element or no even numbers in that array.
#include <math.h>
#include <stdio.h>
int main() {
int n,small,big,a[50],b1,s1,diff;
scanf("%d",&n);
for(int i =0;i<n;i++){
scanf("%d",&a[i]);
}
small = a[0];
big = a[0];
for (int i = 1; i < n; i++)
{
if (a[i] < small && a[i]%2 == 0)
{
small = a[i];
s1 = i;
}
if (a[i] > big && a[i]%2 == 0)
{
big = a[i];
b1 = i;
}
}
diff = b1-s1;
if(diff==0){
printf("NO");
}
else{
printf("%d",diff);
}
return 0;
}
When I give as input
4
120 0 4 7
It doesn't return 1 . It returns 32657.
What logic am I not understanding here? Please help me.

In this code snippet
small = a[0];
big = a[0];
you also need to initialize s1 and b1
s1 = 0;
b1 = 0;
In general your approach is incorrect because a[0] can be an odd number and can be the greatest or smallest number in the array.
So at first you need to find in the array the first even number and if such a number exists (for example at index i) then write
small = a[i];
big = a[i];
s1 = i;
b1 = i;
Pay attention to that you can include the header <stdio.h> in fact in any place in your program because after the first inclusion of the header all other headers will not be actually included. But do not do that because it makes your program very strange.:)
So remove this directive in main
#include <stdio.h>
Also the directive
#include <math.h>
is redundant because neither declaration from the header is used in your program. You may also remove it.

Related

Finding the maximum integer of three integers in C

I just started learning how to code in C.
I tried creating a program that finds the maximum of three integers using arrays, but I don't really understand why does it work.
Can anybody more experienced help explain to me; why do I need to let max = 0 in order for the program to function?
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main()
{
int size, max;
int arr[3];
for (int i = 0; i < 3; i++) {
printf("Please enter your integer:\n");
scanf("%d", &arr[i]);
}
max = 0;
for (int i = 0; arr[i] >= max; i++) {
max = arr[i];
}
printf("This is the max number: %d", max);
return 0;
}
Thanks for the help everyone.
The proper loop would be:
int max= INT_MIN;
for (int i = 0; i<3; i++)
if (arr[i]> max) max= arr[i];
First of all, your code won't find the right answer in all test cases, and that's because of how you wrote your second for loop. For example if you have an input like 3, 2, 4, after the first for iteration you'll have max = 3 and the for loop will stop because the next element (2) is less than the current max (3). But the max value of this array is 4, not 3. You should change the second for loop like this:
for (int i=0;i<3;i++) {
(if array[i]>max) max = array[i];
}
Also, take note that you can initialize max to 0 only if you don't have negative numbers in the array, otherwise you might have incorrect results. So, if you can't make assumptions about your input values I would suggest you to simply initialize max with the first element of the array and do a loop starting from the second one to the end (for(i=1;i<3;i++).
A variable must be initialized before it can be used. The first use of max is:
for (int i = 0; arr[i] >= max; i++) {
... ^^^^^^^^^^^^^
}
The boundary condition in a for loop (i.e. arr[i] >= max) is evaluated before every iteration of the loop. A value for max is therefore required before the body of the loop is ever executed.
Thus, you must assign some value to max outside the loop, and, as you discovered, max = 0 is a suitable initial value for some inputs.
However as mentioned by Paul in the comments, this is not a suitable boundary condition for the result you’re trying to achieve. You should instead iterate over the entire array, setting the max value only if each array element is greater than the existing max value:
max = 0;
for (int i = 0; i < 3; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
If it's just for three:
#define MAX_SIMPLE(a, b) (((a) > (b)) ?(a) :(b))
int a[3] = {3, 2, 1};
printf("max is: %d\n", MAX_SIMPLE(a[0], MAX_SIMPLE(a[1], a[2])));

Find largest value x in array a so that -x also in a using C code (interview question)

You get an array a of integers. Need to return the largest value x in a so that -x is also in a. If there's no such value - return 0.
Example:
For [6,5,2,-1,-2,-5] the return value is 5 since -5 is in the array (the answer isn't 6 since -6 isn't in the array).
Edit: the input array isn't necessarily sorted.
Now, if I could use Java - I would solve it using HashSet which I'll add all array elements to in their absolute value, looping over the array and updating the maximum value if it's the largest I've seen so far and if I find the absolute value of it in the Hash. This will result in O(n) average time.
But on the interview I needed to solve it using C code, without creating any special data structures like HashSet.
The only idea I had was to sort the array, use two pointers (one for the start and one for the end) and move the pointers toward each other till I find the answer.
This wasn't good enough since it's O(nlogn).
Do you have an idea how can I solve it in C code in O(n), using built-in libraries only?
#include <stdio.h>
#include <stdlib.h>
int found = 0;
int n = 0;
int len = 6; // your array has 6 elements
for(int i = 0; i < len -1; i++) {
for(int j = i+1; j < len; j++) {
if(a[i] == -a[j] && (found = 0 || abs(a[i] > n)) n = abs(a[i]);
}
}
if(found) printf("Number is : %d\n", n);
else printf("Not found");
Ok, this is the real O(n) solution without libraries, but requires an ordered array. Just one loop, and moving the pointers initial and final.
#include <stdio.h>
int a[] = {6,5,2,-1,-2,-5};
int main(int argc, char** argv) {
int* left = a; // point to first
int* right = a + 5; // point to last
while(right > left) {
int result = *left + *right;
if(!result) {
printf("Number is %d\n", *left);
return 0;
}
if(result > 0) left++;
else right--;
}
printf("No result");
return 1;
}

How can I use the rand() function to generate a different number that hasn't been generated before?

// What I mean by this is shown by my example:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int i;
int a;
for (a = 0;a <10;a ++) {
i = (rand()%10)+1; // generates a number from 1-10
printf("%d\n", i);
}
// I would like for the loop to generate a number that gives a number that was not generated before. For example, an output such as:
1,3,6,2,8,9,4,10,5,7
instead of:
3,9,10,3,7,9,2,7,10,1
In other words, I would like no copies.
You obviously don't just want no copies, but you want every number in a given set exactly once. This is, as commented by Robert, similar to shuffling a deck of cards. You don't have "decks" in C, but you can model one as an array:
int deck[] = {1,1,1,1,1,1,1,1,1,1};
This should represent 10 different "cards" (identified by their index in the array), each available one time. Now, just write code that "draws" cards:
int i = 0; // starting point for searching for the next card to draw
for (int n = 10; n > 0; --n) // how many cards are left
{
int skip = rand() % n; // randomly skip 0 .. n cards
while (1)
{
if (deck[i]) // card still available?
{
if (!skip) break; // none more to skip -> done
--skip; // else one less to skip
}
if (++i > 9) i = 0; // advance index, wrapping around to 0
}
deck[i] = 0; // draw the card
printf("%d\n", i+1); // and print it out
}
of course, seed the PRNG (e.g. srand(time(0))) first, so you don't get the same sequence every time.
The idea shown in the question is to print numbers within a range, without repetition. Here is one way to do that, by putting each value into an array and swapping its elements around.
A variation could be that you don't want to use all the possible numbers, in that case just change PICKED.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRLEN 10
#define PICKED 10
int main(void) {
int array[ARRLEN];
srand((unsigned)time(NULL)); // seed the PRNG
for(int i = 0; i < ARRLEN; i++) { // generate the numbers
array[i] = i + 1;
}
for(int i = 0; i < ARRLEN; i++) { // shuffle the array
int index = rand() % ARRLEN;
int temp = array[i];
array[i] = array[index]; // by randomly swapping
array[index] = temp;
}
for(int i = 0; i < PICKED; i++) { // output the numbers
printf("%d ", array[i]);
}
printf("\n");
}
Program output:
9 8 4 5 1 10 7 3 6 2
The library's PRNG is not very random, but for many cases that is not important. If it is, better algorithms are available.

C How to Keep a Random Variable From Repeating the Same Number

So I'm just learning C and I would like to know how you could prevent a variable randomized with the rand() function from repeating the same number. I have a script which simply randomizes and prints a variable in a for loop 4 times. How could I make it so the variable never gets the same number after each time it uses the rand() function?
#include <stdio.h>
#include <stdlib.h>
int randomInt;
int main()
{
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
On most machines, int is 32 bits. So after 232 iterations, you are sure that you'll get some repetition (and probably much before).
If you restrict yourself to much less loops, consider e.g. keeping an array of previously met random numbers (or some hash table, or some binary tree, or some other container).
For a loop repeated only 4 times, keeping an array of (at most 4-1) previously emitted numbers is quite simple, and efficient enough.
Read also about the pigeonhole principle.
A slightly different approach.
int set[] = {0, 1, 2, 3 } ;
srand(time(0));
shuffle(set,4);
using the shuffle algorithm given in this question
https://stackoverflow.com/a/6127606/9288531
I'm guessing that you are getting the same numbers because your are running your program multiple times within the same second. If time(0) hasn't changed, you will have the same seed and the same random numbers generated. Unless your program runs extremely quickly, I imagine using a seed based on microseconds instead of seconds would work:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int randomInt;
int main()
{
struct timeval my_microtimer;
gettimeofday(&t1, NULL);
srand(t1.tv_sec * my_microtimer.tv_usec);
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
What you could do is keeping track of each number you already generated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int hasMyNumberAlreadyBeenGenerated(int number, int generatedNumbers[], int size){
for(int i = 0; i < size + 1; i++){
//If you already generated the number, it should be present somewhere in your array
if(generatedNumbers[i] == number) return 1;
//If you did not, find the first available space in your array, and put the number you generated into that space
if(generatedNumbers[i] == 0){
generatedNumbers[i] = number;
break; //No need to continue to check the array
}
}
return 0;
}
int main()
{
int randomInt;
int generatedNumbers[4];
//We set "0" in all the array, to be sure that the array doesn't contain unknown datas when we create it
memset(generatedNumbers, 0x0, sizeof(generatedNumbers));
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4 + 1;
//As long as the number you generate has already been generated, generate a new one
while(hasMyNumberAlreadyBeenGenerated(randomInt, generatedNumbers, i) == 1){
randomInt = rand() % 4 + 1;
}
printf("generated : %d\n", randomInt);
}
return 0;
}
The problem with this method is that you can't generate a 0, because if you do you'll endlessly loop.
You can bypass this problem using a dynamic array using malloc() function.
If you want to write clean code you should define how many numbers you want to generate with a #define.
What you seem to be asking is a non-random set of numbers 0 to 3 in a random order. Given that;
int set[] = {0, 1, 2, 3 } ;
int remaining = sizeof(set) / sizeof(*set) ;
while( remaining != 0 )
{
int index = rand() % sizeof(set) / sizeof(*set) ;
if( set[index] > 0 )
{
printf( "%d\n", set[index] ) ;
set[index] = -1 ;
remaining-- ;
}
}
For very large sets, this approach may not be practical - the number of iterations necessary to exhaust the set is non-deterministic.

C programming - A array and a random number combined question?

this is the part of my code I'm having trouble with. I can't understand why its doing it wrong. I have an array where it stores numbers 0 - 25 which are cases. The numbers are to be randomized and overwritten into the array. Only condition is is that no number can be doulbes, there can only be one of that number. I'm not asking you to do my code but do hint me or point me in the write directions. I am trying to learn :)
The problem lies within the second do loop. I can get the numbers to be randomized, but I get doubles. I have created a loop to check and fix this, but it's not working. The code does run, and doubles do still happen and I can't see why. It looks correct to me. Please look, thank you (:
This is what I have done originally (at the very end is where I am at now):
int check_double = 0;
int i = 0;
int counter = 0;
int array_adder = 0;
int random_number = 0;
int cases[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
};
float money[] = {
0.01,1,5,10,25,50,75,100,200,300,400,500,750,1000,5000,10000,25000,50000,750000,100000,200000,300000,400000,500000,750000,1000000
};
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
cases[counter]= rand() % 26;
counter += 1;
printf("%d\n", cases[counter]);
}
while (counter <= 25);
//make sure there are no doubles in the array, just 0 - 25 and not a single number repeated twice
do
{
check_double = 0;
for (i = 0; i < counter; i++)
{
if (cases[counter] == cases[i])
{
cases[counter] = rand()% 26;
check_double == 1;
}
}
}
while (check_double != 0);
Currently, what I had achived after that was combing both loops and check for doubles as the array goes. This is what I made, it still has doubles and im not sure why, I only posted the cose with both loops combined:
do
{
cases[counter]= rand() % 26;
if (cases[counter]>=1);
for(i=0;i<=counter;i++)
if (cases[counter]==cases[i])
{
cases[counter]=rand()% 26;
}
printf("%d\n",cases[counter]);
counter+=1;
}
Robsta, you could try the following piece of code, I have run this in Dev-C++, any changes that you require can be made from your side. But, I assure you that this code generates what you intend.
int check_double = 0;
int i = 0;
int counter = 0;
int cases[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
};
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
cases[counter]= rand() % 26;
for(i=0;i<counter;i++)
if (cases[counter]==cases[i]){
while (cases[counter]==cases[i])
{
cases[counter]=rand()% 26;
}
i=0;
}
printf("%d\t%d\n",counter,cases[counter]);
counter+=1;
}while (counter <= 25);
If you have any clarifications required, I would love to discuss with you.
-Sandip
You're only ever writing over the last value in the array:
for(i=0;i<counter;i++)
if (cases[counter]==cases[i])
You need to loop through as you are, then have an inner loop, where you compare all the other entries to the current one.
Even easier would be to do the loop where you set each random number, so when you set cases[3] for example, loop from 0 to 2 and check to see if your new value for 3 clashes, if so, wash - rinse - repeat!
You have this line of code:
check_double==1;
That doesn't change check_double because it's ==, not =. == compares; it doesn't assign. Change that line to this:
check_double=1;
A helpful compiler (clang in this example) will give you a warning about this:
test.c:5:14: warning: expression result unused [-Wunused-value]
check_double==1;
~~~~~~~~~~~~^ ~
You can't check for duplicates with a single loop. You need to at least compare every possible pair of elements to be able to see if there's a duplicate. I'm guessing you forgot to loop over counter somewhere inside the second do...while?
Note that your method is not guaranteed to terminate. (Very, very likely but not certain.) Why don't you simply shuffle the cases array? Shuffling is simple but tricky; see Fisher-Yates (or Knuth) Shuffle for a simple algorithm.
If you are asking how to randomly sequence the number 1-25 then you could do something like this. This is a very brute-force way of generating the sequence, but it does work and might give you a starting point for something more optimized.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <conio.h>
const int LastNumber = 25;
bool HasEmpty(int available[LastNumber][2])
{
bool result = false;
for(int i = 0; i < LastNumber; i++)
{
if (available[i][1] == 0)
{
result = true;
break;
}
}
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int available[LastNumber][2];
int newSequence[LastNumber];
srand((unsigned int)time(NULL));
for(int i = 0; i < LastNumber; i++)
{
available[i][0]=i;
available[i][1]=0;
}
int usedIndex = 0;
while (HasEmpty(available))
{
int temp = rand() % (LastNumber + 1);
if (available[temp][1] == 0)
{
newSequence[usedIndex++] = available[temp][0];
available[temp][1] = 1;
}
}
for(int i = 0; i < LastNumber; i++)
{
printf("%d\n",newSequence[i]);
}
getch();
return 0;
}

Resources