# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Lecture 3：一共有多少袋大米？

# - **Name (姓名)**: <NAME>
# - **Date (日期)**: 05/22/2021
#
#
# - **Score (成绩)**:[Provided by Teacher]
# - **Comment By Teacher (评语)**: A+
# 很好，特别是用了自己身边的例子举一反三。联系最后一题条件判断写得不是很符合题意，虽然结果是正确的。考虑把

# ## Problem
# 在古代，由于科学技术水平并不是很发达，人们并不是总能吃饱，因而像米面这样的食物就显得很珍贵，经常会被用来作为礼物赠送或奖赏给关系亲密的人。有这样一位生活在古代的国王，他准备给他手下一位非常得力的将军2000袋大米作为奖赏，可是他并不打算将这2000袋大米一次全部赏给这位将军，而是在第1天奖赏1袋大米，第2天奖赏2袋，第3天奖赏3袋，也就是每一天都在前一天奖赏的大米袋数上增加1袋，这样连续每天奖赏直到国王自己手中剩下的大米不够下一次对将军的奖赏为止。现在请你算一算，按照国王这样的奖赏办法，2000袋的奖赏大米足够连续奖赏这位将军多少天？在最后一天国王手中剩下的大米不够当天的奖赏时，国王手中剩下多少袋大米？

# ## Objective 学习目标
#
# - 学习`while`引导的循环语句，理解循环语句语法构成、循环体以及退出循环的条件判断等
# - 使用`>=`,`<=`进行“不少于”、“不多于”等比较
# - 体验循环语句对编写不重复代码的帮助
# - 理解掌握变量自增、自减代码的完整和简便写法（例如：`a = a + 1` 和 `a += 1`)
# - 思考如何管理大量的一组同类性质的数据
# - 字符串中`\n`,`\t`,`\r`的意义
# - 开始尝试理解程序的bug，错误和bug的区别。

# ## Math
#
# - 数列的概念
# - 数的大小比较
# - 寻找解决实际问题中不变的量

# ## Python

# +
# How do you solve this problem if using arithmetic calculation instead of programming
# 思考如果不使用用编程，而使用传统算术的方法来求解这个问题，你会怎么做？

# +
# Solution 0
rice_in_king_initial = 2000
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 1, 0
while rice_in_king >= rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded = days_awarded + 1
    rice_to_general = rice_to_general + 1
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)

# +
# Another solution with detailed explanation and output
# 另一个有详细解释和输出的实现方案

# declare and initiate some variables before calculating
# 在正式计算模拟前声明一些变量，并给这些变量一些初始的数值

# rice that King has at the very begining
# 国王一开始打算奖赏的大米总袋数 2000
rice_in_king_initial = 2016
# rice that King has for awarding 
# 国王手中拥有的用来奖赏的大米
rice_in_king = rice_in_king_initial

# rice that General awarded from King 
# 将军手中所有的奖赏大米
rice_in_general = 0

# rice that will awarded to General in some day，set to 0 in the begining
# 某一天里，将军从国王那里获得的大米代数，一开始设为1
rice_to_general = 1       

# days already awarded, set to 0 in the begining
# 已经奖赏的天数，一开始没有奖赏，设为0天
days_awarded = 0

# No. of current day
# 当前是第几天
cur_day = 1

# while rice in King is more than the rice that will be awarded to General
# 当国王手中（剩余）的大米足够下一次发给将军时
while rice_in_king >= rice_to_general:
    print("\n今天是第", cur_day, "天")
    print("  国王有大米:", rice_in_king, "袋，需要奖赏给将军: ", rice_to_general, "袋")
    print("  国王大米足够，开始奖赏:")
    rice_in_king = rice_in_king - rice_to_general
    rice_in_general = rice_in_general + rice_to_general
    days_awarded = days_awarded + 1
    print("  今天的奖赏已经完成，奖赏了", rice_to_general, "袋大米")
    print("  国王还剩下", rice_in_king, "袋大米")
    print("  将军目前共有:", rice_in_general,"袋大米")
    print("  到今天为止，一共连续奖赏了", days_awarded, "天")
    # prepare rice awarded to general for next day
    rice_to_general_next_day = rice_to_general + 1
    print("  明天的奖赏将会是", rice_to_general_next_day,"袋大米")
    
    # here comes the next day 第二天来了
    cur_day = cur_day + 1
    
    # update rice_to_general for compare with rice_in_king
    # 更新这一天要奖赏给将军的大米袋数
    rice_to_general = rice_to_general_next_day

# when program are executed here, it means king's rice is not enough for
# nex day's awarding.
# 当程序运行到此处时，说明国王的大米已经不够第二天的奖赏了
print("\n今天是第", cur_day, "天，国王的大米不够了，奖赏停止。") 
print("  国王还剩下", rice_in_king, "袋大米")
print("  今天原本需要奖赏将军", rice_to_general, "袋大米")
print("  国王一共奖赏给了将军", rice_in_general, "袋大米")

# +
RMB_in_Dad_initial = 2000

RMB_in_Dad = RMB_in_Dad_initial

RMB_wasted_by_Yunlei = 0

RMB_to_Yunlei = 1       

days_payed = 0

cur_day = 1

while RMB_in_Dad >= RMB_to_Yunlei:
    print("\n今天是第", cur_day, "天")
    print("  爸爸手上有:", RMB_in_Dad, "元，云耒索要: ", RMB_to_Yunlei, "元")
    print("  爸爸有钱给，那就给吧:")
    RMB_in_Dad = RMB_in_Dad - RMB_to_Yunlei
    RMB_wasted_by_Yunlei = RMB_wasted_by_Yunlei + RMB_to_Yunlei
    days_payed = days_payed + 1
    print("  今天给了", RMB_to_Yunlei, "元")
    print("  还剩下", RMB_in_Dad, "元")
    print("  云耒挥霍了:", RMB_wasted_by_Yunlei,"元")
    print("  到今天为止，连续一共给了云耒", days_payed, "天")
    RMB_to_Yunlei_next_day = RMB_to_Yunlei * 2
    print("  明天要给云耒", RMB_to_Yunlei_next_day,"元")
    
    cur_day = cur_day + 1
    
    RMB_to_Yunlei = RMB_to_Yunlei_next_day
        
print("\n今天是第", cur_day, "天，爸爸钱不够了，给不起了，不能再给了。") 
print("  爸爸只剩下", RMB_in_Dad, "元")
print("  今天云耒原本还想要", RMB_to_Yunlei, "元")
print("  这家伙已经挥霍了", RMB_wasted_by_Yunlei, "元")
# -

print('Sophie\ns name is \rYefei\tadsfafd')

# correction 纠正
# number of parameters in method 'print' can be infinite, not 1.
# print方法可以接受的数据个数可以是无限多个，不是1个.
print(123, 1244, 567, 1234)

# \t         \r
print("Luchuannnnn\r Yunzi       ")

print(Jason)

# +
# review randint, find bugs in the follow codes
# 复习randint, 寻找下面代码中的bug
from random import randint
num = randint(1, 10)
n_tries = 1
while num < 10:
    print(n_tries, "try, num generated is", num)
    num = randint(1, 10)
    n_tries = n_tries + 1
    
print("tried randint(1, 10)", n_tries, "times \nbefore we got 10")

# +
a = 10
a = a + 1
print("a =", a)

a = 10
a += 1
print("a =", a)
# -

a = 10
a += 2
print(a, type(a))
a -= 2
print(a, type(a))
a *= 2
print(a, type(a))
a /= 2
print(a, type(a))

rice_in_generals = [0, 1, 3, 6, 10, 15, 21]

# ## Did you know?
# 现代计算机编程语言有很多种，每一种现代计算机语言都有自己的语法来表示条件和循环控制。此外，在Python语言中，`while`引导的循环语句只是实现循环的形式之一。

# ## Exercise

# 1. 通常一个问题会有不止一种编程方案来求解，像本节的国王问题，本题下的代码单元格里提供了包括原始解法在内的一共3不同的编程写法，其中另外2种写法在国王打算奖赏的大米数量为2000的时候都也得到正确的答案，但是其中的一种方法当国王大米数量不是2000的时候有可能会得到错误的结果。试着将国王一开始拟奖赏的大米总数从2000修改为2016，分别运行本讲示例中的解法以及本练习题额外提供的两种解法，观察三种解法给出的结果有什么不同，指出本题提供的哪一种解法是错误的。尝试着去解释为什么会出现这样的错误。
#    
#    把你的答案写在这里：
#    - 第（二）种额外解决方案是错误的；
#    - 当国王一开始的大米总数变为2016时，它给出的答案是：（62），与另外两种方法得到的结果不一样；
#    - 出现这种错误的原因是：没有考虑到“while rice_in_king = rice_to_general”的情形。

# try to change the value to 2000 and 2016
# 尝试修改变量 rice_in_king_initial 值分别为2000， 2016
rice_in_king_initial = 2016

# +
# Solution 0 (Original for the lecture)
# 第零种解决方案（原始解决方案）
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 1, 0
while rice_in_king >= rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1
    rice_to_general += 1
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)

# +
# Extra Solution 1
# 第一种额外解决方案
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 0, 0
while rice_in_king > rice_to_general:
    rice_to_general += 1
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1

print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)

# +
# Extra Solution 2
# 第二种额外解决方案
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 1, 0
while rice_in_king > rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1
    rice_to_general += 1
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)
# -

# 2. 如果在本讲的大米奖赏问题中，把国王第一天对将军的奖赏从1袋大米增加为10袋大米，以后每过一天仍然在前一天的基础上多奖赏一袋，那么2000袋大米可以奖赏多少天，国王手中是否有剩余的大米？如果国王一开始的大米为2016袋结果又是怎样呢？请在下面的代码单元格中修改原始的代码后，求解该问题。并将答案写本单元格相应的位置。
#
#    提示：你只需要修改一行代码即可
#    
#    把你的结果写在这里：
#    - 国王一开始有2000袋大米，可连续奖赏（54）天，国王剩余（29）袋；
#    - 国王一开始有2016袋大米，可连续奖赏（54）天，国王剩余（45）袋。

# +
rice_in_king_initial = 2000
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 10, 0
while rice_in_king >= rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1
    rice_to_general += 1
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)

# +
rice_in_king_initial = 2016
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 10, 0
while rice_in_king >= rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1
    rice_to_general += 1
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)
# -

# 3. 继续以本讲示例的大米问题为背景，如果把国王对将军的奖赏从每天增加1袋大米到每天增加10袋大米，保持第一天的奖赏为1袋大米不变。那么2000袋大米可以奖赏多少天？国王手中是否有剩余的大米？如果国王一开始的大米为2016袋结果又是怎样呢？请在下面的代码单元格中修改现成的代码后，求解该问题。
#
#    提示：你只需要修改一行代码即可
#    
#    把你的结果写在这里：
#    - 国王一开始有2000袋大米，可连续奖赏（62）天，国王剩余（47）袋；
#    - 国王一开始有2016袋大米，可连续奖赏（63）天，国王剩余（0）袋。

# +
rice_in_king_initial = 2016
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 1, 0
while rice_in_king >= rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1
    rice_to_general += 1
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)
# -

# 4. 继续以本讲示例的大米问题为背景，如果把国王对将军的奖赏改为：第一天奖赏1袋，第2天奖赏2袋，第三天奖赏4袋，第4天奖赏8袋，...。也就是每一天的奖赏都是前一天奖赏的2倍。那么2000袋大米可以奖赏多少天？国王手中是否有剩余的大米？如果国王一开始的大米为2016袋结果又是怎样呢？请在下面的代码单元格中修改现成的代码后，求解该问题。
#
#    提示：你只需要修改一行代码即可
#    
#    把你的结果写在这里：
#    - 国王一开始有2000袋大米，可连续奖赏（10）天，国王剩余（977）袋；
#    - 国王一开始有2016袋大米，可连续奖赏（10）天，国王剩余（993）袋。   

# +
rice_in_king_initial = 2016
rice_in_king = rice_in_king_initial
rice_in_general, rice_to_general, days_awarded = 0, 1, 0
while rice_in_king >= rice_to_general:
    rice_in_king -= rice_to_general
    rice_in_general += rice_to_general
    days_awarded += 1
    rice_to_general *= 2
    
print("days awarded: ", days_awarded, 
      ", rice left in king:", rice_in_king, 
      ", total rice in general: ", rice_in_general)
# -

# 5. 自己动手编写一段包括`while`循环语句的程序，计算打印出从1开始到100所有100个连续的自然数的和。你的程序应该返回的正确数值是5050。如果让你求解1-100这100个自然数内所有奇数或偶数的和，你的程序应该做怎样的修改？最后的答案分别是什么？

# +
sum_n, num_n = 1, 1
while num_n < 100 :
    num_n += 1
    sum_n += num_n 
    
print("总和是：", sum_n)

# +
# sum_odd
num_initial = 1
num_n = num_initial
sum_n, num_n = 1, 1
while num_n <= 97 :           # 为什么这里是97？有凑数字嫌疑，考虑把它设为<=100
    num_n += 2
    sum_n += num_n
    
print("奇数总和是：", sum_n)

# +
# sum_even
num_initial = 2
num_n = num_initial
sum_n, num_n = 2, 2
while num_n <= 98:  # 为什么这里是98？有凑数字嫌疑，考虑把它设为<=100
    num_n += 2
    sum_n += num_n
    
print("偶数总和是：", sum_n)
# -



StarcoderdataJupyterScriptsDedupFiltered