0

The problem is

Brown, Clark, Jones and Smith are four substantial citizens who serve the community as architect, banker, doctor and lawyer, though not necessarily respectively. Brown who is more conservative than Jones but more liberal than Smith, is a better golfer than the men who are older than he is and has a larger income than the men who are younger than Clark

The banker who earns more than the architect, is neither the youngest or the oldest.

The doctor, who is a poorer golfer than the lawyer, is less conservative than the architect

As might be expected, the oldest man is the most conservative and has the largest income, and the youngest man is the best golfer

what is each man's profession?

I've written

jobs(L) :- L = [[brown,_,_,_,_,_],
           [clark,_,_,_,_,_],
           [jones,_,_,_,_,_],
           [smith,_,_,_,_,_]],
        % [name,job,conservative,golf,income,age]
        % conserative: 1 = least conservative, 4 = most conservative
        % golf: 1 = worst golfer, 4 = best golfer
        % income: 1 = least income, 4 = highest income
        % age: 1 = youngest, 4 = oldest

        % Brown is more conservative than Jones. Brown is less conservative than Smith.
        member([brown,_,C1,_,_,_],L),
        member([jones,_,C2,_,_,_],L),
        C1 > C2,
        member([smith,_,C3,_,_,_],L),
        C1 < C3,

        % Brown is a better golfer than those older than him.
        member([brown,_,_,G1,_,A1],L),
        member([_,_,_,G2,_,A2],L),
        G1 > G2, 
        A2 > A1,

        % Brown has a higher income than those younger than Clark.
        member([brown,_,_,_,I1,_],L),
        member([clark,_,_,_,_,A3],L),
        member([_,_,_,_,I2,A4],L),
        I1 > I2,
        A3 > A4,

        % Banker has a higher income than architect. Banker is neither youngest nor oldest.
        member([_,banker_,_,I3,A5],L),
        member([_,architect,_,_,I4,_],L),
        I3 > I4,
        (A5 = 2;A5 = 3),

        % Doctor is a worse golfer than lawyer. Doctor is less conservative than architect.
        member([_,doctor,C4,G3,_,_],L),
        member([_,lawyer,_,G4,_,_],L),
        member([_,architect,C5,_,_,_],L),
        G3 < G4,
        C4 < C5,

        % Oldest is most conservative and has highest income.
        member([_,_,4,_,4,4],L),

        % Youngest is the best golfer.
        member([_,_,_,4,_,1],L).

When I ask it

?- jobs(L).

I get

ERROR: >/2: Arguments are not sufficiently instantiated

I'm not sure what the error means, I believe I've translated all the clues.

4
  • I don't know about your code, but your puzzle has a contradiction: Brown is a better golfer than the men younger than he is, but the best golfer is the youngest man. Good luck!
    – user1864610
    Commented Nov 14, 2013 at 2:10
  • You're right. I can't believe I never noticed that, although I still get the same error after fixing it. Commented Nov 14, 2013 at 2:27
  • 2
    You're trying to do a numeric comparison on variables that haven't been instantiated yet. Commented Nov 14, 2013 at 3:33
  • 1
    can we assume that they all have different ages, incomes, golf playing skills and conservatism levels?
    – Will Ness
    Commented Nov 14, 2013 at 19:03

5 Answers 5

2

You code works exactly as expected if you just use finite domain constraints instead of lower-level arithmetic. For example, use (#>)/2 instead of (>)/2.

After you get it to run beyond this instantiation error by using constraints, you will then notice that among other things, your code has a typo: banker_. Also, you are not formulating the implication correctly, and your predicate will therefore yield false.

Here is a slightly modified version of your code, changed to use finite domain constraints and correcting the two mentioned mistakes:

:- use_module(library(clpfd)).

older_worse_golfer([], _, _).
older_worse_golfer([[_,_,_,G,_,A]|Rest], G0, A0) :-
        A #> A0 #==> G #< G0,
        older_worse_golfer(Rest, G0, A0).

younger_higher_income([], _, _).
younger_higher_income([[_,_,_,_,I,A]|Rest], I0, A0) :-
        A #< A0 #==> I0 #> I,
        younger_higher_income(Rest, I0, A0).

man_profession_rest([M,P|Rest], M-P, Rest).

jobs(Ls, Vs) :-
        Ls = [[brown,_,_,_,_,_],
              [clark,_,_,_,_,_],
              [jones,_,_,_,_,_],
              [smith,_,_,_,_,_]],
        maplist(man_profession_rest, Ls, _, Rests),
        append(Rests, Vs),
        Vs ins 1..4,

        % [name,job,conservative,golf,income,age]
        % conserative: 1 = least conservative, 4 = most conservative
        % golf: 1 = worst golfer, 4 = best golfer
        % income: 1 = least income, 4 = highest income
        % age: 1 = youngest, 4 = oldest

        % Oldest is most conservative and has highest income.
        member([_,_,4,_,4,4], Ls),

        % Brown is more conservative than Jones. Brown is less
        % conservative than Smith.
        memberchk([brown,_,C1,_,_,_], Ls),
        memberchk([jones,_,C2,_,_,_], Ls),
        memberchk([smith,_,C3,_,_,_], Ls),
        C1 #> C2,
        C1 #< C3,

        % Brown is a better golfer than those older than him.
        memberchk([brown,_,_,G1,_,A1], Ls),
        older_worse_golfer(Ls, G1, A1),

        % IMPLIED: Brown is not the oldest
        A1 #< 4,

        % Brown has a higher income than those younger than Clark.
        memberchk([brown,_,_,_,I1,_], Ls),
        memberchk([clark,_,_,_,_,A3], Ls),
        younger_higher_income(Ls, I1, A3),

        % IMPLIED: Clark is not the youngest
        A3 #> 1,

        % Banker has a higher income than architect. Banker is neither
        % youngest nor oldest.
        I3 #> I4,
        A5 in 2..3,
        member([_,banker,_,_,I3,A5], Ls),
        member([_,architect,_,_,I4,_], Ls),

        % Doctor is a worse golfer than lawyer. Doctor is less
        % conservative than architect.
        member([_,doctor,C4,G3,_,_], Ls),
        member([_,lawyer,_,G4,_,_], Ls),
        member([_,architect,C5,_,_,_], Ls),
        G3 #< G4,
        C4 #< C5,

        % Youngest is the best golfer.
        member([_,_,_,4,_,1], Ls).

You can use label/1 to search for concrete solutions. As you can see with the following query, there is a unique solution with respect to professions:

?- time(setof(MP, Ls^Vs^Rs^(jobs(Ls, Vs),
                            label(Vs),
                            maplist(man_profession_rest, Ls, MP, Rs)), MP)).

which yields:

% 124,485 inferences, 0.041 CPU in 0.042 seconds (97% CPU, 3043643 Lips)
MP = [[brown-banker, clark-doctor, jones-architect, smith-lawyer]].

And that's without even requiring that all income levels etc. be different. If you want, you can express this constraint easily by adding:

        transpose(Rests, RestsT), maplist(all_different, RestsT)

to this formulation.

2

(continuing the trail blazed by CapelliC...) Selecting from domains and (better yet, while) applying the rules is usually the way to go in such puzzles. Carefully testing as soon as possible, to eliminate wrong choices as soon as possible -- but not sooner.

We can't arithmetically compare unknown values, this is what the error means: > compares two known arithmetical values to which its arguments are instantiated. But if a Prolog logical variable is not yet instantiated it means that its value is still unknown.

In constraint logical programming (CLP) we can register such constraints upfront, -- but not in vanilla Prolog. Though many a modern Prolog has CLP packages or predicates available in them. SWI Prolog has it too. But in vanilla Prolog code, we must be careful.

mselect([A|As],S,Z):- select(A,S,S1), mselect(As,S1,Z).
mselect([],Z,Z).         % (* instantiate a domain by selecting from it *)

puzzle(L):- % (* [_,_,Conserv,Golf,Income,Age] *)
  L =      [ [brown,_,C1,G1,I1,A1],
             [clark,_,C2,_ ,I2,A2],
             [jones,_,C3,_ ,I3,A3],
             [smith,_,C4,_ ,I4,A4] ],

  L1 = [[_,_,4,_,4,4], [_,_,_,4,_,1]],           % (* 6,7 - oldest, youngest *)
  mselect( L1, L, L2),                           % (* L2: neither youngest nor oldest *)
  mselect( [A3,A4], [1,2,3,4], [A2,A1]), A2 > 1, % (* 3b. 1 < A2 < A1  *)
  select( C2, [1,2,3,4], [C3,C1,C4]),            % (* 1.  C3 < C1 < C4 *)

  select(    [_, banker, _ ,GB,IB,_ ], L2, [P3] ),
  mselect( [ [_, archct, CA,GA,IA,_ ],           % (* second view into the same matrix *)
             [_, doctor, CD,GD,ID,_ ] ], [P3|L1], 
           [ [_, lawyer, _ ,GL,IL,_ ] ]         ),
  CD < CA,                                       % (* 5b.          *)
  mselect( [ID,IL], [1,2,3,4], [IA,IB]),         % (* 4a.  IA < IB *)
  mselect( [GA,GB], [1,2,3,4], [GD,GL]),         % (* 5a.  GD < GL *)

  % (* 2. ( X in L : A1 < AX ) => G1 > GX  *)
  % (* 3. ( Y in L : AY < A2 ) => I1 > IY ... so, not(A1<A2)! i.e. % 3b. 1 < A2 < A1 *)
  forall( (member(X,L), last(X,AX), AX>A1), (nth1(4,X,GX), G1>GX) ),
  forall( (member(Y,L), last(Y,AY), A2>AY), (nth1(5,Y,IY), I1>IY) ).

Testing: ([_,_,Conserv,Golf,Income,Age])

7 ?- time(( puzzle(_X), maplist(writeln,_X),nl, false; true )).
[brown,banker,3,3,3,3]
[clark,doctor,1,1,1,2]
[jones,archct,2,4,2,1]
[smith,lawyer,4,2,4,4]

[brown,banker,3,3,3,3]
[clark,doctor,1,1,2,2]
[jones,archct,2,4,1,1]
[smith,lawyer,4,2,4,4]

[brown,banker,3,3,2,3]
[clark,doctor,1,1,3,2]
[jones,archct,2,4,1,1]
[smith,lawyer,4,2,4,4]

% (* 2,299 inferences, 0.000 CPU in 0.120 seconds (0% CPU, Infinite Lips) *)
true.

This is actually one solution, according to the way the puzzle question is asked.

8
  • @CapelliC this puzzle is extremely clever and subtle. :) My three solutions are actually one, according to the way it is asked. :) Some implications of # 3 are also quite subtle (i.e. non-emptiness of premise, like "those who are younger than the best golfer are made of green cheese" (not that it proves it; it's just consistent, adds no knowledge i.e. makes no elimination of possibilities...)). Plus, I had to assume that they all are of different ages, incomes etc., for simplicity. Maybe the answer is still the same without that assumption, but it's very hard to formulate it, then.
    – Will Ness
    Commented Nov 15, 2013 at 9:15
  • @CapelliC btw, how much inferences are those 540 solutions? :)
    – Will Ness
    Commented Nov 15, 2013 at 9:16
  • 2,702,933 inferences, 15 distinct solutions... Maybe I have some bug around.
    – CapelliC
    Commented Nov 15, 2013 at 9:23
  • Enigmativity has 15 solutions too... Do you allow for Clark to be the youngest? I don't - "Brown has a larger income than the men who are younger than Clark" seems to imply the existence of men younger than Clark (not in mathematical implication kind of way, but in everyday's).
    – Will Ness
    Commented Nov 15, 2013 at 9:45
  • yes, the implementation is quite similar to that for Brown is a better golfer than those older than him that I posted. Of course, I could make it less verbose, but wanted to keep things simple for the OP. Your code is quite compact, but maybe switching to CLP(FD) could make more sense once understood the basics...
    – CapelliC
    Commented Nov 15, 2013 at 9:56
1

Here's my answer to the problem:

puzzle(Puzzle) :-
    Names = [brown,clark,jones,smith],

    permute(Names,Conservatives),

% Brown is more conservative than Jones.
    ismore(brown,jones,Conservatives),

% Brown is less conservative than Smith.
    isless(brown,smith,Conservatives),

    permute(Names,Golfs),
    permute(Names,Ages),

% Brown is a better golfer than those older than him.
    worsethans(brown,Golfs,WorseAtGolfThanBrown),
    betterthans(brown,Ages,OlderThanBrown),
    members(OlderThanBrown,WorseAtGolfThanBrown),

    permute(Names,Incomes),

% Brown has a higher income than those younger than Clark.
    worsethans(brown,Incomes,WorseIncomeThanBrown),
    worsethans(clark,Ages,YoungerThanClark),
    members(YoungerThanClark,WorseIncomeThanBrown),

    permute([banker,architect,lawyer,doctor],Jobs),

% Banker has a higher income than architect.
    lookup(banker,Jobs,Names,Banker),
    lookup(architect,Jobs,Names,Architect),
    ismore(Banker,Architect,Incomes),

% Banker is neither youngest nor oldest.
    ([_,Banker,_,_]=Ages;[_,_,Banker,_]=Ages),

% Doctor is a worse golfer than lawyer.
    lookup(doctor,Jobs,Names,Doctor),
    lookup(lawyer,Jobs,Names,Lawyer),
    ismore(Lawyer,Doctor,Golfs),

% Doctor is less conservative than architect.
    ismore(Architect,Doctor,Conservatives),

% Oldest is most conservative and has highest income.
    [Oldest,_,_,_]=Ages,
    [Oldest,_,_,_]=Conservatives,
    [Oldest,_,_,_]=Incomes,

% Youngest is the best golfer.
    [_,_,_,Youngest]=Ages,
    [Youngest,_,_,_]=Golfs,

    Puzzle = [Names,Jobs,c(Conservatives),g(Golfs),i(Incomes),a(Ages)].

It needs these supporting predicates:

ismore(X,Y,Zs) :-
    append(Xs,[Y|_],Zs),
    member(X,Xs).

isless(X,Y,Zs) :-
    append(_,[Y|Xs],Zs),
    member(X,Xs).

betterthans(X,Ys,Zs) :-
    append(Zs,[X|_],Ys).

worsethans(X,Ys,Zs) :-
    append(_,[X|Zs],Ys).

%lookup(X,Xs,Ys,Y)
lookup(X,[X|_],[Y|_],Y).
lookup(X,[_|Xs],[_|Ys],Y) :-
    lookup(X,Xs,Ys,Y).

members([], _).
members([X|Xs], Ys) :-
    member(X, Ys),
    members(Xs, Ys).

select([X|Xs], X, Xs).
select([X|Xs], Y, [X|Ys]) :- select(Xs, Y, Ys).

permute([], []).
permute(Xs, [X|Zs]) :-
    select(Xs, X, Ys),
    permute(Ys, Zs).

Now, the only issue I had is that this gives me more than one answer. Unless I've got the logic wrong this is what I got:

[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,brown,clark,jones]),g([clark,brown,smith,jones]),i([smith,brown,clark,jones]),a([smith,brown,jones,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,brown,clark,jones]),g([clark,brown,smith,jones]),i([smith,brown,jones,clark]),a([smith,brown,jones,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,brown,clark,jones]),g([clark,brown,smith,jones]),i([smith,jones,brown,clark]),a([smith,brown,jones,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,brown,clark,jones]),g([clark,brown,smith,jones]),i([smith,brown,clark,jones]),a([smith,jones,brown,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,brown,clark,jones]),g([clark,brown,smith,jones]),i([smith,brown,jones,clark]),a([smith,jones,brown,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,brown,clark,jones]),g([clark,brown,smith,jones]),i([smith,jones,brown,clark]),a([smith,jones,brown,clark])]
[[brown,clark,jones,smith],[banker,doctor,architect,lawyer],c([smith,brown,jones,clark]),g([jones,brown,smith,clark]),i([smith,brown,clark,jones]),a([smith,brown,clark,jones])]
[[brown,clark,jones,smith],[banker,doctor,architect,lawyer],c([smith,brown,jones,clark]),g([jones,brown,smith,clark]),i([smith,brown,jones,clark]),a([smith,brown,clark,jones])]
[[brown,clark,jones,smith],[banker,doctor,architect,lawyer],c([smith,brown,jones,clark]),g([jones,brown,smith,clark]),i([smith,clark,brown,jones]),a([smith,brown,clark,jones])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,clark,brown,jones]),g([clark,brown,smith,jones]),i([smith,brown,clark,jones]),a([smith,brown,jones,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,clark,brown,jones]),g([clark,brown,smith,jones]),i([smith,brown,jones,clark]),a([smith,brown,jones,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,clark,brown,jones]),g([clark,brown,smith,jones]),i([smith,jones,brown,clark]),a([smith,brown,jones,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,clark,brown,jones]),g([clark,brown,smith,jones]),i([smith,brown,clark,jones]),a([smith,jones,brown,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,clark,brown,jones]),g([clark,brown,smith,jones]),i([smith,brown,jones,clark]),a([smith,jones,brown,clark])]
[[brown,clark,jones,smith],[banker,architect,doctor,lawyer],c([smith,clark,brown,jones]),g([clark,brown,smith,jones]),i([smith,jones,brown,clark]),a([smith,jones,brown,clark])]

I can constrain it to a single solution if I also say that Clark's income is greater than Brown's.

Can anyone confirm if my answer is correct or not and if there should be more constraints?

1
  • "Brown has a larger income than the men who are younger than Clark" seems to imply the existence of men younger than Clark. other than that, your 1st solution seems consistent with the rules. -- my three solutions are actually one, according to how the puzzle is asked. Your 15 are two. :) And if we eliminate solutions where Clark is the youngest, you are left with my solution(s).
    – Will Ness
    Commented Nov 15, 2013 at 9:53
1

you need to bind your variables to a domain before to use them, the easiest way is permutation/2:

    L = [   [brown,J1,C1,G1,I1,A1],
            [clark,J2,C2,G2,I2,A2],
            [jones,J3,C3,G3,I3,A3],
            [smith,J4,C4,G4,I4,A4]],

permutation([1,2,3,4], [C1,C2,C3,C4]),
permutation([1,2,3,4], [I1,I2,I3,I4]),
permutation([1,2,3,4], [A1,A2,A3,A4]),
permutation([1,2,3,4], [G1,G2,G3,G4]),
permutation([banker,archit,doctor,lawyer], [J1,J2,J3,J4]),

now the rules can be used

    % Brown is more conservative than Jones. Brown is less conservative than Smith.
    member([brown,_,CB,GB,IB,AB],L),
    member([jones,_,CJ,_,_,_],L),
    CB > CJ,
    member([smith,_,CS,_,_,_],L),
    CB < CS,

efficiency wise, when you select (via member) a named member, 'fetch' all related variables at once (brown attributes' are used later). Also beware that referencing in different selection variables J1,C1, etc could lead to unwanted binding.

A rule difficult to express is

    % Brown is a better golfer than those older than him.

    member([_,_,_,GO1,_,AO1],L),
    (AO1 > AB, GB > GO1 ; AO1 < AB),
    member([_,_,_,GO2,_,AO2],L),
    (AO2 > AB, GB > GO2 ; AO2 < AB),
    member([_,_,_,GO3,_,AO3],L),
    (AO3 > AB, GB > GO3 ; AO3 < AB),

    vardiff(GO1,GO2,GO3),
    vardiff(AO1,AO2,AO3),  % bug: AO1 was GO1

where vardiff/3 is a simple convenience:

vardiff(A,B,C) :- A\=B,A\=C,B\=C.

Of course, if your Prolog has available, CLP(FD) is a much better choice.

2
  • If I use variables like CB and G01, wouldn't I get the same error as before? Commented Nov 14, 2013 at 18:55
  • it depends :) To understand what's happening, use the debugger or place some writeln(L), between rules.
    – CapelliC
    Commented Nov 14, 2013 at 19:07
0

My solution based off what CapelliC said

% [name,job,conservative,golf,income,age]
% conserative: 1 = least conservative, 4 = most conservative
% golf: 1 = worst golfer, 4 = best golfer
% income: 1 = lowest income, 4 = highest income
% age: 1 = youngest, 4 = oldest

jobs(L) :- L = 
       [[brown,J1,C1,G1,I1,A1],
        [clark,J2,C2,G2,I2,A2],
        [jones,J3,C3,G3,I3,A3],
        [smith,J4,C4,G4,I4,A4]],

        permutation([1,2,3,4], [C1,C2,C3,C4]),
        permutation([1,2,3,4], [I1,I2,I3,I4]),
        permutation([1,2,3,4], [A1,A2,A3,A4]),
        permutation([1,2,3,4], [G1,G2,G3,G4]),
        permutation([banker,architect,doctor,lawyer], [J1,J2,J3,J4]),

        % Brown is more conservative than Jones. Brown is less conservative than Smith.
        member([brown,_,CB,GB,IB,AB],L),
        member([jones,_,CJ,_,_,_],L),
        member([smith,_,CS,_,_,_],L),
        CB > CJ,
        CB < CS,

        % Brown is a better golfer than those older than him.
        member([_,_,_,G01,_,A01],L),
        (A01 > AB, GB > G01 ; A01 < AB),
        member([_,_,_,G02,_,A02],L),
        (A02 > AB, GB > G02 ; A02 < AB),
        member([_,_,_,G03,_,A03],L),
        (A03 > AB, GB > G03 ; A03 < AB),

        vardiff(G01,G02,G03),
        vardiff(G01,A02,A03),

        % Brown has a higher income than those younger than Clark.
        member([clark,_,_,_,_,AC],L),
        member([_,_,_,_,I01,A04],L),
        (A04 < AC, IB > I01; AC < A04),

        % Banker has a higher income than architect. Banker is neither youngest nor oldest.
        member([_,banker,_,_,IBa,ABa],L),
        member([_,architect,CAr,_,IAr,_],L),
        IBa > IAr,
        (ABa \= 1, ABa \= 4),

        % Doctor is a worse golfer than lawyer. Doctor is less conservative than architect.
        member([_,doctor,CDo,GDo,_,_],L),
        member([_,lawyer,_,GLa,_,_],L),
        GDo < GLa,
        CDo < CAr,

        % Oldest is most conservative and has highest income.
        member([_,_,4,_,4,4],L),

        % Youngest is the best golfer.
        member([_,_,_,4,_,1],L).

vardiff(A,B,C) :- A\=B, A\=C, B\=C.

I get

3 ?- jobs(L).
L = [[brown,architect,2,4,1,1],[clark,banker,3,1,2,2],[jones,doctor,1,2,3,3],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,2,2,2],[jones,doctor,1,1,3,3],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,3,2,2],[jones,doctor,1,1,3,3],[smith,lawyer,4,2,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,1,2,3],[jones,doctor,1,2,3,2],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,2,2,3],[jones,doctor,1,1,3,2],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,3,2,3],[jones,doctor,1,1,3,2],[smith,lawyer,4,2,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,1,3,2],[jones,doctor,1,2,2,3],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,2,3,2],[jones,doctor,1,1,2,3],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,3,3,2],[jones,doctor,1,1,2,3],[smith,lawyer,4,2,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,1,3,3],[jones,doctor,1,2,2,2],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,2,3,3],[jones,doctor,1,1,2,2],[smith,lawyer,4,3,4,4]] ;
L = [[brown,architect,2,4,1,1],[clark,banker,3,3,3,3],[jones,doctor,1,1,2,2],[smith,lawyer,4,2,4,4]] ;

Multiple answers that repeat so I deleted some of them.

All the clues are satisfied except when Clark is the second oldest for example

L = [[brown,architect,2,4,1,1],[clark,banker,3,1,2,3],[jones,doctor,1,2,3,2],[smith,lawyer,4,3,4,4]] ;

This clue is violated

% Brown has a higher income than those younger than Clark.

And for all of my answers Brown is the youngest so clues like

% Brown is a better golfer than those older than him.
% Brown has a higher income than those younger than Clark.
% Youngest is the best golfer.

seem a bit pointless...

8
  • 1
    By default, SWI-Prolog limits the length of the output when writing long terms. See the documentation on the toplevel_print_options flag, whose value you can change using the standard built-in predicate set_prolog_flag/2. Commented Nov 15, 2013 at 18:10
  • Is there a way to save it? It defaults back every time I close and re-open SWI-Prolog. Commented Nov 15, 2013 at 19:00
  • SWI-Prolog supports a user initialization file that is consulted at startup. It uses ~/.plrc on POSIX systems and pl.ini on Windows systems. You can add to this file the directive :- set_prolog_flag(toplevel_print_options, ...). In alternative, you can add this directive to the top of your program source file. Commented Nov 15, 2013 at 19:08
  • your first solution is invalid. "Brown ... has a larger income than the men who are younger than Clark" but the only man who is younger than Clark is Brown himself.
    – Will Ness
    Commented Nov 15, 2013 at 19:43
  • the 1st and 3rd clues that you say are pointless are perfectly OK, when (if) Brown is youngest and the best golfer. But if your code violates that 2nd clue, then it is wrong; you need to correct it.
    – Will Ness
    Commented Nov 15, 2013 at 19:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.