# 【Python CheckiO 题解】Count Consecutive Summers

CheckiO 是面向初学者和高级程序员的编码游戏，使用 Python 和 JavaScript 解决棘手的挑战和有趣的任务，从而提高你的编码技能，本博客主要记录自己用 Python 在闯关时的做题思路和实现代码，同时也学习学习其他大神写的代码。

CheckiO 官网：https://checkio.org/

CheckiO 题解系列专栏：https://itrhx.blog.csdn.net/category_9536424.html

CheckiO 所有题解源代码：https://github.com/TRHX/Python-CheckiO-Exercise

## 题目描述

【Count Consecutive Summers】：一个正整数可以用几个连续的正整数之和来表示，例如，正整数42，可以有四种方法来表示：（1）3 + 4 + 5 + 6 + 7 + 8 + 9、（2）9 + 10 + 11 + 12、（3）13 + 14 +15、（4）42，其中第四种方法表示该正整数仅由其本身组成，你的任务是计算有多少种表示方法。

【输入】：整数

【输出】：整数

【前提】：输入始终是一个正整数

【范例】

count_consecutive_summers(42) == 4
count_consecutive_summers(99) == 6


## 代码实现

def count_consecutive_summers(num):
n = 0
for i in range(1,num+1):
m = i
while m < num:
i,m = i+1,m+i+1
if m == num:
n += 1
return n

if __name__ == '__main__':
print("Example:")
print(count_consecutive_summers(42))

# These "asserts" are used for self-checking and not for an auto-testing
assert count_consecutive_summers(42) == 4
assert count_consecutive_summers(99) == 6
assert count_consecutive_summers(1) == 1
print("Coding complete? Click 'Check' to earn cool rewards!")


## 大神解答

#### 大神解答 NO.1

count_consecutive_summers = lambda n: sum(not n%k for k in range(1, n+1, 2))


#### 大神解答 NO.2

def count_consecutive_summers(num):
# s + (s + 1) + (s + 2) + ... + (s + n)
# = (n + 1) * s + n * (n + 1) / 2 = num
# s = (num - n * (n + 1) / 2) / (n + 1)
# we need denominator of s is divisible by n + 1
count = 0
for n in range(0, num): # we move n
d = num - n * (n + 1) // 2 # calculate denominator
if d <= 0: break
if d % (n + 1) == 0: # s is integer?
count += 1
return count


#### 大神解答 NO.3

def count_consecutive_summers(num):
ways = 0
for i in range(1, num + 1):
n = 1 - 2 * i + ((2 * i - 1) ** 2 + 8 * num) ** (1/2)
if n % 1 == 0:
ways += 1

return ways


#### 大神解答 NO.4

count_consecutive_summers=lambda n:sum([n%b*2==b-b%2*b for b in range(1,int((2*n)**.5)+1)])
"""
Is this really working?
Yes it is, it's one of the shortest code to solve the problem and
it's doing it very efficiently as well

2nd version
-----------
How does it work:
sum from p to p+a when p and a are integers is (2p+a)*(a+1)/2
so n=(2p+a)*(a+1)/2
so 2p+a=2n/(a+1)
finally p=(2n-a-a^2)(2*(a+1))
replacing a+1 with b
p=(2n-b(b-1))/2b
and we know that p should b an integer, which means that 2n-b(b-1)%(2b)==0
or 2n%(2b)==b(b-1)%(2b)
Left part can be reduce to n%b*2
Right part can be reduce to (b-1)%2*b which can be written b-b%2*b for 2 characters less

Values for a are from a=0 (sum of a single value) to a=0.5*(-1+sqrt(1+8*n)) when we have the lonest sum of numbers
This value does not make a nice 'golf' code, but 0.5*(-1+sqrt(1+8*n)) is just slightly smaller than sqrt(2n)
for n=1 000 000, this means that the program will evaluate a up to 1414 instead of 1413, acceptable trade off for a shorter code :)
Values for b are therefore from 1 to sqrt(2n)+1

2nd version uses:
- b in place of a+1 for a lot of save characters
- modulo instead of int(x)==x to define if x is integer, greatly save chars but it's much faster (20-30%)

It was a great exerice so found a way to solve it for both code size and speed
"""


©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客