function calc(x) {
// Множитель для разряда, 100 для x = 849
let e = Math.pow(10, Math.floor(Math.log10(x)));
while (e >= 1) {
const r = x % e;
const d = (x - r) / e % 10; // Очередная цифра x
if (d > 7) {
// Первое приближение a
// Для x = 849: a = 0 * 100 + 49 + 22 + 1
let a = (d - 8) * e + r + (e - 1) / 9 * 2 + 1;
e = 1;
while (e < a) {
const r = (a - a % e) / e % 10; // Очередная цифра a
if (r > 7) {
a += (10 - r) * e; // Увеличиваем разряд до 10
}
e *= 10;
}
return a;
}
e /= 10;
}
return 0;
}
function print(x) {
const a = calc(x);
const b = x - a;
console.log(x + ' = ' + a + ' + ' + b);
}
print(100);
print(777);
print(849);
print(859);
print(868);
print(890);
print(899);
print(900);
print(985);
print(993);
import numpy as np
# find maximal number which is <= num and does not contain 8 and 9
# ex: 849 => 777; # 178 => 177; # 234 => 234
def normalize_right_part(num):
num_arr = np.array(tuple(str(num)))
m = np.argmax(num_arr > '7')
if m > 0 or num_arr[0] > '7':
num_arr[m:] = '7'
return int( ''.join(num_arr) )
# if num does not contains 8 or 9 then leave it as is
# otherwise round it up to nearest number which does not contain 8 and 9
# ex: 849 => 1000; # 178 => 200; 234 => 234; 158 => 160
def normalize_left_part(num):
num_arr = np.fromiter(str(num), dtype=int)
m = np.argmax(num_arr > 7)
if m == 0 and num_arr[0] < 8:
return num
increase = False
for i in range(0, m+1):
if increase:
num_arr[m-i] += 1
increase = False
if num_arr[m-i] > 7:
num_arr[m-i] = 0
increase = True
num_arr[m:] = 0
if increase:
num_arr = np.insert(num_arr, 0, 1)
return int( ''.join(num_arr.astype(dtype=str)) )
# find number = a + b, where a and b don't contain 8 and 9
# and a is the minimal possible
def find_sum(num):
right_part = normalize_right_part(num)
left_part = num - right_part
while True:
left_part = normalize_left_part(left_part)
right_part = num - left_part
right_part_new = normalize_right_part(right_part)
if right_part_new == right_part:
break
left_part += right_part - right_part_new
return left_part, right_part
def solve(x):
a = []
b = []
while x:
d = x % 10
x //= 10
a.append(max(d-7, 0))
b.append(min(d, 7))
for i in range(len(a)-1, 1, -1):
if a[i] == 1 and a[i-1] == 0 and b[i-1] < 5:
a[i] = 0
a[i-1] = b[i-1] + 3
b[i-1] = 7
l = 0
r = 0
for d in a[::-1]:
l = l*10 + d
for d in b[::-1]:
r = r*10 + d
return (l,r)
for x in [100, 107, 108, 777, 821, 849, 853, 859, 863, 867, 890, 899, 900, 985, 993, 880088, 821000849, 8000000001]:
a,b = solve(x)
print(x, "=", a, "+", b, x == a + b)
def uptake(x):
sx = str(x)
br = False
for i in range(len(sx)):
if sx[i] > '7':
br = True
break
if br:
tail = '0' * (len(sx) - i)
head = ''
c = '1'
for j in range(i - 1, -1, -1):
d = int(sx[j]) + 1
if d > 7:
head = '0' + head
else:
head = sx[:j] + str(d) + head
c = ''
break
sx = c + head + tail
return int(sx)
def seven(x):
sx = str(x)
for i in range(len(sx)):
if sx[i] > '7':
sx = sx[:i] + '7' * (len(sx) - i)
break
return int(sx)
def test7(x):
sx = str(x)
return '8' in sx or '9' in sx
def p(x):
y = x - seven(x)
while test7(y):
y = x - seven(x - uptake(y))
print('Result: ', x, y, x - y)
p(100);
p(107);
p(108);
p(777);
p(849);
p(853);
p(859);
p(863);
p(890);
p(899);
p(900);
p(985);
p(993);
n = 859 # или другое число
x = 0 # первое слагаемое
y = 0 # второе слагаемое
# ------- делим число на цифры
digits = [] # список для цифр n
digits.append(n % 10) # первая цифра
# для остальных цифр
div_a_mod_num = 10
i=0
sub_num = digits[0] # число для вычета
while n > div_a_mod_num/10:
digits.append((n - sub_num) // div_a_mod_num % div_a_mod_num) # остальные цифры
i+=1
div_a_mod_num*=10
sub_num+=digits[i]
digits.reverse()
然后你需要找到最大数量:
# ------- ищем максимальное число
i=0
for e in digits:
digits[i] = e
if e > 7:
digits[i] = 7
i+=1
接下来,将数字转换回数字:
# ------- превращаем список цифр в число
digits.reverse()
i=0
j=1
while i < len(digits):
y += digits[i] * j
i+=1
j*=10
并计算第一个:
# ------- вычисляем первое число
x = n - y
最终代码:
n = 859 # или другое число
x = 0 # первое слагаемое
y = 0 # второе слагаемое
# ------- делим число на цифры
digits = [] # список для цифр n
digits.append(n % 10) # первая цифра
# для остальных цифр
div_a_mod_num = 10
i=0
sub_num = digits[0] # число для вычета
while n > div_a_mod_num/10:
digits.append((n - sub_num) // div_a_mod_num % div_a_mod_num) # остальные цифры
i+=1
div_a_mod_num*=10
sub_num+=digits[i]
digits.reverse()
# ------- ищем максимальное число
i=0
for e in digits:
digits[i] = e
if e > 7:
digits[i] = 7
i+=1
# ------- превращаем список цифр в число
digits.reverse()
i=0
j=1
while i < len(digits):
y += digits[i] * j
i+=1
j*=10
# ------- вычисляем первое число
x = n - y
# ------- показ конечного результата
print(x, y)
您肯定需要检查所有数字。
我们正在寻找左边的第一个8或9,如果你还没有找到,那么
a = 0一切就很简单了。如果我们找到它,那么我们会进行第一个近似,
a这样我们就可以得到这里的所有 7 以及右边到最后的值。例子:
此后需要对其进行标准化
a。这里我们反其道而行之,向右将所有 8 和 9 增加到 10。为什么这已经足够了,并且标准化后
a您不必b再次标准化?每个等级的a增幅不会超过2,而b这个等级的y值是7,所以你肯定不会得到8ka或9ka。我以前主要用 Delphi 编写代码,所以如果有什么问题我深表歉意......
运行tio
一个数字的每一位数字都会变成两个数字之和:
max(x-7, 0) + min(x, 7)。没有转移。然后,对于第一个数字中的每个片段10,我们检查是否可以用更小的数字替换这 10,以便在第二个数字的右侧数字中我们得到 7,如果可以,我们将其替换。运行tio更新的解决方案:
算法:
首先你需要将数字分成几个数字:
然后你需要找到最大数量:
接下来,将数字转换回数字:
并计算第一个:
最终代码:
我将添加一个带字符串的版本。我们正在寻找最大允许数量
y。我们找到数字中的n第一个字符8|9,并将从找到的字符到末尾的所有字符替换为7。这就是我们得到的y。接下来,我们检查(和 的
x差)是否存在 8 或 9。在 中 的相应位置,我们减去 2 或 1。我们不碰数字本身。我们从初始最大值和最终最大值之间的差值获得它。nyyxny附言。当然,在 Python 中处理字符串要容易得多)。