Defective Binary search in C - c

Currently, I have a program the implements insertion sort and then uses binary search to search it (an array of ints). I currently have a 1 off error it seems.
My insertion sort should sort in descending order. Right now, it seems as if the value stored in the last position is missing.
#include <stdio.h>
void insertionSort(int nums[], int size)
{
int i, key, j;
for (i = 1; i < size; i++)
{
key = nums[i];
j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && nums[j] > key)
{
nums[j + 1] = nums[j];
j = j - 1;
}
nums[j + 1] = key;
}
}
int binarySearch(int nums[], int size, int searchVal)
{
int l = 0, r = size - 1;
while (l <= r)
{
int m = l + (r - l) / 2;
// Check if x is present at mid
if (nums[m] == searchVal)
return m;
// If x greater, ignore left half
if (nums[m] < searchVal)
l = m + 1;
// If x is smaller, ignore right half
else
r = m - 1;
}
// if we reach here, then element was
// not present
return -1;
}
int main()
{
int n;
printf("Enter the number of elements (between 1 and 50) in the array: \n");
scanf("%d", &n);
int i, nums[n];
printf("Enter %d positive integers: \n", n);
for (i = 0; i < n; i++)
{
scanf("%d", &nums[i]);
}
int x = 0;
insertionSort(nums, n);
printf("Enter a positive integer or -1 to quit: \n");
scanf("%d", &x);
do
{
int ind = binarySearch(nums, n, x);
if (ind > 0)
{
printf("Found\n");
}
else
{
printf("Not Found\n");
}
printf("Enter a positive integer or -1 to quit: \n");
scanf("%d", &x);
} while (x != -1);
return 0;
}
Results:
Enter the number of elements (between 1 and 50) in the array:
9
Enter 9 positive integers:
7
4
10
49
6
12
32
17
Enter a positive integer or -1 to quit:
4
Not Found
Enter an positive integer -1 or to quit
12
Found
Enter a positive integer or -1 to quit:
5
Not Found
Enter a positive integer or -1 to quit:
49
Found
Enter a positive integer or -1 to quit:
-1
As you can see everything works but the first test where I test for the number 4. Does anyone know why I'm off by 1?

#include <stdio.h>
void insertionSort (int nums[], int size)
{
int i, key, j;
for (i = 1; i < size; i++) {
key = nums[i];
j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && nums[j] > key) {
nums[j + 1] = nums[j];
j = j - 1;
}
nums[j + 1] = key;
}
}
int binarySearch (int nums[], int size, int searchVal)
{
int l = 0, r = size - 1;
while (l <= r) {
int m = l + (r - l) / 2;
// Check if x is present at mid
if (nums[m] == searchVal)
return m;
// If x greater, ignore left half
if (nums[m] < searchVal)
l = m + 1;
// If x is smaller, ignore right half
else
r = m - 1;
}
// if we reach here, then element was
// not present
return -1;
}
int main ()
{
int n;
printf
("Enter the number of elements (between 1 and 50) in the array: \n");
scanf ("%d", &n);
int i, nums[n];
printf ("Enter %d positive integers: \n", n);
for (i = 0; i < n; i++) {
scanf ("%d", &nums[i]);
}
int x = 0;
insertionSort (nums, n);
printf ("Enter a positive integer or -1 to quit: \n");
scanf ("%d", &x);
do {
int ind = binarySearch (nums, n, x);
if (ind >= 0) {
printf ("Found\n");
} else {
printf ("Not Found\n");
}
printf ("Enter a positive integer or -1 to quit: \n");
scanf ("%d", &x);
} while (x != -1);
return 0;
}
Try this one
just one error that is solve- if(ind>=0)

While you have discovered that checking the (ind > 0) causes failure to find the elements at index 0 and (ind >= 0) provides a solution, let's look at a short test case that validates the binarySearch() finds all elements of your sorted array without the user having to continually enter or redirect information to your program.
Any time you are testing algorithms, provides a simple validation framework that tests all elements, numbers, etc. without a user input requirement. Take your '9' numbers for example. Simply including an initialized array and sorting and then looping over all values will validate whether the binarySearch() is performing as intended. (it will save you no end of grief in the process as well). A short code exercising your search over the complete array can be as simple as:
int main (void) {
int nums[] = { 7, 4, 10, 49, 6, 12, 32, 17, 21 },
n = sizeof nums / sizeof *nums;
insertionSort (nums, n);
for (int i = 0; i < n; i++)
printf (" %2d (%s)\n", nums[i],
binarySearch (nums, n, nums[i]) >= 0 ? "found" : "not found");
}
Example Use/Output
$ ./bin/bsearchtest
4 (found)
6 (found)
7 (found)
10 (found)
12 (found)
17 (found)
21 (found)
32 (found)
49 (found)
Each element is now listed as "found" or "not found" and the code exits on its own.

Related

How to find a minimum?

I need to make a user enter the N (the number) between 7 and 12 ([7;12]). Then, I need to make the user enter the amount of numbers, which should be equal to N. Then, I need to output the sum of these numbers, find the average, min and max.
It works perfectly, except the minimum. When the count of numbers starts from 1, my program shows me that the minimum is 0. Thank you ahead...
#include <stdio.h>
int main(void) {
int i = 0;
int N;
float numbers;
float sum = 0;
float average, min, max;
printf("Choose a number between 7 and 12: ");
scanf("%d", &N);
if (N >= 7 && N <= 12) {
printf("You have chosen: %d\n", N);
printf("Now choose the amount of N numbers you have chosen: ");
for (i = 0; i < N; i++) {
numbers = N; // the numbers the user enters must be
// strictly == N
scanf("%f", &numbers);
sum = sum + numbers;
average = sum / numbers;
if (numbers < min) {
min = numbers;
}
if (numbers > max) {
max = numbers;
}
}
printf("The sum of your numbers is: %f\n The average of "
"numbers: %f\n The max: %f\n The min: %f\n",
sum, average, max, min);
}
}
The output is:
Choose a number between 7 and 12: 7
You have chosen: 7
Now choose the amount of N numbers you have chosen: 1
2
3
4
5
6
7
The sum of your numbers is: 28.000000
The average of numbers: 4.000000
The max: 7.000000
The min: 0.000000
Your min and max values are used uninitialized. On your platform/compiler, it appears that these are being default initialized to zero, but the C Standard does not require that.
To fix this issue, just initialize those variables (at the time of their declarations) to values that cannot be the final values (like the +/- values of the FLT_MAX constant, defined in <float.h>):
//...
float average, min = FLT_MAX, max = -FLT_MAX;
//...
I would go about this in a completely different fashion. Store the numbers in an array and then sort them. This is an example using integers, but it is very easy to modify for float usage.
#include <stdio.h>
// Bubble sort
void bubbleSort (int *numArray, int numElements) {
int sorted = 0, temp;
while (!sorted) {
// Set this flag here
sorted = 1;
for (int i = 0; i < numElements - 1; i++) {
// Swaps the numbers
if (numArray [i] > numArray [i + 1]) {
temp = numArray [i];
numArray [i] = numArray [i + 1];
numArray [i + 1] = temp;
sorted = 0;
}
}
}
}
float calcAverage (int numArray [], int numElements) {
float avg = 0;
for (int i = 0; i < numElements; i++) avg += numArray [i];
return avg / numElements;
}
int main() {
int numElements = 0;
// Ensure they actually enter a number!
while (numElements < 7 || numElements > 12) {
printf ("Please enter a number between 7 and 12: ");
// Input validation is always important in my opinion.
if (!scanf ("%d", &numElements)) {
printf ("ERROR: NaN value passed! ");
}
else if (numElements < 7 || numElements > 12) printf ("ERROR: Invalid number! ");
// Clear the buffer
while (getchar() != '\n');
}
printf ("You have chosen: %d.\n", numElements);
// Create our array and store our current number.
int numArray [numElements], fGood;
for (int i = 0; i < numElements; i++) {
// Reset this flag at the beginning of the loop
fGood = 0;
while (!fGood) {
printf ("Please enter value %d: ", i + 1);
// Assume it's a good value
fGood = 1;
if (!scanf ("%d", &numArray [i])) {
printf ("ERROR: Invalid value passed! ");
}
while (getchar() != '\n');
}
}
bubbleSort (numArray, numElements);
printf ("Average of entered numbers: %.2f\nMinimum value: %d\nMaximum value: %d\n", calcAverage(numArray, numElements), numArray [0], numArray [numElements - 1]);
return 0;
}

Why doesn't my C program for the Collatz sequence print the final value (1)?

I am currently making a program for the collatz sequence on C, however the last value, which is 1, is not being printed. For example, when I input 8, the outcome must be 8 4 2 1, but it only prints 8 4 2, or when I input 5, it only prints 5 16 8 4 2. What can I put inside the while ( ) to print the complete answer? Thank you!!
void
CollatzSequence(int n)
{
int x = 1;
do {
x++;
printf("%3d", n);
if (n%2==0)
n /= 2;
else
n = 3 * n + 1;
}
while ( );
printf("\n");
}
int
main()
{
int n;
do {
printf("Input an integer greater than 0: ");
scanf("%d", &n);
if (n <= 0)
printf("Invalid input. Try again.\n");
} while (n <= 0);
CollatzSequence(n);
return 0;
}
Code needs new loop exit condition.
Loop is done once 1 is printed.
Sample below.
void CollatzSequence(int n) {
for (;;) {
printf("%3d", n);
if (n == 1)
break;
if (n % 2 == 0)
n /= 2;
else
n = 3 * n + 1;
}
printf("\n");
}

C program to find the trailing ZEROS at the end of a FACTORIAL of a given number

I have return the code to find a factorial and to display trailing zeros at the end of the factorial, but the output is wrong... could you please help me to find the mistake?
#include <stdio.h>
int main() {
int m = 1, i, N, count = 0;
scanf("%d", &N);
for (i = 1; i <= N; i++) {
m = m * i;
}
printf("%d", m);
while (m > 0) {
if ((m % 10) == 0) {
count = count + 1;
m = m / 10;
}
break;
}
printf("%d", count);
return 0;
}
Your code only works for very small values of N: up to 9. For slightly larger values, you would need to add an else keyword before the break statement and you would get a correct result for a few more cases.
For larger values, you must compute the power of 5 that divides the factorial. You can do this incrementally by summing the power of 5 that divide each individual number up to and including N.
#include <stdio.h>
int main() {
int N, count;
if (scanf("%d", &N) != 1)
return 1;
/* only consider factors that are multiples of 5 */
count = 0;
for (int i = 5; i <= N; i += 5) {
for (int j = i; j % 5 == 0; j /= 5)
count++;
}
printf("%d\n", count);
return 0;
}
An even simpler and faster solution is this: compute the number of multiples of 5 less or equal to N, add the number of multiples of 5*5, etc.
Here is the code:
#include <stdio.h>
int main() {
int N, count;
if (scanf("%d", &N) != 1)
return 1;
count = 0;
for (int i = N; (i /= 5) > 0;) {
count += i;
}
printf("%d\n", count);
return 0;
}
you have two problems
your collapse the two outputs so you see only one of them / you cannot see who is who, just add a separator between them
an else is missing when you count so you count to only up to 1 and the result is wrong from factorial 10
So the minimal changes produce :
int main()
{
int m=1,i,N,count=0;
scanf("%d",&N);
for(i=1;i<=N;i++)
{
m=m*i;
}
printf("%d\n",m); /* <<< added \n */
while(m>0)
{
if((m%10)==0)
{
count=count+1;
m=m/10;
}
else /* <<< added else */
break;
}
printf("%d\n",count); /* <<< added \n */
return 0;
}
after the changes :
pi#raspberrypi:/tmp $ ./a.out
5
120
1
pi#raspberrypi:/tmp $ ./a.out
10
3628800
2
Of course that supposes first you are able to compute the factorial without overflow
I also encourage you to check a value was read by scanf, checking it returns 1
#include <stdio.h>
int main()
{
int n,i,f=1,t,c=0;
printf("Enter number ");
scanf("%d",&n);
t=n;
for(i=1;t>=5;i++)
{
t=n/5;
c=c+t;
n=t;
}
printf("number of zeros are %d",c);
return 0;
}

Why does this ISBN checking code turn '0' into 45?

Can you help me find out why the second 0 in the array turns into 45 please.
Everything is okay but except this number makes the result goes wrong. I cannot find out what's the matter with this.
Here is my code:
#include <stdio.h>
int getuserchoice() {
int n;
printf("---ISBN Validate---");
printf("\n1-ISBN Checking");
printf("\n2-Quit");
printf("\nSelect: ");
scanf("%d", &n);
return n;
}
int main() {
long a[10];
long sum = 0;
int i = 0, n = 1;
long x;
if (getuserchoice() == 1) {
printf("\nEnter the values for ISBN number : ");
scanf("%ld", &x);
if (x > 0) {
while (x > 0) {
a[i] = x % 10;
x = x / 10;
i++;
}
}
for (i = 0; i < 10; i++)
printf("%ld\t", a[i]);
for (i = 0; i < 10; i++) {
sum += a[i] * n;
n++;
}
if (sum % 11 == 0)
printf("\nISBN Status: Valid!");
else
printf("\nISBN Status: Invalid!");
} else
printf("\nSee you later!");
getchar();
return 0;
}
By default uninitialized arrays contain garbage (literally anything). It so happens that that particular element contains 45 (amazing, isn't it?).
It stays 45 because leading 0s are discarded when reading a number (you should read it as a string (C++) or char[]), so you are never accessing that particular array element to give it a meaningful value.
Here's SO post on how to initialize an array with 0s in C.

Factorize a number in C

I want do a program of factorization like this: 72 = 3 * 2 ^ 3 ^ 2
in C language, how can i do the program ?
I tried to do this but I can not do it :
#include <stdio.h>
int main(){
int n;
int j;
printf("Insert a positive integer number greater than 1\n")
scanf("%d", &n);
j = 2;
do
{
if( n % j == 0)
{
printf("%d\n", j);
n = n / j;
}
else{
j++;
}
}
while ( n > 1);
}
Assuming that given 72, you want to output 2^3 X 3^2 this code should do it:
/* Decides when to print multiplication sign */
const char *get_mult_string()
{
static int first_divisor=1;
if (first_divisor==1) {
first_divisor=0;
return "";
} else {
return " X ";
}
}
void factorize() {
int n;
int j;
printf("Insert a positive integer number greater than 1: ");
scanf("%d", &n);
j = 2;
int power_count=0;
do {
if (n % j == 0) {
power_count++;
n = n / j;
}
else {
if (power_count>0) {
printf("%s(%d^%d)", get_mult_string(), j, power_count);
power_count=0;
}
j++;
}
}
while (n > 1);
if (power_count>0) {
printf("%s(%d^%d)\n", get_mult_string(), j, power_count);
}
}
Try creating an array, where each slot represents a prime number, and initialize them all to 0. For example, array[0] means 2, array[1] 3, array[2] 5, array[3] 7, array[4] 11.
Rather than printing out the prime number when you reach it, as you do in your code, increment that slot in the array. In the end, you can call something like printf("2^%d * 3^%d * 5^%d * 7^%d * 11^%d",array[0],array[1],array[2],array[3],array[4]).
Note: switch statements would probably be your friend here.

Resources