Prolog 中的阶乘列表
List of factorials in Prolog
我在解决以下练习时遇到问题...
阶乘在 Prolog 中可以描述为:
factorial(0, 1).
factorial(N, F) :-
N1 is N - 1,
factorial(N1, F1),
F is N * F1.
我需要扩展此代码,以便 return 列出 N
之前的所有阶乘。但它 return 只是第一个阶乘 (1),然后是错误:ERROR: Out of local stack
。这是我的代码:
insertList(H, L, [H|L]) :-
!.
factorial(0, 1, [1]).
factorial(N, F, L) :-
N1 is N - 1,
factorial(N1, F1, L),
F is N * F1,
insertList(F, L, [F|L]).
list_factorial(X, L) :-
factorial(X, F, L).
我做错了什么?
你让我安装 SWI-prolog 哈哈。
list_fact(N,M,A):- A is N * M.
list_fact(N,M,A):- N1 is N + 1, M1 is N * M, list_fact(N1,M1,A).
调用为
list_fact(1,1,A).
很简单。第一条规则将下一个阶乘计算为 N * M。
第二条规则进行递归调用,其中 N = N + 1 且 M = 在规则 1 中计算的前一个阶乘。
最小修正,说明主要问题
insertList(H, L, [H|L]):- !.
factorial(0, 1, [1]).
factorial(N, F, Fs):- N1 is N-1, factorial(N1, F1, L), F is N * F1, insertList(F, L, Fs).
list_factorial(X, L):- factorial(X, F, L).
但返回第一个解后请求回溯会循环。您可以添加 @false 建议的测试...否则,另一个定义可能是
factorials(N, L) :-
N > 0 -> L = [F,G|Fs], M is N-1, factorials(M, [G|Fs]), F is G*N ; L = [1].
:- use_module(library(clpfd)).
list_factorial([1], 0).
list_factorial(Zs0, N) :-
length(Zs0, N),
N #> 0,
list_n_fac(Zs0, 1, 1).
list_n_fac([], _, _).
list_n_fac([Z1|Zs], N0, Z0) :-
Z1 #= Z0 * N0,
N1 #= N0 + 1,
list_n_fac(Zs, N1, Z1).
示例查询:
?- list_factorial(Zs, 8).
Zs = [1,2,6,24,120,720,5040,40320].
这是最一般的查询:
?- list_factorial(Zs, N).
( N = 0, Zs = [1]
; N = 1, Zs = [1]
; N = 2, Zs = [1,2]
; N = 3, Zs = [1,2,6]
; N = 4, Zs = [1,2,6,24]
; N = 5, Zs = [1,2,6,24,120]
...
另一个解决方案是:
factorial(0,1) :- !.
factorial(N,F) :-
N>0, N1 is N - 1, factorial(N1,F1), F is N * F1.
list_factorial(N,L) :-
N>1, !, N2 is N-1, list_factorial(N2,L2), factorial(N,F), append(L2,[F],L).
list_factorial(N,[F]) :- factorial(N,F).
我用 N 是否大于 0 的测试更改了你的 factorial
,因为你不能计算负数的阶乘,并且只能得到一个解。
我在解决以下练习时遇到问题...
阶乘在 Prolog 中可以描述为:
factorial(0, 1).
factorial(N, F) :-
N1 is N - 1,
factorial(N1, F1),
F is N * F1.
我需要扩展此代码,以便 return 列出 N
之前的所有阶乘。但它 return 只是第一个阶乘 (1),然后是错误:ERROR: Out of local stack
。这是我的代码:
insertList(H, L, [H|L]) :-
!.
factorial(0, 1, [1]).
factorial(N, F, L) :-
N1 is N - 1,
factorial(N1, F1, L),
F is N * F1,
insertList(F, L, [F|L]).
list_factorial(X, L) :-
factorial(X, F, L).
我做错了什么?
你让我安装 SWI-prolog 哈哈。
list_fact(N,M,A):- A is N * M.
list_fact(N,M,A):- N1 is N + 1, M1 is N * M, list_fact(N1,M1,A).
调用为
list_fact(1,1,A).
很简单。第一条规则将下一个阶乘计算为 N * M。 第二条规则进行递归调用,其中 N = N + 1 且 M = 在规则 1 中计算的前一个阶乘。
最小修正,说明主要问题
insertList(H, L, [H|L]):- !.
factorial(0, 1, [1]).
factorial(N, F, Fs):- N1 is N-1, factorial(N1, F1, L), F is N * F1, insertList(F, L, Fs).
list_factorial(X, L):- factorial(X, F, L).
但返回第一个解后请求回溯会循环。您可以添加 @false 建议的测试...否则,另一个定义可能是
factorials(N, L) :-
N > 0 -> L = [F,G|Fs], M is N-1, factorials(M, [G|Fs]), F is G*N ; L = [1].
:- use_module(library(clpfd)). list_factorial([1], 0). list_factorial(Zs0, N) :- length(Zs0, N), N #> 0, list_n_fac(Zs0, 1, 1). list_n_fac([], _, _). list_n_fac([Z1|Zs], N0, Z0) :- Z1 #= Z0 * N0, N1 #= N0 + 1, list_n_fac(Zs, N1, Z1).
示例查询:
?- list_factorial(Zs, 8). Zs = [1,2,6,24,120,720,5040,40320].
这是最一般的查询:
?- list_factorial(Zs, N). ( N = 0, Zs = [1] ; N = 1, Zs = [1] ; N = 2, Zs = [1,2] ; N = 3, Zs = [1,2,6] ; N = 4, Zs = [1,2,6,24] ; N = 5, Zs = [1,2,6,24,120] ...
另一个解决方案是:
factorial(0,1) :- !.
factorial(N,F) :-
N>0, N1 is N - 1, factorial(N1,F1), F is N * F1.
list_factorial(N,L) :-
N>1, !, N2 is N-1, list_factorial(N2,L2), factorial(N,F), append(L2,[F],L).
list_factorial(N,[F]) :- factorial(N,F).
我用 N 是否大于 0 的测试更改了你的 factorial
,因为你不能计算负数的阶乘,并且只能得到一个解。