簡體   English   中英

prolog 是 X 數字 A、B、C 的中位數

[英]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分成兩半LowHigh ,即。 MedianList值分布的“中間元素”。

事實上,上面的程序通過檢查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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM