Prolog 组合函数
Prolog Combination Function
我在 prolog 中编写组合函数时遇到了麻烦,它遵循以下数学方程式:b! / ((b-c)! * c!) 我是 prolog 的新手,不确定它到底有什么问题。我收到的错误是:ERROR: is/2: Arithmetic: `fact1/2' is not a function
下面是我的代码:
%fac(0,1).
%fac(N,X) :- N > 0, M is N - 1, fac(M,Y), X is Y * N.
fact1(0,Result) :- Result is 1.
fact1(N,Result) :- N > 0, N1 is N-1,
fact1(N1,Result1), Result is Result1*N.
main :- current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
%read_input,
R1 is 1,
R2 is 1,
R3 is 1,
FB is fact1(BB,R1),
ABS is abs(BB - CC),
FE is fact1(ABS,R2),
FC is fact1(CC,R3),
TI is FE * FC,
BF is FB / TI,
%BF is fac(BB) / (fac(abs(BB-CC)) * fac(CC))),
write($BF),
halt.
感谢您的帮助。
没关系。我找到了解决办法。但是,为了其他人的利益,我已经在此处发布了解决方案。显然,这些函数没有 return 和 return,而是将它们生成的值放在给定变量中。
%fac(0,1).
%fac(N,X) :- N > 0, M is N - 1, fac(M,Y), X is Y * N.
fact1(0,Result) :- Result is 1.
fact1(N,Result) :- N > 0, N1 is N-1, fact1(N1,Result1), Result is Result1*N.
main :- current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
%read_input,
fact1(BB,FB), %notice change
ABS is abs(BB - CC),
fact1(ABS,FE), %notice change
fact1(CC,FC), %notice change
TI is FE * FC,
BF is FB / TI,
%BF is fac(BB) / (fac(abs(BB-CC)) * fac(CC))),
print('Number of bracelets: '),
write(BF),
halt.
根据问题,我认为您对什么是谓词有误解。谓词只能导致 true
或 false
(当然可能会出现错误,或者如果您也将它们视为 "possible outcomes",它们可能会永远循环)。谓词可以通过 统一 尚未固定的变量来响应值。通常在 Prolog 中,使谓词尽可能通用,这样就可以调用谓词 multidirectional.
你这样调用谓词:
FB is fact1(BB,R1),
但是 fact1
不是函数(在 is/2
谓词中语义已知的函子)。
谓词可以计算事物,通过统一传递结果,例如:
?- fac1(5, X).
X = 120 .
我们因此调用fac1/2
谓词,第一个参数固定为5
,Prolog会将X
统一为120
。
我们可以将谓词重写为:
main :- current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
fact1(BB, <b>FB</b>),
ABS is abs(BB - CC),
fact1(ABS, <b>FA</b>),
fact1(CC, <b>FC</b>),
Res is <b>FB</b> / (<b>FA</b> * <b>FC</b>),
write(Res).
我们还可以使 fac1
更具声明性:现在它仅在第一个参数固定的情况下有效(或者在第二个参数为 1
的情况下)。此外,它的效率有点低,因为它没有使用 尾调用优化 (TCO)。我们可以使用 clpfd
库来改进谓词,并像这样实现它:
:- use_module(library(clpfd)).
fac(0, 1).
fac(I, F) :-
I #> 0,
F #= I*F1,
I1 #= I-1,
fac(I1, F1).
现在我们可以查询几个方向的阶乘关系:
?- fac(I, 120).
I = 5 ;
false.
?- fac(I, 130).
false.
?- fac(5, 120).
true ;
false.
?- fac(7, 120).
false.
?- fac(7, Y).
Y = 5040 ;
false.
因此我们可以查询 i
、i!
等于 120
等
我们还可以通过针对特定范围实施产品来提高性能,因此:
b
------
| |
| | i
i=a+1
所以 prodrange
基本上是:
prodrange(A, B, P) :-
fac(A, FA),
fac(B, FB),
P 是 FB / FA.
但效率更高,因为这是 O(a + b),我们可以将其减少到 O(b - a),其中:
prodrange(A, A, 1).
prodrange(A, B, P) :-
B > A,
B1 is B-1,
prodrange(A, B1, P1),
P is P1 * B1.
或更多声明:
prodrange(A, A, 1).
prodrange(A, B, P) :-
B #> A,
P #= B*P1,
B1 #= B-1,
prodrange(A, B1, P1).
那么我们可以实现一个comb/3
谓词来计算组合的数量:
comb(BB, CC, Res) :-
MX is max(BB, CC),
MN is min(BB, CC),
prodrange(MN, MX, Num),
Abs is MX-MN,
fac(Abs, Den),
Res is Num / Den.
那么 main
看起来像:
main :-
current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
comb(BB, CC, BF),
print('Number of bracelets: '),
write(BF),
halt.
我在 prolog 中编写组合函数时遇到了麻烦,它遵循以下数学方程式:b! / ((b-c)! * c!) 我是 prolog 的新手,不确定它到底有什么问题。我收到的错误是:ERROR: is/2: Arithmetic: `fact1/2' is not a function
下面是我的代码:
%fac(0,1).
%fac(N,X) :- N > 0, M is N - 1, fac(M,Y), X is Y * N.
fact1(0,Result) :- Result is 1.
fact1(N,Result) :- N > 0, N1 is N-1,
fact1(N1,Result1), Result is Result1*N.
main :- current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
%read_input,
R1 is 1,
R2 is 1,
R3 is 1,
FB is fact1(BB,R1),
ABS is abs(BB - CC),
FE is fact1(ABS,R2),
FC is fact1(CC,R3),
TI is FE * FC,
BF is FB / TI,
%BF is fac(BB) / (fac(abs(BB-CC)) * fac(CC))),
write($BF),
halt.
感谢您的帮助。
没关系。我找到了解决办法。但是,为了其他人的利益,我已经在此处发布了解决方案。显然,这些函数没有 return 和 return,而是将它们生成的值放在给定变量中。
%fac(0,1).
%fac(N,X) :- N > 0, M is N - 1, fac(M,Y), X is Y * N.
fact1(0,Result) :- Result is 1.
fact1(N,Result) :- N > 0, N1 is N-1, fact1(N1,Result1), Result is Result1*N.
main :- current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
%read_input,
fact1(BB,FB), %notice change
ABS is abs(BB - CC),
fact1(ABS,FE), %notice change
fact1(CC,FC), %notice change
TI is FE * FC,
BF is FB / TI,
%BF is fac(BB) / (fac(abs(BB-CC)) * fac(CC))),
print('Number of bracelets: '),
write(BF),
halt.
根据问题,我认为您对什么是谓词有误解。谓词只能导致 true
或 false
(当然可能会出现错误,或者如果您也将它们视为 "possible outcomes",它们可能会永远循环)。谓词可以通过 统一 尚未固定的变量来响应值。通常在 Prolog 中,使谓词尽可能通用,这样就可以调用谓词 multidirectional.
你这样调用谓词:
FB is fact1(BB,R1),
但是 fact1
不是函数(在 is/2
谓词中语义已知的函子)。
谓词可以计算事物,通过统一传递结果,例如:
?- fac1(5, X).
X = 120 .
我们因此调用fac1/2
谓词,第一个参数固定为5
,Prolog会将X
统一为120
。
我们可以将谓词重写为:
main :- current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
fact1(BB, <b>FB</b>),
ABS is abs(BB - CC),
fact1(ABS, <b>FA</b>),
fact1(CC, <b>FC</b>),
Res is <b>FB</b> / (<b>FA</b> * <b>FC</b>),
write(Res).
我们还可以使 fac1
更具声明性:现在它仅在第一个参数固定的情况下有效(或者在第二个参数为 1
的情况下)。此外,它的效率有点低,因为它没有使用 尾调用优化 (TCO)。我们可以使用 clpfd
库来改进谓词,并像这样实现它:
:- use_module(library(clpfd)).
fac(0, 1).
fac(I, F) :-
I #> 0,
F #= I*F1,
I1 #= I-1,
fac(I1, F1).
现在我们可以查询几个方向的阶乘关系:
?- fac(I, 120).
I = 5 ;
false.
?- fac(I, 130).
false.
?- fac(5, 120).
true ;
false.
?- fac(7, 120).
false.
?- fac(7, Y).
Y = 5040 ;
false.
因此我们可以查询 i
、i!
等于 120
等
我们还可以通过针对特定范围实施产品来提高性能,因此:
b
------
| |
| | i
i=a+1
所以 prodrange
基本上是:
prodrange(A, B, P) :- fac(A, FA), fac(B, FB), P 是 FB / FA.
但效率更高,因为这是 O(a + b),我们可以将其减少到 O(b - a),其中:
prodrange(A, A, 1).
prodrange(A, B, P) :-
B > A,
B1 is B-1,
prodrange(A, B1, P1),
P is P1 * B1.
或更多声明:
prodrange(A, A, 1).
prodrange(A, B, P) :-
B #> A,
P #= B*P1,
B1 #= B-1,
prodrange(A, B1, P1).
那么我们可以实现一个comb/3
谓词来计算组合的数量:
comb(BB, CC, Res) :-
MX is max(BB, CC),
MN is min(BB, CC),
prodrange(MN, MX, Num),
Abs is MX-MN,
fac(Abs, Den),
Res is Num / Den.
那么 main
看起来像:
main :-
current_prolog_flag(argv,[BB_S,CC_S]),
atom_number(BB_S,BB),
atom_number(CC_S,CC),
comb(BB, CC, BF),
print('Number of bracelets: '),
write(BF),
halt.