You're a treasure sir!
The thing I find especially interesting about these sorts of puzzles is the translation from the word problem to the logical formalism. It seems like a separate domain from solving the problem itself.
The thing I find especially interesting about these sorts of puzzles is the translation from the word problem to the logical formalism. It seems like a separate domain from solving the problem itself.
For instance, in this concrete case, with a suitable operator definition for the operator says, we can write:
:- op(800, xfy, says).
solution([A,B,C,D,E,F,G]) :-
G = salesman,
E = salesman,
C says D = engineer,
A = engineer,
A says B says C says D says E says F says G = engineer.
It is then left to interpret the statements, which we can do for example with: :- use_module(library(dif)).
engineer says Stmt :- false(Stmt).
salesman says Stmt :- true(Stmt).
false(A = B) :- dif(A, B).
false(engineer says Stmt) :- true(Stmt).
false(salesman says Stmt) :- false(Stmt).
true(A = A).
true(engineer says Stmt) :- false(Stmt).
true(salesman says Stmt) :- true(Stmt).
Yielding: ?- solution(S).
S = [engineer,engineer,engineer,salesman,salesman,salesman,salesman]
; S = [engineer,salesman,engineer,salesman,salesman,engineer,salesman]
; S = [engineer,engineer,salesman,engineer,salesman,salesman,salesman]
; S = [engineer,salesman,salesman,engineer,salesman,engineer,salesman]
; false.