在 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 == 10050 + 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 == 10025+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))

一种可能的方式,为每个逻辑步骤分成函数:

  1. 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)))
  1. 对于 nsplit 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)]
  1. 检查步骤 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 缩减。

生成器只获取 l1l 的所有正因数,包括两者。使用 math.sqrtdivmod.

对于大型 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