這篇文章是從我的訂閱號從copy來的。歡迎關注哈:學術學習小助手。剛開始玩訂閱號,請多指教
-
概述
可能很多人小時候都玩過24點這個遊戲,遊戲的規則是從紙牌(除去小丑派)中抽四張,每張派只能用一次,通過+、-、x、÷最終得到24的值。
最近想到了這個問題,出現了靈感,決定把它記錄下來。
-
原理
首先是24點的計算過程,取兩張牌,計算,得到一個數,接着重複兩次。最終得到一個數。。。
如果用球形表示數,用方形表示運算符,那麼我們可以這樣表示:
每次取兩個球,一個方塊,計算得到一個新的球,並放到回這個新的球。
重複這個操作三次,就能夠將四個球消去成一個球:
此時,只需要判斷最終剩下的球是不是等於24呢?如果答案是肯定的,那麼這個過程就是求解24點的過程。如果答案是否定的,則需要進行循環,包括運算符和兩個球的的選擇,需要注意,兩個球的順序是有影響的(也就是說可以把球認爲是排列)。這樣循環下去,最終如果所有情況全部遍歷完還沒有解,這時就說明真的沒有解了。
這個時候我們需要估計一下,這個循環次數有多少,如果最大的循環次數過大,就不能直接解出來。這個問題不就類似於高中的排列組合問題嘛。
所有的可能性N爲:
最多循環9216次就能夠得到24點。
分析到這我認爲這個問題就可以交給計算機了。
這時用任何編程語言都能夠實現上述的方法(當然,如果邏輯有問題也請各位批評指正)
-
實現
我選擇使用MATLAB的函數來實現上述的方法。
邏輯和原理是一致的,只不過增加了一些判斷防止運算出錯,再次特別說明一下。
-
輸入必須爲正整數,如果不是,那麼會報錯。
-
運算過程中取出的數也都應當是非零的,如果不是,則會跳過當前循環。
-
如果遍歷完還沒有出現解,那麼說明無解;當最終的數與24點差距在0.01以內認爲已經求出解(由於運算過程中可能出現小數,因此需要容錯區間)。
下面分享我的代碼:
function point_24(a,b,c,d)
if a<=0||b<=0||c<=0||d<=0
error('輸入應爲正整數')
end
xulie=[a b c d];
fuhao=['+-*/'];
temp_0=xulie;
log=[];
for i=1:4
%讀取第1步序列,選擇第1個數
temp_1_1=temp_0;
num_1=temp_1_1(i);
temp_1_1(i)=[];
for j=1:3
%選擇第2個數
temp_1_2=temp_1_1;
num_2=temp_1_2(j);
temp_1_2(j)=[];
for k=1:4
%選擇第1次運算,並結果保存到temp_1_C。
if num_1<=0||num_2<=0
continue
end
temp_cacu=[num2str(num_1),fuhao(k),num2str(num_2)];
log={log;temp_cacu};
temp_1_C=[temp_1_2,eval(temp_cacu)];
for l=1:3
%讀取第2步序列,選擇第三個數
temp_2_1=temp_1_C;
num_3=temp_2_1(l);
temp_2_1(l)=[];
for m=1:2
%選擇第四個數
temp_2_2=temp_2_1;
num_4=temp_2_2(m);
temp_2_2(m)=[];
for n=1:4
%選擇第二次運算,並結果保存到temp_2_C。
if num_3<=0||num_4<=0
continue
end
temp_cacu=[num2str(num_3),fuhao(n),num2str(num_4)];
log={log;temp_cacu};
temp_2_C=[temp_2_2,eval(temp_cacu)];
for o=1:2
%讀取第3步序列,選擇第五個數
temp_3_1=temp_2_C;
num_5=temp_3_1(o);
temp_3_1(o)=[];
%選擇第六個數
temp_3_2=temp_3_1;
num_6=temp_3_2;
temp_3_2=[];
for p=1:4
%選擇第三次運算,並結果保存到temp_3_1。
if num_5<=0||num_6<=0
continue
end
temp_cacu=[num2str(num_5),fuhao(p),num2str(num_6)];
log={log;temp_cacu};
temp_3_C=[temp_3_2,eval(temp_cacu)];
temp_4=temp_3_C;
if abs(temp_4-24)<=1e-3
temp_a=[num2str(num_1),fuhao(k),num2str(num_2)];
temp_b=[num2str(num_3),fuhao(n),num2str(num_4)];
temp_c=[num2str(num_5),fuhao(p),num2str(num_6)];
disp([temp_a,'=',num2str(eval(temp_a))]);
disp([temp_b,'=',num2str(eval(temp_b))]);
disp([temp_c,'=',num2str(eval(temp_c))]);
return
end
end
end
end
end
end
end
end
end
disp('算不出來')
end
這段代碼保存爲'point_24.m' 放置在MATLAB的工作文件夾就行了。
-
測試
-
大家可以按照下面的代碼進行測試:
-
A=[4,7,2,12;9,11,5,3;9,3,4,10;8,6,7,7;13,5,8,6;1,9,5,12]; for e=1:6 a=A(e,1); b=A(e,2); c=A(e,3); d=A(e,4); point_24(a,b,c,d); disp(['↑第',num2str(e),'個答案']) end
測試的結果如下: