如何将列表列表中的一个列表的头部放在另一个列表中?

时间:2014-01-28 09:04:16

标签: prolog

我有一个列表列表,看起来像这样:

[[b,c],[],[a]]

我想编写一个谓词,它将从其中一个列表的顶部获取一个特定的字母,并将其放在另一个列表中。要移动的字母是事先指定的。它可以放在列表的顶部,该列表为空,或者包含较大的字母(b可以放在c上,但不能放在其他位置)。移动后,该信件应从原始列表中删除。

我无法告诉Prolog查找以指定字母开头的列表,以及如何告诉Prolog将其放入另一个列表中。

3 个答案:

答案 0 :(得分:0)

以下是一些查找以某个元素开头的列表的规则。

starts_with([H|T], H). 
find_starts_with([],C,[]).
find_starts_with([H|T],C,[H|Y]) :- starts_with(H,C),find_starts_with(T,C,Y).
find_starts_with([H|T],C,L) :- \+ starts_with(H,C), find_starts_with(T,C,L).

示例:

| ?- find_starts_with([[1,2],[3,4],[1,5]],1,X).

X = [[1,2],[1,5]] ? ;

答案 1 :(得分:0)

这是我的解决方案,基于否[nth1][1]/4(好吧,你应该阅读nth0/4的文档,真的)

/* takes a specific letter from the top of one of the lists, and puts it in another list.
   The letter to be moved is specified beforehand.
   It can be placed on top of a list which is either empty, or contains a letter that is larger (b can be placed on c, but not otherwise).
   The letter should be removed from the original list after it has been moved.
*/

move_letter(Letter, Lists, Result) :-
    % search Letter, Temp0 miss amended list [Letter|Rest]
    nth1(I, Lists, [Letter|Rest], Temp0),
    % reinsert Rest, Temp1 just miss Letter
    nth1(I, Temp1, Rest, Temp0),
    % search an appropriate place to insert Letter
    nth1(J, Temp1, Candidate, Temp2),
    % insertion constraints
    J \= I, (Candidate = [] ; Candidate = [C|_], C @> Letter),
    % update Result
    nth1(J, Result, [Letter|Candidate], Temp2).

用法示例:

?- move_letter(a,[[b,c],[],[a]],R).
R = [[a, b, c], [], []] ;
R = [[b, c], [a], []] ;
false.

?- move_letter(b,[[b,c],[],[a]],R).
R = [[c], [b], [a]] ;
false.

我遵循了这个'非惯用'路线,以便于检查插入是否发生在与删除不同的地方。

答案 2 :(得分:0)

我喜欢@CapelliC的简洁解决方案。这是一个不使用nth1内置的替代解决方案。为这些糟糕的变量名称道歉。

% move_letter : Result is L with the letter C removed from the beginning
% of one sublist and re-inserted at the beginning of another sublist
% such that the new letter is less than the original beginning letter
% of that sublist
%
move_letter(C, L, Result) :-
    removed_letter(C, L, R, N),        % Find & remove letter from a sublist
    insert_letter(C, R, 0, N, Result). % Result is R with the letter inserted

% removed_letter : R is L with the letter C removed from the beginning of a
% sublist. The value N is the position within L that the sublist occurs 
%
removed_letter(C, L, R, N) :-
    removed_letter(C, L, R, 0, N).
removed_letter(C, [[C|T]|TT], [T|TT], A, A).
removed_letter(C, [L|TT], [L|TTR], A, N) :-
    A1 is A + 1,
    removed_letter(C, TT, TTR, A1, N).

% Insert letter in empty sublist if it's not where the letter came from;
% Insert letter at front of a sublist if it's not where the letter came from
% and the new letter is less than the current head letter;
% Or insert letter someplace later in the list of sublists
%
insert_letter(C, [[]|TT], A, N, [[C]|TT]) :-
    A \== N.
insert_letter(C, [[C1|T]|TT], A, N, [[C,C1|T]|TT]) :-
    A \== N,
    C @< C1.
insert_letter(C, [L|TT], A, N, [L|TTR]) :-
    A1 is A + 1,
    insert_letter(C, TT, A1, N, TTR).

结果:

| ?- move_letter(a, [[b,c],[],[a]], R).

R = [[a,b,c],[],[]] ? a

R = [[b,c],[a],[]]

no

| ?- move_letter(b, [[b,c],[],[a]], R).

R = [[c],[b],[a]] ? a

no

| ?- move_letter(b, [[b,c], [], [a], [b,d]], R).

R = [[c],[b],[a],[b,d]] ? a

R = [[b,c],[b],[a],[d]]

no
相关问题