在 python 上测试一个数字中的数字总和是否相等?
Testing the equality of the sum of a digits within a number on python?
例如def f(n):
我想检查n
内的数字之和是否等于100是否在1s,2s,3,s 4s,5s等等,取决于[=15的长度=].
f(5050)
>>> True
这测试是否 5 + 0 + 5 + 0 == 100
和 50 + 50 ==100
是否为真,如果有的话,它 returns True
.
是否按1s、2s、3s、4s等测试,取决于数字的长度。例如长度为 5 的数字只能在 1s 内测试。
f(12345)
>>> False
这测试是否 1 + 2 + 3 + 4 + 5 == 100
且仅此。
如果n
的长度为15,则测试1s、3s、5s中的数字。
最后还有一个例子:
f(25252525)
>>> True
这将测试是否 2+5+2+5+2+5+2+5 == 100
和 25+25+25+25==100
以及是否 2525+2525==100
因此,长度为 8 的 n
将在 1s 、 2s 和 4s 中进行测试。它不能用 3s 和 5s 来测试,因为被求和的数字中所有数字的长度必须相同。
我希望我能够解释我所追求的。通常我会 post 我试过的方法,但我不知道如何以这种方式遍历数字的数字
假设数字总是正整数,你可以通过 10
divmod()
直到你得到零:
def int_iter(number):
while number > 0:
number, last_digit = divmod(number, 10)
yield last_digit
请注意,数字的顺序是相反的。不过,如果您只是将它们相加,那也没关系。
您可以传递它或在 for
循环中使用它,就像任何其他可迭代对象一样:
digit_sum = sum(int_iter(number))
如果你真的需要一个序列,把它传给list()
:
digit_list = list(int_iter(number))
如果您需要它们以最重要的优先顺序,将其传递给 reversed()
:
digits_msf = reversed(list(int_iter(number)))
编辑:
糟糕,我错过了……大约一半的问题。事情要复杂得多。您将需要一个函数来获取数字的所有因数——我相信有很多,所以我将把它作为练习留给您。假设有一个函数 factors(number)
,它 returns 是所有数字因子(包括非素数和 1,但不包括 number
本身)的可迭代项。我们还将使用我原始答案中的 int_iter()
,一个采用数字列表的 int_from_digits()
和 returns 单个整数(有点像 int_iter()
的倒数) ,以及 the itertools
recipes.
中的 grouper()
from itertools import zip_longest
def int_from_digits(digits):
"Generate an integer from an iterable of single decimal digits"
# int_from_digits([4, 0, 2, 8, 9]) --> 40289
# int_from_digits([]) --> 0
number = 0
for digit in digits:
number *= 10
number += digit
return number
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
def digit_subsequences(number):
digits = list(reversed(list(int_iter(number))))
for factor in factors(number):
for digit_grouping in grouper(digits, factor):
yield int_from_digits(digit_grouping)
最后,有了所有这些工具(或者更确切地说,一个工具及其依赖项),我们可以通过简单的理解和调用 any()
:
来执行您的检查
any(digit_subsequence == 100 for digit_subsequence in digit_subsequences(number))
一种可能的方式,为每个逻辑步骤分成函数:
- Get factors of
n
:
def get_factors(n):
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
- 对于
n
、split str(n)
into chunks of length l
的每个 l
因子:
def get_chunks(str_n, chunk_size):
total_size = len(str_n)
return [int(str_n[i:i+chunk_size]) for i in range(0, total_size, chunk_size)]
- 检查步骤 2 中的块总和是否等于 100。
def f(n):
factors = get_factors(n)
for l in factors:
if sum(get_chunks(str(n), l)) == 100:
return True
return False
我 认为 这样就可以了。虽然不确定:
def f(n):
s = str(n)
l = len(s)
for n in (n for n in range(1, l + 1) if l % n == 0):
ints = [int(''.join(x)) for x in zip(*[iter(s)]*n)]
if sum(ints) == 100:
return True
return False
zip
的东西来自 here。这有点奇怪,但它允许我将字符串拆分为 n 个长度的段,然后将它们重新连接在一起,这样我就可以应用 int
映射,然后进行 sum
缩减。
生成器只获取 l
从 1
到 l
的所有正因数,包括两者。使用 math.sqrt
和 divmod
.
对于大型 n
可能有更快的方法
以下方法使用生成器拆分整数,没有 integer <-> string
转换。
这可能是当前列出的方法中最有效的方法。
import math
# Define a generator that will split the integer v into chunks of length cl
# Note: This will return the chunks in "reversed" order.
# split(1234, 2) => [34, 12]
def split(v, cl):
while v:
(v,c) = divmod(v, 10**cl)
yield c
def f(v):
# Determine the number of digits in v
n = int(math.log10(v)) + 1
m = int(math.sqrt(v))
# Check all chunk lengths in [1, sqrt(v)]
for cl in range(m):
# Skip the chunk lengths that would result in unequal chunk sizes
if n % (cl+1): continue
# Create a generator, to split the value v into chunks of length cl
chunks = split(v, cl+1)
# If the sum of the chunks is 100, print a message and return True
if sum(chunks) == 100:
print("sum = 100 with chunklength: %d" % cl)
return True
# If we get here, none of the chunk lengths result in a sum of 100, return False
return False
print(f(5050)) # True (cl=2)
print("---")
print(f(12345)) # False
print("---")
print(f(25252525)) # True (cl=2)
print("---")
输出:
sum = 100 with chunklength: 2
True
---
False
---
sum = 100 with chunklength: 2
True
---
没有评论和调试print
:
import math
def split(v, cl):
while v:
(v,c) = divmod(v, 10**cl)
yield c
def f(v):
n = int(math.log10(v)) + 1
m = int(math.sqrt(v))
for cl in range(m):
if n % (cl+1): continue
if sum(split(v, cl+1)) == 100: return True
return False
print(f(5050)) # True
print(f(12345)) # False
print(f(25252525)) # True
def factors(num):
yield 1
for i in range(2, num - 1):
if num % i == 0:
yield i
def pieces(string, sz):
for i in range(0, len(string), sz):
yield string[i:i+sz]
def check_sum(string):
for f in factors(len(string)):
pcs = pieces(string, f)
if sum([int(x) for x in pcs]) == 100:
print 'True'
return
print 'False'
>>> check_sum('5050')
True
>>> check_sum('25252525')
True
>>> check_sum('12345')
False
例如def f(n):
我想检查n
内的数字之和是否等于100是否在1s,2s,3,s 4s,5s等等,取决于[=15的长度=].
f(5050)
>>> True
这测试是否 5 + 0 + 5 + 0 == 100
和 50 + 50 ==100
是否为真,如果有的话,它 returns True
.
是否按1s、2s、3s、4s等测试,取决于数字的长度。例如长度为 5 的数字只能在 1s 内测试。
f(12345)
>>> False
这测试是否 1 + 2 + 3 + 4 + 5 == 100
且仅此。
如果n
的长度为15,则测试1s、3s、5s中的数字。
最后还有一个例子:
f(25252525)
>>> True
这将测试是否 2+5+2+5+2+5+2+5 == 100
和 25+25+25+25==100
以及是否 2525+2525==100
因此,长度为 8 的 n
将在 1s 、 2s 和 4s 中进行测试。它不能用 3s 和 5s 来测试,因为被求和的数字中所有数字的长度必须相同。
我希望我能够解释我所追求的。通常我会 post 我试过的方法,但我不知道如何以这种方式遍历数字的数字
假设数字总是正整数,你可以通过 10
divmod()
直到你得到零:
def int_iter(number):
while number > 0:
number, last_digit = divmod(number, 10)
yield last_digit
请注意,数字的顺序是相反的。不过,如果您只是将它们相加,那也没关系。
您可以传递它或在 for
循环中使用它,就像任何其他可迭代对象一样:
digit_sum = sum(int_iter(number))
如果你真的需要一个序列,把它传给list()
:
digit_list = list(int_iter(number))
如果您需要它们以最重要的优先顺序,将其传递给 reversed()
:
digits_msf = reversed(list(int_iter(number)))
编辑:
糟糕,我错过了……大约一半的问题。事情要复杂得多。您将需要一个函数来获取数字的所有因数——我相信有很多,所以我将把它作为练习留给您。假设有一个函数 factors(number)
,它 returns 是所有数字因子(包括非素数和 1,但不包括 number
本身)的可迭代项。我们还将使用我原始答案中的 int_iter()
,一个采用数字列表的 int_from_digits()
和 returns 单个整数(有点像 int_iter()
的倒数) ,以及 the itertools
recipes.
grouper()
from itertools import zip_longest
def int_from_digits(digits):
"Generate an integer from an iterable of single decimal digits"
# int_from_digits([4, 0, 2, 8, 9]) --> 40289
# int_from_digits([]) --> 0
number = 0
for digit in digits:
number *= 10
number += digit
return number
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
def digit_subsequences(number):
digits = list(reversed(list(int_iter(number))))
for factor in factors(number):
for digit_grouping in grouper(digits, factor):
yield int_from_digits(digit_grouping)
最后,有了所有这些工具(或者更确切地说,一个工具及其依赖项),我们可以通过简单的理解和调用 any()
:
any(digit_subsequence == 100 for digit_subsequence in digit_subsequences(number))
一种可能的方式,为每个逻辑步骤分成函数:
- Get factors of
n
:
def get_factors(n):
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
- 对于
n
、splitstr(n)
into chunks of lengthl
的每个l
因子:
def get_chunks(str_n, chunk_size):
total_size = len(str_n)
return [int(str_n[i:i+chunk_size]) for i in range(0, total_size, chunk_size)]
- 检查步骤 2 中的块总和是否等于 100。
def f(n):
factors = get_factors(n)
for l in factors:
if sum(get_chunks(str(n), l)) == 100:
return True
return False
我 认为 这样就可以了。虽然不确定:
def f(n):
s = str(n)
l = len(s)
for n in (n for n in range(1, l + 1) if l % n == 0):
ints = [int(''.join(x)) for x in zip(*[iter(s)]*n)]
if sum(ints) == 100:
return True
return False
zip
的东西来自 here。这有点奇怪,但它允许我将字符串拆分为 n 个长度的段,然后将它们重新连接在一起,这样我就可以应用 int
映射,然后进行 sum
缩减。
生成器只获取 l
从 1
到 l
的所有正因数,包括两者。使用 math.sqrt
和 divmod
.
n
可能有更快的方法
以下方法使用生成器拆分整数,没有 integer <-> string
转换。
这可能是当前列出的方法中最有效的方法。
import math
# Define a generator that will split the integer v into chunks of length cl
# Note: This will return the chunks in "reversed" order.
# split(1234, 2) => [34, 12]
def split(v, cl):
while v:
(v,c) = divmod(v, 10**cl)
yield c
def f(v):
# Determine the number of digits in v
n = int(math.log10(v)) + 1
m = int(math.sqrt(v))
# Check all chunk lengths in [1, sqrt(v)]
for cl in range(m):
# Skip the chunk lengths that would result in unequal chunk sizes
if n % (cl+1): continue
# Create a generator, to split the value v into chunks of length cl
chunks = split(v, cl+1)
# If the sum of the chunks is 100, print a message and return True
if sum(chunks) == 100:
print("sum = 100 with chunklength: %d" % cl)
return True
# If we get here, none of the chunk lengths result in a sum of 100, return False
return False
print(f(5050)) # True (cl=2)
print("---")
print(f(12345)) # False
print("---")
print(f(25252525)) # True (cl=2)
print("---")
输出:
sum = 100 with chunklength: 2 True --- False --- sum = 100 with chunklength: 2 True ---
没有评论和调试print
:
import math
def split(v, cl):
while v:
(v,c) = divmod(v, 10**cl)
yield c
def f(v):
n = int(math.log10(v)) + 1
m = int(math.sqrt(v))
for cl in range(m):
if n % (cl+1): continue
if sum(split(v, cl+1)) == 100: return True
return False
print(f(5050)) # True
print(f(12345)) # False
print(f(25252525)) # True
def factors(num):
yield 1
for i in range(2, num - 1):
if num % i == 0:
yield i
def pieces(string, sz):
for i in range(0, len(string), sz):
yield string[i:i+sz]
def check_sum(string):
for f in factors(len(string)):
pcs = pieces(string, f)
if sum([int(x) for x in pcs]) == 100:
print 'True'
return
print 'False'
>>> check_sum('5050')
True
>>> check_sum('25252525')
True
>>> check_sum('12345')
False