mogę dostać rekurencyjną Prolog orzecznik posiadający dwa argumenty, zwanej odwróconej, która zwraca odwrotność listy:Recursive Prolog predykatu do tyłu/palindromu
zapytanie Sample i oczekiwany wynik:
?- reverse([a,b,c], L). L = [c,b,a].
Rekurencyjny predykat Prologu z dwoma argumentami o nazwie
palindrome
, który zwraca wartość true, jeśli podana lista jest palindromem. Zapytaniepróbki z oczekiwanego rezultatu:
?- palindrome([a,b,c]). false. ?- palindrome([b,a,c,a,b]). true.
Odpowiedz
Ad 1: To jest niemożliwe do zdefiniowania reverse/2
jako ( bezpośrednio edycji thx do @repeat tail) rekurencyjnego orzecznika - jeśli nie zezwalają orzeczenie pomocnicze.
Ad 2:
palindrome(X) :- reverse(X,X).
Ale najprostszym sposobem jest zdefiniowanie takich predykatów z DCGs:
iseq([]) --> [].
iseq([E|Es]) --> iseq(Es), [E].
reverse(Xs, Ys) :-
phrase(iseq(Xs), Ys).
palindrome(Xs) :-
phrase(palindrome, Xs).
palindrome --> [].
palindrome --> [E].
palindrome --> [E], palindrome, [E].
Nie jest skutecznym sposobem definiowania reverse/2
z jednym rekurencyjnej definicji bez korzystania jakiś pomocniczy predykat. Jeśli jednak mimo wszystko jest dozwolone, to proste rozwiązanie, które nie opiera się na żadnych wbudowanych ins jak append/3
(i powinny być stosowane do większości implementacji Prolog) byłoby użyć listy akumulatora, co następuje:
rev([],[]).
rev([X|Xs], R) :-
rev_acc(Xs, [X], R).
rev_acc([], R, R).
rev_acc([X|Xs], Acc, R) :-
rev_acc(Xs, [X|Acc], R).
rev/2
jest orzecznikiem odwrócenie, które po prostu „delegatów” (lub, okłady) wersja akumulator opartych o nazwie rev-acc/2
, który rekursywnie dodaje elementy z listy wejściowej do akumulatora w odwrotnej kolejności.
Running to:
?- rev([1,3,2,x,4],L).
L = [4, x, 2, 3, 1].
i rzeczywiście jak @false zwracał już uwagę (+1),
palindrome(X) :- rev(X,X).
Tylko dla ciekawości tu idzie rekurencyjną implementację odwrotnej/2, który nie użyj pomocniczych predykatów i nadal odwraca listę. Możesz uważać to za oszustwo, ponieważ używa odwrotnego/2 list i struktury -/2 jako argumentów.
reverse([], []):-!.
reverse([], R-R).
reverse(R-[], R):-!.
reverse(R-NR, R-NR).
reverse([Head|Tail], Reversed):-
reverse(Tail, R-[Head|NR]),
reverse(R-NR, Reversed).
Niezła próba, ale niepoprawna. I tak dałem ci +1. 'reverse (1- [], Ys) .' powinien się nie udać, ale mu się to uda z' Ys = 1.' Następnie 'reverse (Xs, Ys), Xs = [1] .' powinien się powieść, ale się nie powiedzie. Więc nie oszukujesz, ale po prostu wdrażasz inną procedurę. Zgadzamy się nie nazywać tego orzeczeniem - przypuszczam. – false
@false. Masz rację!. Będzie działać tylko z odpowiednimi listami wejściowymi. – gusbro
'reverse (Xs, [1]).' Czy to nie jest właściwa lista wejściowa? Udaje mu się to z 'Xs = [1] - [].' – false
conca([],L,L).
conca([X|L1],L2,[X|L3]):- conca(L1,L2,L3).
rev([],[]).
rev([X|Y],N):- rev(Y,N1),conca(N1,[X],N).
palindrome([X|Y]):- rev([X|Y],N),equal([X|Y],N).
equal([X],[X]).
equal([X|Y],[X|Z]):- equal(Y,Z).
-1. Brak linii między twoimi źle określonymi predykatami, 'conca/3' jest po prostu kopią' append/3' która jest ISO, 'palindrome/1' niszczą listę bez żadnego zysku (z wyjątkiem zapobiegania pustym listom z palindromów za nie powód), a "równy/2" nie jest poprawą w stosunku do '=/2', z tym wyjątkiem, że jest niepotrzebnie bardziej ograniczony. "Co nowego nie jest dobre, a co dobre nie jest nowe". –
Korzystanie DCGs jest ładne rozwiązanie tutaj. – sharky