最近在學(xué)習(xí)Python、算法和一些數(shù)學(xué)知識(shí),希望自己能夠在理解世界、抽象、建模方面能再有所前進(jìn),持續(xù)建設(shè)和完善自己。
倒水趣題:
有兩個(gè)水瓶,一個(gè)的容量是9升,另一個(gè)的容量是4升。問(wèn)如何才能從河中打出6升水?
分析過(guò)程:
設(shè),9升的水瓶容量為A,4升的水瓶容量為B,6升水容量為C。
這道題的本質(zhì)是,計(jì)算并判斷,C能否被A和B來(lái)進(jìn)行度量。求A和B的最大公因數(shù)(或稱:最大公約數(shù)、最大公度)gcm(greatest common measure),進(jìn)而判斷出C能否被gcm度量。
C如果能夠被A和B的gcm度量,那么這道題就可解,進(jìn)而繼續(xù)使用循環(huán)、以及合理的分支,進(jìn)行處理邏輯的設(shè)計(jì),最后編碼實(shí)現(xiàn),測(cè)試驗(yàn)證。最后再用大O表示法,判斷一下最糟糕情況下的運(yùn)行時(shí)間,看看能否進(jìn)行算法優(yōu)化。
解題過(guò)程:
環(huán)境:Windows 11 專業(yè)版,64 位操作系統(tǒng);Python 3.11.1
代碼測(cè)試及調(diào)試方式:IDLE Shell 3.11.1 終端(或Visual Studio Code終端),輸入代碼,按回車即可
一、首先判斷C能否被A和B的gcm進(jìn)行度量
(一)求A和B的最大公因數(shù)gcm:
1、輾轉(zhuǎn)相除法
def calc_gcm(a, b):
? ? while b != 0:
? ? ? ? a, b = b, a % b
? ? return a
2、遞歸法(自己調(diào)用自己)
def calc_gcm(a, b):
? ? if b == 0:
? ? ? ? return a
? ? else:
? ? ? ? return calc_gcm(b, a % b)
(二)判斷C能否被A和B的最大公因數(shù)gcm進(jìn)行度量,即整除
def judge_c(ab, c):
? ? if c % ab == 0:
? ? ? ? return 'ture'
? ? else:
? ? ? ? return 'false'
進(jìn)行判斷:
judge_c(calc_gcm(9, 4), 6)
得到的結(jié)果是:'ture'
二、算法設(shè)計(jì)、編碼實(shí)現(xiàn)(要記得增加必要的注釋哦,讓未來(lái)的自己還能讀懂它,這很重要)
輾轉(zhuǎn)相減的解決方案:
import numpy as np
import csv
def pour(in1, in2, in3):
? ? b = np.array([0, 0])
? ? i = np.array([in1, in2])
? ? d = in3
? ? # 循環(huán)條件
? ? while b[0] >= 0 and b[1] >= 0 and i[0] >= i[1] and i[0] >= d and b[0] != d:
? ? ? ? if b[0] == 0:
? ? ? ? ? ? # print(b)
? ? ? ? ? ? """給第一個(gè)桶,加滿水"""
? ? ? ? ? ? b[0] = i[0]
? ? ? ? ? ? print('為A桶,加滿水')
? ? ? ? ? ? print(b)
? ? ? ? else:
? ? ? ? ? ? # b[0] > 0
? ? ? ? ? ? if b[1] == i[1]:
? ? ? ? ? ? ? ? """第二個(gè)桶,水滿,需倒空"""
? ? ? ? ? ? ? ? b[1] = 0
? ? ? ? ? ? ? ? print('B桶,水滿,需倒空')
? ? ? ? ? ? ? ? print(b)
? ? ? ? ? ? elif b[1] == 0:
? ? ? ? ? ? ? ? if b[0] >= i[1]:
? ? ? ? ? ? ? ? ? ? """第二個(gè)桶,空桶,第一個(gè)桶,可以為第二個(gè)桶倒?jié)M水"""
? ? ? ? ? ? ? ? ? ? b[0] = b[0] - i[1]
? ? ? ? ? ? ? ? ? ? b[1] = i[1]
? ? ? ? ? ? ? ? ? ? print('A桶為空桶B加滿水')
? ? ? ? ? ? ? ? ? ? print(b)
? ? ? ? ? ? ? ? elif b[0] < i[1]:
? ? ? ? ? ? ? ? ? ? """第二個(gè)桶,空桶,第一個(gè)桶,不可以為第二個(gè)桶倒?jié)M水"""
? ? ? ? ? ? ? ? ? ? b[1] = b[1] + b[0]
? ? ? ? ? ? ? ? ? ? b[0] = 0
? ? ? ? ? ? ? ? ? ? print('A桶為空桶B加水')
? ? ? ? ? ? ? ? ? ? print(b)
? ? ? ? ? ? elif b[1] > 0 and b[1] < i[1]:
? ? ? ? ? ? ? ? if b[0] < (i[1] - b[1]):
? ? ? ? ? ? ? ? ? ? """第二個(gè)桶,不是空桶,第一個(gè)桶不可以為第二個(gè)桶倒?jié)M水"""
? ? ? ? ? ? ? ? ? ? b[1] = b[1] + b[0]
? ? ? ? ? ? ? ? ? ? b[0] = 0
? ? ? ? ? ? ? ? ? ? print('A桶為非空桶B加水')
? ? ? ? ? ? ? ? ? ? print(b)
? ? ? ? ? ? ? ? elif b[0] > (i[1] - b[1]):
? ? ? ? ? ? ? ? ? ? """第二個(gè)桶,不是空桶,第一個(gè)桶可以為第二個(gè)桶倒?jié)M水"""
? ? ? ? ? ? ? ? ? ? b[0] = b[0] - (i[1] - b[1])
? ? ? ? ? ? ? ? ? ? b[1] = i[1]
? ? ? ? ? ? ? ? ? ? print('A桶為非空桶B加滿水')
? ? ? ? ? ? ? ? ? ? print(b)
? ? print('結(jié)束')
? ? print(b)
測(cè)試執(zhí)行:
pour(9, 4, 6)
執(zhí)行結(jié)果:
>>> pour(9, 4, 6)
為A桶,加滿水
[9 0]
A桶為空桶B加滿水
[5 4]
B桶,水滿,需倒空
[5 0]
A桶為空桶B加滿水
[1 4]
B桶,水滿,需倒空
[1 0]
A桶為空桶B加水
[0 1]
為A桶,加滿水
[9 1]
A桶為非空桶B加滿水
[6 4]
結(jié)束
[6 4]
好啦,倒水趣題的每一步驟,都被很好的展示出來(lái)了,接下來(lái),需要根據(jù)大O表示法,考慮一下算法優(yōu)化了,等我再多學(xué)一些處理手段,再更新倒水趣題的新算法哈
補(bǔ)充知識(shí):
如果遇到下載numpy模塊失敗的情況,需要使用國(guó)內(nèi)的源,通過(guò)pip開(kāi)展numpy模塊安裝
環(huán)境:Windows 11 專業(yè)版,64 位操作系統(tǒng);Python 3.11
1、安裝numpy模塊:
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
2、升級(jí)pip:
首先,打開(kāi)【文件資源管理器】--訪問(wèn)【Python安裝目錄? D:\Program Files\Python\Python311\ 】
而后,在目錄位置,輸入其中的命令?【cmd】
輸入其中的命令,升級(jí)pip到25.3 【python.exe -m pip install --upgrade pip==25.3 -i https://pypi.tuna.tsinghua.edu.cn/simple】
3、添加信任主機(jī):
輸入其中的命令,添加信任主機(jī) 【python -m pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org numpy】