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;
}
Related
#include <stdio.h>
int succ(int x) {
return x+1;
}
int pred(int x) {
return x-1;
}
int is_zero(int x) {
return x == 0;
}
int is_pos(int x) {
return x >= 0;
}
int half(int x, int y) {
return is_zero(y) ? x: half(pred(x), pred(pred(y)));
}
int half1(int x) {
return half(x,x);
}
int main() {
int x;
scanf("%d", &x);
int z = half1(x);
printf("%d\n", z);
return 0;
}
This is one of the first exercises I received in college and I am having a little difficulty. I can only use the functions succ,pred,is_zero,is_pos to make a recursive function that calculates half of a number and I can't use if or while. I made this code, but it only works for even numbers, for example input=30 output=15 but if input=17 it will not return an output. Any tips?
What happens when you try half1(17)?
half1(17)
half(17, 17)
half(pred(17), pred(pred(17)))
half(16, pred(16))
half(16, 15)
half(15, 13)
half(14, 11)
half(13, 9)
half(12, 7)
half(11, 5)
half(10, 3)
half(9, 1)
half(8, -1)
half(7, -3)
...
y in this case will never equal 0, so the recursion never ends.
You want to check if y is negative (not positive) or equal to zero.
int half(int x, int y) {
return !is_pos(y) || is_zero(y) ? x : half(pred(x), pred(pred(y)));
}
Now, the recursion will end with half(8, -1) and 8 will be returned.
Nesting AND recursion? Too complicated for my little brain... Trying to double increment one parameter while aiming for a particular target (zero)? Could be tricky to get the conditionals right (as comments and another answer have already indicated.)
Why not simply "meet in the middle"?
#include <stdio.h>
int succ(int x) { return x+1; }
int pred(int x) { return x-1; }
// int is_zero(int x) { return x == 0; }
int is_pos(int x) { return x >= 0; }
int half( int l, int h ) {
return is_pos( l - h ) ? h : half( succ(l), pred(h) );
}
int half1( int x ) {
// terms are multiplied by 0 or 1 depending on x being +/-.
return half( (!is_pos(x))*x, is_pos(x)*x );
}
int main() {
int vals[] = { 30, 17, -42, 0 };
for( int i = 0; i < sizeof vals/sizeof vals[0]; i++ )
printf( "%3d/2 = %d\n", vals[i], half1( vals[i] ) );
return 0;
}
30/2 = 15
17/2 = 8
-42/2 = -21
0/2 = 0
I wrote this code to find the prime factorization of a number. I just cannot figure out the last part. If x is entered as a double or float, the program should print an error message and terminate. How do I achieve this?
#include <stdio.h>
int main()
{
int x, i;
printf("Enter an integer: ");
scanf("%d", &x);
if (x <= 1)
{
return 1;
}
printf("The prime factorization of %d is ", x);
if (x > 1)
{
while (x % 2 == 0)
{
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2)
{
while (x % i == 0)
{
printf("%d ", i);
x = x / i;
}
}
}
return 0;
}
Your starting point should cover all desired and undesired cases so you should take float number from a user, not int. Then, you should check whether whole decimal part of the number is 0. That is, if all of them equals 0, the user want to provide an int number instead of float.
First step is to declare a float number:
float y;
After, take its value from the user:
scanf("%f", &y);
Second step is to check whether it is int or float. There are many ways for this step. For example, I find roundf() function useful. It takes a float number and computes the nearest integer to this number. So if the nearest integer is the number itself then the number has to be int. Right?
if(roundf(y)!=y)
If you are sure it is an int, you can move onto the third step: convert float type to int type. It is called type-casting. This step is required for the remaining part of your program because in your algorithm you manipulate the number with int type so just convert it to int:
x = (int)y;
After adding the line above, you can use the rest of code which you typed. I give the whole program:
#include <stdio.h>
#include <math.h>
int main()
{
int x,i;
float y;
printf("Enter an integer: ");
scanf("%f", &y);
if(roundf(y)!=y){
printf("%f is not an integer!",y);
return 1;
}
else{
x = (int)y;
}
if (x <= 1)
{
printf("%d <= 1",x);
return 1;
}
else
{
printf("The prime factorization of %d is ", x);
while (x%2 == 0)
{
printf("2 ");
x = x / 2;
}
for ( i = 3; i < 1009; i = i + 2)
{
while (x%i == 0)
{
printf("%d ",i);
x = x / i;
}
}
}
return 0;
}
The use of scanf() is a bit tricky, I would avoid it to scan user generated input at almost all cost. But nevertheless here is a short overview for how to get the errors of scanf()
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int x, i, scanf_return;
printf("Enter an integer: ");
/* Reset "errno". Not necessary here, just in case. */
errno = 0;
/* scanf() returns a value in case of an error */
scanf_return = scanf("%d", &x);
/*
* scanf() returns "EOF" if it didn't find all what you wanted or
* and error happened.
* It sets "errno" to the value of the actual error. See manpage
* for all of the details.
*/
if (scanf_return == EOF) {
/*
* The error is connected to the stream, so we can differ between
* an error within scanf() and and error with the input stream
* (here: stdin)
*/
if (ferror(stdin)) {
fprintf(stderr, "Something went wrong while reading stdin: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
/* e.g. a conversion error, a float instead of an integer, letters
instead of a decimal number */
fprintf(stderr, "Something went wrong within scanf()\n");
exit(EXIT_FAILURE);
}
}
/*
* If no error occurred, the return holds the number of objects
* scanf() was able to read. We only need one, but it would throw an
* error if cannot find any objects, so the check is here for
* pedagogical reasons only.
*/
if (scanf_return != 1) {
fprintf(stderr, "Something went wrong within scanf(): wrong number of objects read.\n");
exit(EXIT_FAILURE);
}
if (x <= 1) {
fprintf(stderr, "Input must be larger than 1!\n");
exit(EXIT_FAILURE);
}
printf("The prime factorization of %d is ", x);
/* No need for that test, x is already larger than one at this point. */
/* if (x > 1) { */
while (x%2 == 0) {
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2) {
while (x%i == 0) {
printf("%d ",i);
x = x / i;
}
}
/* } */
/* Make it pretty. */
putchar('\n');
exit(EXIT_SUCCESS);
}
Does it work?
$ ./stackoverflow_003
Enter an integer: 1234
The prime factorization of 1234 is 2 617
$ factor 1234
1234: 2 617
$ ./stackoverflow_003
Enter an integer: asd
Something went wrong within scanf(): wrong number of objects read.
$ ./stackoverflow_003
Enter an integer: 123.123
The prime factorization of 123 is 3 41
No, it does not work. Why not? If you ask scanf() to scan an integer it grabs all consecutive decimal digits (0-9) until there is no one left. The little qualifier "consecutive" is most likely the source of your problem: a floating point number with a fractional part has a decimal point and that is the point where scanf() assumes that the integer you wanted ended. Check:
$ ./stackoverflow_003
Enter an integer: .123
Something went wrong within scanf(): wrong number of objects read
How do you find out? #weather-vane gave one of many ways to do so: check if the next character after the integer is a period (or another decimal separator of your choice):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int x, i, scanf_return;
char c = -1;
printf("Enter an integer: ");
/* Reset "errno". Not necessary here, just in case. */
errno = 0;
/* scanf() returns a value in case of an error */
scanf_return = scanf("%d%c", &x, &c);
/*
* scanf() returns "EOF" if it didn't find all what you wanted or
* and error happened.
* It sets "errno" to the value of the actual error. See manpage
* for all of the details.
*/
if (scanf_return == EOF) {
/*
* The error is connected to the stream, so we can differ between
* an error within scanf() and and error with the input stream
* (here: stdin)
*/
if (ferror(stdin)) {
fprintf(stderr, "Something went wrong while reading stdin: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
/* e.g. a conversion error, a float instead of an integer, letters
instead of a decimal number */
fprintf(stderr, "Something went wrong within scanf()\n");
exit(EXIT_FAILURE);
}
}
/*
* If no error occurred, the return holds the number of objects
* scanf() was able to read. We can use this information now.
* If there is a period (actually any character) after the integer
* it returns 2 (assuming no error happened, of course)
*/
/* If no integer given, the following character ("%c") gets ignored. */
if (scanf_return == 0) {
fprintf(stderr, "Something went wrong within scanf(): no objects read.\n");
exit(EXIT_FAILURE);
}
/* Found two objects, check second one which is the character. */
if (scanf_return == 2) {
if (c == '.') {
fprintf(stderr, "Floating point numbers are not allowed.\n");
exit(EXIT_FAILURE);
}
}
if (x <= 1) {
fprintf(stderr, "Input must be larger than 1!\n");
exit(EXIT_FAILURE);
}
printf("The prime factorization of %d is ", x);
/* No need for that test, x is already larger than one at this point. */
/* if (x > 1) { */
while (x%2 == 0) {
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2) {
while (x%i == 0) {
printf("%d ",i);
x = x / i;
}
}
/* } */
/* Make it pretty. */
putchar('\n');
exit(EXIT_SUCCESS);
}
Check:
$ ./stackoverflow_003
Enter an integer: 123
The prime factorization of 123 is 3 41
$ ./stackoverflow_003
Enter an integer: 123.123
Floating point numbers are not allowed.
$ ./stackoverflow_003
Enter an integer: .123
Something went wrong within scanf(): no objects read.
Looks good enough for me. With one little bug:
$ ./stackoverflow_003
Enter an integer: 123.
Floating point numbers are not allowed
But I think I can leave that as an exercise for the dear reader.
You can try this simple C99 implementation of Pollard Rho algorithm :
// Integer factorization in C language.
// Decompose a composite number into a product of smaller integers.
unsigned long long pollard_rho(const unsigned long long N) {
// Require : N is a composite number, not a square.
// Ensure : you already performed trial division up to 23.
// Option : change the timeout, change the rand function.
static const int timeout = 18;
static unsigned long long rand_val = 2994439072U;
rand_val = (rand_val * 1025416097U + 286824428U) % 4294967291LLU;
unsigned long long gcd = 1, a, b, c, i = 0, j = 1, x = 1, y = 1 + rand_val % (N - 1);
for (; gcd == 1; ++i) {
if (i == j) {
if (j >> timeout)
break;
j <<= 1;
x = y; // "x" takes the previous value of "y" when "i" is a power of 2.
}
a = y, b = y; // computes y = f(y)
for (y = 0; a; a & 1 ? b >= N - y ? y -= N : 0, y += b : 0, a >>= 1, (c = b) >= N - b ? c -= N : 0, b += c);
y = (1 + y) % N; // function f performed f(y) = (y * y + 1) % N
for (a = y > x ? y - x : x - y, b = N; (a %= b) && (b %= a););
gcd = a | b; // the GCD(abs(y - x), N) was computed
// it continues until "gcd" is a non-trivial factor of N.
}
return gcd;
}
Usually you performed some trial division before calling the algorithm
The algorithm isn't designed to receive a prime number as input
Two consecutive calls may not result in the same answer
Alternately, there is a pure C quadratic sieve which factors numbers from 0 to 300-bit.
If in doubt about the primality of N you can use a C99 primality checker :
typedef unsigned long long int ulong;
ulong mul_mod(ulong a, ulong b, const ulong mod) {
ulong res = 0, c; // return (a * b) % mod, avoiding overflow errors while doing modular multiplication.
for (b %= mod; a; a & 1 ? b >= mod - res ? res -= mod : 0, res += b : 0, a >>= 1, (c = b) >= mod - b ? c -= mod : 0, b += c);
return res % mod;
}
ulong pow_mod(ulong n, ulong exp, const ulong mod) {
ulong res = 1; // return (n ^ exp) % mod
for (n %= mod; exp; exp & 1 ? res = mul_mod(res, n, mod) : 0, n = mul_mod(n, n, mod), exp >>= 1);
return res;
}
int is_prime(ulong N) {
// Perform a Miller-Rabin test, it should be a deterministic version.
const ulong n_primes = 9, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
for (ulong i = 0; i < n_primes; ++i)
if (N % primes[i] == 0) return N == primes[i];
if (N < primes[n_primes - 1]) return 0;
int primality = 1, a = 0;
ulong b;
for (b = N - 1; ~b & 1; b >>= 1, ++a);
for (ulong i = 0; i < n_primes && primality; ++i) {
ulong c = pow_mod(primes[i], b, N);
if (c != 1) {
for (int j = a; j-- && (primality = c + 1 != N);)
c = mul_mod(c, c, N);
primality = !primality;
}
}
return primality;
}
To try it there is a factor function :
// return the number that was multiplied by itself to reach N.
ulong square_root(const ulong num) {
ulong res = 0, rem = num, a, b;
for (a = 1LLU << 62 ; a; a >>= 2) {
b = res + a;
res >>= 1;
if (rem >= b)
rem -= b, res += a;
}
return res;
}
ulong factor(ulong num){
const ulong root = square_root(num);
if (root * root == num) return root ;
const ulong n_primes = 9, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
for (ulong i = 0; i < n_primes && primes[i] <= root; ++i)
if (num % primes[i] == 0) return primes[i];
if (is_prime(num))
return 1 ;
return pollard_rho(num);
}
Which is completed by the main function :
#include <assert.h>
int main(void){
for(ulong i = 2; i < 63; ++i){
ulong f = factor(i);
assert(f <= 1 || f >= i ? is_prime(i) : i % f == 0);
ulong j = (1LLU << i) - 1 ;
f = factor(j);
assert(f <= 1 || f >= j ? is_prime(j) : j % f == 0);
j = 1 | pow_mod((ulong) &main, i, -5);
f = factor(j);
assert(f <= 1 || f >= j ? is_prime(j) : j % f == 0);
}
}
There are some problems in your code:
you do not check the return value of scanf, so you cannot detect invalid or missing input and will have undefined behavior in those cases.
you only test divisors up to 1009, so composite numbers with larger prime factors do not produce any output.
prime numbers larger than 1009 do not produce any output.
you should probably output a newline after the factors.
Testing and reporting invalid input such as floating point numbers can be done more easily by reading the input as a full line and parsing it with strtol().
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char input[120];
char ch;
char *p;
long x, i;
int last_errno;
printf("Enter an integer: ");
if (!fgets(input, sizeof input, stdin)) {
fprintf(stderr, "missing input\n");
return 1;
}
errno = 0;
x = strtol(input, &p, 0);
last_errno = errno;
if (p == input || sscanf(p, " %c", &ch) == 1) {
fprintf(stderr, "invalid input: %s", input);
return 1;
}
if (last_errno == ERANGE) {
fprintf(stderr, "number too large: %s", input);
return 1;
}
if (x < 0) {
fprintf(stderr, "number is negative: %ld\n", x);
return 1;
}
if (x <= 1) {
return 1;
}
printf("The prime factorization of %ld is", x);
while (x % 2 == 0) {
printf(" 2");
x = x / 2;
}
for (i = 3; x / i >= i;) {
if (x % i == 0) {
printf(" %ld", i);
x = x / i;
} else {
i = i + 2;
}
}
if (x > 1) {
printf(" %ld", x);
}
printf("\n");
return 0;
}
Thats one wrong with my code and I dont have any idea about this wrong
Please be attention to that I can just use from for and while and if
The question is:
Write a code that gets the natural number n then tries to find x,y,z (natural numbers) in some way:
n=x+y+z
Then if the following is true of x, y, z, print these three numbers in the output, otherwise print the Not Found statement:
x = y ^ 2 + z ^ 2
(x or y or z) = i + (i + 1) + (i + 2)
Where i is a natural number.
Be it. Then if the following is true of x, y, z, print these three numbers in the output, otherwise print the Not Found statement:
x = y ^ 2 + z ^ 2
(x or y or z) = i + (i + 1) + (i + 2)
Where i is a natural number.
(Note that the input n is such that the int variable is sufficient and does not overflow.)
Input
The input contains a line in which a natural number is given.
Output
The output must either consist of three lines, each integer x, y, and z, respectively, from small to large, or the expression Not Found.
Example
Sample Input 1
48
Copy
Sample output 1
2 6 40
Copy
Sample input 2
5
Copy
Sample output 2
Not found
#include <stdio.h>
int main() {
int z,x,y,n;
scanf("%u",&n);
for(y=1;y<(n/3);y++) {
for(z=y;z<=((2*n)/3);z++) {
(x=(n-(y+z)));
if(x==((y*y)+(z*z))) {
if(((((y-3)%3)!=0)||(y==3))&&((((z-3)%3)!=0)||(z==3))&&((((x-3)%3)!=0)||(x==3))) {
continue;
}
printf("%d\n",y);
printf("%d\n",z);
printf("%d",x); return 0;
}
}
}
printf("Not found");
return 0;
}
This syntax (if(x==((yy)+(zz))) is wrong. It should be if (x == ((y*y)+(z*z))) or use pow function from math.h library like this (if(x == (pow(y,2)+pow(z,2)))
int main()
{
int z, x, y, n;
scanf("%u", &n);
for (y = 1; y < (n / 3); y++)
{
for (z = y; z <= ((2 * n) / 3); z++)
{
(x = (n - (y + z)));
if (x == ((y*y)+(z*z)))
{
if (((((y - 3) % 3) != 0) || (y == 3)) && ((((z - 3) % 3) != 0) || (z == 3)) && ((((x - 3) % 3) != 0) || (x == 3)))
{
continue;
}
printf("%d\n", y);
printf("%d\n", z);
printf("%d", x);
return 0;
}
}
}
printf("Not found");
return 0;
}
I need to write a recursive function that returns 1 if digits of a whole number are ascending (left to right), return -1 if descending or return 0 if neither.
My solution attempt returns 0 every time and I know why but I don't know how to get around it.
Here's my code:
#include <stdio.h>
int check_order(int n)
{
if (n % 10 > n / 10 % 10)
{
return check_order(n / 10);
if (n == 0)
{
return 1;
}
}
else if (n % 10 < n / 10 % 10)
{
return check_order(n / 10);
if (n == 0)
{
return -1;
}
}
else
{
return 0;
}
}
int main()
{
int n;
printf("enter a whole number (n > 9):");
scanf_s("%d", &n);
printf("function returned: %d\n", check_order(n));
}
Here's a simple recursion:
int f(int n){
if (n < 10)
return 0;
int dr = n % 10; // rightmost digit
n = n / 10;
int dl = n % 10; // second digit from the right
int curr = dl < dr ? 1 : -1; // current comparison
if (dl == dr) curr = 0; // keep strict order
if (n < 10)
return curr;
return curr == f(n) ? curr : 0; // are the comparisons consistent?
}
Explain your algorithm?
Suppose you use the following:
You are given a number.
You need to turn that number into a sequence of digits.
If you are given a number, you can convert that number to a sequence of digits.
If you are given a sequence of digits, use
that.
Compare each pair of digits -> ascending, descending, or neither.
Combine the results from each pair, sequentially/recursively.
We can use a string to make the digit comparisons easier, and accept very long sequences of digits.
We can use an enum(erated) type to represent the ordering.
How do you combine the results? Define a function that combines the order of two adjacent, overlapping pairs, then you can combine results.
#include <stdio.h>
#include <string.h>
typedef enum { descending=-1, other=0, ascending=1 } order_t;
order_t pair_order(int a, int b) {
if( a < b ) return ascending;
if( a > b ) return descending;
return other;
}
//strict (increasing/decreasing)
order_t strict_order( order_t x, order_t y ) {
if( x == y ) return x;
return other;
}
//monotone (increasing/decreasing)
order_t monotone_order( order_t x, order_t y ) {
if( x == y ) return x;
if( other == x ) return y;
if( other == y ) return x;
return other;
}
order_t check_order( char* p, int remain ) {
//printf("p:%s\n",p); //uncomment to watch progress
if( remain<2 ) return other;
if( remain==2 ) return pair_order(p[0], p[1]);
return strict_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
//return monotone_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
}
char* order_name[] = {
"descending",
"other",
"ascending"
""
};
int main()
{
char line[666] = "none";
while ( strlen(line) > 0 ) {
printf("enter a number (at least 2 digits):");
fgets(stdin,line,sizeof(line)-1);
if( strlen(line) > 0 && line[strlen(line)-1] == '\n' )
line[strlen(line)-1] = '\0';
order_t order = check_order(line);
printf("function returned: (%d)%s\n", order, order_name[order+1]);
}
}
I think you were started on the right track but need to flesh out your code more. My solution borrows on that of #ChuckCottrill as I like his enum but I don't like that he doesn't play the ball as it lays (i.e. converts to a string instead of dealing with the int.) I also borrow the nice test examples of #ggorlen but I don't like that solution either as it can take multiple passes through the number to figure out the answer when only one pass should be needed:
#include <stdio.h>
typedef enum { descending=-1, other=0, ascending=1 } order_t; // a la #ChuckCottrill
order_t check_order(int n)
{
if (n > 9) {
int right = n % 10;
int left = n / 10 % 10;
if (right > left) {
n /= 10;
if (n > 9) {
return (ascending == check_order(n)) ? ascending : other;
}
return ascending;
}
if (right < left) {
n /= 10;
if (n > 9) {
return (descending == check_order(n)) ? descending : other;
}
return descending;
}
}
return other;
}
int main() { // a la #ggorlen
printf("12345: %d\n", check_order(12345));
printf("54321: %d\n", check_order(54321));
printf("54323: %d\n", check_order(54323));
printf("454321: %d\n", check_order(454321));
printf("1: %d\n", check_order(1));
printf("12: %d\n", check_order(12));
printf("21: %d\n", check_order(21));
}
OUTPUT
> ./a.out
12345: 1
54321: -1
54323: 0
454321: 0
1: 0
12: 1
21: -1
>
A version that works for any length since it takes the string as parameter.
And feeding the recursive function with previous status (ascending or descending) allows for some shorter code and less functions.
int check_order(char *str, int index, int previous) {
char current = str[index]; // char at index
char next = str[index+1]; // char at index+1
if (current == 0 || next == 0) {
return previous; // End of string
}
// Ascending or descending?
int status = next > current ? 1 : (next < current ? -1 : 0);
if (status == 0 || index > 0 && status != previous) {
// If neither -1/1 nor status == previous (while not initial call)
return 0;
}
return check_order(str, index+1, status); // Check from next index
}
The main function must ensure the string is at least 2 chars
int main(int argc, char **argv) {
char *str = *++argv;
// Some optional checks on str here... (like this is a number)
int status = 0; // Default value if string length < 2
if (strlen(str) >= 2) {
status = check_order(str, 0, 0);
}
printf("Check order for %s is %d\n", str, status);
return 0;
}
Code after a return statement like this is unreachable:
return check_order(n / 10);
if (n == 0)
{
return -1;
}
Beyond this, you're on the right track of checking the current digit against the next digit, but I don't see a clear base case (when n < 10, that is, a single digit).
Trying to check ascending and descending in one recursive function is difficult to manage. In particular, communicating state between stack frames and determining which cases are still valid at a given call suggests that the return value is overworked.
To save having to return a struct or use an enum or magic numbers as flags, I'd write two general helper functions, ascending_digits and descending_digits.
#include <stdbool.h>
#include <stdio.h>
bool ascending_digits(int n) {
if (n < 10) return true;
if (n % 10 < n / 10 % 10) return false;
return ascending_digits(n / 10);
}
bool descending_digits(int n) {
if (n < 10) return true;
if (n % 10 > n / 10 % 10) return false;
return descending_digits(n / 10);
}
int check_order(int n) {
if (ascending_digits(n)) return 1;
if (descending_digits(n)) return -1;
return 0;
}
int main() {
printf("12345: %d\n", check_order(12345));
printf("54321: %d\n", check_order(54321));
printf("54323: %d\n", check_order(54323));
printf("454321: %d\n", check_order(454321));
printf("1: %d\n", check_order(1));
printf("12: %d\n", check_order(12));
printf("21: %d\n", check_order(21));
return 0;
}
Output:
12345: 1
54321: -1
54323: 0
454321: 0
1: 1
12: 1
21: -1
Not only are these functions easier to understand and maintain individually, they're also more reusable than if they were inseparably tied together.
This doesn't handle negative numbers--you could apply abs and go from there if you want. Same goes for handling equal values; this implementation accepts numbers such as 1223 but you could use <= to enforce strict ordering.
I'm facing some difficulties in the last few days while trying to finish the following task, I hope you guys can assist :
I'm given a single number N, and I'm allowed to perform any of the two operations on N in each move :
One - If we take 2 integers where N = x * y , then we can change the value of N to the maximum between x and y.
Two - Decrease the value of N by 1.
I want to find the minimum number of steps to reduce N to zero.
This is what I have so far, I'm not sure what is the best way to implement the function to find the divisor (someFindDevisorFunction), and if this 'f' function would actually produce the required output.
int f(int n)
{
int div,firstWay,secondWay;
if(n == 0)
return 0;
div = SomefindDivisorFunction(n);
firstWay = 1 + f(n-1);
if(div != 1)
{
secondWay = 1 + f(div);
if (firstWay < secondWay)
return firstWay;
return secondWay;
}
return firstWay;
}
For example, if I enter the number 150 , the output would be :
75 - 25 - 5 - 4 - 2 - 1 - 0
I see this a recursive or iterative problem.
OP's approach hints at recursive.
A recursive solution follows:
At each step, code counts the steps of the various alternatives:
steps(n) = min(
steps(factor1_of_n) + 1,
steps(factor2_of_n) + 1,
steps(factor3_of_n) + 1,
...
steps(n-1) + 1)
The coded solution below is inefficient, but it does explore all possibilities and gets to the answer.
int solve_helper(int n, bool print) {
int best_quot = 0;
int best_quot_score = INT_MAX;
int quot;
for (int p = 2; p <= (quot = n / p); p++) {
int rem = n % p;
if (rem == 0 && quot > 1) {
int score = solve_helper(quot, false) + 1;
if (score < best_quot_score) {
best_quot_score = score;
best_quot = quot;
}
}
}
int dec_score = n > 0 ? solve_helper(n - 1, false) + 1 : 0;
if (best_quot_score < dec_score) {
if (print) {
printf("/ %d ", best_quot);
solve_helper(best_quot, true);
}
return best_quot_score;
}
if (print && n > 0) {
printf("- %d ", n - 1);
solve_helper(n - 1, true);
}
return dec_score;
}
int main() {
int n = 75;
printf("%d ", n);
solve(n, true);
printf("\n");
}
Output
75 / 25 / 5 - 4 / 2 - 1 - 0
Iterative
TBD
If you start looking for a divisor with 2, and work your way up, then the last pair of divisors you find will include the largest divisor. Alternatively you can start searching with divisor = N/2 and work down, when the first divisor found will have be largest divisor of N.
int minmoves(int n){
if(n<=3){
return n;
}
int[] dp=new int[n+1];
Arrays.fill(dp,-1);
dp[0]=0;
dp[1]=1;
dp[2]=2;
dp[3]=3;
int sqr;
for(int i=4;i<=n;i++){
sqr=(int)Math.sqrt(i);
int best=Integer.MAX_VALUE;
while(sqr >1){
if(i%sqr==0){
int fact=i/sqr;
best=Math.min(best,1+dp[fact]);
}
sqr--;
}
best=Math.min(best,1+dp[i-1]);
dp[i]=best;
}
return dp[n];
}