Code not assessing peaks correctly - c

i have a code that prints out the number of peaks and their given magnitudes. the input is in the form of a single line that contains random integers separated by white space. a peak is only defined to be so when it is directly preceded and followed by a smaller value.
examples:
0 4 18 18 26 40 40 29 25 2 0 //has one peak of magnitude 40.
20 10 20 /*has no peaks, because both 20's are either not
preceded or followed by a smaller number.*/
the code fails to behave correctly when the input data, c, begins with a declining set of numbers.
for example, the input: 9 8 7 6 5 4 returns a peak of "9", when it shouldn't return any magnitude.
another situation where it's behaving incorrectly is when we have the following input: 10 10 10 5 5 5 12 12 12 -1. its returning a magnitude of "10", while again, it shouldn't return any magnitude because it doesn't fulfill the conditions of a peak .
the following is the code:
#include <stdio.h>
int main(void)
{
int a = 0;
int b = 0;
int c = 0;
int counter = 0;
scanf("%d", &c);
printf("Number Magnitude\n");
while (c >= 0){
if ((b > a) && (b > c)) { //to check if we have a peak
counter++;
printf("%4d%11d\n", counter, b);
a = b;
b = c;
scanf("%d", &c);
}
else if ((a < b) && (b == c)) {
b = c;
scanf("%d", &c);
}
else {
a = b;
b = c;
scanf("%d", &c);
}
}
}
i prefer to keep the level of coding as minimum as possible, as i haven't done more than loops and if statements at this stage.

The issue is being caused because you initialize your boundary values to the minimum possible value. Any possible peak value will test positive when compared to that boundary value.
A small change fixes it, both boundary values should be set to a value that tests negative when compared to any possible peak value:
int a = INT_MAX;
int b = INT_MAX;
You will however to detect new lines and reset your values if you want to be able to do multiple lines of input, but I believe this is an existing problem

In that case, you should try to ask the program to mimic what you would to by hand: you must considere 3 value, so you must read 3 values before testing for a peak. And you should always control the return value from scanf to be able to process and end of file or an incorrect input.
Your code could become:
#include <stdio.h>
int main(void)
{
int a = 0;
int b = 0;
int c = 0;
int counter = 0;
int cr;
cr = scanf("%d%d%d", &a,&b,&c);
if (cr != 3) {
printf("Incorrect input\n");
return 1;
}
printf("Number Magnitude\n");
while ((cr > 0) && (c >= 0)) {
if ((b > a) && (b > c)) { //to check if we have a peak
counter++;
printf("%4d%11d\n", counter, b);
a = b;
b = c;
}
else if ((a >= b) || (b != c)) {
a = b;
b = c;
} // nothing to do if a<b and b==c
cr = scanf("%d", &c); // read once outside of the loop
}
return 0;
}
BTW, above code allows multi-line input.

Related

Program that inputs a number and then prints the set bits of that number with the bit integer displayed next to it

for example, if I enter 12, I want to get 81 41 as the set bits in 12 are 1100
This is what I have for now, I do not think I am implementing the for loop correctly
#include <stdio.h>
void bin(unsigned n)
{
char list[6];
int x = 0, y = 1;
/* step 1 */
if (n > 1)
bin(n / 2);
/* step 2 */
list[x] = n % 2;
x++;
/*for(int i = 0; i < x; i++) {
printf("%d\n",list[i]);
}*/
for(int i = 0; i < 5; i++) {
if(list[i] == 1 && i == 5) {
printf("32%i",y);
}
if(list[i] == 1 && i == 4) {
printf("16%i",y);
}
if(list[i] == 1 && i == 3) {
printf("8%i",y);
}
if(list[i] == 1 && i == 2) {
printf("4%i",y);
}
if(list[i] == 1 && i == 1) {
printf("2%i",y);
}
if(list[i] == 1 && i == 0) {
printf("1%i",y);
}
}
}
I checked that I was correctly storing the bytes in the array, and it outputted correctly, but when I try to look for them one at a time in a loop, it seems to get stuck on the 32 bit integer, so for 12, it would print 321 321
This program has Undefined Behaviour from accessing uninitialized values of list. I'm going to refactor this code so its easier to talk about, but know this refactored code is still incorrect.
x is always 0. y is always 1. x++ has no effect. This function can be rewritten as:
void bin(unsigned n)
{
char list[6];
if (n > 1)
bin(n / 2);
list[0] = n % 2;
for (int i = 0; i < 5; i++) {
if (list[i] == 1) {
switch (i) {
case 5: printf("321"); break;
case 4: printf("161"); break;
case 3: printf("81"); break;
case 2: printf("41"); break;
case 1: printf("21"); break;
case 0: printf("11"); break;
}
}
}
}
There are some problems here.
Firstly, list is not shared between calls to bin, nor are any other variables.
In every call to bin, only list[0] is assigned a value - all others indices contain uninitialized values. You are (un)lucky in that these values are seemingly never 1.
With your example of 12 as the starting value:
When you initially call bin(12), what happens is:
bin(12) calls bin(6), bin(6) calls bin(3), bin(3) calls bin(1).
Starting from the end and working backwards, in bin(1):
n = 1, so list[0] = n % 2; assigns 1. The loop checks each element of list for the value 1, finds it when the index (i) equals 0, and prints 11.
This is repeated in bin(3), as 3 % 2 is also 1, and again this result is assigned to the first element of list. Again, we print 11.
In bin(6), 6 % 2 is 0. The loop finds no elements of list that equal 1. Nothing is printed.
And again, this is repeated in bin(12), as 12 % 2 is 0. Nothing is printed.
To reiterate, it is pure luck that this program appears to work. Accessing list[1] through list[4] (i < 5 ensures you never access the last element) in each function call is Undefined Behaviour. It is generally not worth reasoning about a program once UB has been invoked.
When dealing with bits, it would be a good time to use some bitwise operators.
Here is a program that more-or-less does what you have described.
It assumes 32-bit unsigned (consider using fixed width types from <stdint.h> to be more precise).
This program works by repeatedly shifting the bits of our initial value to the right b number of places and testing if the rightmost bit is set.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
unsigned num = argc > 1 ? atoi(argv[1]) : 42;
unsigned b = 32;
while (b--)
if ((num >> b) & 1)
printf("%u1 ", 1 << b);
putchar('\n');
}
$ ./a.out 12
81 41

Print a different result than actual answer (Ciel and A-B Problem)

Input:
An input contains 2 integers A and B.
Output:
Print a wrong answer of A-B. Your answer must be a positive integer containing the same number of digits as the correct answer, and exactly one digit must differ from the correct answer. Leading zeros are not allowed. If there are multiple answers satisfying the above conditions, anyone will do.
Code:
#include <stdio.h>
int no_of_zeroes(int x);
int main()
{
int a, b;
int res1, res2;
int n1, n2;
scanf("%d",&a);
scanf("%d",&b);
res1 = a - b;
res2 = res1 + 10;
n1 = no_of_zeroes(res1);
n2 = no_of_zeroes(res2);
if(res1 < 9) printf("%d",res1 + 1);
else if(res1 == 9) printf("%d",res1-1);
else if((n1 == n2) && (res1 > 9)) printf("%d",res2);
else if((n2 > n1) && (res1>9))
{
res2 = res2 - 20;
printf("%d",res2);
}
}
int no_of_zeroes(int x)
{
int count = 0;
while(x>0)
{
x = x / 10;
count++;
}
return count;
}
Error:
What different should i do, basically else if blocks are creating trouble.
Your answer must be a positive integer containing the same number of digits as the correct answer
So the answer should be a-b. But the statement also says
exactly one digit must differ from the correct answer
Since it didn't specify the position of the digit, changing the last digit only should give us the correct answer to this problem. And so counting the number of digits of the difference is redundant.
Now the issue is - how to change the last digit? It's simple. We add 1 to the difference.
But there is a catch! If the difference is 99 and we add 1 to it, the result will be 100. Here, not only we're changing more than one digit, but also the number of digits.
And so, all we have to do is subtract 1 from the difference if the last digit of the difference is 9.
And so, the if-else block should look something like this:
int diff = a - b;
if(diff%10 == 9) {
diff--;
}
else {
diff++;
}
Here's my full code:
#include <stdio.h>
int main(void) {
int a, b;
scanf("%d%d", &a, &b);
int diff = a - b;
if(diff%10 == 9) {
diff--;
}
else {
diff++;
}
printf("%d\n", diff);
return 0;
}
On a different note, the function no_of_zeroes(int x) will return 0 if x=0. But, it should return 1 under general circumstances. And so the function should be something like this:
int no_of_digits(int x)
{
/* Adding the following line should fix the issue */
if(x==0) return 1;
int count = 0;
while(x>0)
{
x = x / 10;
count++;
}
return count;
}
I think you are making this much more complicated than needed. All you need is to check the last digit of the correct result and then change it.
For 0 and positive numbers:
last digit is 0 : add 1
last digit is 1 : add 1
...
last digit is 8 : add 1
last digit is 9 : subtract 1
For negative numbers, you simply change the sign and handle it as the positive number. This can be done because -123 has the same digits as 123.
So the code can be:
void wrongCalc(int a, int b)
{
int res = a - b; // Calculate result
if (res < 0) res = -res; // Change sign if negative
int lastDigit = res % 10; // Find last digit
if (lastDigit == 9)
{
--res; // Subtract 1
}
else
{
++res; // Add 1
}
printf("%d - %d = %d (correct result is %d)\n", a, b, res, a-b);
}
Limitations:
1) The program doesn't handle the possible integer overflow in a-b
2) The program doesn't handle the possible integer overflow in res = -res;
3) The program doesn't handle the case where the correct result is INT_MAX

C variable specified as a long long but recognized as an int

I'm working on a program that checks the validity of credit card numbers for the CS50 class I'm taking (it's legal I swear haha) and I'm currently working on correctly getting the first two numbers of each CC# to check what company it is from. I've commented what each part does for clarity and also commented where my problem arises.
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <math.h>
#include <string.h>
int main(void)
{
long long ccn = get_long_long("Enter CCN: \n");
int count = 0;
long long ccn1 = ccn;
// finds the amount of digits entered and stores that in int count.
while (ccn1 != 0)
{
ccn1 /= 10;
+count;
}
printf("%i \n", count);
// ln 17- 19 should take int count, subtract two, put that # as the power of 10,
// then divide the CC# by that number to get the first two numbers of the CC#.
long long power = count - 2;
// here is where i get the error. its a long long so it
// should hold up to 19 digits and im only storing 14 max
// but it says that 10^14th is too large for type 'int'
long long divide = pow(10,power);
long long ft = ccn / divide;
printf("power: %i \n", power); //ln 20-22 prints the above ints for debug
printf("Divide: %lli \n", divide);
printf("First two: %lli \n", ft);
string CCC;
// ln 24-35 cross references the amount of digits in the CC#
// and the first two digits to find the comapany of the credit card
if ((count == 15) && (ft = 34|37))
{
CCC = "American Express";
}
else if ((count == 16) && (ft = 51|52|53|54|55))
{
CCC = "MasterCard";
}
else if ((count = 13|16) && (ft <=49 && ft >= 40))
{
CCC = "Visa";
}
printf("Company: %s\n", CCC);
}
The first issue is the +count in the loop. This should be ++count. Because of this, count stays at 0 and power = -2. You can avoid all that power stuff. You already have the loop, you can use it to get the first two digits:
int ft = 0;
while (ccn1 != 0)
{
// When you are down to 10 <= ccn1 < 100, store it
if (ccn1 < 100 && ccn1 > 9) ft = ccn1;
ccn1 /= 10;
++count;
}
Your second issue is how you do your comparisons.
if ((count == 15) && (ft = 34|37))
First, = is assignment, and == tests equality. Second, | is bitwise OR, || is logical OR. Third, you can't test multiple values like that. Correct way:
if ((count == 15) && (ft == 34 || ft == 37))

If condition on modulo, failing logical condition?

I wanted to check if a fraction 2 4 (for example) can be simplified to 1 2!!
However logical condition fails.
#include <stdio.h>
int main()
{
int a,b,live=1;
printf("\n\nInput integers for fraction:");
scanf(" %d%d",&a,&b);
while(live){
if(!(a%2 && b%2)){
a/=2;
b/=2;
}else if(!(a%3 && b%3)){
a/=3;
b/=3;
}else if(!(a%5 && b%5)){
a/=5;
b/=5;
}else if(!(a%7 && b%7)){
a/=7;
b/=7;
}else live--;
}
printf("Simplified Fraction is %d/%d",a,b);
}
The condition a%2 is equivalent to a%2 != 0, i.e. it tests if a is not divisible by 2. From De Morgan's Laws, the condition if(!(a%2 && b%2)) is equivalent to if(!(a%2) || !(b%2)) or if((a%2 == 0) || (b%2 == 0)), which is not what you want.
You really want to test if((a%2 == 0) && (b%2 == 0)) -- that is, if both are divisible by 2, not if either is divisible by 2. Writing it this way is also much less confusing.
And it should also be obvious that in order to simplify any fraction, you need to test for all possible prime factors, which is impossible to do with a finite number of if statements. The recommended way of doing this is to use the Euclidean algorithm to determined the greatest common divisor of the numerator and denominator, and then you divide both by the GCD to get the fraction in reduced form.
(!(a%2 && b%2)) will yield true even if only one of a%2 or b%2 holds.
Have a look at the following example:
3/4 -> a%2 == 0, b%2 == 1 -> (a%2 && b%2) == 0 -> (!(a%2 && b%2)) == 1
You are looking for (a%2 == 0 && b%2 == 0) instead of your condition, and similarly for other conditions.
An "after an accepted answer" answer.
This does not detail the issues with OP's code nicely like #Adam Rosenfield, but does address the larger OP desire of "I wanted to check if a fraction 2 4 (for example) can be simplified to 1 2!!" in a general way.
Use the Euclidean Algorithm to find the greatest-common-denominator, then divide a,b by it. No need to generate prime number list. Very fast.
// Euclidean Algorithm
unsigned gcd(unsigned a, unsigned b) {
while (b != 0) {
int t = b;
b = a % b;
a = t;
}
return a;
}
#include <stdio.h>
int main() {
int a, b;
for (;;) {
printf("\nInput positive fraction like 12/30: ");
if (scanf("%u/%u", &a, &b) != 2)
break;
unsigned g = gcd(a, b);
a /= g;
b /= g;
printf("Simplified Fraction is %u/%u", a, b);
}
return 0;
}
In addition to the logical or issue identified by others, you also have an infinite loop with your while condition. You don't need (or want) to loop with your current code. Try this
#include <stdio.h>
int main ()
{
int a, b;
printf ("\n\nInput integers for fraction:");
scanf (" %d%d", &a, &b);
while (a % 2 == 0 && b % 2 == 0)
{
a /= 2;
b /= 2;
}
while (a % 3 == 0 && b % 3 == 0)
{
a /= 3;
b /= 3;
}
while (a % 5 == 0 && b % 5 == 0)
{
a /= 5;
b /= 5;
}
while (a % 7 == 0 && b % 7 == 0)
{
a /= 7;
b /= 7;
}
printf ("Simplified Fraction is %d/%d", a, b);
}
Output(s) with your given input(s)
Input integers for fraction:2 4
Simplified Fraction is 1/2
Input integers for fraction:8 24
Simplified Fraction is 1/3

Extracting individual digits from a long in C

I'm doing a homework assignment for my course in C (first programming course).
Part of the assignment is to write code so that a user inputs a number up to 9 digits long, and the program needs to determine whether this number is "increasing"/"truly increasing"/"decreasing"/"truly decreasing"/"increasing and decreasing"/"truly decreasing and truly increasing"/"not decreasing and not increasing". (7 options in total)
Since this is our first assignment we're not allowed to use anything besides what was taught in class:
do-while, for, while loops, else-if, if,
break,continue
scanf, printf ,modulo, and the basic operators
(We can't use any library besides for stdio.h)
That's it. I can't use arrays or getchar or any of that stuff. The only function I can use to receive input from the user is scanf.
So far I've already written the algorithm with a flowchart and everything, but I need to separate the user's input into it's distinct digits.
For example, if the user inputs "1234..." i want to save 1 in a, 2 in b, and so on, and then make comparisons between all the digits to determine for example whether they are all equal (increasing and decreasing) or whether a > b >c ... (decreasing) and so on.
I know how to separate each digit by using the % and / operator, but I can't figure out how to "save" these values in a variable that I can later use for the comparisons.
This is what I have so far:
printf("Enter a positive number : ");
do {
scanf ("%ld", &number);
if (number < 0) {
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
while (number < 0) {
a = number % 10;
number = number - a;
number = number / 10;
b = a;
}
Why not scan them as characters (string)? Then you can access them via an array offset, by subtracting the offset of 48 from the ASCII character code. You can verify that the character is a digit using isdigit from ctype.h.
EDIT
Because of the incredibly absent-minded limitations that your professor put in place:
#include <stdio.h>
int main()
{
int number;
printf("Enter a positive number: ");
do
{
scanf ("%ld", &number);
if (number < 0)
{
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
int a = -1;
int b = -1;
int c = -1;
int d = -1;
int e = -1;
int f = -1;
int g = -1;
int h = -1;
int i = -1;
while (number > 0)
{
if (a < 0) a = number % 10;
else if (b < 0) b = number % 10;
else if (c < 0) c = number % 10;
else if (d < 0) d = number % 10;
else if (e < 0) e = number % 10;
else if (f < 0) f = number % 10;
else if (g < 0) g = number % 10;
else if (h < 0) h = number % 10;
else if (i < 0) i = number % 10;
number /= 10;
}
/* Printing for verification. */
printf("%i", a);
printf("%i", b);
printf("%i", c);
printf("%i", d);
printf("%i", e);
printf("%i", f);
printf("%i", g);
printf("%i", h);
printf("%i", i);
return 0;
}
The valid numbers at the end will be positive, so those are the ones you validate to meet your different conditions.
Since you only need to compare consecutive digits, there is an elegant way to do this without arrays:
int decreasing = 2;
int increasing = 2;
while(number > 9)
{
int a = number % 10;
int b = (number / 10) % 10;
if(a == b)
{
decreasing = min(1, decreasing);
increasing = min(1, increasing);
}
else if(a > b)
decreasing = 0;
else if(a < b)
increasing = 0;
number /= 10;
}
Here, we walk through the number (by dividing by 10) until only one digit remains. We store info about the number up to this point in decreasing and increasing - a 2 means truly increasing/decreasing, a 1 means increasing/decreasing, and a 0 means not increasing/decreasing.
At each step, a is the ones digit and b is the tens. Then, we change increasing and decreasing based on a comparison between a and b.
At the end, it should be easy to turn the values of increasing and decreasing into the final answer you want.
Note: The function min returns the smaller of its 2 arguments. You should be able to write your own, or replace those lines with if statements or conditionals.
It's stupid to ask you to do loops without arrays --- but that's your teacher's fault, not yours.
That being said, I would do something like this:
char c;
while (1) {
scanf("%c", &c);
if (c == '\n') /* encountered newline (end of input) */
break;
if (c < '0' || c > '9')
break; /* do something to handle bad characters? */
c -= '0';
/*
* At this point you've got 0 <= c < 9. This is
* where you do your homework :)
*/
}
The trick here is that when you type numbers into a program, you send the buffer all at once, not one character at a time. That means the first scanf will block until the entire string (i.e. "123823" or whatever) arrives all at once, along with the newline character ( '\n' ). Then this loop parses that string at its leisure.
Edit For testing the increasing/decreasing-ness of the digits, you may think you need to store the entire string, but that's not true. Just define some additional variables to remember the important information, such as:
int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far;
etc. etc.
Let us suppose you have this number 23654
23654 % 10000 = 2 and 3654
3654 % 1000 = 3 and 654
654 % 100 = 6 and 54
54 % 10 = 5 and 4
4
This way you can get all the digits. Of course, you have to know if the number is greater than 10000, 1000, 100 or 10, in order to know the first divisor.
Play with sizeof to get the size of the integer, in order to avoid a huge if...else statement
EDIT:
Let us see
if (number>0) {
// Well, whe have the first and only digit
} else if (number>10) {
int first_digit = number/10;
int second_digit = number % 10;
} else if (number>100) {
int first_digit = number/100;
int second_digit = (number % 100)/10;
int third_digit = (number % 100) % 10;
} ...
and so on, I suppose
// u_i is the user input, My homework asked me to extract a long long, however, this should also be effective for a long.
int digits = 0;
long long d_base = 1;
int d_arr[20];
while (u_i / d_base > 0)
{
d_arr[digits] = (u_i - u_i / (d_base * 10) * (d_base * 10)) / d_base;
u_i -= d_arr[digits] * d_base;
d_base *= 10;
digits++;
}
EDIT: the extracted individual digit now lives in the int array d_arr. I'm not good at C, so I think the array declaration can be optimized.
Here's a working example in plain C :
#include <stdio.h>
unsigned long alePow (unsigned long int x, unsigned long int y);
int main( int argc, const char* argv[] )
{
int enter_num, temp_num, sum = 0;
int divisor, digit, count = 0;
printf("Please enter number\n");
scanf("%d", &enter_num);
temp_num = enter_num;
// Counting the number of digits in the entered integer
while (temp_num != 0)
{
temp_num = temp_num/10;
count++;
}
temp_num = enter_num;
// Extracting the digits
printf("Individual digits in the entered number are ");
do
{
divisor = (int)(alePow(10.0, --count));
digit = temp_num / divisor;
temp_num = temp_num % divisor;
printf(" %d",digit);
sum = sum + digit;
}
while(count != 0);
printf("\nSum of the digits is = %d\n",sum);
return 0;
}
unsigned long alePow(unsigned long int x, unsigned long int y) {
if (x==0) { return 0; }
if (y==0||x==1) { return 1; }
if (y==1) { return x; }
return alePow(x*x, y/2) * ((y%2==0) ? 1 : x);
}
I would suggest loop-unrolling.
int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits
int count = 0; //for number of digits in the given number
if(number>0) {
i=number%10;
number/=10;
count++;
}
if(number>0) {
h=number%10;
number/=10;
count++;
}
if(number>0) {
g=number%10;
number/=10;
count++;
}
....
....
/* All the way down to the storing variable a */
Now, you know the number of digits (variable count) and they are stored in which of the variables. Now you have all digits and you can check their "decreasing", "increasing" etc with lots of if's !
I can't really think of a better soltion given all your conditions.

Resources