一道經典面試邏輯題的python解法
前言:
好早之前看到的一個邏輯題:有兩個2到99之間的整數,a知道這兩個數的和,b知道這兩個數的積。
第一句:a對b說:我不知道這兩個數是多少,但我確信你也不知道。
第二句:b說:我知道了。
第三句:a說:我也知道了。
問這兩個數是多少? 題不難,只是手動去找沒有python寫程式找的快,而且用python程式可以在後面進行進一步的探索。
分析:
首先是a手上的數是兩個數的和,那是在[4,198]之間。
第一句話分析:a確信b不知道這兩個數
(1)
比如a手上的數字是8,那麼要求的兩個數字就有可能是(2,6),(3,5),(4,4)這三種情況,對應的b手上的數字就可能是12,15,16這三種情況,這是來自a的視角。
但簡單分析,第一句話 a確信b不知道這兩個數字是多少。那麼b手上的數字肯定不可能是15,為什麼呢?因為15只有一種分解情況(兩個素數相乘):3*5。如果b手上是15,那麼b肯定知道這兩個數字是3和5了。
進而可以分析出 a 手上的數字肯定不是8, 因為a手上是8的話,那b手上可能的三種情況(12,15,16) 其中的15這種情況,b是可以分析出這兩個數字分別是多少的,而a確信b不知道,所以可以排除8。
進一步,那a手上什麼數字可以排除掉呢?通過上面的分析,
可以得出 結論(1):a是不能分解成兩個素數的和,凡是可以分解成兩個素數的和的情況,b是可以知道這兩個數的
上python程式碼:
asum1裡面存了a手上還可能的數,54個(排除了那些能分解成兩個素數的數)
(2)
上面的54個可能裡面全是奇數,沒有偶數。
進一步分析:a 手上的數字也不能寫成(53+2*x,x>=2)這種形式,因為如果可以分解成這種形式,b=53*2*x,因為兩個數是小於等於99的,53*2>99了,也只有一種分解情況53,2*x,進而b也知道這兩個數字了。
所以結論(2):比上限/2(99/2=49.5)大的第一個素數(53),+3(56)以後的數字就排除了。
為什麼是+3,因為2*x最小是4.
所以經過第一句話後,a手上的數字asum2集合 還剩11個
[11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53] <-asum2
把他們分解了,相乘得到b的粗略集合:
第二句話分析:b知道了
b在什麼情況下可以說這樣的話呢?
比如b =24, 那麼可能的分解(2,12),(3,8),(4,6)兩種情況,那麼對於的 a就是14,11和10三種情況,這是來自b的視角。
剛開分析了那麼多得出a手上剩下的可能性:[11, 17, 23, 27, 29, 35, 37, 41, 47, 51, 53],這個集合的意思是當a手上是這些數的時候a才敢說第一句話,反言之a手上不是這些數時a就不敢說這些話。
那麼24分解出來得到的 14,11和10三種情況:14,10不在a可能集合裡,11在可能集合裡。
11是唯一一個在a可能集合裡的,所以b可以分析出a手上的數字是11,因為如果是其他兩個數的話,a不敢說第一句話。
進而得出一個結論:b分解出來的所有兩個數eg:(2,12),(3,8),(4,6)所組成的和eg:14,11和10, 有且只有一個存在在a的可能集合裡
經過第二句話b手上可能數字有102個,存入bmul1
第三句話分析:a知道了
和第二句話一模一樣的分析,a為什麼能知道?唯一的可能性就是a手上的數的分解後組成的積有且只有一種情況在集合bmul1裡(第二句話算出的集合b)
現在就只有唯一一個結果了。
輸出結果
原題到這裡就結束了,後面可以展開一些思考。
(1)既然得出的結論是4和13,不算大,而條件給的是2-99,那麼有沒有可能把條件範圍給小一點,比如給2-20來降低題目難度呢,畢竟這樣計算量要小很多。程式裡面可以直接把初始條件從99改成20,結果是沒有找到符合要求的兩個數。為什麼呢?
原因是雖然4和13小於20,但a看到的是17,那麼有可能分解成8和9,在a的視角b的數字有可能是72,同時在b的視角的可以分解成2*36,這個36就一下大於20了哦。
那麼把題目換個有趣的問法,同樣的對話,兩個數字的範圍是2-N,N至少取多大,才能保證至少有一個解?
用程式解很簡單,讓N從10到99進行一次遍歷,看從哪次開始有解了就輸出
得到的結論是:N至少是64才有一個解,(4,13)
(2) 那麼把N擴大,範圍擴大,解會變多嗎
如果範圍擴大到2-999了,有了第二個解4,61。大家可以思考一下為什麼範圍在2-99的時候沒有出現這個解
範圍擴大到2-9999了,算出來了13個解,分別是:
1 兩個數和: 17 兩個數積: 52
兩個數為: [4, 13]
2 兩個數和: 65 兩個數積: 244
兩個數為: [4, 61]
3 兩個數和: 89 兩個數積: 1168
兩個數為: [16, 73]
4 兩個數和: 127 兩個數積: 1776
兩個數為: [16, 111]
5 兩個數和: 137 兩個數積: 4672
兩個數為: [64, 73]
6 兩個數和: 163 兩個數積: 4192
兩個數為: [32, 131]
7 兩個數和: 179 兩個數積: 2608
兩個數為: [16, 163]
8 兩個數和: 185 兩個數積: 724
兩個數為: [4, 181]
9 兩個數和: 191 兩個數積: 8128
兩個數為: [64, 127]
10 兩個數和: 233 兩個數積: 916
兩個數為: [4, 229]
11 兩個數和: 247 兩個數積: 1912
兩個數為: [8, 239]
12 兩個數和: 343 兩個數積: 9952
兩個數為: [32, 311]
13 兩個數和: 373 兩個數積: 19776
兩個數為: [64, 309]