Breaking a number into the sum of two numbers - c

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.

Related

Why does my program only work half the time?

I have an assignment to write a program for a natural number where its inverse is divisible by its number of digits. A natural number n ( n > 9) is entered from the keyboard. To find and print the largest natural number less than n that its inverse is divisible by its number of digits. If the entered number is not valid, print a corresponding message (Brojot ne e validen).
I have tried :
#include <stdio.h>
int main() {
int n,r,s=0,a=0;
int m;
scanf("%d",&n);
int t=n;
if(t<10)
{ printf("Brojot ne e validen");}
else {
for (int i = n - 1; i > 0; i--) {
while (n != 0) {
r = n % 10;
s = (s * 10) + r;
n = n / 10;
a++;
if (s % a == 0) {
m = i;
break;
}
}
}
printf("%d\n", m);
}
return 0;
}
And when my inputs is 50, it gives the correct answer which is 49, but when I try numbers like 100 or 17 it prints 98 instead of 89 and 16 instead of 7 respectively. I have been baffled by this for more than an hour now
check your logic.
you can check each value by
#include <stdio.h>
int main() {
int t,r,s=0,a=0;
int m;
scanf("%d",&t);
if(t<10)
{ printf("Brojot ne e validen");}
else {
for (int i = t - 1; i > 0; i--) {
while (t != 0) {
r = t % 10;
printf("%d \n", r);
s = (s * 10) + r;
printf("%d \n", s);
t = t / 10;
printf("%d \n", t);
a++;
if (s % a == 0) {
m = i;
break;
}
}
}
printf("%d\n", m);
}
return 0;
}

couldn't find out how to solve this algorithm problem

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.

How optimize below code to determine the total number of prime numbers below 1,000,000,000 have the sum of their digits equal to 14 in C?

/Write a program to determine the total number of prime numbers below 1000,000,000 have the sum of their digits equal to 14? Make sure the execution time is few seconds./
#include<stdio.h>
#include<math.h>
int main() {
int i, j, count = 0, temp = 0, n, ans = 0, tot = 0;
for (i = 1; i <= 1000000000; i++) {
for (j = 2; j <= i / 2; j++) {
if (i % j == 0) {
count++;
}
}
if (count == 0) {
n = i;
while (n != 0) {
temp = n % 10;
n = n / 10;
ans = ans + temp;
}
if (ans == 14) {
tot++;
printf("%d,", i);
}
ans = 0;
temp = 0;
}
count = 0;
}
// printf("%d:\n",tot);
return 0;
}
Two simply improvements (amongst other):
1: Rather than iterate to i/2, iterate to the square root of i - that is j*j <= i.** This is a huge speed-up.
2: Quit loop once a factor found.
// for(j=2;j<=i/2;j++) {
// if(i%j==0) {
// count++;
// }
//}
for(j=2;j<=i/j;j++) { // _much_ lower limit
if(i%j==0) {
count++;
break; // No need to find more factors: `i` is not a prime.
}
}
Functionality: Inside if(count==0), I'd expect ans == 0 before while(n!=0).
** Use j<=i/j to prevent overflow. A good compiler will see a nearby i%j and often perform both i/j, i%j for the time cost of one.
The digit-sum function could also use a early return like:
int dsum14(int n) {
int sum = 0;
for (; n; n /= 10)
if ((sum += n % 10) > 14)
return 0;
return sum == 14 ? 1 : 0;
}
But how to combine the (efficient) prime search and this sum condition?
int n, cnt = 0;
for (n = 3; n < 1000*1000*1000; n += 2)
if (n%3 && n%5 && dsum14(n) && n%7 && n%11 && n%13)
cnt++;
This gives 77469 in 1.5 seconds. With dsum() at either end of the logical chain it is almost double.
The && n%7 && n%11 && n%13 part would be replaced by a function using a list of primes up to about 32000 (square root of max).
...or you can optimize it to 0.1 seconds, by tweaking the digsum function.
There are "only" 575 three-digit numbers 000-999 with sum 14 or less. So I prepare them and combine three of them to get a 9-digit number. Generating them instead of filtering them.
The tail looks like:
920000021
920000201
920001011
920010011
920100011
920100101
920101001
921001001
931000001
total count: 22588
real 0m0.098s
user 0m0.100s
sys 0m0.002s
And the start:
59
149
167
239
257
293
347
383
419
Not 100% sure if it's correct, but the total count also seems reasonable.
It all relies on the given max of 1000 Mio. digsum_prime() uses it to build the candidate number from three (almost) equal parts.
Code:
#include <stdio.h>
#include <stdlib.h>
int parr[5000] = {3};
struct {
int tri, sum;
} ts[999];
void primarr(void) {
int maxn = 32000;
int i = 1;
for (int n = 5; n < maxn; n += 2)
for (int div = 3;; div += 2) {
if (!(n % div))
break;
if (div*div > n) {
parr[i++] = n;
break;
}
}
}
int isprime(int n) {
for(int i = 0;; i++) {
if (!(n % parr[i]))
return 0;
if (parr[i]*parr[i] > n)
return 1;
}
}
int dsum(int n) {
int sum = 0;
for (; n; n /= 10)
sum += n % 10;
return sum;
}
int tsarr(void) {
int i = 0;
for (int n = 0; n < 1000; n++) {
int digsum = dsum(n);
if (digsum <= 14) {
ts[i].tri = n;
ts[i].sum = digsum;
i++;
}
}
return i;
}
int digsum_prime() {
int cnt = 0;
int tslen = tsarr();
printf("tslen: %d\n", tslen);
int high, mid, low;
int sum, num;
for (high = 0; high < tslen; high++) {
if(ts[high].sum > 13)
continue;
for (mid = 0; mid < tslen; mid++) {
if(ts[mid].sum + ts[high].sum > 13)
continue;
sum = ts[mid].sum + ts[high].sum;
for (low = 0; low < tslen; low++)
if (ts[low].tri % 2)
if(ts[low].sum + sum == 14) {
num = ts[high].tri * 1000*1000
+ ts[mid] .tri * 1000
+ ts[low] .tri;
if (isprime(num)) {
cnt++;
printf("%d\n", num);
}
}
}
}
return cnt;
}
int main(void) {
primarr();
printf("total count: %d\n", digsum_prime());
}
Changing 13-13-14 to 3-3-4 (but same preparation part) gives an overview - in 0.005 s!
tslen: 575
13
31
103
211
1021
1201
2011
3001
10111
20011
20101
21001
100003
102001
1000003
1011001
1020001
1100101
2100001
10010101
10100011
20001001
30000001
101001001
200001001
total count: 25
real 0m0.005s
user 0m0.005s
sys 0m0.000s
Make sure the execution time is few seconds.
oops
But the limits of OP are well chosen: a naive approach takes several seconds.

Determine if we can put '+' and '-' between numbers so that the result is divisible by a number: where's my mistake?

We have howmanynums numbers. We must determine if there's a way to put '+' and '-' between them in a way that makes the result divisible by given number mod.
(It is preferred to do it by means of dynamic programming, but I am just counting every sequence from the scratch because very short on time and just need it to work).
int howmanynums, mod;
int ring(int num) {
if ((num >= 0) && (num <= mod - 1))
return num;
if (num >= mod) {
while (num >= mod)
num -= mod;
return num;
}
if (num < 0) {
while (num < 0)
num += mod;
return num;
}
}
long int p(int n) {
long int t = 1;
while (n > 0) {
t *= 2;
n--;
}
return t;
}
int sequence[10000][2];
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%d%d%d", &howmanynums, &mod, &sequence[0][0]);
sequence[0][0] = ring(sequence[0][0]);
int temp;
int k = 1;
while (k < howmanynums) {
scanf("%d", &temp);
sequence[k][0] = ring(temp);
sequence[k][1] = ring(-temp);
k++;
}
long int x = (p(howmanynums - 1));
while (x > 0) {
long int a = sequence[0][0];
long int permutation = x;
long int insidePermutation = x % 2;
int l = 1;
while (l < howmanynums) {
a += sequence[l][insidePermutation];
l++;
permutation = permutation / 2;
insidePermutation = permutation % 2;
}
if (a % mod == 0) {
printf("%s", "Divisible");
goto e;
}
x--;
}
printf("%s", "Not divisible");
e:
return 0;
}
It passes 10 tests out of 20. I don't know the tests.
I also tried substituting all ints for long ints, but same result.
Where's my mistake?
I simplified your code and it looks OK to me. It should do the job. My only concern is efficiency. It takes about 20 seconds to find the answer "Not divisible" for the next sequence of 30 numbers: 30 2 1 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. Every additional number will double the previous time. So, the tests that your code didn't pass could be because of the allowed test time.
Dynamic programming is a must to pass the tests.
#include <stdio.h>
#pragma warning(disable : 4996)
int howmanynums, mod, sequence[64];
int main() {
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
scanf("%d%d", &howmanynums, &mod);
if (howmanynums > 64)
{
printf("Too many %d", howmanynums);
}
int k = 0;
while (k < howmanynums)
scanf("%d", &sequence[k++]);
int x = (2 << (howmanynums - 2)) - 1;
bool divisible = false;
while (!divisible && x >= 0)
{
int a = sequence[0], bit = 1; k = 1;
while (k < howmanynums)
{
a += x & bit ? sequence[k] : -sequence[k];
k++;
bit *= 2;
}
divisible = a % mod == 0;
x--;
}
printf("%s", divisible ? "Divisible": "Not divisible");
return 0;
}

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;
}

Resources