简体   繁体   English

在python上测试数字中数字之和的相等性?

[英]Testing the equality of the sum of a digits within a number on python?

for example def f(n): 例如def f(n):

and I wanna check whether the sum of the numbers within n equal to 100 whether it is in 1s, 2s, 3,s 4s, 5s and so on, depending on the length of n . 我想检查n中的数字之和是否等于100,无论是1s,2s,3,s4s,5s等等,这取决于n的长度。

f(5050)
>>> True

This tests whether 5 + 0 + 5 + 0 == 100 and whether 50 + 50 ==100 and if any are true, it returns True . 这测试5 + 0 + 5 + 0 == 100以及50 + 50 ==100是否为真,如果有,则返回True

Whether it tests in 1s, 2s 3s 4s and so on, depends on the length of the number. 它是以1s,2s 3s 4s等进行测试,取决于数字的长度。 For example a number with a length of 5 can only be tested in 1s. 例如,长度为5的数字只能在1秒内测试。

f(12345)
>>> False

This tests whether 1 + 2 + 3 + 4 + 5 == 100 and only that. 这测试1 + 2 + 3 + 4 + 5 == 100只有那个。

If the length of n was 15, it would test the digits in 1s, 3s and 5s. 如果n的长度是15,它将测试1s,3s和5s中的数字。

and finally one more example: 最后再举一个例子:

f(25252525)
>>> True

This would test whether 2+5+2+5+2+5+2+5 == 100 and 25+25+25+25==100 and whether 2525+2525==100 So n , which has a length of 8 would be tested in 1s , 2s , and 4s. 这将测试2+5+2+5+2+5+2+5 == 10025+25+25+25==100以及2525+2525==100所以n ,其长度为8将在1s,2s和4s进行测试。 It cannot be tested with 3s and 5s because the length of all the digits within the number being summed up must be the same. 它不能用3和5进行测试,因为总和的数字中所有数字的长度必须相同。

I hope I was able to explain what I'm after. 我希望我能够解释我所追求的是什么。 Usually I would post what I've tried but I have no idea how to iterate over the digits of a number in such a way 通常我会发布我尝试过但我不知道如何以这种方式迭代数字的数字

The below approach uses generator to split the integer, and no integer <-> string conversion. 下面的方法使用generator来分割整数,而不是integer <-> string转换。

This will likely be the most efficient approach of the ones currently listed. 这可能是目前列出的最有效的方法。

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("---")

Output: 输出:

sum = 100 with chunklength: 2
True
---
False
---
sum = 100 with chunklength: 2
True
---

Without comments and debugging print : 没有评论和调试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

Assuming that the numbers are always positive integers, you can just divmod() them by 10 until you get to zero: 假设数字总是正整数,你可以将它们divmod()除以10直到你得到零:

def int_iter(number):
    while number > 0:
        number, last_digit = divmod(number, 10)
        yield last_digit

Note that gives you the digits in reverse order. 请注意,它以相反的顺序为您提供数字。 That doesn't matter if you're just adding them together, though. 但是,如果您只是将它们组合在一起并不重要。

You can pass this around or use it in a for loop, like any other iterable: 你可以传递它或在for循环中使用它,就像任何其他iterable一样:

digit_sum = sum(int_iter(number))

If you really need a sequence, just pass it to list() : 如果你真的需要一个序列,只需将它传递给list()

digit_list = list(int_iter(number))

And if you need them in most-significant-first order, pass it to reversed() : 如果您需要以最重要的第一顺序将它们传递给reversed()

digits_msf = reversed(list(int_iter(number)))

EDIT: 编辑:

Whoops, I missed…about half of the question. 哎呀,我错过了〜大约一半的问题。 Things are rather more complicated. 事情变得更加复杂。 You'll need a function to get all the factors of a number—I'm sure there are plenty, so I'll leave that as an excercise for you. 你需要一个功能来获得一个数字的所有因素 - 我确定有很多,所以我会把它留给你作为一个练习。 Let's assume there's a function factors(number) that returns an iterable of all a number's factors (including nonprimes and 1, but not number itself). 让我们假设有一个函数factors(number)返回所有数字因子的迭代(包括非主数和1,但不是number本身)。 We'll also use the int_iter() from my original answer, an int_from_digits() that takes a list of digits and returns a single integer (sort of like the inverse of int_iter() ), and something called grouper() from the itertools recipes . 我们也将使用int_iter()从我原来的答复,一个int_from_digits()它利用数字列表并返回一个整数(有点像的倒数int_iter()以及一种叫grouper()itertools食谱

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)

Finally, armed with all these tools (or rather, one tool and its dependencies), we can perform your check with a simple comprehension and a call to any() : 最后,使用所有这些工具(或者更确切地说,一个工具及其依赖项),我们可以通过简单的理解和对any()的调用来执行检查:

any(digit_subsequence == 100 for digit_subsequence in digit_subsequences(number))

One possible way, separated into functions for each logical step : 一种可能的方法,分为每个逻辑步骤的函数:

  1. Get factors of n : 得到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. For each l factor of n , split str(n) into chunks of length l : 对于每个l因子nstr(n)拆分为长度为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. Check if sum of chunks in step 2 equals 100. 检查步骤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

I think this does the trick. 认为这样做了。 Not sure though: 但不确定:

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

The zip thing comes from here . zip东西来自这里 It's a little weird but it allows me to split the string up into n-length segments and then join it back together so I can apply an int mapping and then a sum reduction. 这有点奇怪,但它允许我将字符串分成n长度段,然后将它连接在一起,这样我就可以应用int映射然后减少sum

The generator just gets all positive divisors of l from 1 to l , both inclusive. 生成器只获得l所有正除数,从1l ,包括两者。 There may be faster ways of doing it for large n using math.sqrt and divmod . 使用math.sqrtdivmod可能有更快的方法为大n做这divmod

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM