Elimina vocali in un elenco

Scrivi un programma che NoVowelsString vocali ( String , NoVowelsString ) che NoVowelsString tutte le vocali da una determinata stringa.

Finora ho la condizione vowel(X):- member(X,[a,e,i,o,u]) . Poi ho pensato a quello che elimina tutti gli elementi dall’altra lista:

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

Quindi, avendo questi due, ho pensato che avrei potuto porre una condizione per eliminare quegli elementi che dovevano essere un membro di [a,e,i,o,u] . Sebbene non sia ancora arrivato da nessuna parte.

Ecco il codice

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

Cosa fa? Prima si mette in discussione? È la testa una vocale Sì-> Noi la ignoriamo. No-> Ne abbiamo bisogno. Se trova una lista vuota, costruisce la lista dei risultati, e quando ritorna dal backtracking aggiunge le consonati di fronte. Questo codice è stato testato su SWIProlog.

Quanto segue si basa sulla reificazione dell’uguaglianza / disuguaglianza di termine .

Innanzitutto, definiamo list_memberd_t/3 , che si comporta proprio come memberd_truth/3 ma ha un ordine di argomenti diverso:

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

Per brevità, definiamo memberd_t/3 basato su list_memberd_t/3 :

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

Come parallelo alla library(apply) , definiamo 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 è un altro nome per tinclude/3 :

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

Successivamente, definiamo il meta-predicato texclude/3 , l’opposto di 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). 

Ora usiamoli insieme!

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

modificare

In alternativa all’utilizzo di sopra di texclude/3 , usiamo tinclude/3 con un predicato ausiliario not/3 per capovolgere il valore di verità:

 :- 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). 

Query di esempio:

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

qui una soluzione che utilizza DCG. Nota come si ottiene l’output (nessun argomento che passa, solo liste di differenze)

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

Devo confessare che il secondo taglio non mi piace, ma sembra obbligatorio.

test:

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

modifica Informazioni sul secondo taglio, sembra richiesto dalla notazione ‘mano sinistra’: se codice con argomento, senza taglio, ottengo un parsing corretto:

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

test:

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

Mi chiedo se questo è un bug del traduttore DCG, o (più probabilmente) colpa mia …