0
votes

Say I have two lists [A, B, C] and [D, E, F] on my hand now. The values in list1 and list2 are in the same range, but I don't exactly know how they match with each other.

There is one possibility that A = D = 1, B = E = 2, C = F = 3.

Based on the condition above, how can I print the result in the following format???

(ONE, A, D)

(TWO, B, E)

(THREE, C, F)

The original problem is, you have to figure out the value of each variable in list1 and list2 under the given constraints. The constraints are as following:

A < B, B < C, D < E, E < F, 
the range of [A, B, C] is from 1 to 3, 
the range of [D, E, F] is from 1 to 3, 
[A, B, C] are all different numbers, 
[D, E, F] are all different numbers.

So far I write something like:

calculate([A, B, C, D, E, F]) :-
    between(1, 3, A),
    between(1, 3, B),
    between(1, 3, C),
    between(1, 3, D),
    between(1, 3, E),
    between(1, 3, F),
    A < B, B < C, D < E, E < F.

After I consult this code file and call calculate([A, B, C, D, E, F]), I get the final result A = D = 1, B = E = 2, C = F = 3, but how can I print in an elegant format???

3
This is not clear. Names starting with upper case are normally variables in Prolog. Do you want to print the variable names or the values? Are the values in each list unique? Generally, you want to first collect the matching values, and then print (two loops). - Tomas By
This isn't clear at all. What are the inputs? At least show the query you want to make in Prolog and some attempts you've made to solve it. Some specific examples would help clarify as well. - lurker
@lurker Please check my new edit. - Acepcs
@TomasBy Please check my new edit. - Acepcs
@TomasBy But I want to output the result based on the calculation, I can't fix my code to be write('A = '), write(A) - Acepcs

3 Answers

1
votes

Here is one way to do it.

printnicely([A,B,C],[D,E,F]) :-
  count(A,'A',mapping([],[],[]),M0), count(B,'B',M0,M1), count(C,'C',M1,M2),
  count(D,'D',M2,M3), count(E,'E',M3,M4), count(F,'F',M4,M),
  printmapping(M).

count(1,Name,mapping(Ones,Twos,Threes),mapping([Name|Ones],Twos,Threes)).
count(2,Name,mapping(Ones,Twos,Threes),mapping(Ones,[Name|Twos],Threes)).
count(3,Name,mapping(Ones,Twos,Threes),mapping(Ones,Twos,[Name|Threes])).

printmapping(mapping(Ones,Twos,Threes)) :-
  reverse(Ones,RevOnes), reverse(Twos,RevTwos), reverse(Threes,RevThrees),
  write('ONE '),write(RevOnes),nl,
  write('TWO '),write(RevTwos),nl,
  write('THREE '),write(RevThrees),nl.

Produces:

| ?- calculate([A,B,C],[D,E,F]), printnicely([A,B,C],[D,E,F]).
ONE [A,D]
TWO [B,E]
THREE [C,F]
yes
0
votes

This code can solve your problem.

number(1,'ONE').
number(2,'TWO').
number(3,'THREE').

position(1,'L1','A').
position(2,'L1','B').
position(3,'L1','C').

position(1,'L2','D').
position(2,'L2','E').
position(3,'L2','F').

find(Curr,Max):-
    Curr > Max.

find(Curr,Max):-
    Curr =< Max,
    number(Curr,V),
    position(Curr,'L1',A),
    position(Curr,'L2',B),
    write('('),
    write((V,A,B)),
    write(')'), 
    nl,
    C is Curr+1,
    find(C,Max).

?- find(1,3).
(ONE,A,D)
(TWO,B,E)
(THREE,C,F)

First you have to define some predicates (in this case number/2) to match the number with its word. Then you have to define a predicate (position/2) to link the position of the element with the associated letter. Then you can traverse all the list with find/2. BTW this solution is not modular at all...

-1
votes

This is the best!



    ?- writeln('(ONE,A,D)'),writeln('(TWO,B,E)'),writeln('(THREE,C,F)').
    (ONE,A,D)
    (TWO,B,E)
    (THREE,C,F)
    true.