[英]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 == 100
和25+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 : 一种可能的方法,分为每个逻辑步骤的函数:
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)))
l
factor of n
, split str(n)
into chunks of length l
: l
因子n
, 将str(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)]
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
所有正除数,从1
到l
,包括两者。 There may be faster ways of doing it for large n
using math.sqrt
and divmod
. 使用
math.sqrt
和divmod
可能有更快的方法为大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.