Prolog Logic/Einstein Puzzle

后端 未结 5 992
我寻月下人不归
我寻月下人不归 2021-01-29 01:26

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 respe

5条回答
  •  隐瞒了意图╮
    2021-01-29 01:59

    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.

提交回复
热议问题