简体   繁体   English

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

[英]prolog is X the median of numbers A, B, C

I am having a bit of trouble with prolog as I have just started learning it.我刚开始学习 prolog 时遇到了一些麻烦。 I am unsure how to test if X is the median of A, B, C. My first thought was to make a list of A, B, C and then sort it.我不确定如何测试 X 是否是 A、B、C 的中位数。我的第一个想法是列出 A、B、C 的列表,然后对其进行排序。 I would then check if X is equal to the second number.然后我会检查 X 是否等于第二个数字。 The problem being that I don't know how to take three values and turn them into a list (If you can).问题是我不知道如何取三个值并将它们变成一个列表(如果可以的话)。 Is this even the most effecent way to do this?这甚至是最有效的方法吗? Honestly I have no Idea so any insite would be helpful.老实说,我不知道所以任何网站都会有帮助。

this is a very basic solution, with a sorting only accepting 3 values, but it should make the problem solved.这是一个非常基本的解决方案,排序只接受 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).

To check it, query:要检查它,请查询:

    is_median_of_3([1,10,4],4). 

Or if you want to check what is the median of a given list:或者,如果您想检查给定列表的中位数:

    is_median_of_3([1,10,4],X).

You can also check it via browser at: https://swish.swi-prolog.org/p/three_values_median.pl您也可以通过浏览器查看: https : //swish.swi-prolog.org/p/three_values_median.pl

What is does is : is_median_of_3 first gets a matching sorted list, and then checks agains is_median_of_sorted , which just picks a 2nd element of the list.它的作用是: is_median_of_3首先获取一个匹配的排序列表,然后再次检查is_median_of_sorted它只选择列表的第二个元素。

Hope I could help.希望我能帮上忙。

If you want to create a modular program, you had to insert all the elements in a list, sort it and find the median.如果您想创建一个模块化程序,您必须将所有元素插入一个列表中,对其进行排序并找到中位数。 This could be done in this way:这可以通过这种方式完成:

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

This solution will works also with list with an even number of elements, returning the element after the middle of the list (ex. 4 elements, [0,1,2,3] , it returns 2 ).此解决方案也适用于具有偶数个元素的列表,返回列表中间之后的元素(例如 4 个元素, [0,1,2,3] ,它返回2 )。 In this case you have to decide what to do (fail, return the two elements in the middle ecc...)在这种情况下,您必须决定要做什么(失败,返回中间 ecc 中的两个元素...)

EDIT: as suggested in the comment, you should use msort/2 instead sort/2 because sort/2 removes duplicated elements.编辑:正如评论中所建议的,您应该使用msort/2而不是sort/2因为sort/2删除重复的元素。

I would choose a solution similar to @damianodamiano's, but I would find the middle element of a list without using length/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).

A simple answer to " check if X is the median of A,B,C? " is: 检查 X 是否是 A、B、C 的中位数? ”的简单答案是:

is_median_of_3(A,B,C,X):-
    msort([A,B,C],[_,X,_]).

This will try to match if [A,B,C] sorted consists of any list (of three elements) with X as the middle element.如果[A,B,C]排序由任何列表(三个元素)组成,其中X作为中间元素[A,B,C]这将尝试匹配。


I don't know everywhere, but in swish there are residuals coming out from msort as such:我不知道无处不在,但在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]

and so on...等等...

Also, I couldn't test it in tutorialspoint because it seems broken.另外,我无法在tutorialspoint 中对其进行测试,因为它似乎已损坏。

Following a generate & test approach you can write:遵循生成和测试方法,您可以编写:

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, !.

This has a convenient declarative reading: Median is the value of a non-empty List that splits the sorted version SList of List into two halves Low and High , viz.这有一个方便的声明性阅读: Median值是一个非空List的值, SList List的排序版本SList分成两半LowHigh ,即。 Median is the "middle element" of the distribution of the values in List . MedianList值分布的“中间元素”。

Indeed, the program above determines Median by checking whether SList can be written as a list concatenation Low + [Median] + High such that the length of Low is half the length of SList .事实上,上面的程序通过检查SList是否可以写成列表串联Low + [Median] + High来确定Median ,使得Low的长度是SList长度的SList Since High is never used (ie it is a singleton), the program can be rewritten by substituting it with _ as in:由于从不使用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, !.

Naturally, it is also possible to distinguish the case in which the length of the list is odd from the case it is even, so to return the average of the two median elements in the latter case:自然,也可以区分列表长度为奇数的情况和偶数的情况,因此在后一种情况下返回两个中值元素的平均值:

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