couldn't find out how to solve this algorithm problem - c

I am beginner I tried so many times but I couldn't solve this problem I will be very pleased if you help me...
the question is:
Let x be an integer, and R(x) is a function that returns the reverse of the x in terms of its digits.
For example , if x:1234 then R(x)=4321.
Let’s call a positive integer mirror-friendly if it satisfies the following condition: π‘₯ + 𝑅(π‘₯) = 𝑦^2 π‘€β„Žπ‘’π‘Ÿπ‘’ 𝑦 𝑖𝑠 π‘Žπ‘› π‘–π‘›π‘‘π‘’π‘”π‘’π‘Ÿ
Write a program that reads a positive integer as n from the user and prints out a line for each of the first n mirror-friendly integers as follows: x + R(x) = y^2
Example: If the user enters 5 as n, then the program should print out the following:
2 + 2 = 2^2
8 + 8 = 4^2
29 + 92 = 11^2
38 + 83 = 11^2
47 + 74 = 11^2
Here is the my code:
int
reverse(int num)
{
int reverse,
f,
i;
reverse = 0;
i = 0;
for (; i < num + i; i++) {
f = num % 10;
reverse = (reverse * 10) + f;
num /= 10;
}
return reverse;
}
int
sqrt(int n)
{
int i = 1;
int sqrt;
for (; i <= n; i++) {
sqrt = i * i;
}
return sqrt;
}
int
main()
{
int j = 1;
int main_num = 0;
for (; main_num <= 0;) {
printf("Please enter a positive integer: \n");
scanf_s("%d", &main_num);
}
int count = 0;
for (int i = 1; i <= main_num; i++) {
for (; j <= main_num; j++) {
if (j + reverse(j) == sqrt(?)) {
printf("%d + %d = %d\n", j, reverse(j), sqrt(?));
}
}
}
}

A few issues ...
sqrt does not compute the square root
reverse seems overly complicated
main_num (i.e. n from the problem statement) is the desired maximum count of matches and not the limit on x
Too many repeated calls to sqrt and reverse
No argument given to sqrt
The if in main to detect a match is incorrect.
sqrt conflicts with a standard function.
The variables you're using don't match the names used in the problem statement.
The printf didn't follow the expected output format.
Using a function scoped variable that is the same as the function is a bit confusing (to humans and the compiler).
Unfortunately, I've had to heavily refactor the code. I've changed all the variable names to match the names used in the problem statement for clarity:
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
int
reverse(int x)
{
int r = 0;
for (; x != 0; x /= 10) {
int f = x % 10;
r = (r * 10) + f;
}
return r;
}
int
isqrt(int x)
{
int y = 1;
while (1) {
int y2 = y * y;
if (y2 >= x)
break;
++y;
}
return y;
}
int
main(int argc,char **argv)
{
int n = -1;
--argc;
++argv;
if (argc > 0) {
n = atoi(*argv);
printf("Positive integer is %d\n",n);
}
while (n <= 0) {
printf("Please enter a positive integer:\n");
scanf("%d", &n);
}
int x = 1234;
dbgprt("x=%d r=%d\n",x,reverse(x));
int count = 0;
for (x = 1; count < n; ++x) {
dbgprt("\nx=%d count=%d\n",x,count);
// get reverse of number (i.e. R(x))
int r = reverse(x);
dbgprt("r=%d\n",r);
// get x + R(x)
int xr = x + r;
dbgprt("xr=%d\n",xr);
// get y
int y = isqrt(xr);
dbgprt("y=%d\n",y);
if (xr == (y * y)) {
printf("%d + %d = %d^2\n", x, r, y);
++count;
}
}
return 0;
}
Here is the program output:
Positive integer is 5
2 + 2 = 2^2
8 + 8 = 4^2
29 + 92 = 11^2
38 + 83 = 11^2
47 + 74 = 11^2
UPDATE:
The above isqrt uses a linear search. So, it's a bit slow.
Here is a version that uses a binary search:
// isqrt -- get sqrt (binary search)
int
isqrt(int x)
{
int ylo = 1;
int yhi = x;
int ymid = 0;
// binary search
while (ylo <= yhi) {
ymid = (ylo + yhi) / 2;
int y2 = ymid * ymid;
// exact match (i.e. x == y^2)
if (y2 == x)
break;
if (y2 > x)
yhi = ymid - 1;
else
ylo = ymid + 1;
}
return ymid;
}
UPDATE #2:
The above code doesn't scale too well for very large x values (i.e. large n values).
So, main should check for wraparound to a negative number for x.
And, a possibly safer equation for isqrt is:
ymid = ylo + ((yhi - ylo) / 2);
Here is an updated version:
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG
#define dbgprt(_fmt...) printf(_fmt)
#else
#define dbgprt(_fmt...) do { } while (0)
#endif
// reverse -- reverse a number (e.g. 1234 --> 4321)
int
reverse(int x)
{
int r = 0;
for (; x != 0; x /= 10) {
int f = x % 10;
r = (r * 10) + f;
}
return r;
}
// isqrt -- get sqrt (linear search)
int
isqrt(int x)
{
int y = 1;
while (1) {
int y2 = y * y;
if (y2 >= x)
break;
++y;
}
return y;
}
// isqrt2 -- get sqrt (binary search)
int
isqrt2(int x)
{
int ylo = 1;
int yhi = x;
int ymid = 0;
// binary search
while (ylo <= yhi) {
#if 0
ymid = (ylo + yhi) / 2;
#else
ymid = ylo + ((yhi - ylo) / 2);
#endif
int y2 = ymid * ymid;
// exact match (i.e. x == y^2)
if (y2 == x)
break;
if (y2 > x)
yhi = ymid - 1;
else
ylo = ymid + 1;
}
return ymid;
}
int
main(int argc,char **argv)
{
int n = -1;
--argc;
++argv;
setlinebuf(stdout);
// take number from command line
if (argc > 0) {
n = atoi(*argv);
printf("Positive integer is %d\n",n);
}
// prompt user for expected/maximum count
while (n <= 0) {
printf("Please enter a positive integer:\n");
scanf("%d", &n);
}
int x = 1234;
dbgprt("x=%d r=%d\n",x,reverse(x));
int count = 0;
for (x = 1; (x > 0) && (count < n); ++x) {
dbgprt("\nx=%d count=%d\n",x,count);
// get reverse of number (i.e. R(x))
int r = reverse(x);
dbgprt("r=%d\n",r);
// get x + R(x)
int xr = x + r;
dbgprt("xr=%d\n",xr);
// get y
#ifdef ISQRTSLOW
int y = isqrt(xr);
#else
int y = isqrt2(xr);
#endif
dbgprt("y=%d\n",y);
if (xr == (y * y)) {
printf("%d + %d = %d^2\n", x, r, y);
++count;
}
}
return 0;
}
In the above code, I've used cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k

for(;i<num+i;i++)
is equal to
for(; 0<num;i++)
or for(; num;i++) if we are working with positive values only.
or even to while(num)
So, we don't need variable i in reverse function.
We don't need cycle at all in sqrt function. Just return n * n; is ok. But it is not sqrt then
The last cycle is too strange. At least variable j is not initialized.

Related

How to interlace two integers in C?

Let say I have two ints
a = 1234
b = 45678
Now I want to "interlace" them into a third int c that looks something like this
c = 415263748 assume the the length of these don't change. So far I've been able to do this:
unsigned interlace(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}
You have to get digits one by one. When you say x % 10 you get the least significant digit. When you say x = x /10 you remove the least significant digit. Start doing it for y then keep alternating:
unsigned interlace(unsigned x, unsigned y)
{
//If the parameters order could be inverted...
if(x > y)
{
unsigned z = x;
x = y;
y = z;
}
unsigned ans = y % 10;
y = y/10;
unsigned exponent = 10;
while(y)
{
ans += (x%10)*exponent;
x = x/10;
exponent *= 10;
ans += (y%10)*exponent;
y = y/10;
exponent *= 10;
}
return ans;
}
A slight twist on approach can eliminate the order of parameter issue by handling the interlacing on string representations of the values. This allows a simple way to sew the two numbers together. While strlen() is used here, you can also use snprintf (NULL, 0, "%u", a) and snprintf (NULL, 0, "%u", b) to determine the number of digits in each.
A simple approach interlacing the string representations would be:
#define NUMC 32
unsigned interlace (unsigned a, unsigned b)
{
char sa[NUMC], sb[NUMC], result[2*NUMC];
size_t lena, lenb, n = 0;
sprintf (sa, "%u", a);
sprintf (sb, "%u", b);
lena = strlen(sa);
lenb = strlen(sb);
if (lena > lenb) {
for (size_t i = 0, j = 0; sa[i]; i++) {
result[n++] = sa[i];
if (sb[j])
result[n++] = sb[j++];
}
result[n] = 0;
return (unsigned)strtoul (result, NULL, 0);
}
for (size_t i = 0, j = 0; sb[i]; i++) {
result[n++] = sb[i];
if (sa[j])
result[n++] = sa[j++];
}
result[n] = 0;
return (unsigned)strtoul (result, NULL, 0);
}
(note: the validations on conversion and length checks greater than zero should be added above. They were intentionally omitted for brevity)
The order of parameters is irrelevant. You can call it as interlace (a, b) or interlace (b, a) and the result will be correct each time.
A short example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMC 32
unsigned interlace (unsigned a, unsigned b)
{
char sa[NUMC], sb[NUMC], result[2*NUMC];
size_t lena, lenb, n = 0;
sprintf (sa, "%u", a);
sprintf (sb, "%u", b);
lena = strlen(sa);
lenb = strlen(sb);
if (lena > lenb) {
for (size_t i = 0, j = 0; sa[i]; i++) {
result[n++] = sa[i];
if (sb[j])
result[n++] = sb[j++];
}
result[n] = 0;
return (unsigned)strtoul (result, NULL, 0);
}
for (size_t i = 0, j = 0; sb[i]; i++) {
result[n++] = sb[i];
if (sa[j])
result[n++] = sa[j++];
}
result[n] = 0;
return (unsigned)strtoul (result, NULL, 0);
}
int main (void) {
unsigned a = 1234, b = 45678;
printf ("interlaced: %u\n", interlace (a, b));
}
Example Use/Output
$ ./bin/interlace_int
interlaced: 415263748
Another completely different approach, more inline with your original can make use of the div function and the div_t struct to automate handling the division and remainder. You can use the snprintf (NULL, 0, "%u", var); function to determine the number of digits so you can swap parameters if necessary.
A short example is:
#include <stdio.h>
#include <stdlib.h>
unsigned interlace (unsigned a, unsigned b)
{
unsigned result = 0, mult = 1;
div_t da = { .quot = a }, db = { .quot = b };
if (snprintf (NULL, 0, "%u", b) > snprintf (NULL, 0, "%u", a)) {
div_t tmp = da;
da = db;
db = tmp;
}
do {
da = div (da.quot, 10);
result += da.rem * mult;
mult *= 10;
if (db.quot) {
db = div (db.quot, 10);
result += db.rem * mult;
mult *= 10;
}
} while (da.quot);
return result;
}
int main (void) {
unsigned a = 1234, b = 45678;
printf ("interlaced: %u\n", interlace (a, b));
}
(note: here again, the order of parameters is irrelevant and you can provide a and b in any order and still arrive at the correct result)
Example Use/Output
$ ./bin/interlace_unsinged
interlaced: 415263748
Let me know if you have further questions. Just another way to skin the interlace cat.
This is not exactly what you asked for but maybe you can reuse some of this logic on your function....
OUTPUT:
Interlace 2 numbers as a printf
Enter number a: forty-three
Insert digit : 1234
Enter number b: 45678
Interlaced numbers: 142536478
CODE:
#include <stdio.h>
int main(void){
long int num , num2, temp , factor = 1, factor2 = 1;
puts("Interlace 2 numbers as a printf");
printf("Enter number a: ");
while(!scanf(" %ld",&num)){
while ((temp = getchar()) != '\n' && temp != EOF);
printf("Insert digit : ");
}
printf("Enter number b: ");
while(!scanf(" %ld",&num2)){
while ((temp = getchar()) != '\n' && temp != EOF);
printf("Insert digit : ");
}
temp = num;
while(temp){
temp /= 10;
factor *= 10;
}
temp = num2;
while(temp){
temp /= 10;
factor2 *= 10;
}
printf("Interlaced numbers: ");
while(factor>1)
{
factor /= 10;
printf("%ld",num/factor);
num %= factor;
if (factor2 > 1)
{
factor2 /= 10;
printf("%ld",num2/factor2);
num2 %= factor2;
}
}
while(factor2>1)
{
factor2 /= 10;
printf("%ld",num2/factor2);
num2 %= factor2;
}
putchar('\n');
return 0;
}
#include <stdio.h>
#include <math.h>
int main(void) {
int a = 1234;
int b = 45678;
int c = 0;
while(a || b)
{
if (b)
{
int m = pow(10, (int)log10(b));
c=c*10 + b/m;
b = b%m;
}
if (a)
{
int m = pow(10, (int)log10(a));
c=c*10+a/m;
a = a%m;
}
}
printf("Result: %d\n", c);
return 0;
}
Output:
Success #stdin #stdout 0s 4692KB
Result: 415263748
IDEOne Link
Appending the last digit of the two numbers alternatively to n * 10(repeated operation), gives you the reverse of the interlace.
Just to help if you are stuck in generating reversed interlace.
unsigned interlace (unsigned x, unsigned y)
{
unsigned n, r;
if( x > y)
{
temp = x;
x = y;
y = temp;
}
n = y % 10;
y = y / 10;
while (x || y) // To Generate reverse of the interlace
{
n = n * 10 + (x % 10);
x /= 10;
n = n * 10 + (y % 10);
y /= 10;
}
r = n % 10;
n = n / 10;
while(n != 0) // reverse it to get the interlaced number
{
r = r * 10 + (n % 10);
n /= 10;
}
return r;
}

Breaking a number into the sum of two numbers

I have a problem with a such a task:
Write a program that finds such a pair of numbers x and y that their sum is equal to n. In addition, the pair of numbers should meet the following conditions:
the number x has at least 2 digits,
the number y is one digit less than the number x.
N is from the range <10 ; 10^5>
for number 80, the output should look like this:
79 + 1 = 80
78 + 2 = 80
77 + 3 = 80
76 + 4 = 80
75 + 5 = 80
74 + 6 = 80
73 + 7 = 80
72 + 8 = 80
71 + 9 = 80
I wrote a code that works in most cases but the system rejects the solution when testing the number 100000, because the program does not find such pairs - the test requires 9000 such pairs. I can't understand what's wrong because I think the program is okay. I'd like to ask for some advice.
My code:
#include <stdio.h>
#include <math.h>
int digit_count(int n)
{
int i = 0;
while (n > 0)
{
n /= 10;
i++;
}
return i;
}
int breakdown(int n)
{
long n_digits = digit_count(n), check = 0, count = 1;
long double y_max = pow(10, (n_digits - 1)) - 1, y_min = (pow(10, (n_digits - 2)));
for (int i = (int)y_min; i <= (int)y_max; i++)
{
if (digit_count(n - i) >= 2 && digit_count(i)+1 == digit_count(n - 1))
{
printf("%d + %d = %d %d\n", n - i, i, n, count);
check = 1;
count++;
}
}
if (check == 0)
{
printf("Nothing to show.");
}
return 0;
}
int main(void)
{
unsigned int n = 0;
printf("Podaj N: ");
if (1 != scanf("%u", &n))
{
printf("Incorrect input");
return 1;
}
if (n > 1000000 || n < 10)
{
printf("Incorrect input");
return 1;
}
breakdown(n);
return 0;
}
PS: I forgot to mention that the count variable is here only for debugging
I solved the problem in this way. Now it works for all numbers in the range according to the task.
#include <stdio.h>
#include <math.h>
int digit_count(int n)
{
int i = 0;
while (n > 0)
{
n /= 10;
i++;
}
return i;
}
int breakdown(int n)
{
int n_digits = digit_count(n), check = 0;
double y_max = pow(10, n_digits - 1) - 1;
//int i = 0 instead of i = y_min = (pow(10, (n_digits - 2))
for (int i = 0; i <= (int)y_max; i++)
{
//instead of if (digit_count(n - i) >= 2 && digit_count(i)+1 == digit_count(n - i))
if (digit_count(n - i) >= 2 && digit_count(n - i) == digit_count(i) + 1)
{
printf("%d + %d = %d\n", n - i, i, n);
check = 1;
}
}
if (check == 0)
{
printf("Nothing to show.");
}
return 0;
}
int main(void)
{
unsigned int n = 0;
printf("Podaj N: ");
if (1 != scanf("%u", &n))
{
printf("Incorrect input");
return 1;
}
if (n > 1000000 || n < 10)
{
printf("Incorrect input");
return 1;
}
breakdown(n);
return 0;
}
The posted code checks all the numbers in [10k - 2, 10k - 1 - 1], k beeing the number of digits of n, using the expansive (and wrong) condition
if (digit_count(n - i) >= 2 && digit_count(i)+1 == digit_count(n - 1)) { /* ... */ }
// ^
You can solve the problem avoiding all (or at least most of) those digits counts, by carefully calculating the valid extents of the ranges of the x and y values.
The following is a possible implementation
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
static inline long min_(long a, long b)
{
return b < a ? b : a;
}
static inline long max_(long a, long b)
{
return b < a ? a : b;
}
int digit_count(long n);
// Specilization for integer exponent.
long pow_10_(int exponent);
// A little helper struct
typedef struct range_s
{
long begin, end;
} range_t;
// Shrinks the range of the y values so that all the x = z - y are valid
// (the right nummber of digits and less than z).
range_t find_range(long z, long x_0)
{
range_t y = {max_(1, x_0 / 10), x_0};
range_t x = {x_0, min_(z, x_0 * 10)};
long x_1 = z - y.begin;
if (x_1 < x.begin)
y.end = y.begin;
else if (x_1 >= x.end)
y.begin = min_(z - x.end + 1, y.end);
long x_2 = z - y.end;
if (x_2 > x.end)
y.begin = y.end;
else if (x_2 <= x.begin)
y.end = max_(z - x.begin + 1, y.begin);
return y;
}
long print_sums(long z, range_t y);
long breakdown(long z)
{
int n_digits = digit_count(z); // <- Only once.
long x_0 = pow_10_(n_digits - 1);
// Depending on z, the x values may have the same number of digits of z or
// one less.
long count = 0;
if (n_digits > 2)
{
count += print_sums(z, find_range(z, x_0 / 10));
}
count += print_sums(z, find_range(z, x_0));
return count;
}
int main(void)
{
long n = 0;
if (1 != scanf("%lu", &n))
{
printf("Incorrect input");
return 1;
}
if (n > 1000000 || n < 10)
{
printf("Incorrect input");
return 1;
}
printf("\nCount: %ld\n", breakdown(n));
return 0;
}
int digit_count(long n)
{
int i = 0;
while (n > 0)
{
n /= 10;
i++;
}
return i ? i : 1; // I consider 0 a 1-digit number.
}
long pow_10_(int exponent)
{
if (exponent < 0)
return 0;
long result = 1;
while (exponent-- > 0)
result *= 10;
return result;
}
#define SAMPLES 5
long print_sums(long z, range_t y)
{
for (long i = y.begin; i < y.end; ++i)
#ifndef SHOW_ONLY_SAMPLES
printf("%ld + %ld = %ld\n", z - i, i, z);
#else
if ( i < y.begin + SAMPLES - 1 || i > y.end - SAMPLES )
printf("%ld + %ld = %ld\n", z - i, i, z);
else if ( i == y.begin + SAMPLES )
puts("...");
#endif
return y.end - y.begin;
}
Testable here.

Program in C , working with 3 digits but not working with 5 digits

145 = sum of 1! + 4! + 5!. I need to write a program in C, that finds the 5 digit numbers that have this property.
I have written the code successfully for the 3 digits. I used the same code for 5 digits, but it cant find any number.
I would like to help me with my solution, in order for me to see where am I wrong.
#include <stdio.h>
int factorial(int n);
main() {
int pin[5];
int q = 1;
int w = 0;
int e = 0;
int r = 0;
int t = 0;
int result = 0;
int sum = 0;
for (q = 1; q <= 9; q++) {
for (w = 0; w <= 9; w++) {
for (e = 0; e <= 9; e++) {
for (r = 0; r <= 9; r++) {
for (t = 0; t <= 9; t++) {
pin[0] = q;
pin[1] = w;
pin[2] = e;
pin[3] = r;
pin[4] = t;
int factq = factorial(q);
int factw = factorial(w);
int facte = factorial(e);
int factr = factorial(r);
int factt = factorial(t);
sum = factq + factw + facte + factr + factt;
result = 10000 * q + 1000 * w + 100 * e + 10 * r + t * 1;
if (sum == result)
printf("ok");
}
}
}
}
}
}
int factorial(int n) {
int y;
if (n == 1) {
y = 1;
} else if (n == 0)
y = 0;
else {
y = n * factorial(n - 1);
return y;
}
}
Your factorial function doesn't return a value in all cases:
int factorial (int n) {
int y;
if (n==1) {
y = 1;
}
else
if (n==0)
y = 0;
else {
y = n * factorial(n-1);
return y;
}
}
It only returns a value when it makes a recursive call. The base cases don't return anything. Failing to return a value from a function and then attempting to use that value invokes undefined behavior.
Move the return statement to the bottom of the function so it gets called in all cases. Also the value of 0! is 1, not 0.
int factorial (int n) {
int y;
if (n<=1)
y = 1;
else
y = n * factorial(n-1);
return y;
}
Also, when you find the target value you probably want to print it:
printf("ok: %d\n", result);
dbush's answer is accurate in pointing out why your code didn't work. This is an alternative solution to reduce the amount of calculation done by your program by not re-calculating the factorial of each numeral every step of the way. The way your program currently works, it winds up being around 500,000 calls to the factorial function from your nested loop, and then in turn recursively calls the function on average 4ish times for each call from the nested loop, so that's around 2 million calls to factorial. The more digits you tack on, the faster that number grows and more expensive it gets. To avoid all these recalculations, you can create a Look-up table that stores the factorial of the numerals [0-9] and just looks them up as needed.
You can calculate these values ahead of time and initialize your LUT with these values, but if hypothetically you wanted them to be calculated by the program because this is a programming assignment where you can't cut out such a step, it is still pretty trivial to populate the LUT.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
void populate_lut(uint32_t *lut);
int main(void) {
// lut is an array holding the factorials of numerals 0-9
uint32_t lut[10];
populate_lut(lut);
for (uint8_t q = 1; q <= 9; q++) {
for (uint8_t w = 0; w <= 9; w++) {
for (uint8_t e = 0; e <= 9; e++) {
for (uint8_t r = 0; r <= 9; r++) {
for (uint8_t t = 0; t <= 9; t++) {
// now instead of calculating these factorials, just look them up in the look-up table
uint32_t sum = lut[q] + lut[w] + lut[e] + lut[r] + lut[t];
uint32_t result = 10000 * q + 1000 * w + 100 * e + 10 * r + t * 1;
if (sum == result) {
printf("Solution: %" PRIu32 "\n", result);
}
}
}
}
}
}
}
// populate your lookup table with the factorials of digits 0-9
void populate_lut(uint32_t *lut) {
lut[0] = 1;
lut[1] = 1;
for(uint8_t i = 2; i < 10; ++i) {
lut[i] = lut[i-1] * i;
}
}

Collatz sequence from 1 to a given value

#include <stdio.h>
int main() {
int rangeValue;
int x;
printf("Please input a number to be considered in the range:\n");
scanf("%d", &rangeValue);
while (rangeValue != 1) {
x = rangeValue;
if ((x % 2) == 0) {
x = x / 2;
printf("%d,", x);
} else {
x = (3 * x) + 1;
printf("%d,", x);
}
rangeValue--;
}
return 0;
}
My goal is to do the Collatz sequence of every number from 1 to the number I give to rangeValue. I expected this to work. Can anyone help me make it work?
You are mixing the range of sequences to print, the maximum number of iterations and the current number in the sequence.
Here is how to fix the code:
#include <stdio.h>
int main(void) {
int rangeValue;
printf("Please input a number to be considered in the range:\n");
if (scanf("%d", &rangeValue) != 1)
return 1;
// iterate for all numbers upto rangeValue
for (int n = 1; n <= rangeValue; n++) {
printf("%d", n);
for (long long x = n; x != 1; ) {
if ((x % 2) == 0) {
x = x / 2;
} else {
x = (3 * x) + 1;
}
printf(",%lld", x);
}
printf("\n");
}
return 0;
}

How to divide digits and compare them, in C

Write a program that will find the largest number smaller than N that is totally different from a given number X. One number is totally different from other only if it doesn't contain any of the digits from the other number. N and X are read from standard input. The problem should be solved without the use of arrays.
Example Input 1: 400 897
Example Output 1: 366
Example Input 2: 1000 1236498
Example Output 2:777
No it's not homework, it was on one of the midterms and it's been killing me. I though about taking the first numbers last digit with %10 then taking the second numbers digit with %10 comparing them but...I just can't get it to work...I ended up with an endless loop...I just don't understand how to get every digit of the numbers and compare them to the other number.
#include <stdio.h>
int main () {
int N, X, num_N, num_X, i, lastDigit_N, lastDigit_X, flag, smaller_than_N;
scanf("%d%d", &N, &X);
smaller_than_N = N - 1;
for (i = smaller_than_N; i > 0; i--) {
num_N = i;
num_X = X;
flag = 0;
while (num_N > 0) {
lastDigit_N = num_N % 10;
while (num_X > 0) {
lastDigit_X = num_X % 10;
if (lastDigit_N == lastDigit_X) {
break;
}
else {
flag = 1;
}
num_X /= 10;
}
num_N /= 10;
}
if(flag) {
printf("%d", i);
break;
}
}
return 0;
}
You could build a bitmask for your numbers showing the digits which are contained.
uint16_t num2bitmask(int number)
{
uint16_t result = 0;
while (number) {
int digit = number % 10;
number /= 10;
result |= (1 << digit);
}
return result;
}
With this function, you can create your bitmask for X and then iterate from N-1 down to 1 until you find a value which doesn't have any bits in common with the other value.
If you have a number with digits d_1, d_2, ..., d_n, and you're allowed to use digits in the set D, then possible solutions look like:
d_1, ..., d_{i-1}, max(d in D | d < d_i), max(d in D), ..., max(d in D).
That is, the digits are the same up to some point, then the next digit is as large as possible while being below the input digit, then the rest are just as large as possible.
Not all these "solutions" will be valid, but if you iterate through them in reverse order (there's exactly n for an input number of size n), the first valid one you find is the answer.
Some code, including tests:
#include <stdio.h>
int digit_length(int a) {
int r = 0;
while (a) {
a /= 10;
r += 1;
}
return r;
}
int get_digit(int a, int k) {
while (k--) a /= 10;
return a % 10;
}
int largest_different(int a, int b) {
int lena = digit_length(a);
int invalid = b ? 0 : 1;
for (; b; b /= 10) invalid |= 1 << (b % 10);
int max_valid = 9;
while (max_valid >= 0 && (invalid & (1 << max_valid)))
max_valid--;
if (max_valid == -1) return -1;
for (int i = 0; i < lena; i++) {
int d = get_digit(a, i) - 1;
while (d >= 0 && (invalid & (1 << d)))d--;
if (d < 0) continue;
int solution = 0;
for (int k = lena - 1; k >= 0; k--) {
solution *= 10;
solution += (k < i ? max_valid : k > i ? get_digit(a, k) : d);
}
return solution;
}
return -1;
}
int main(int argc, char *argv[]) {
struct {int n; int x; int want;} examples[] = {
{400, 897, 366},
{1000, 1236498, 777},
{998, 123, 997},
};
int error = 0;
for (int i = 0; i < sizeof(examples) / sizeof(*examples); i++) {
int got = largest_different(examples[i].n, examples[i].x);
if (got != examples[i].want) {
error = 1;
printf("largest_different(%d, %d) = %d, want %d\n",
examples[i].n, examples[i].x, got, examples[i].want);
}
}
return error;
}
There's not always a solution. In that case, the function returns -1.

Resources