[英]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.