Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Prolog 如何在一个列表中选择一个列表的开头,然后将其放入另一个列表中?_Prolog - Fatal编程技术网

Prolog 如何在一个列表中选择一个列表的开头,然后将其放入另一个列表中?

Prolog 如何在一个列表中选择一个列表的开头,然后将其放入另一个列表中?,prolog,Prolog,我有一个列表,看起来像这样: [[b,c],[],[a]] 我想写一个谓词,它将从一个列表的顶部获取一个特定的字母,并将其放入另一个列表中。要移动的字母是事先指定的。它可以放在一个列表的顶部,该列表要么是空的,要么包含一个更大的字母(b可以放在c上,但不能放在其他位置)。信件移动后,应将其从原始列表中删除 我无法告诉Prolog查找以指定字母开头的列表,也无法告诉Prolog如何将其放入另一个列表。下面是查找以某个元素开头的列表的一些规则 starts_with([H|T], H). fin

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

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


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

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

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]] ? ;

这是我的解决方案,基于no
[nth1][1]/4
(实际上,您应该阅读
nth0/4
的文档)

用法示例:

?- 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.

我遵循这种“非惯用”的方法,以便于检查插入是否发生在与删除不同的位置。

我喜欢@capelical的简明解决方案。这里有一个替代解决方案,它不使用内置的
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).

非常感谢。这已经是朝着好的方向迈出的一步,但你会建议我如何删除该列表的顶部,并将其放在另一个空列表或包含较大字母的列表的顶部?你能提供一个输入/输出方面的示例吗?输入可以是(b,[[b,c],[a]],X),输出应该是X=[[c],[b],[a]]
nth0/3-4
nth1/3-4
通常是库谓词,而不是内置谓词。对于没有指定特定Prolog实现的问题,最好始终添加关于非标准(官方或事实上)谓词使用的说明。谢谢@PauloMoura。当然,你是对的。不久前还有一个关于实现nth1/4的问题,我也做出了很大的贡献!我认为尽可能避免使用内置谓词是很好的。谢谢。@Boreq谢谢。从技术上讲,像
is/2
这样的谓词是内置谓词,因此此解决方案不会完全避免内置谓词。但它确实坚持ISO结构,并且可以在大多数Prolog解释器中使用。看到不同的解决方案的好处在于,在每种情况下都需要学习Prolog编程
% 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