What's an elegant way to unify X,Y with (1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1) , (-2,1), (-2,-1)?
-
20-09-2019 - |
Question
What's an elegant way to unify X,Y with (1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1) , (-2,1), (-2,-1)?
Doing it this way seems error prone and tedious:
foo(1,2).
foo(1,-2).
foo(-1,-2).
...
...
...
And this way seems too expensive:
foo(X,Y) :-
L = [1,-1,2,-2],
member(X,L),
member(Y,L),
abs(X,X1), abs(Y,Y1),
X1 =\= Y1.
Solution
A further development on what was commented:
generate_pairs_foo(X,Y) :-
L = [1,-1,2,-2],
member(X,L),
member(Y,L),
abs(X,X1), abs(Y,Y1),
X1 =\= Y1.
assert_all_foo([]).
assert_all_foo([(X,Y)|T]) :-
assert(foo(X,Y)), assert_all_foo(T).
find_all((X,Y),generate_pairs_foo(X,Y),L), assert_all_foo(L).
Hmmmmmm... look, it's easier and shorter to just write all the cases xD
OTHER TIPS
foo0(X,Y):-
member(X,[1,-1]),
member(Y,[2,-2]).
foo(X,Y):-
foo0(X,Y);
foo0(Y,X).
Using member/2 this way is kind of a Prolog anti pattern. Although member/2 is short, usually member/2 cannot do clause indexing.
You can try your self and compare these two solutions:
Foo Member:
foo_member0(X,Y):-
member(X,[1,-1]),
member(Y,[2,-2]).
foo_member(X,Y):-
foo_member0(X,Y);
foo_member0(Y,X).
Foo Clause:
foo_clause0(1).
foo_clause0(-1).
foo_clause1(2).
foo_clause1(-2).
foo_clause2(X,Y) :- foo_clause0(X), foo_clause1(Y).
foo_clause(X,Y) :- foo_clause2(X,Y).
foo_clause(X,Y) :- foo_clause2(Y,X).
Now run it in GNU Prolog:
| ?- between(1,1000000,_), foo_member(-2,-1), fail; true.
(516 ms) yes
| ?- between(1,1000000,_), foo_clause(-2,-1), fail; true.
(375 ms) yes
Well, the situation might change if some Prolog starts automatically compiling member/1 into clauses, when the second argument is ground.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow