使用序言查找三个数字之间的最大数
Finding the maximum number between three numbers using prolog
我从昨天开始学习序言,我被告知要找到三个数字之间的最大数字。我正在使用 SWI Prolog,这是我到目前为止编写的程序。
% If-Elif-Else statement
gte(X,Y,Z) :- X > Y,write('X is greater').
gte(X,Y,Z) :- X =:= Y,write('X and Y are same').
gte(X,Y,Z) :- X < Y < Z,write('Y is greater').
gte(X,Y,Z) :- X < Z,write('Z is greater').
gte(X,Y,Z) :- X > Z,write('X is greater').
gte(X,Y,Z) :- Y > Z,write('Y is greater').
gte(X,Y,Z) :- Y < Z,write('Z is greater').
gte(X,Y,Z) :- X=:=Z,write('X and Z are same').
gte(X,Y,Z) :- Y=:=Z,write('Y and Z are same').
输出应该是 ->
gte(12,24,36)
24 is greater.
True
而是给我看这个
Warning: c:/users/i3/documents/prolog/test.pl:3:
Warning: Singleton variables: [Z]
Warning: c:/users/i3/documents/prolog/test.pl:4:
Warning: Singleton variables: [Z]
Warning: c:/users/i3/documents/prolog/test.pl:5:
Warning: Singleton variables: [Z]
Warning: c:/users/i3/documents/prolog/test.pl:6:
Warning: Singleton variables: [Y]
Warning: c:/users/i3/documents/prolog/test.pl:7:
Warning: Singleton variables: [Y]
Warning: c:/users/i3/documents/prolog/test.pl:8:
Warning: Singleton variables: [X]
Warning: c:/users/i3/documents/prolog/test.pl:9:
Warning: Singleton variables: [X]
Warning: c:/users/i3/documents/prolog/test.pl:10:
Warning: Singleton variables: [Y]
Warning: c:/users/i3/documents/prolog/test.pl:11:
Warning: Singleton variables: [X]
true.
我不明白这个程序的错误在哪里。
学习 Prolog 的很大一部分是学习 递归地思考 。所以....
你应该首先解决最简单的问题:两个数中较大的一个是多少?这很简单,对吧?
max( X, X , X ) .
max( X, Y , X ) :- X > Y .
max( X, Y , Y ) :- X < Y .
现在我们可以做到这一点,扩展解决方案 space 以考虑 3 个值也很容易:只需确定第一个两个值的最大值,然后是那个最大值和第三个值:
max( X , Y , Z , R ) :- max(X,Y,T), max(T,Z,R).
进一步扩展解决方案以考虑任意数量的值也很容易:只需重复上述过程,直到您将列表筛选为单个值。
max( [Z] , Z ) . % the max of a 1-item list is that item.
max( [X,Y|Zs] , M ) :- % the max of a list of 2+ items can be found by...
max(X,Y,Z) , % - find the max of the first two items, and
max([Z|Zs],M) % - recursing down, replacing those two items with that max value
. % Easy!
[编辑注释]
确定一列数字最大值的基本算法是:
- 虽然列表的长度大于 1,
- 确定列表的前两个元素中较大的一个
- [递归地用两个值中的较大者替换列表的第一个两个元素
因此在递归的每次迭代中,源列表的长度减 1,列表的头部始终是当前 high-water 标记,即当前最大值。一旦列表的长度减为一,我们就解决了手头的问题。
可以将 max/3
和 max/2
合并为一个谓词:
max( [X] , X ) .
max( [X,Y|Zs] , R ) :- X =:= Y , max( [X|Zs] , R ) .
max( [X,Y|Zs] , R ) :- X > Y , max( [X|Zs] , R ) .
max( [X,Y|Zs] , R ) :- X < Y , max( [Y|Zs] , R ) .
但我认为找到 2 个值中的最大值是一个非常常见的特例,值得将其分解成自己的谓词:max(X,Y,Max)
.
也可以使用带有额外参数的辅助谓词,该参数显式携带额外状态,即当前高值,因此:
max( [X|Xs] , R ) :- max(Xs,X,R) .
max( [] , R , R ) .
max( [X|Xs] , Y , R ) :- X =:= Y , max(Xs,Y,R) .
max( [X|Xs] , Y , R ) :- X < Y , max(Xs,Y,R) .
max( [X|Xs] , Y , R ) :- X > Y , max(Xs,X,R) .
所以在上面,我们简单地弹出源列表的头部,并调用带有该值种子的累加器的助手。源列表用完后,累加器将包含所需的结果。
TIMTOWTDI[1] 正如他们所说。
[1] 方法不止一种
我从昨天开始学习序言,我被告知要找到三个数字之间的最大数字。我正在使用 SWI Prolog,这是我到目前为止编写的程序。
% If-Elif-Else statement
gte(X,Y,Z) :- X > Y,write('X is greater').
gte(X,Y,Z) :- X =:= Y,write('X and Y are same').
gte(X,Y,Z) :- X < Y < Z,write('Y is greater').
gte(X,Y,Z) :- X < Z,write('Z is greater').
gte(X,Y,Z) :- X > Z,write('X is greater').
gte(X,Y,Z) :- Y > Z,write('Y is greater').
gte(X,Y,Z) :- Y < Z,write('Z is greater').
gte(X,Y,Z) :- X=:=Z,write('X and Z are same').
gte(X,Y,Z) :- Y=:=Z,write('Y and Z are same').
输出应该是 ->
gte(12,24,36)
24 is greater.
True
而是给我看这个
Warning: c:/users/i3/documents/prolog/test.pl:3:
Warning: Singleton variables: [Z]
Warning: c:/users/i3/documents/prolog/test.pl:4:
Warning: Singleton variables: [Z]
Warning: c:/users/i3/documents/prolog/test.pl:5:
Warning: Singleton variables: [Z]
Warning: c:/users/i3/documents/prolog/test.pl:6:
Warning: Singleton variables: [Y]
Warning: c:/users/i3/documents/prolog/test.pl:7:
Warning: Singleton variables: [Y]
Warning: c:/users/i3/documents/prolog/test.pl:8:
Warning: Singleton variables: [X]
Warning: c:/users/i3/documents/prolog/test.pl:9:
Warning: Singleton variables: [X]
Warning: c:/users/i3/documents/prolog/test.pl:10:
Warning: Singleton variables: [Y]
Warning: c:/users/i3/documents/prolog/test.pl:11:
Warning: Singleton variables: [X]
true.
我不明白这个程序的错误在哪里。
学习 Prolog 的很大一部分是学习 递归地思考 。所以....
你应该首先解决最简单的问题:两个数中较大的一个是多少?这很简单,对吧?
max( X, X , X ) .
max( X, Y , X ) :- X > Y .
max( X, Y , Y ) :- X < Y .
现在我们可以做到这一点,扩展解决方案 space 以考虑 3 个值也很容易:只需确定第一个两个值的最大值,然后是那个最大值和第三个值:
max( X , Y , Z , R ) :- max(X,Y,T), max(T,Z,R).
进一步扩展解决方案以考虑任意数量的值也很容易:只需重复上述过程,直到您将列表筛选为单个值。
max( [Z] , Z ) . % the max of a 1-item list is that item.
max( [X,Y|Zs] , M ) :- % the max of a list of 2+ items can be found by...
max(X,Y,Z) , % - find the max of the first two items, and
max([Z|Zs],M) % - recursing down, replacing those two items with that max value
. % Easy!
[编辑注释] 确定一列数字最大值的基本算法是:
- 虽然列表的长度大于 1,
- 确定列表的前两个元素中较大的一个
- [递归地用两个值中的较大者替换列表的第一个两个元素
因此在递归的每次迭代中,源列表的长度减 1,列表的头部始终是当前 high-water 标记,即当前最大值。一旦列表的长度减为一,我们就解决了手头的问题。
可以将 max/3
和 max/2
合并为一个谓词:
max( [X] , X ) .
max( [X,Y|Zs] , R ) :- X =:= Y , max( [X|Zs] , R ) .
max( [X,Y|Zs] , R ) :- X > Y , max( [X|Zs] , R ) .
max( [X,Y|Zs] , R ) :- X < Y , max( [Y|Zs] , R ) .
但我认为找到 2 个值中的最大值是一个非常常见的特例,值得将其分解成自己的谓词:max(X,Y,Max)
.
也可以使用带有额外参数的辅助谓词,该参数显式携带额外状态,即当前高值,因此:
max( [X|Xs] , R ) :- max(Xs,X,R) .
max( [] , R , R ) .
max( [X|Xs] , Y , R ) :- X =:= Y , max(Xs,Y,R) .
max( [X|Xs] , Y , R ) :- X < Y , max(Xs,Y,R) .
max( [X|Xs] , Y , R ) :- X > Y , max(Xs,X,R) .
所以在上面,我们简单地弹出源列表的头部,并调用带有该值种子的累加器的助手。源列表用完后,累加器将包含所需的结果。
TIMTOWTDI[1] 正如他们所说。
[1] 方法不止一种