Format minimal path

212 Views Asked by At

So I've been working on something to help me understand Prolog better. I took the traditional water jug problem but added a bit of difficulty. Thus, my code is working pretty good. The only thing left to do would be to do some nice formatting for the output. Currently, it only shows the minimal path found with my code for the jug filling. (see example below)

So far, I thought a way I can do it, but I have no clue how to do it in Prolog.

The final list of my optimal path is formatted like this : [ [x(a,b),y(c,d),z(e,f)], [], [], ...]

I want to reach this format (see below for a more detailed output):

a -> b
c -> d
etc
  • First, I print the initial one that as liquid (in our case, 1. Otherwise, the first element on the list is the initial pattern). Then, I follow by taking the first sub-list, and comparing with the one before to see which of the jug did transfer to the other and print it. Then, continue until the list is empty.

Currently, it shows this:

?- problem.
[[jug(3,0),jug(5,0),jug(8,8)],[jug(3,0),jug(5,5),jug(8,3)],
 [jug(3,3),jug(5,2),jug(8,3)],[jug(3,0),jug(5,2),jug(8,6)],
 [jug(3,2),jug(5,0),jug(8,6)],[jug(3,2),jug(5,5),jug(8,1)],
 [jug(3,3),jug(5,4),jug(8,1)],[jug(3,0),jug(5,4),jug(8,4)]]
true .

Which is the right path for the current jugs configuration. (I'll add a way to do with n jugs later)

This is the way I would like it to show (in my code, you can see the index I want for each of them):

?- problem.
1 -> 2
2 -> 3
3 -> 1
2 -> 3
1 -> 2
2 -> 3
3 -> 1
true.

I'd love to get help with this one since everything I'm trying is a logical mess.

Thanks guys/girls <3

2

There are 2 best solutions below

2
On BEST ANSWER

Provided that you have an actual solution path (I believe your code will not yield correct results for some initial/end states), you can write the procedure as follows:

show([_]).
show([S1, S2|Tail]):-
  show1(S1, S2, 3, Gain, Loss),  # 3 here is the number of jugs
  write(Loss), write(' -> '), write(Gain),nl,
  show([S2|Tail]).

show1([], [], _, _, _).
show1([jug(Max1,Cur1)|S1], [jug(Max2,Cur2)|S2], Idx, Gain, Loss):-
  succ(NIdx, Idx),
  (Max1-Cur1=Max2-Cur2 -> true;
   (Cur2 > Cur1 -> Gain=Idx ;
    Loss=Idx
  )),
  show1(S1, S2, NIdx, Gain, Loss).

However, I'd advice you to improve the original code to compute these values when you build the solution path.

Sampe run:

show([[jug(3,0),jug(5,0),jug(8,8)],[jug(3,0),jug(5,5),jug(8,3)], 
     [jug(3,3),jug(5,2),jug(8,3)],[jug(3,0),jug(5,2),jug(8,6)], 
     [jug(3,2),jug(5,0),jug(8,6)],[jug(3,2),jug(5,5),jug(8,1)], 
     [jug(3,3),jug(5,4),jug(8,1)],[jug(3,0),jug(5,4),jug(8,4)]]).
1 -> 2
2 -> 3
3 -> 1
2 -> 3
1 -> 2
2 -> 3
3 -> 1
true.
0
On

see the pattern to inspect two adjacent elements

show(L) :-
    findall(T, (append(_,[A,B|_],L), transition(A,B,T)), Ts),
    maplist(writeln, Ts).

transition(
    [jug(3,A),jug(5,B),jug(8,C)],
    [jug(3,U),jug(5,V),jug(8,Z)],
    S->T
) :-
    P=[A^U,B^V,C^Z],
    nth0(L,P,X^M), X>M,
    nth0(R,P,Y^N), Y<N,
    S is 3-L, T is 3-R.