[英]prolog is X the median of numbers A, B, C
我剛開始學習 prolog 時遇到了一些麻煩。 我不確定如何測試 X 是否是 A、B、C 的中位數。我的第一個想法是列出 A、B、C 的列表,然后對其進行排序。 然后我會檢查 X 是否等於第二個數字。 問題是我不知道如何取三個值並將它們變成一個列表(如果可以的話)。 這甚至是最有效的方法嗎? 老實說,我不知道所以任何網站都會有幫助。
這是一個非常基本的解決方案,排序只接受 3 個值,但它應該可以解決問題。
is_median_of_sorted([_, ValueToCheck, _],ValueToCheck).
sorted_list_of_3([A,B,C],R) :-
A>B, A>C, B>C, R = [A,B,C];
A>C, A>B, C>B, R = [A,C,B];
B>A, B>C, A>C, R = [B,A,C];
B>C, B>A, C>A, R = [B,C,A];
C>A, C>B, A>B, R = [C,A,B];
C>B, C>A, B>A, R = [C,B,A].
is_median_of_3(List, ValueToCheck) :-
sorted_list_of_3(List,SortedList),
is_median_of_sorted(SortedList, ValueToCheck).
要檢查它,請查詢:
is_median_of_3([1,10,4],4).
或者,如果您想檢查給定列表的中位數:
is_median_of_3([1,10,4],X).
您也可以通過瀏覽器查看: https : //swish.swi-prolog.org/p/three_values_median.pl
它的作用是: is_median_of_3首先獲取一個匹配的排序列表,然后再次檢查is_median_of_sorted ,它只選擇列表的第二個元素。
希望我能幫上忙。
如果您想創建一個模塊化程序,您必須將所有元素插入一個列表中,對其進行排序並找到中位數。 這可以通過這種方式完成:
findMedian([H|_],0,H):- !.
findMedian([_|T],C,X):-
C1 is C-1,
findMedian(T,C1,X).
median(L,X):-
msort(L,SortedL),
length(SortedL,Len),
Len2 is Len//2,
findMedian(SortedL,Len2,X).
?- median([1,10,4,5,7],X).
X = 5
?- median([1,10,4,5,7],5).
true
此解決方案也適用於具有偶數個元素的列表,返回列表中間之后的元素(例如 4 個元素, [0,1,2,3]
,它返回2
)。 在這種情況下,您必須決定要做什么(失敗,返回中間 ecc 中的兩個元素...)
編輯:正如評論中所建議的,您應該使用msort/2
而不是sort/2
因為sort/2
刪除重復的元素。
我會選擇一個類似於@damianodamiano 的解決方案,但我會在不使用length/2
情況下找到列表的中間元素:
median(List, Median) :-
msort(List, SortedList),
middle_element(SortedList, SortedList, Median).
middle_element([], [M|_], M).
middle_element([_], [M|_], M).
middle_element([_,_|Xs], [_|Ys], M) :-
middle_element(Xs, Ys, M).
“檢查 X 是否是 A、B、C 的中位數? ”的簡單答案是:
is_median_of_3(A,B,C,X):-
msort([A,B,C],[_,X,_]).
如果[A,B,C]
排序由任何列表(三個元素)組成,其中X
作為中間元素[A,B,C]
這將嘗試匹配。
我不知道無處不在,但在swish 中,有來自msort
殘差:
msort([2,8,4],L).
L = [2, 4, 8],
_residuals = []
L = [2, 4, 8],
_residuals = [_1080]
L = [2, 4, 8],
_residuals = [_1122, _1128]
L = [2, 4, 8],
_residuals = [_1170, _1176, _1182]
L = [2, 4, 8],
_residuals = [_1224, _1230, _1236, _1242]
L = [2, 4, 8],
_residuals = [_1284, _1290, _1296, _1302, _1308]
L = [2, 4, 8],
_residuals = [_716, _722, _728, _734, _740, _746]
L = [2, 4, 8],
_residuals = [_788, _794, _800, _806, _812, _818, _824]
L = [2, 4, 8],
_residuals = [_866, _872, _878, _884, _890, _896, _902, _908]
等等...
另外,我無法在tutorialspoint 中對其進行測試,因為它似乎已損壞。
遵循生成和測試方法,您可以編寫:
median(List,Median) :-
dif(List,[]), msort(List,SList), length(List,Len),
append(Low,[Median],Tmp), append(Tmp,High,SList),
length(Low,LowLen), div(Len,2)=:=LowLen, !.
這有一個方便的聲明性閱讀: Median
值是一個非空List
的值, SList
List
的排序版本SList
分成兩半Low
和High
,即。 Median
是List
值分布的“中間元素”。
事實上,上面的程序通過檢查SList
是否可以寫成列表串聯Low + [Median] + High
來確定Median
,使得Low
的長度是SList
長度的SList
。 由於從不使用High
(即它是一個單例),程序可以通過用_
替換它來重寫,如下所示:
median(List,Median) :-
dif(List,[]), msort(List,SList), length(List,Len),
append(Low,[Median],Tmp), append(Tmp,_,SList),
length(Low,LowLen), div(Len,2)=:=LowLen, !.
自然,也可以區分列表長度為奇數的情況和偶數的情況,因此在后一種情況下返回兩個中值元素的平均值:
median(List,Median) :-
is_list(List), dif(List,[]),
msort(List,SList), length(List,Len),
median(SList,Len,Median).
median(SList,Len,Median) :-
Len mod 2 =:= 1,
append3(Low,[Median],_,SList),
length(Low,LowLen), div(Len,2)=:=LowLen, !.
median(SList,Len,Median) :-
Len mod 2 =:= 0,
append3(Low,[M1,M2],_,SList),
length(Low,LowLen), div(Len,2)=:=LowLen + 1,
Median is (M1+M2)/2, !.
append3(L1,L2,L3,L) :- append(L1,L2,T), append(T,L3,L).
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.