Prolog,给定 N 并找到所有不能被 3 和 5 整除的数字,并且这些数字必须小于 N
Prolog, given N and find all numbers not divisible by 3 and 5 and these numbers must be smaller than N
我无法找到问题的解决方案。
Divisible/2 谓词检查数字 N 是否可以被列表中的数字之一整除
divisible([H|_],N) :- N mod H =:= 0.
divisible([H|T],N) :- N mod H =\= 0, divisible(T,N).
我需要构建一个谓词 find 来查找不能被数字列表整除的 Number < N
示例 input/output:
?- find(5, [3,5],Num).
output is :
Num = 4; Num = 2; Num = 1. False
Here N is 5 and list of number is [3,5]
当前代码:
findNum(1, LN, Num) :- \+ divisible(LN,1),
Num is 1.
findNum(Rank, LN, Num) :- Rank > 1,
Num1 is Rank - 1,
( \+ divisible(LN,Num1) -> Num is Num1;
findNum(Num1,LN, Num) ).
只打印Num = 4;由于某些原因,它从不打印 2 和 1
而且我不确定哪里出了问题..
感谢任何帮助...
用三种不同的方式完成
- 使用递归
find_rec(0,_,[]) :- !.
find_rec(N0,Possible_divisors,[N0|Successful_divisors]) :-
divisible(Possible_divisors,N0),
N is N0 - 1,
find_rec(N,Possible_divisors,Successful_divisors).
find_rec(N0,Possible_divisors,Successful_divisors) :-
\+ divisible(Possible_divisors,N0),
N is N0 - 1,
find_rec(N,Possible_divisors,Successful_divisors).
示例运行
?- find_rec(5,[3,5],Num).
Num = [5, 3] ;
false.
- 使用分区
find_par(N,Possible_divisors,Successful_divisors) :-
findall(Ns,between(1,N,Ns),List),
partition(partition_predicate(Possible_divisors),List,Successful_divisors,_).
partition_predicate(L,N) :-
divisible(L,N).
示例运行
?- find_par(5,[3,5],Num).
Num = [3, 5].
- 使用条件 ( -> ; )
find_con(0,_,[]) :- !.
find_con(N0,Possible_divisors,Result) :-
(
divisible(Possible_divisors,N0)
->
Result = [N0|Successful_divisors]
;
Result = Successful_divisors
),
N is N0 - 1,
find_con(N,Possible_divisors,Successful_divisors).
示例运行
?- find_con(5,[3,5],Num).
Num = [5, 3].
很高兴看到 divisible/2 的一些测试用例以快速了解其工作原理。
:- begin_tests(divisible).
divisible_test_case_generator([13,1],13).
divisible_test_case_generator([20,10,5,4,2,1],20).
divisible_test_case_generator([72,36,24,18,12,9,8,6,4,3,2,1],72).
divisible_test_case_generator([97,1],97).
divisible_test_case_generator([99,33,11,9,3,1],99).
test(1,[nondet,forall(divisible_test_case_generator(List,N))]) :-
divisible(List,N).
:- end_tests(divisible).
运行 次测试
?- make.
% c:/users/groot/documents/projects/prolog/so_question_177 compiled 0.00 sec, 0 clauses
% PL-Unit: divisible ..... done
% All 5 tests passed
true.
关于您的代码的一些反馈。
- 通常,谓词的格式在
:-
之后开始一个新行
- 当使用
;
运算符时,最好将它单独放在一行上,这样非常明显,许多程序员花了几个小时寻找错误,因为看到了 ;
作为 ,
并且理解不正确。
findNum(1, LN, Num) :-
\+ divisible(LN,1),
Num is 1.
findNum(Rank, LN, Num) :-
Rank > 1,
Num1 is Rank - 1,
(
\+ divisible(LN,Num1)
->
Num is Num1
;
findNum(Num1,LN, Num)
).
<true case>
您的代码中的错误在此处
->
Num is Num1
您没有像 <false case>
那样递归下一个值
;
findNum(Num1,LN, Num)
尝试将 findNum 谓词修改为:
findNum(Rank, LN, Num) :- Rank > 1,
Num1 is Rank - 1,
\+ divisible(LN,Num1) -> Num is Num1.
findNum(Rank, LN, Num) :- Rank > 1,
Num1 is Rank - 1,
findNum(Num1,LN, Num).
对我来说,它给出了要求的答案。
我无法找到问题的解决方案。
Divisible/2 谓词检查数字 N 是否可以被列表中的数字之一整除
divisible([H|_],N) :- N mod H =:= 0.
divisible([H|T],N) :- N mod H =\= 0, divisible(T,N).
我需要构建一个谓词 find 来查找不能被数字列表整除的 Number < N
示例 input/output:
?- find(5, [3,5],Num).
output is :
Num = 4; Num = 2; Num = 1. False
Here N is 5 and list of number is [3,5]
当前代码:
findNum(1, LN, Num) :- \+ divisible(LN,1),
Num is 1.
findNum(Rank, LN, Num) :- Rank > 1,
Num1 is Rank - 1,
( \+ divisible(LN,Num1) -> Num is Num1;
findNum(Num1,LN, Num) ).
只打印Num = 4;由于某些原因,它从不打印 2 和 1
而且我不确定哪里出了问题..
感谢任何帮助...
用三种不同的方式完成
- 使用递归
find_rec(0,_,[]) :- !.
find_rec(N0,Possible_divisors,[N0|Successful_divisors]) :-
divisible(Possible_divisors,N0),
N is N0 - 1,
find_rec(N,Possible_divisors,Successful_divisors).
find_rec(N0,Possible_divisors,Successful_divisors) :-
\+ divisible(Possible_divisors,N0),
N is N0 - 1,
find_rec(N,Possible_divisors,Successful_divisors).
示例运行
?- find_rec(5,[3,5],Num).
Num = [5, 3] ;
false.
- 使用分区
find_par(N,Possible_divisors,Successful_divisors) :-
findall(Ns,between(1,N,Ns),List),
partition(partition_predicate(Possible_divisors),List,Successful_divisors,_).
partition_predicate(L,N) :-
divisible(L,N).
示例运行
?- find_par(5,[3,5],Num).
Num = [3, 5].
- 使用条件 ( -> ; )
find_con(0,_,[]) :- !.
find_con(N0,Possible_divisors,Result) :-
(
divisible(Possible_divisors,N0)
->
Result = [N0|Successful_divisors]
;
Result = Successful_divisors
),
N is N0 - 1,
find_con(N,Possible_divisors,Successful_divisors).
示例运行
?- find_con(5,[3,5],Num).
Num = [5, 3].
很高兴看到 divisible/2 的一些测试用例以快速了解其工作原理。
:- begin_tests(divisible).
divisible_test_case_generator([13,1],13).
divisible_test_case_generator([20,10,5,4,2,1],20).
divisible_test_case_generator([72,36,24,18,12,9,8,6,4,3,2,1],72).
divisible_test_case_generator([97,1],97).
divisible_test_case_generator([99,33,11,9,3,1],99).
test(1,[nondet,forall(divisible_test_case_generator(List,N))]) :-
divisible(List,N).
:- end_tests(divisible).
运行 次测试
?- make.
% c:/users/groot/documents/projects/prolog/so_question_177 compiled 0.00 sec, 0 clauses
% PL-Unit: divisible ..... done
% All 5 tests passed
true.
关于您的代码的一些反馈。
- 通常,谓词的格式在
:-
之后开始一个新行
- 当使用
;
运算符时,最好将它单独放在一行上,这样非常明显,许多程序员花了几个小时寻找错误,因为看到了;
作为,
并且理解不正确。
findNum(1, LN, Num) :-
\+ divisible(LN,1),
Num is 1.
findNum(Rank, LN, Num) :-
Rank > 1,
Num1 is Rank - 1,
(
\+ divisible(LN,Num1)
->
Num is Num1
;
findNum(Num1,LN, Num)
).
<true case>
->
Num is Num1
您没有像 <false case>
;
findNum(Num1,LN, Num)
尝试将 findNum 谓词修改为:
findNum(Rank, LN, Num) :- Rank > 1,
Num1 is Rank - 1,
\+ divisible(LN,Num1) -> Num is Num1.
findNum(Rank, LN, Num) :- Rank > 1,
Num1 is Rank - 1,
findNum(Num1,LN, Num).
对我来说,它给出了要求的答案。