【问题标题】:prolog is X the median of numbers A, B, Cprolog 是 X 数字 A、B、C 的中位数
【发布时间】:2018-07-21 10:23:39
【问题描述】:

我刚开始学习 prolog,遇到了一些麻烦。我不确定如何测试 X 是否是 A、B、C 的中位数。我的第一个想法是列出 A、B、C 的列表,然后对其进行排序。然后我会检查 X 是否等于第二个数字。问题是我不知道如何取三个值并将它们变成一个列表(如果可以的话)。这甚至是最有效的方法吗?老实说,我没有任何想法,所以任何网站都会有所帮助。

【问题讨论】:

  • 只需将它们插入到列表中,然后调用排序谓词。 prolog 中最简单的方法是将内容放入列表中,因为它不进行类型检查。
  • 如果要将ABC放入一个列表中,[A,B,C]是一个由ABC组成的列表。你只需要写它。
  • 给出了四个答案。他们都不能接受吗?

标签: list prolog median


【解决方案1】:

这是一个非常基本的解决方案,排序只接受 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,它只选择列表的第二个元素。

希望我能帮上忙。

【讨论】:

  • 如果你有 20 个变量呢?你会写所有变量的 20 倍吗?
  • :) 当然不是 - 对于中位数为 3 的给定问题,这只是一个简单的示例。对于像 N 个变量进行排序,您可以实现快速排序或任何其他示例,并在中间取一个值. - 就像这里的另一个答案一样。我的意思是轻松展示如何做到这一点。
【解决方案2】:

如果你想创建一个模块化程序,你必须将所有元素插入到一个列表中,对其进行排序并找到中间值。这可以通过这种方式完成:

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 会删除重复的元素。

【讨论】:

  • 这里要小心。 sort 消除重复。因此,如果您有任何重复的元素,这应该是一个有效的案例,它将无法正常工作。您可以改用msort/2
  • 你绝对是对的@lurker,谢谢你的通知
【解决方案3】:

我会选择类似于@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).

【讨论】:

    【解决方案4】:

    检查 X 是否是 A,B,C 的中位数?的简单答案是:

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

    如果[A,B,C] sorted 由任何列表(三个元素)组成,X 作为中间元素,这将尝试匹配。


    我不知道到处都是,但在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 中测试它,因为它似乎坏了。

    【讨论】:

    • “有来自msort/2 的残差”是什么意思?可以举个例子吗?
    • @damianodamiano 查看我的更新,例如 msort/2 in swish
    • 你是在程序的查询中直接写msort([2,8,4],L)吗?因为在这两种情况下,我都没有得到_residuals,而只有排序的列表...... @Rafalon
    • @damianodamiano 直接在查询中,但可能只在我的电脑或浏览器上。无论如何_residuals 不会在这里,所以如果我是唯一看到这个的人,那么我的回答是有效的:)
    • 哈哈,我刚查了FF,没有_residuals!那么很可能是 IE 出了问题(我应该像往常一样说吗?)
    【解决方案5】:

    按照 generate & test 方法,您可以编写:

    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 的值,它将List 的排序版本SList 分成两半LowHigh,即。 MedianList 中值分布的“中间元素”。

    确实,上面的程序通过检查SList是否可以写成列表连接Low + [Median] + High来确定Median,使得Low的长度是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).
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 2015-02-06
      • 2016-10-27
      • 2013-05-26
      • 1970-01-01
      相关资源
      最近更新 更多