@j4n_bur53. The two Euler problems mentioned above (#14 and #18) are ported to B-Prolog with the same result (and almost as fast) as the Picat versions.
http://hakank.org/bprolog/euler14.pl
http://hakank.org/bprolog/euler18.pl
I’m not sure that I understand all your questions, but I’ll give it a try. Sorry for the long post (and I hope that it’s not off-topic for the forum).
Let’s start with euler14.pl (http://hakank.org/bprolog/euler14.pl )
%%
%% From
%% http://hakank.org/picat/euler14.pi
%% which is slightly adjusted from
%% http://picat-lang.org/euler/p14.pi
%%
%% All numbers 2..999999: 1.4s
%% Odd numbers: 3..2..999999: 1.3s
%% (My Picat version using odd numbers takes ~ 1.2s)
%%
euler14 :-
max_chain(N,_Chain,Len),
writeln([n=N,len=Len]).
:- table max_chain(-,-,max).
max_chain(N,Chain,Len) :-
between(2,999999,N), % checking all numbers
% between(3,2,999999,N), % just checking the odd numbers
gen(N,Chain,Len).
:- table gen(+,-,-).
gen(1,Chain,Len) :-
Chain=[1],
Len is 1.
gen(N,Chain,Len) :-
N > 1,
N mod 2 =:= 0,
T is N div 2,
gen(T,Chain1,Len1),
Chain=[N|Chain1],
Len is Len1+1.
gen(N,Chain,Len) :-
N > 1,
N mod 2 =:= 1,
T is 3*N+1,
gen(T,Chain1,Len1),
Chain=[N|Chain1],
Len is Len1+1.
between(From,Step,To,N) :-
To2 is To div Step,
between(From,To2,Tmp),
N is (Tmp-From)*Step+From.
If the first table is commented out, i.e.
:- table max_chain(-,-,max).
then there’s no generation at all of the numbers: it just handle N=2 (the first number) and then stops. I.e. it acts as a kind of generator. I’m not sure how to consider this case.
The second tabling:
:- table gen(+,-,-).
is just for caching the previous results. Commenting it out give the correct answer but takes a very long time (116s vs 1.5s).
Here’s the second example, euler18.pl (http://hakank.org/bprolog/euler18.pl )
euler18 :-
p18(Tri),
pp(1,1,Tri,Sum),
writeln(max_val=Sum).
p18(Triangle) :-
Triangle = [[75],
[95,64],
[17,47,82],
[18,35,87,10],
[20, 4,82,47,65],
[19, 1,23,75, 3,34],
[88, 2,77,73, 7,63,67],
[99,65, 4,28, 6,16,70,92],
[41,41,26,56,83,40,80,70,33],
[41,48,72,33,47,32,37,16,94,29],
[53,71,44,65,25,43,91,52,97,51,14],
[70,11,33,28,77,73,17,78,39,68,17,57],
[91,71,52,38,17,14,91,43,58,50,27,29,48],
[63,66, 4,68,89,53,67,30,73,16,69,87,40,31],
[ 4,62,98,27,23, 9,70,98,73,93,38,53,60, 4,23]].
%%
%% From Neng-Fa Zhou.
%%
:- table pp(+,+,+,max).
pp(Row,_Column,Tri,Sum) :-
length(Tri,Len),
Row > Len,
Sum is 0.
pp(Row,Column,Tri,Sum) :-
length(Tri,Len),
Row =< Len,
Row1 is Row+1,
pp(Row1,Column,Tri,Sum1),
matrix_element(Tri,Row,Column,TriRC),
Sum is Sum1 + TriRC.
pp(Row,Column,Tri,Sum) :-
length(Tri,Len),
Row =< Len,
Row1 is Row + 1,
Column1 is Column + 1,
pp(Row1,Column1,Tri,Sum1),
matrix_element(Tri,Row,Column,TriRC),
Sum is Sum1 + TriRC.
matrix_element(X, I, J, Val) :-
nth1(I, X, Row),
nth1(J, Row, Val).
If the table statement
:- table pp(+,+,+,max).
is commented out, the program don’t loop through the complete matrix, just a single pass of each line and then stops with an incorrect answer (the last). So it acts as a generator as well.
Does this answer any of your questions?
After your comments, I realize that these two examples might not work in SWI-Prolog even after Jan W have fixed the found tabling bug. They might just work in B-Prolog/Picat land.
(Neng-Fa has written some other B-Prolog programs with tabling using min/max: http://www.picat-lang.org/bprolog/examples/#TAB , but I have not analyzed them. )