Prolog 使用clpfd生成闰年序列
下面的代码检查给定年份是否为闰年。该算法是使用库中的声明性整数算法制定的,以便查询可以“反向”运行以生成闰年序列。代码有两种变体,改变了对一年是否为一个世纪的测试,但每种变体的行为都不同,它们都不能正常工作 我想生成从1990年到2005年的闰年序列。为此,我要输入查询Prolog 使用clpfd生成闰年序列,prolog,clpfd,Prolog,Clpfd,下面的代码检查给定年份是否为闰年。该算法是使用库中的声明性整数算法制定的,以便查询可以“反向”运行以生成闰年序列。代码有两种变体,改变了对一年是否为一个世纪的测试,但每种变体的行为都不同,它们都不能正常工作 我想生成从1990年到2005年的闰年序列。为此,我要输入查询yearin1990..2005,leap_year1(Year),indomain(Year)。(或者leap_year2来测试第二个变量) 我编写的代码是(使用SWI Prolog 8.0.2): 查询结果如下(SWI Pro
yearin1990..2005,leap_year1(Year),indomain(Year)。
(或者leap_year2
来测试第二个变量)
我编写的代码是(使用SWI Prolog 8.0.2):
查询结果如下(SWI Prolog 8.0.2):
如您所见,两个查询都不能正确生成闰年的完整序列(1992、1996、2000、2004)
此外,以下1900年前后的查询也会产生异常结果(添加注释):
这种行为有什么解释吗?我应该如何修改leap\u year()
,以便生成完整的序列
更新:(更多?)完成,但不理解原因(!)
将支票拆分几个世纪可以提高查询的完整性:
leap_year_century_fix(Year) :-
Year mod 100 #\= 0.
leap_year_century_fix(Year) :-
Year mod 100 #= 0,
Year mod 400 #= 0. % 2000 is a leap year, 1900 is not
leap_year3(Year) :-
Year #> 0,
Year mod 4 #= 0,
leap_year_century_fix(Year).
现在:
简单地用和和或表达,并对或使用物化:
leap(Y) :-
Y #> 0,
Y mod 4 #= 0,
(Y mod 100 #\= 0) #\/ (Y mod 400 #= 0).
不要混合使用
->
和约束。相反,对于这两种情况,直接使用析取和“卫士”。更好,用户
% Verify that 1900 is not a leap year
?- not(leap_year1(1900)), not(leap_year2(1900)).
true.
% Verify that 1892, 1896, 1904 are leap years
?- leap_year1(1892), leap_year1(1896), leap_year1(1904).
true.
?- leap_year2(1892), leap_year2(1896), leap_year2(1904).
true.
% No solutions found (!)
?- Year in 1890..1905,leap_year1(Year),indomain(Year).
false.
% Solutions found as expected (complete result)
?- Year in 1890..1905,leap_year2(Year),indomain(Year).
Year = 1892 ;
Year = 1896 ;
Year = 1904.
leap_year_century_fix(Year) :-
Year mod 100 #\= 0.
leap_year_century_fix(Year) :-
Year mod 100 #= 0,
Year mod 400 #= 0. % 2000 is a leap year, 1900 is not
leap_year3(Year) :-
Year #> 0,
Year mod 4 #= 0,
leap_year_century_fix(Year).
?- Year in 1890..1905,leap_year3(Year),indomain(Year).
Year = 1892 ;
Year = 1896 ;
Year = 1904 ;
false.
?- Year in 1990..2015,leap_year3(Year),indomain(Year).
Year = 1992 ;
Year = 1996 ;
Year = 2004 ;
Year = 2008 ;
Year = 2012 ;
Year = 2000.
leap(Y) :-
Y #> 0,
Y mod 4 #= 0,
(Y mod 100 #\= 0) #\/ (Y mod 400 #= 0).