Files
mercury/tests/benchmarks/crypt.m
Zoltan Somogyi 9cacd33f47 Remove "is" as a synonym for "=", step 1.
This first step deals with the consequences of such removal.
The removal itself will happen in stage 2. That step will
add "is" to the prolog module in the library.

compiler/add_pred.m:
    Prepare for "is" being in the prolog module.

compiler/options.m:
    Add a way to test whether the change to add_pred.m is in the
    installed compiler.

tests/accumulator/base.m:
tests/accumulator/call_in_base.m:
tests/accumulator/chain.m:
tests/accumulator/commutative.m:
tests/accumulator/construct_test.m:
tests/accumulator/dcg.m:
tests/accumulator/deconstruct_test.m:
tests/accumulator/disj.m:
tests/accumulator/func.m:
tests/accumulator/heuristic.m:
tests/accumulator/highorder.m:
tests/accumulator/identity.m:
tests/accumulator/inter.m:
tests/accumulator/nonrec.m:
tests/accumulator/out_to_in.m:
tests/accumulator/qsort.m:
tests/accumulator/simple.m:
tests/accumulator/split.m:
tests/accumulator/swap.m:
tests/benchmarks/cqueens.m:
tests/benchmarks/crypt.m:
tests/benchmarks/deriv.m:
tests/benchmarks/deriv2.m:
tests/benchmarks/nrev.m:
tests/benchmarks/poly.m:
tests/benchmarks/primes.m:
tests/benchmarks/qsort.m:
tests/benchmarks/query.m:
tests/benchmarks/tak.m:
tests/debugger/interactive.m:
tests/declarative_debugger/Mercury.options:
tests/declarative_debugger/io_read_bug.m:
tests/declarative_debugger/queens.exp:
tests/declarative_debugger/queens.m:
tests/dppd/imperative_solve_impl.m:
tests/dppd/map_impl.m:
tests/dppd/max_length_impl.m:
tests/dppd/sum.m:
tests/dppd/upto_sum_impl.m:
tests/par_conj/dep_par_21.m:
tests/tabling/seq.m:
tests/term/dds3_14.m:
tests/term/mmatrix.m:
tests/term/money.m:
tests/term/occur.m:
tests/term/pl4_5_2.m:
tests/term/queens.m:
tests/typeclasses/inference_test.m:
tests/typeclasses/inference_test_2.m:
tests/valid/lazy_list.m:
tests/warnings/duplicate_const.m:
    Replace calls to "is" with unifications. In many places,
    bring programming style up to date.
2020-08-21 10:42:37 +10:00

196 lines
4.0 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
%
% crypt
%
% Cryptomultiplication:
% Find the unique answer to:
% OEE
% EE
% ---
% EOEE
% EOE
% ----
% OOEE
%
% where E=even, O=odd.
% This program generalizes easily
% to any such problem.
% Originally written by Peter Van Roy
:- module crypt.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is cc_multi.
:- implementation.
:- import_module int.
:- import_module list.
:- import_module prolog.
:- import_module require.
main(!IO) :-
( if crypt(Out) then
print_list(Out, !IO)
else
io.write_string("No solution\n", !IO)
).
:- pred crypt(list(int)::out) is nondet.
crypt([A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P]) :-
crypt.odd(A),
crypt.even(B),
crypt.even(C),
crypt.even(E),
mult([C, B, A], E, [I, H, G, F | X]),
lefteven(F),
crypt.odd(G),
crypt.even(H),
crypt.even(I),
zero(X),
lefteven(D),
mult([C, B, A], D, [L, K, J | Y]),
lefteven(J),
crypt.odd(K),
crypt.even(L),
zero(Y),
sum2([I, H, G, F], [0, L, K, J], [P, O, N, M | Z]),
crypt.odd(M),
crypt.odd(N),
crypt.even(O),
crypt.even(P),
zero(Z).
% write(' '), write(A), write(B), write(C), nl,
% write(' '), write(D), write(E), nl,
% write(F), write(G), write(H), write(I), nl,
% write(J), write(K), write(L), nl,
% write(M), write(N), write(O), write(P), nl.
% In the usual source this predicate is named sum. However, sum is a
% language construct in NU-Prolog, and cannot be defined as a predicate.
% If you try, nc comes up with an obscure error message.
:- pred sum2(list(int)::in, list(int)::in, list(int)::out) is det.
sum2(AL, BL, CL) :-
sum2(AL, BL, 0, CL).
:- pred sum2(list(int)::in, list(int)::in, int::in, list(int)::out) is det.
sum2([], [], Carry, Cs) :-
( if Carry = 0 then
Cs = []
else
Cs = [Carry]
).
sum2([], [B | BL], Carry, Cs) :-
( if Carry = 0 then
Cs = [B | BL]
else
X = B + Carry,
NewCarry = X // 10,
C = X mod 10,
sum2([], BL, NewCarry, CL),
Cs = [C | CL]
).
sum2([A | AL], [], Carry, Cs) :-
( if Carry = 0 then
Cs = [A | AL]
else
X = A + Carry,
NewCarry = X // 10,
C = X mod 10,
sum2([], AL, NewCarry, CL),
Cs = [C | CL]
).
sum2([A | AL], [B | BL], Carry, Cs) :-
X1 = A + B,
X = X1 + Carry,
C = X mod 10,
NewCarry = X // 10,
sum2(AL, BL, NewCarry, CL),
Cs = [C | CL].
:- pred mult(list(int)::in, int::in, list(int)::out) is det.
mult(AL, D, BL) :-
mult(AL, D, 0, BL).
:- pred mult(list(int)::in, int::in, int::in, list(int)::out) is det.
mult([A | AL], D, Carry, [B | BL] ) :-
X1 = A * D,
X = X1 + Carry,
B = X mod 10,
NewCarry = X // 10,
mult(AL, D, NewCarry, BL).
mult([], _, Carry, [C, Cend]) :-
C = Carry mod 10,
Cend = Carry // 10.
:- pred zero(list(int)::in) is semidet.
zero([]).
zero([0 | L]) :-
zero(L).
:- pred odd(int).
:- mode odd(in) is semidet.
:- mode odd(out) is multi.
odd(1).
odd(3).
odd(5).
odd(7).
odd(9).
:- pred even(int).
:- mode even(in) is semidet.
:- mode even(out) is multi.
even(0).
even(2).
even(4).
even(6).
even(8).
:- pred lefteven(int).
:- mode lefteven(in) is semidet.
:- mode lefteven(out) is multi.
lefteven(2).
lefteven(4).
lefteven(6).
lefteven(8).
:- pred print_list(list(int)::in, io::di, io::uo) is det.
print_list(Xs, !IO) :-
(
Xs = [],
io.write_string("[]\n", !IO)
;
Xs = [H | T],
io.write_string("[", !IO),
print_list_elements(H, T, !IO),
io.write_string("]\n", !IO)
).
:- pred print_list_elements(int::in, list(int)::in, io::di, io::uo) is det.
print_list_elements(X, Xs, !IO) :-
io.write_int(X, !IO),
(
Xs = []
;
Xs = [H | T],
io.write_string(", ", !IO),
print_list_elements(H, T, !IO)
).