It took me 12+ hours to write my original article and you wrote an equivalent followup in one afternoon. Crazy.
Anyway your Layton solution inspired me to try it too. Hereβs what I came up with:
% Constraint Logic Programming
:- use_module(library(dif)). % Sound inequality
:- use_module(library(clpfd)). % Finite domain constraints
score([], [], 0).
score([A|As], [K|Ks], N) :-
(A = K, N #= M + 1 ;
dif(A, K), N #= M),
score(As, Ks, M).
keytype([]).
keytype([K|Ks]) :- member(K, [a, b]), keytype(Ks).
key(Key) :-
length(Key, 10),
keytype(Key),
score([b, b, a, b, a, b, b, a, b, b], Key, 7),
score([b, a, a, a, b, a, b, a, a, a], Key, 5),
score([b, a, a, a, b, b, b, a, b, a], Key, 3).
key(Key), score([b, b, a, a, a, b, b, a, a, a], Key, X).
The keytype
predicate bothers me, I wish I knew how to properly typecheck a list.