Given the letters [a, b, c] generate the list containing all the words of length N, formed out of this letters. For example:
?- generate(2, L).
should output:
L = [aa, ab, ac, ba, bb, bc, ca, cb, cc].
At first, this seemed like a pretty simple problem, but I've discovered that none of my implementations work.
This is the second implementation, the one that kind of works.
letter(X) :- member(X, [a, b, c]).
generateWord(0, []) :- !.
generateWord(N, [H|T]) :-
letter(H),
NextN is N - 1,
generateWord(NextN, T).
generateAtomicWord(N, Word) :-
generateWord(N, WList),
atomic_list_concat(WList, Word).
maxSolutions(N, R) :- R is N ** 3.
generate(N, CurrentList, ResultList) :-
maxSolutions(N, R),
length(CurrentList, L),
L =:= R,
append(CurrentList, [], ResultList), !.
generate(N, CurrentList, ResultList) :-
generateAtomicWord(N, NewWord),
\+ member(NewWord, CurrentList),
append(CurrentList, [NewWord], NewList),
generate(N, NewList, ResultList).
generate(N, ResultList) :-
generate(N, [], ResultList).
It kind of works because when given N = 3 the program outputs:
L = [aaa, aab, aac, aba, abb, abc, aca, acb, acc|...]
My first implementation is different, but I can't make it work on any case.
letter(X) :- member(X, [a, b, c]).
generateWord(0, []) :- !.
generateWord(N, [H|T]) :-
letter(H),
NextN is N - 1,
generateWord(NextN, T), !.
generateAtomicWord(N, Word) :-
generateWord(N, WList),
atomic_list_concat(WList, Word).
maxSolutions(N, R) :- R is N ** 3.
generate(N, [H]) :- generateAtomicWord(N, H).
generate(N, [H|T]) :-
generate(N, T),
length(T, TailLen),
maxSolutions(N, M),
(TailLen =:= M -> !;
generateAtomicWord(N, H),
\+ member(H, T)).
This one just outputs:
L = [aa]
and when requested for the rest of the solutions it cycles.
The problem must be solved without using predicates such as:
findall, findnsol, bagof, setof, etc...
that find all the solutions.
I've added the tag backtracking because it does resemble a backtracking problem, but I've no idea what a standard implementation might look like in Prolog.