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)?

StackOverflow https://stackoverflow.com/questions/1525622

  •  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.
Was it helpful?

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
scroll top