# 【Python CheckiO 题解】Feed Pigeons

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

## 题目描述

【Feed Pigeons】：此题任务是模拟喂鸽子，最开始只有 1 只鸽子，1 分钟后飞来 2 只鸽子，再过 1 分钟飞来了 3 只，以此类推（1+2+3 +4+…），1 份饲料可以让鸽子吃 1 分钟，如果没有足够的食物，会让先到的鸟先吃，鸽子永远不会停止进食，如果我有 N 份饲料，有多少鸽子至少吃到一份饲料？

【输入】：饲料的份数（int）

【输出】：已经喂食过的鸽子的数目（int）

【前提】：0 < N < 105

【范例】

checkio(1) == 1
checkio(2) == 1
checkio(5) == 3
checkio(10) == 6

## 代码实现

def checkio(number):
fed = minute = pigeons = 0
while number >= 0:
number -= pigeons
minute += 1
if number <= 0:
return fed
if minute < number:
fed += minute
number -= minute
else:
fed += number
return fed
pigeons += minute
return fed

if __name__ == '__main__':
# These "asserts" using only for self-checking and not necessary for auto-testing
assert checkio(1) == 1, "1st example"
assert checkio(2) == 1, "2nd example"
assert checkio(5) == 3, "3rd example"
assert checkio(10) == 6, "4th example"

## 大神解答

#### 大神解答 NO.1

"""Determine the number of (greedy) pigeons who will be fed."""
import itertools

def checkio(food):
"""Given a quantity of food, return the number of pigeons who will eat."""
pigeons = 0
for t in itertools.count(1):
if pigeons + t > food:
# The food will be consumed this time step.
# All pigeons around last time were fed, and there is enough food
# this time step to feed 'food' pigeons, so return the max of each.
return max(pigeons, food)
# Increase pigeons, decrease food.
pigeons += t
food -= pigeons

#### 大神解答 NO.2

def checkio(number):
sum = 0
m = 1
n = 0
while(sum < number):
n = m*(m+1)/2
sum = sum + n
m = m + 1
if (sum - number) >= m-1:
return (m-2+1)*(m-2)/2
else:
return n - (sum - number)

#### 大神解答 NO.3

def checkio(food):
birds = new = 0
while food > 0:
new += 1
birds += new
food -= birds
return birds + max(food, -new)

#### 大神解答 NO.4

def allpigeon(min):
if min==0:
return 0
return allpigeon(min-1)+min

def allneed(min):
if min==0:
return 0
return allneed(min-1)+allpigeon(min)

def checkio(number):
i=0
while allneed(i)<=number:
i+=1
cur=number-allneed(i-1)
if cur>allpigeon(i-1):
return cur
return allpigeon(i-1)

#### 大神解答 NO.5

def checkio(n):                               # explanation follows...
p = lambda t: t * (t+1) // 2
q = lambda t: (t*t*t + 3*t*t + 2*t) // 6
h = 9*n*n - 1/27
R = 3*n + h**(1/2)
T = 3*n - h**(1/2)
X1 = R**(1/3) + T**(1/3) - 1
w = int(X1)
return p(w) + max(0, n-q(w)-p(w))

"""
p(t): number of of pigeons at round t
p(1) = 1
p(n) = p(n-1) + n

p(n) = 1 + 2 + 3 + ... + n = n*(n+1)/2

q(t): number of portions to feed all pigeons in the first t rounds

q(t)
= \sum_{i=1}^{n} p(i)
= 1/2 * \sum_{i=1}^{n} n^2 + 1/2 * \sum_{i=1}^{n} n
= 1/2 * n * (n+1) * (2*n+1) / 6 + 1/2 * n * (n+1) / 2
= 1/12 * (2*n^3 + 3*n^2 + n) + 1/4 * (n^2 + n)
= 1/12 * (2*n^3 + 3*n^2 + n + 3*n^2 + 3*n)
= 1/12 * (2*n^3 + 6*n^2 + 4*n)
= 1/6 * (n^3 + 3*n^2 + 2*n)

Suppose we start with N portions and w full rounds of pidgeons are fed:

q(w) <= N
<=> w^3 + 3*w^2 + 2*w - 6*N <= 0

Single real root is calculated by:

a = 1, b = 3, c = 2, d = -6*N

f = (3*c/a - b*b/a/a)/3
g = (2*b*b*b/a/a/a - 9*b*c/a/a + 27*d/a)/27
h = g*g/4 + f*f*f/27
R = -(g/2) + h**(1/2)
S = R**(1/3)
T = -(g/2) - h**(1/2)
U = T**(1/3)
X1 = S + U - b/3/a

theferore:  w = int(X1)

We can feed p(w) pidgeons and we are left with N - q(w) portions for round w+1.
But the first p(w) pidgeons in round w+1 have already been fed.
So, if N - q(w) > p(w), we can feed N - q(w) - p(w) more pidgeons.
"""

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