I'm making a function that checks if 2 integers are relatively prime / coprime. The function returns 1 if they are relatively prime and 0 if they are not relatively prime.
The function should be able to accept any integer in any order, given that a and b are both not 0;
To my knowledge having a gcd of -1 is the same as having a gcd of 1. Is that correct?
This is my code:
int relatively_prime(int a, int b){
if (a == 0 || b == 0) return 0;
if (a%b == 0 && (b != 1 || b != -1)) return 0;
else if (a%b== 0 && (b == 1 || b == -1)) return 1;
else return relatively_prime(b, a % b);
}
Is this correct? Is there any way to simplify or improve my code?
Thanks!
int gcd(int a, int b)
{
a=abs(a);
b=abs(b);
if (b == 0)
return a;
return gcd(b, a % b);
}
Now if the result is 1 they are coprime . You can convert negative number into positive to see if they are co prime and simplify the code .Technically speaking we can write 0 as 0* any number so 0 will not be co prime with any number other than 1 .
Is this correct?
No.
b != 1 || b != -1 is always true. So code is like
int relatively_prime(int a, int b){
if (a == 0 || b == 0) return 0;
if (a%b == 0 /* && (b != 1 || b != -1) */) return 0;
// a%b== 0 is never true below after the above line
// else if (a%b== 0 && (b == 1 || b == -1)) return 1;
else return relatively_prime(b, a % b);
}
... and does not return 1.
OP's code fails with undefined behavior (UB) at least with the case of relatively_prime(INT_MIN, -1) as it attempts INT_MIN % -1.
Is there any way to simplify ?
// Do not call with gcd_recursive(INT_MIN, -1)
static int gcd_recursive(int a, int b) {
if (b == 0) return a;
return gcd_recursive(b, a % b);
}
int relatively_prime_alt(int a, int b) {
if (b == -1) b = 1; // Avoid a INT_MIN % -1 in gcd_recursive()
int gcd = gcd_recursive(a, b);
return gcd == 1 || gcd == -1;
}
Related
#include <stdio.h>
int main(void) {
int a = 0, b = 0, c = 0,
total = 0, helper = 0, helper_2 = 0, helper_3 = 0;
scanf("%d%d%d%d", &total, &a, &b, &c);
helper = (a <= b && a <= c ? a : (b <= c ? b : c));
helper_2 = (c >= b && a >= c ? c : (b >= a && a >= c ? a : (c >= b && b >= a ? b : 0)));
helper_3 = (a >= b && a >= c ? a : (b >= c ? b : c));
if ((total < 0) || (total > 1000) || (helper <= 0) ||
(helper_2 <= 0) || (helper_3 <= 0) || (helper > 1000) ||
(helper_2 > 1000) || (helper_3 > 1000)) {
printf("0");
return 0;
}
else if ((helper + helper_2 + helper_3) <= total) {
printf("3");
}
else if (helper + helper_2 <= total) {
printf("2");
}
else if (helper <= total) {
printf("1");
}
else {
printf("0");
}
return 0;
}
That is the code. I sort three variables, and store them in 3 different variables according to their size, the small one goes to the first one and so on...
The thing is, all the variables MUST be between 0 and 1001.
It seems to work well, but it does not. It has errors but I cannot find them. I just would like to know if some of you guys can help me to improve this code or even tell me what inputs to use that would return an unexpected value.
Thanks so much:D
Edit: I fixed part of them by removing the 0 from the helper_2 expression:D it would return 0 if the input would be for ex: 6, 1, 3, 2.
EDIT2: I've already answered it how you solve using ternary, but the other answers are so much better than the one I was using. So, thank you so much for everyone who helped me:D
The expression:
helper_2 = (c >= b && a >= c ? c : (b >= a && a >= c ? a : (c >= b && b >= a ? b : 0)));
is wrong. The last part can return zero! That's a bug. When we know that a, b and c are all greater than zero, the result just can't be zero.
Try input a=1, b=3, c=2 and print the value of the helper variables.
int a = 1;
int b = 3;
int c = 2;
int helper_1 = (a <= b && a <= c ? a : (b <= c ? b : c));
int helper_2 = (c >= b && a >= c ? c : (b >= a && a >= c ? a : (c >= b && b >= a ? b : 0)));
int helper_3 = (a >= b && a >= c ? a : (b >= c ? b : c));
printf("%d %d %d --> %d %d %d\n", a, b, c, helper_1, helper_2, helper_3);
Output:
1 3 2 --> 1 0 3
which is obviously wrong
My advice is to avoid the complex ternary conditionals. Write simple if statements instead.
For instance:
if (a > b)
{
// swap a and b
}
if (a > c)
{
// swap a and c
}
if (b > c)
{
// swap b and c
}
// Now a, b and c is sorted with a being smallest
You could really use a few helper functions to clean up your code.
One function to "swap" a pair of variables if the first is greater than the second:
void Sort2(int* x, int* y) {
if (*x > *y) {
int tmp = *x;
*x = *y;
*y = tmp;
}
}
Another to validate a range:
int isInRange(int minimum, int maximum, int value) {
return ((minimum <= value) && (value <= maximum));
}
Then your code gets really simple:
int main(void) {
int a = 0, b = 0, c = 0,
total = 0;
scanf("%d%d%d%d", &total, &a, &b, &c);
Sort2(&a, &b);
Sort2(&a, &c);
Sort2(&b, &c);
// a,b, and c are in sorted order
if !(isInRange(0, 1000, total) && isInRange(1, 1000, a) && isInRange(1, 1000, b) && isInRange(1, 1000, c))
{
printf("0");
return 0;
}
if ((a + b + c) <= total) {
printf("3");
}
else if (a + b <= total) {
printf("2");
}
else if (a <= total) {
printf("1");
}
else {
printf("0");
}
return 0;
}
Just remove helper_2 condition and use:
a>b? ( c>a? a : (b>c? b:c) ) : ( c>b? b : (a>c? a:c) ) )
instead. :D
So to change my question. It refuses to recognize that there are four twos in a row. It recognizes that there are four ones in a row but that happens after the four twos. Why is this happening?
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 0 0
1 2 2 2 2 0 0
int checkFour(int a, int b, int c, int d){
if (a == b == c == d){
return 1;
}
else{
return 0;
}
return 0;
}
//check for the horizontal win
int checkHorizontal(){
for(int i=0; i < rows; i++){
for(int j=0; j < column - 3; j++){
if ((board[i][j] != 0) && (board[i][j+1] != 0) && (board[i][j+2]!= 0) && (board[i][j+3] != 0)){
if (checkFour(board[i][j],board[i][j+1],board[i][j+2],board[i][j+3]) == 1){
printf("Game Over\n");
exit(0);
}
}
}
}
}
What am I doing wrong?
if (a == b == c == d){ does not work the way you might think. The result of a comparison in C is a boolean value of 0 or 1. Given that == operator has left-to-right associativity, your statement can be re-written as:
if ((((a == b) == c) == d)
This appears to give correct results when they are all 1. This is because it ends up comparing the values (1) to the result of the comparison operation, also (1).
(((a == b) == c) == d) a == b -> 1
((1 == c) == d) 1 == c -> 1
(1 == d) 1 == d -> 1
The correct way is to use logical AND.
if (a == b && a == c && a == d)
All three comparisons need to evaluate to true for the entire statement to be true.
Note that there are other combinations that work. Ex:
if (a == b && b == c && c == d)
By the way, you can shorten the entire function to
int checkFour(int a, int b, int c, int d){
return a == b && b == c && c == d;
}
The problem is that you misunderstood the mechanism of C. the code if (a == b == c == d) wouldn't take if abcd are all values equal then return 1. because C computes from left to right(same priority), so it would compute a == b first, the result is 1 or 0, then take this result to compare with c, the second result also is 1 or 0, finally take second result to compare with d and the final result is come out.
The right code is like this:
if ((a == b) && (d == c) && (b == c))
return 1;
else
return 0;
I'd like to ask the following misunderstandings of C language, which I see I'm having.
I'm sorry if the code is not properly indented, I tried as much as I could but there are not so many guides on the internet.
The program asked given a starting number 'val' and a Even-Odd or Odd-Even alternating sequence (which stops whenever this rules is violated) to print the greater prime number with 'val'.
I tried with two functions and the main: one to control the GCD between two given numbers and the other to keep tracks of the greatest one, but I think I miss something in the code or in the conception of C function,
Because when compiled it returns me 0 or great number which I'm not entering.
One example to understand what I should do:
If my sequence was 10, 7, 8, 23 and my val was 3, I had to print 23, because it is the greatest integer prime with 3.
Here's the code :
#include <stdio.h>
int mcd(int a, int b)
{ // Gcd function
if (a == 0)
return b;
else
return mcd(b % a, b);
}
int valuta(int val, int h) // Valuing Max function
{
int temp = 0;
if (mcd(val, h) == 1 && h > temp)
temp = h;
return temp;
}
int main()
{
int val, d, x, y, z, t, contatore = 1;
scanf("%d", &val);
scanf("%d%d", &x, &y);
if (x > y && mcd(val, x) == 1)
{ // Two options
t = x;
}
else if (y > x && mcd(val, y) == 1)
{
t = y;
}
if ((x % 2 == 0 && y % 2 == 0) || (x % 2 == 1 && y % 2 == 1))
{ // Bad case
if (x > y && mcd(val, x) == 1)
{
t = x;
contatore = 0;
}
else if (y > x && mcd(val, y) == 1)
{
t = y;
contatore = 0;
}
}
else
{
while (contatore == 1)
{
scanf("%d", &z);
t = valuta(val, z);
if (x % 2 == 0 && z % 2 == 0)
{ // Even- Odd - Even
scanf("%d", &d);
t = valuta(val, d);
if (d % 2 == 0)
{
contatore = 0;
}
else
{
contatore = 0;
}
}
if (x % 2 == 1 && z % 2 == 1)
{ //Odd- Even- Odd
scanf("%d", &d);
t = valuta(val, d);
if (d % 2 == 1)
{
contatore = 0;
}
else
{
contatore = 0;
}
}
}
}
printf("%d\n", t);
return 0;
}
PS. Is there any way to reduce the number of lines of code or to reduce the effort in coding? I mean, a straightforward solution will be helpful.
Your valuta() function is flawed in that it needs to return the maximum qualifying value so far but has no knowledge of the previous maximum - temp is always zero. The following takes the previous maximum as an argument:
int valuta(int val, int h, int previous )
{
return ( mcd(val, h) == 1 && h > previous ) ? h : previous ;
}
And is called from main() thus:
t = valuta( val, x, t ) ;
The test mcd(val, h) == 1 is flawed, because mcd() only ever returns the value of parameter b which is not modified in the recursion, so will never return 1, unless the argument b is 1. Since I have no real idea what mcd() is intended to do, I cannot tell you how to fix it. It appear to be a broken implementation of Euclid's greatest common divisor algorithm, which correctly implemented would be:
int mcd(int a, int b)
{
if(b == 0)
return a;
else
return mcd(b, a % b);
}
But I cannot see how that relates to:
"[...] he greatest integer prime with 3 [...]
The odd/even even/odd sequence handling can be drastically simplified to the extent that it is shorter and simpler than your method (as requested) - and so that it works!
The following is a clearer starting point, but may not be a solution since it is unclear what it is it is supposed to do.
#include <stdio.h>
#include <stdbool.h>
int mcd(int a, int b)
{
if(b == 0)
return a;
else
return mcd(b, a % b);
}
int valuta(int val, int h, int previous )
{
return ( mcd(val, h) && h > previous ) ? h : previous ;
}
int main()
{
int val, x, t ;
printf( "Enter value:") ;
scanf("%d", &val);
typedef enum
{
EVEN = 0,
ODD = 1,
UNDEFINED
} eOddEven ;
eOddEven expect = UNDEFINED ;
bool sequence_valid = true ;
printf( "Enter sequence in odd/even or even/odd order (break sequence to exit):\n") ;
while( sequence_valid )
{
scanf("%d", &x);
if( expect == UNDEFINED )
{
// Sequence order determined by first value
expect = (x & 1) == 0 ? EVEN : ODD ;
}
else
{
// Switch expected odd/even
expect = (expect == ODD) ? EVEN : ODD ;
// Is new value in the expected sequence?
sequence_valid = (expect == ((x & 1) == 0 ? EVEN : ODD)) ;
}
// If the sequence is valid...
if( sequence_valid )
{
// Test if input is largest qualifying value
t = valuta( val, x, t ) ;
}
}
// Result
printf("Result: %d\n", t);
return 0;
}
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
How do I do this in constant time (I do not want to brute for iterate from a to b)?
// return number of multiples of c in [a,b]
long count_multiples(int a, int b, int c) {
assert(b >= a && c != 0);
// todo
return -1;
}
This question looks deceptively simple but is harder than it looks because it has some corner cases e.g. must handle all cases (a,b can be negative/zero and c can be negative too and a may equal b may equal c). The result may not fit in 32-bit for one case (a = 2^31, b = 2^31-1, c = 1 or -1)
long count_multiples(int a, int b, int c) {
if (b < a) return 0;
if (c < 0) c = -c;
long al = a, bl = b, cl = c;
if (c == 1) return bl - al + 1;
return ((bl + (b < 0 ? 1 : 0)) / cl) -
((al - (a > 0 ? 1 : 0)) / cl) +
((a <= 0 && b >= 0) ? 1 : 0);
}