Change these benchmark programs from their original forms

Estimated hours taken: 0.5
Branches: main

tests/benchmarks/{primes,qsort,queens}.m:
	Change these benchmark programs from their original forms
	(which used the horrible variable names inherited from their Prolog
	ancestors and which were set up for our benchmarking exercise a decade
	a half ago to) to examples of good Mercury programming style.
This commit is contained in:
Zoltan Somogyi
2010-05-13 03:12:02 +00:00
parent 452dcd116c
commit 8aa8036bf5
3 changed files with 141 additions and 183 deletions

View File

@@ -2,102 +2,80 @@
:- interface.
:- import_module io, list.
:- import_module io.
:- pred main(io__state, io__state).
:- mode main(di, uo) is det.
:- pred main1(list(int)).
:- mode main1(out) is det.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int, prolog.
:- import_module int.
:- import_module list.
main --> main3(_).
main(!IO) :-
primes(limit, Out),
print_list(Out, !IO).
main1(Out) :-
data(Data),
primes(Data, Out).
:- func limit = int.
:- pred main3(list(int), io__state, io__state).
:- mode main3(out, di, uo) is det.
limit = 98.
main3(Out) -->
{ main1(Out) },
print_list(Out).
:- pred primes(int::in, list(int)::out) is det.
:- pred data(int).
:- mode data(out) is det.
primes(Limit, Primes) :-
integers(2, Limit, Integers),
sift(Integers, Primes).
data(98).
:- pred integers(int::in, int::in, list(int)::out) is det.
:- pred primes(int, list(int)).
:- mode primes(in, out) is det.
primes(Limit, Ps) :-
integers(2, Limit, Is),
sift(Is, Ps).
:- pred integers(int, int, list(int)).
:- mode integers(in, in, out) is det.
integers(Low, High, Result) :-
integers(Low, High, Result) :-
( Low =< High ->
M is Low + 1,
Result = [Low | Rest],
integers(M, High, Rest)
NextLow = Low + 1,
integers(NextLow, High, Rest),
Result = [Low | Rest]
;
Result = []
).
:- pred sift(list(int), list(int)).
:- mode sift(in, out) is det.
:- pred sift(list(int)::in, list(int)::out) is det.
sift([], []).
sift([I | Is], [I | Ps]) :-
remove(I, Is, New),
sift([Integer | Integers], [Integer | Ps]) :-
remove_multiples(Integer, Integers, New),
sift(New, Ps).
:- pred remove(int, list(int), list(int)).
:- mode remove(in, in, out) is det.
:- pred remove_multiples(int::in, list(int)::in, list(int)::out) is det.
remove(_P, [], []).
remove(P, [I | Is], Result) :-
M is I mod P,
( M = 0 ->
Result = Nis,
remove(P, Is, Nis)
remove_multiples(_Prime, [], []).
remove_multiples(Prime, [I | Is], Result) :-
( I mod Prime = 0 ->
remove_multiples(Prime, Is, TailResult),
Result = TailResult
;
Result = [I | Nis],
remove(P, Is, Nis)
remove_multiples(Prime, Is, TailResult),
Result = [I | TailResult]
).
:- pred print_list(list(int), io__state, io__state).
:- mode print_list(in, di, uo) is det.
:- pred print_list(list(int)::in, io::di, io::uo) is det.
print_list(Xs) -->
print_list(Xs, !IO) :-
(
{ Xs = [] }
->
io__write_string("[]\n")
Xs = [],
io.write_string("[]\n", !IO)
;
io__write_string("["),
print_list_2(Xs),
io__write_string("]\n")
Xs = [H | T],
io.write_string("[", !IO),
print_list_elements(H, T, !IO),
io.write_string("]\n", !IO)
).
:- pred print_list_2(list(int), io__state, io__state).
:- mode print_list_2(in, di, uo) is det.
:- pred print_list_elements(int::in, list(int)::in, io::di, io::uo) is det.
print_list_2([]) --> [].
print_list_2([X|Xs]) -->
io__write_int(X),
print_list_elements(X, Xs, !IO) :-
io.write_int(X, !IO),
(
{ Xs = [] }
->
[]
Xs = []
;
io__write_string(", "),
print_list_2(Xs)
Xs = [H | T],
io.write_string(", ", !IO),
print_list_elements(H, T, !IO)
).

View File

@@ -8,84 +8,68 @@
:- interface.
:- import_module io, list.
:- import_module io.
:- pred main(io__state, io__state).
:- mode main(di, uo) is det.
:- pred main1(list(int)).
:- mode main1(out) is det.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int.
:- import_module list.
main --> main3(_).
main1(Out) :-
main(!IO) :-
data(Data),
qsort(Data, Out, []).
qsort(Data, [], SortedData),
print_list(SortedData, !IO).
:- pred main3(list(int), io__state, io__state).
:- mode main3(out, di, uo) is det.
main3(Out) -->
{ main1(Out) },
print_list(Out).
:- pred data(list(int)).
:- mode data(out) is det.
:- pred data(list(int)::out) is det.
data([27,74,17,33,94,18,46,83,65,2,32,53,28,85,99,47,28,82,6,11,55,29,39,81,
90,37,10,0,66,51,7,21,85,27,31,63,75,4,95,99,11,28,61,74,18, 92,40,53,59,8]).
:- pred qsort(list(int), list(int), list(int)).
:- mode qsort(in, out, in) is det.
:- pred qsort(list(int)::in, list(int)::in, list(int)::out) is det.
qsort([X|L], R, R0) :-
partition(L, X, L1, L2),
qsort(L2, R1, R0),
qsort(L1, R, [X|R1]).
qsort([], R, R).
qsort([], !SortedRest).
qsort([H | T], !SortedRest) :-
partition(T, H, Los, His),
qsort(His, !SortedRest),
!:SortedRest = [H | !.SortedRest],
qsort(Los, !SortedRest).
:- pred partition(list(int), int, list(int), list(int)).
:- mode partition(in, in, out, out) is det.
partition([], _P, [], []).
partition([H|T], P, Lo, Hi) :-
( H =< P ->
partition(T, P, Lo1, Hi),
Lo = [H|Lo1]
partition([H | T], Pivot, Lo, Hi) :-
( H =< Pivot ->
partition(T, Pivot, LoTail, Hi),
Lo = [H | LoTail]
;
partition(T, P, Lo, Hi1),
Hi = [H|Hi1]
partition(T, Pivot, Lo, HiTail),
Hi = [H | HiTail]
).
:- pred print_list(list(int), io__state, io__state).
:- mode print_list(in, di, uo) is det.
:- pred print_list(list(int)::in, io::di, io::uo) is det.
print_list(Xs) -->
print_list(Xs, !IO) :-
(
{ Xs = [] }
->
io__write_string("[]\n")
Xs = [],
io.write_string("[]\n", !IO)
;
io__write_string("["),
print_list_2(Xs),
io__write_string("]\n")
Xs = [H | T],
io.write_string("[", !IO),
print_list_elements(H, T, !IO),
io.write_string("]\n", !IO)
).
:- pred print_list_2(list(int), io__state, io__state).
:- mode print_list_2(in, di, uo) is det.
:- pred print_list_elements(int::in, list(int)::in, io::di, io::uo) is det.
print_list_2([]) --> [].
print_list_2([X|Xs]) -->
io__write_int(X),
print_list_elements(X, Xs, !IO) :-
io.write_int(X, !IO),
(
{ Xs = [] }
->
[]
Xs = []
;
io__write_string(", "),
print_list_2(Xs)
Xs = [H | T],
io.write_string(", ", !IO),
print_list_elements(H, T, !IO)
).

View File

@@ -1,110 +1,106 @@
% 9-queens program
% This program solves the N-queens problem. Given an N-by-N chessboard,
% this problem asks us to find positions for N queens on the board such
% that they do not attack each other. This means that no two queens can be
%
% - in the same row
% - in the same column
% - on the same diagnonal.
%
% We print the result as a list of integers. Each integer corresponds to one
% of the board's N columns, and it gives the number of the row occupied by
% the queen in that column. (Given the constraints of the problem, every column
% must be occupied by exactly one queen.)
:- module queens.
:- interface.
:- import_module list, int, io.
:- import_module io.
:- pred main1(list(int)).
:- mode main1(out) is nondet.
:- pred main(io__state, io__state).
:- mode main(di, uo) is cc_multi.
:- pred main(io::di, io::uo) is cc_multi.
:- implementation.
:- import_module prolog.
:- import_module int.
:- import_module list.
main1(Out) :-
main(!IO) :-
data(Data),
queen(Data, Out).
main -->
( { data(Data), queen(Data, Out) } ->
print_list(Out)
( queen(Data, Out) ->
print_list(Out, !IO)
;
io__write_string("No solution\n")
io.write_string("No solution\n", !IO)
).
:- pred data(list(int)).
:- mode data(out) is det.
% With this data, this program solves the 8-queens problem. To solve the
% N-queens problem for some other N, make this predicate return the first
% N integers.
:- pred data(list(int)::out) is det.
data([1,2,3,4,5,6,7,8]).
:- pred queen(list(int), list(int)).
:- mode queen(in, out) is nondet.
:- pred queen(list(int)::in, list(int)::out) is nondet.
queen(Data, Out) :-
qperm(Data, Out),
safe(Out).
queen(Data, Perm) :-
qperm(Data, Perm),
safe(Perm).
:- pred qperm(list(int), list(int)).
:- mode qperm(in, out) is nondet.
:- pred qperm(list(int)::in, list(int)::out) is nondet.
qperm([], []).
qperm([X|Y], K) :-
qdelete(U, [X|Y], Z),
K = [U|V],
qperm(Z, V).
qperm([H | T], Perm) :-
qdelete([H | T], Element, Rest),
qperm(Rest, RestPerm),
Perm = [Element | RestPerm].
:- pred qdelete(int, list(int), list(int)).
:- mode qdelete(out, in, out) is nondet.
:- pred qdelete(list(int)::in, int::out, list(int)::out) is nondet.
qdelete(A, [A|L], L).
qdelete(X, [A|Z], [A|R]) :-
qdelete(X, Z, R).
qdelete([H | T], H, T).
qdelete([H | T], E, [H | NT]) :-
qdelete(T, E, NT).
:- pred safe(list(int)).
:- mode safe(in) is semidet.
:- pred safe(list(int)::in) is semidet.
safe([]).
safe([N|L]) :-
nodiag(N, 1, L),
safe(L).
safe([H | T]) :-
nodiag(H, 1, T),
safe(T).
:- pred nodiag(int, int, list(int)).
:- mode nodiag(in, in, in) is semidet.
:- pred nodiag(int::in, int::in, list(int)::in) is semidet.
nodiag(_, _, []).
nodiag(B, D, [N|L]) :-
NmB is N - B,
BmN is B - N,
( D = NmB ->
nodiag(TestRow, !.Diff, [Row | Rows]) :-
( !.Diff = Row - TestRow ->
fail
; D = BmN ->
; !.Diff = TestRow - Row ->
fail
;
true
),
D1 is D + 1,
nodiag(B, D1, L).
!:Diff = !.Diff + 1,
nodiag(TestRow, !.Diff, Rows).
:- pred print_list(list(int), io__state, io__state).
:- mode print_list(in, di, uo) is det.
:- pred print_list(list(int)::in, io::di, io::uo) is det.
print_list(Xs) -->
print_list(Xs, !IO) :-
(
{ Xs = [] }
->
io__write_string("[]\n")
Xs = [],
io.write_string("[]\n", !IO)
;
io__write_string("["),
print_list_2(Xs),
io__write_string("]\n")
Xs = [H | T],
io.write_string("[", !IO),
print_list_elements(H, T, !IO),
io.write_string("]\n", !IO)
).
:- pred print_list_2(list(int), io__state, io__state).
:- mode print_list_2(in, di, uo) is det.
:- pred print_list_elements(int::in, list(int)::in, io::di, io::uo) is det.
print_list_2([]) --> [].
print_list_2([X|Xs]) -->
io__write_int(X),
print_list_elements(X, Xs, !IO) :-
io.write_int(X, !IO),
(
{ Xs = [] }
->
[]
Xs = []
;
io__write_string(", "),
print_list_2(Xs)
Xs = [H | T],
io.write_string(", ", !IO),
print_list_elements(H, T, !IO)
).