列表中的数字小于给定数字 [英] Numbers in a list smaller than a given number
问题描述
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/3
和lessthan_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:
- 用CLP(FD)约束替换算术比较
<
和>=
:#<
和#>=
; - 使用DCG规则消除定义中的参数.
- Replace the arithmetic comparisons
<
and>=
with CLP(FD) constraints:#<
and#>=
; - 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屋!