序言组合功能

时间:2018-09-21 22:53:40

标签: function prolog combinations factorial

在prolog中编写组合函数很麻烦,它遵循以下数学方程式: b! /((b-c)!* c!)。我是prolog的新手,不确定它到底有什么问题。我收到的错误是:错误:is / 2:算术:'fact1 / 2'不是函数

下面是我的代码:

    %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.

谢谢您的帮助。

2 个答案:

答案 0 :(得分:1)

没关系。我找到了解决方案。但是,为了他人的利益,我在此处发布了解决方案。显然,这些函数没有返回值,而是通过将它们生成的值放在给定变量中来返回。

    %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.

答案 1 :(得分:1)

基于这个问题,我认为您对谓词是一个误解。谓词只能导致truefalse(当然,可能会出错,或者,如果您也将它们视为“可能的结果”,则它们可能会永远循环)。谓词可以通过统一尚未固定的变量来响应值。通常在Prolog中,使谓词尽可能通用,以便可以将谓词称为 multidirectional

您称谓为:

FB is fact1(BB,R1),

但是fact1不是一个函数(在is/2谓词中,函子是已知的函子)。

谓词可以计算事物并通过 unification 传递结果,例如:

?- fac1(5, X).
X = 120 .

因此,我们将第一个参数固定为fac1/2的{​​{1}}谓词进行调用,然后Prolog会将5统一为X

我们可以将谓词重写为:

120

我们还可以使main :- current_prolog_flag(argv,[BB_S,CC_S]), atom_number(BB_S,BB), atom_number(CC_S,CC), fact1(BB, FB), ABS is abs(BB - CC), fact1(ABS, FA), fact1(CC, FC), Res is FB / (FA * FC), write(Res).更具声明性:现在,只有在第一个参数固定的情况下(或者第二个参数为fac1的情况下,它才有效。此外,由于它未使用尾部调用优化(TCO),因此效率较低。我们可以使用1库来改进谓词,并将其实现为:

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(A,B,P):-     fac(A,FA),     fac(B,FB),     P是FB / FA。

,但效率更高,因为它是 O(a + b),我们可以将其简化为 O(b-a),方法如下:

prodrange

或更声明性的:

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