大家好,小弟在做完Day 6之後發現這天專案用到的部分可以拿來做邏輯簡化的範例,主要是想要分享給一些新手,尤其是非本科系或是沒有修過電子電路的人,順便來練習一下發文,那麼我們就ˋ直接從程式碼的部分開始吧。
下面兩個程式碼區塊都是在判斷走迷宮時,根據前方和右方是否有牆壁的條件下所需要做應對的動作。
# 程式區塊 A
while not at_goal():
if front_is_clear() and wall_on_right(): #條件 1
move()
elif right_is_clear(): #條件 2
turn_right()
move()
else: #條件 3
turn_left()
# 程式區塊 B
while not at_goal():
if right_is_clear(): #條件 1
turn_right()
move()
elif front_is_clear(): #條件 2
move()
else: #條件 3
turn_left()
比較細心的人可能會發現這兩個程式的 if/elif 長得有點不太一樣,但其實這兩個程式碼的邏輯是相同的,我們這邊用表格的方式來把邏輯展現出來吧。
表格展現方法 1:
程式區塊 A | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | (非條件1 and 非條件2 and )條件3 | 條件1 |
右方無牆壁 | (非條件1 and )條件2 | (非條件1 and )條件2 |
程式區塊 B | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | (非條件1 and 非條件2 and )條件3 | (非條件1 and )條件2 |
右方無牆壁 | 條件1 | 條件1 |
如果我們把條件裡的動作再用下方表格替換掉的話
實際動作 | 動作類型 |
---|---|
move() | 動作1 |
turn_right() and move() | 動作2 |
turn_left() | 動作3 |
就會變成
表格展現方法 2:
程式區塊 A | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | 動作3 | 動作1 |
右方無牆壁 | 動作2 | 動作2 |
程式區塊 B | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | 動作3 | 動作1 |
右方無牆壁 | 動作2 | 動作2 |
由上面兩個表格我們就可以知道這兩個程式區塊所代表的邏輯其實是相同的,那麼問題來了,為什麼要去簡化它呢?除了一方面可以增加可讀性之外,也還有減少多餘的程式、增加程式執行的速度。首先我們假設進入每個條件的機率都是一樣的,如下方表格所示:
進入條件式的比重 | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | 1 | 1 |
右方無牆壁 | 1 | 1 |
然後將表格展現方法 1 的條件判斷式數量量化 (注:非條件式也代表執行了 1 次判斷喔),然後我們再將比重相乘上去就可以得出程式預期執行時的總判斷式數量了。
程式區塊 A 所需要執行的判斷式數量 | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | 3 | 1 |
右方無牆壁 | 2 | 2 |
1 * 3 + 1 * 1 + 1 * 2 + 1 * 2 = 8
程式區塊 B 所需要執行的判斷式數量 | 前方有牆壁 | 前方無牆壁 |
---|---|---|
右方有牆壁 | 3 | 2 |
右方無牆壁 | 1 | 1 |
1 * 3 + 1 * 2 + 1 * 1 + 1 * 1 = 7
所以到這裡我們不僅可以單從程式碼的部分看出程式區塊 B 的條件式較為簡潔之外,本身執行的判斷式也是較少的,即我們可以花更少的時間就執行完這支程式,打到這裡發現畫了太多表格導致文章有點長,那麼就先將簡化的重頭戲「卡諾圖」放到下一篇文章好了。