Another approach is to memoize solutions.
:- dynamic seen/1.
% Call this always before calling deadly_wrapper/1
clear_seen :-
retractall(seen(_)).
% This wrapper calls deadly/1 but remembers
% the solution using assert/1, and fails
% if the solution has been "seen" before.
deadly_wrapper(X) :-
deadly(X),
(
seen(X)
->
fail
;
assert(seen(X))
).
% This is for testing.
deadly(1).
deadly(1).
deadly(1).
deadly(5).
deadly(1).
deadly(1).
In case your Prolog supports tabling, then it gets even simpler.
Example file:
:- table deadly/1.
deadly(1).
deadly(1).
deadly(5).
deadly(1).
deadly(5).
Example execution with XSB:
$ xsb
[xsb_configuration loaded]
[sysinitrc loaded]
XSB Version 3.2 (Kopi Lewak) of March 15, 2009
[x86_64-unknown-linux-gnu; mode: optimal; engine: slg-wam;
scheduling: local; word size: 64]
| ?- [deadly_tab].
[Compiling ./deadly_tab]
[deadly_tab compiled, cpu time used: 0.0100 seconds]
[deadly_tab loaded]
yes
| ?- deadly(X).
X = 5;
X = 1;
no
| ?-