列表中的数字小于给定数字 [英] Numbers in a list smaller than a given number

查看:85
本文介绍了列表中的数字小于给定数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

xMenores(_,[],[]).
xMenores(X,[H|T],[R|Z]) :-
   xMenores(X,T,Z),
   X > H,
   R is H.

xMenores带有三个参数:

  • 第一个是数字.
  • 第二个是数字列表.
  • 第三个是列表,并且是将包含结果的变量.

规则xMenores的目标是获得一个列表,该列表的编号(第二个参数)小于第一个参数上的值.例如:

The objective of the rule xMenores is obtain a list with the numbers of the list (Second parameter) that are smaller than the value on the first parameter. For example:

?- xMenores(3,[1,2,3],X).
X = [1,2].                        % expected result

问题在于,当X > H为false并且我的编程技能在序言中几乎为空时,xMenores返回false.所以:

The problem is that xMenores returns false when X > H is false and my programming skills are almost null at prolog. So:

?- xMenores(4,[1,2,3],X).
X = [1,2,3].                      % Perfect.

?- xMenores(2,[1,2,3],X).
false.                            % Wrong! "X = [1]" would be perfect.

我考虑使用X > H, R is H.是因为我需要每当X大于H时,R就采用H的值.但是我不知道像Prolog中的if或类似的控件结构可以处理此问题.

I consider X > H, R is H. because I need that whenever X is bigger than H, R takes the value of H. But I don't know a control structure like an if or something in Prolog to handle this.

请问有什么解决办法吗?谢谢.

Please, any solution? Thanks.

推荐答案

使用( if -> then ; else )

您可能要寻找的控制结构是( if -> then ; else ).

警告:您可能应该交换前两个参数的顺序:

Warning: you should probably swap the order of the first two arguments:

lessthan_if([], _, []).
lessthan_if([X|Xs], Y, Zs) :-
    (   X < Y
    ->  Zs = [X|Zs1]
    ;   Zs = Zs1
    ),
    lessthan_if(Xs, Y, Zs1).

但是,如果您正在编写真实代码,则几乎可以肯定应该使用由@CapelliC建议:

However, if you are writing real code, you should almost certainly go with one of the predicates in library(apply), for example include/3, as suggested by @CapelliC:

?- include(>(3), [1,2,3], R).
R = [1, 2].

?- include(>(4), [1,2,3], R).
R = [1, 2, 3].

?- include(<(2), [1,2,3], R).
R = [3].

请参见 include/3 的实现.您会注意到上面的lessthan/3只是库(应用)中更通用的include/3的特化:include/3将重新排列参数并使用( if -> then ; else ).

See the implementation of include/3 if you want to know how this kind of problems are solved. You will notice that lessthan/3 above is nothing but a specialization of the more general include/3 in library(apply): include/3 will reorder the arguments and use the ( if -> then ; else ).

或者,较少程序性"而较多声明性"的谓词:

Alternatively, a less "procedural" and more "declarative" predicate:

lessthan_decl([], _, []).
lessthan_decl([X|Xs], Y, [X|Zs]) :- X < Y,
    lessthan_decl(Xs, Y, Zs).
lessthan_decl([X|Xs], Y, Zs) :- X >= Y,
    lessthan_decl(Xs, Y, Zs).

(lessthan_if/3lessthan_decl/3与Nicholas Carey的解决方案几乎相同,除了顺序争论.)

(lessthan_if/3 and lessthan_decl/3 are nearly identical to the solutions by Nicholas Carey, except for the order of arguments.)

不利的一面是,lessthan_decl/3留下了选择点.但是,对于一般的可读解决方案来说,这是一个很好的起点.我们需要两个代码转换:

On the downside, lessthan_decl/3 leaves behind choice points. However, it is a good starting point for a general, readable solution. We need two code transformations:

  1. 用CLP(FD)约束替换算术比较<>=:#<#>=;
  2. 使用DCG规则消除定义中的参数.
  1. Replace the arithmetic comparisons < and >= with CLP(FD) constraints: #< and #>=;
  2. Use a DCG rule to get rid of arguments in the definition.

您将通过lurker到达解决方案.

You will arrive at the solution by lurker.

Prolog中最通用的比较谓词是 compare/3 .一种使用它的常见模式是显式枚举Order的三个可能值:

The most general comparison predicate in Prolog is compare/3. A common pattern using it is to explicitly enumerate the three possible values for Order:

lessthan_compare([], _, []).
lessthan_compare([H|T], X, R) :-
    compare(Order, H, X),
    lessthan_compare_1(Order, H, T, X, R).

lessthan_compare_1(<, H, T, X, [H|R]) :-
    lessthan_compare(T, X, R).
lessthan_compare_1(=, _, T, X, R) :-
    lessthan_compare(T, X, R).
lessthan_compare_1(>, _, T, X, R) :-
    lessthan_compare(T, X, R).

(与其他解决方案相比,该解决方案可以使用任何术语,而不仅仅是整数或算术表达式.)

(Compared to any of the other solutions, this one would work with any terms, not just integers or arithmetic expressions.)

compare/3替换为 zcompare/3 :

:- use_module(library(clpfd)).

lessthan_clpfd([], _, []).
lessthan_clpfd([H|T], X, R) :-
    zcompare(ZOrder, H, X),
    lessthan_clpfd_1(ZOrder, H, T, X, R).

lessthan_clpfd_1(<, H, T, X, [H|R]) :-
    lessthan_clpfd(T, X, R).
lessthan_clpfd_1(=, _, T, X, R) :-
    lessthan_clpfd(T, X, R).
lessthan_clpfd_1(>, _, T, X, R) :-
    lessthan_clpfd(T, X, R).

这肯定比其他任何解决方案都要多的代码,但它不会留下不必要的选择点:

This is definitely more code than any of the other solutions, but it does not leave behind unnecessary choice points:

?- lessthan_clpfd(3, [1,3,2], Xs).
Xs = [1, 2]. % no dangling choice points!

在其他情况下,其行为与潜伏者的DCG解决方案一样:

In the other cases, it behaves just as the DCG solution by lurker:

?- lessthan_clpfd(X, [1,3,2], Xs).
Xs = [1, 3, 2],
X in 4..sup ;
X = 3,
Xs = [1, 2] ;
X = 2,
Xs = [1] ;
X = 1,
Xs = [] .

?- lessthan_clpfd(X, [1,3,2], Xs), X = 3. %
X = 3,
Xs = [1, 2] ; % no error!
false.

?- lessthan_clpfd([1,3,2], X, R), R = [1, 2].
X = 3,
R = [1, 2] ;
false.

除非您需要这种通用方法,否则include(>(X), List, Result)就足够了.

Unless you need such a general approach, include(>(X), List, Result) is good enough.

这篇关于列表中的数字小于给定数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆