[英]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.编写一个程序,找出这样一对数字 x 和 y,它们的和等于 n。 In addition, the pair of numbers should meet the following conditions:此外,这对数字还应满足以下条件:
N is from the range <10 ; N 来自 <10 的范围; 10^5> 10^5>
for number 80, the output should look like this:对于数字 80,输出应如下所示:
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.我写了一个在大多数情况下都可以工作的代码,但是在测试数字 100000 时系统拒绝了解决方案,因为程序没有找到这样的对 - 测试需要 9000 个这样的对。 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 PS:忘了说count变量这里只是为了调试
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 [10 k - 2 , 10 k - 1 - 1], k beeing the number of digits of n
, using the expansive (and wrong) condition张贴的代码检查所有的数字[10的k - 2,10的k - 1 - 1],K beeing的数字数量n
,使用膨胀(和错误的)条件
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.通过仔细计算x
和y
值范围的有效范围,您可以解决避免所有(或至少大部分)这些数字计数的问题。
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.