1

编写一个删除元音 ( String, NoVowelsString) 的程序,删除给定字符串中的所有元音。

到目前为止,我已经有了条件vowel(X):- member(X,[a,e,i,o,u])。然后我想到了从另一个列表中删除所有元素的那个:

delete2([],L1,L1).
delete2([H|T],L1,L3) :-
   delete2(H,L1,R2),
   delete2(T,R2,L3).

因此,有了这两个,我认为我可以对那些被删除的元素设置一个条件,即它们必须是[a,e,i,o,u]. 虽然我还没有得到任何地方。

4

3 回答 3

4

以下是基于术语 equal/inequality的具体化。

首先,我们首先定义list_memberd_t/3,它的行为就像 ,memberd_truth/3但有不同的参数顺序:

list_memberd_t([]    ,_,false).
list_memberd_t([Y|Ys],X,Truth) :-
   if_(X=Y, Truth=true, list_memberd_t(Ys,X,Truth)).

list_memberd_truth(Xs,X,Truth) :- list_memberd_t(Xs,X,Truth).

为简洁起见,让我们定义memberd_t/3基于list_memberd_t/3

memberd_t(X,Xs,Truth) :- list_memberd_t(Xs,X,Truth).

作为平行于library(apply),让我们定义tinclude/3

:- meta_predicate tinclude(2,?,?).
tinclude(P_2,Xs,Zs) :- 
    list_tinclude_list(Xs,P_2,Zs).

list_tinclude_list([],   _P_2,[]).
list_tinclude_list([E|Es],P_2,Fs0) :-
    if_(call(P_2,E), Fs0 = [E|Fs], Fs0 = Fs),
    list_tinclude_list(Es,P_2,Fs).

tfilter/3是 的另一个名称tinclude/3

tfilter(P_2,As,Bs) :-
   tinclude(P_2,As,Bs).

接下来,我们定义元谓词texclude/3,它的反面tinclude/3

:- meta_predicate texclude(2,?,?).
texclude(P_2,Xs,Zs) :- 
    list_texclude_list(Xs,P_2,Zs).

list_texclude_list([],_,[]).
list_texclude_list([E|Es],P_2,Fs0) :-
    if_(call(P_2,E), Fs0 = Fs, Fs0 = [E|Fs]),
    list_texclude_list(Es,P_2,Fs).

现在让我们一起使用它们!

?- texclude(list_memberd_truth([a,e,i,o,u]),
            [d,e,l,e,t,e,' ',v,o,w,e,l,s,' ',i,n,' ',a,' ',l,i,s,t], Filtered).
Filtered  = [d,  l,  t,  ' ',v,  w,  l,s,' ',  n,' ',  ' ',l,  s,t].

编辑

作为使用 above 的替代方法texclude/3,让我们使用tinclude/3辅助谓词not/3来翻转真值:

:- meta_predicate not(2,?,?).
not(P_2,X,Truth) :-
   call(P_2,X,Truth0),
   truth_flipped(Truth0,Truth).

truth_flipped(true,false).
truth_flipped(false,true).

示例查询:

?- tinclude(not(list_memberd_truth([a,e,i,o,u])),
            [d,e,l,e,t,e,' ',v,o,w,e,l,s,' ',i,n,' ',a,' ',l,i,s,t], Filtered).
Filtered  = [d,  l,  t,  ' ',v,  w,  l,s,' ',  n,' ',  ' ',l,  s,t].
于 2015-04-30T09:05:04.717 回答
1

这里是使用 DCG 的解决方案。注意“输出”是如何获得的(没有参数传递,只有差异列表)

novowels --> ("a";"e";"i";"o";"u"), !, novowels.
% or ..
% novowels --> [C], {memberchk(C, "aeiou")}, !, novowels.
novowels, [C] --> [C], !, novowels.
novowels --> [].

我必须承认第二次剪辑不喜欢我,但似乎是必需的。

测试:

?- phrase(novowels, "abcdefghilmnopq", L),format('~s',[L]).
bcdfghlmnpq
L = [98, 99, 100, 102, 103, 104, 108, 109, 110|...].

编辑关于第二次切割,“左手”表示法似乎需要:如果我用参数编码,没有切割,我得到一个正确的解析:

novowels(Cs) --> ("a";"e";"i";"o";"u"), !, novowels(Cs).
% novowels(Cs) --> [C], {memberchk(C, "aeiou")}, !, novowels(Cs).
novowels([C|Cs]) --> [C], novowels(Cs).
novowels([]) --> [].

测试:

?- phrase(novowels(L), "abcdefghilmnopq"),format('~s',[L]).
bcdfghlmnpq
L = [98, 99, 100, 102, 103, 104, 108, 109, 110|...] ;
false.

我想知道这是否是 DCG 翻译器的错误,或者(更可能)是我的错......

于 2012-11-25T10:10:23.750 回答
0

这是代码

deleteV([H|T],R):-member(H,[a,e,i,o,u]),deleteV(T,R),!.
deleteV([H|T],[H|R]):-deleteV(T,R),!.
deleteV([],[]).

它能做什么?首先它质疑自己?它是元音元音是->我们忽略它。不->我们需要它。如果它找到一个空列表,它会构造结果列表,并且当从回溯返回时,它会在前面附加辅音。此代码在 SWIProlog 中进行了测试。

于 2012-11-23T23:51:11.990 回答