usar portable online inteligencia elementos descargar descarga como artificial prolog

portable - prolog online



Encontrar elementos únicos en una lista (3)

Estoy tratando de escribir una regla que decide si un elemento X ocurre exactamente uno en una lista L

unique(X, [X|T]):- !, /+ member(X, T). unique(X, [_|T]):- unique(X, T).

La regla funciona para determinar si un valor es único dentro de una lista o no, pero cuando trato de obtener valores únicos dentro de una lista usando unique(X, [1,2,3,1,3,2,5,4,3,8]). devuelve simplemente false. Lo que esperaba es esto (como member(X, list).

X = 5 ; X = 4 ; X = 8 ;

Soy un principiante completo y no sé lo que estoy haciendo mal.


Aquí hay una solución simple usando nth0/4 (o select/3 como lo señala @false):

unique(X, L) :- nth0(_, L, X, R), /+ member(X, R).

nth0/4 4º argumento R es la lista L con el elemento X eliminado. Simplemente comprobamos que X no está en R

Mejor versión

unique(X, L) :- nth0(_, L, X, R), maplist(dif(X), R).

Esto soluciona el problema señalado por @false, aunque como eres un principiante dudo que esto sea de mucho interés para ti.

Esto tiene la ventaja de trabajar en situaciones como esta:

?- unique(b, [X, Y, a]). X = b, dif(Y, b) ; Y = b, dif(X, b) ; false.


Esto suena como una pregunta de tarea.

Prueba algo como esto.

unique(M, L) :- member(M, L), count(M, L, 1). count(M, [H|T], C) :- M = H, count(M, T, C1), C is C + 1. ...

Cuando se completa esto da ...

?- unique(X, [1,2,3,1,3,2,5,4,3,8]). X = 5 ; X = 4 ; X = 8 ; false.

Editar: Ya que las respuestas ya han sido dadas ... esta es la hábil.

unique(Item, List) :- select(Item, List, L2), /+ member(Item, L2).


Has estado usando cut y una forma insegura de negación. Ambos deben ser usados ​​con extremo cuidado. Una solución inmediata sería proteger su programa de los usos para los que no está diseñado:

unique(X, Xs) :- iwhen(ground(X+Xs), your_unique(X, Xs)).

Esto usa iwhen/2 que es similar a when/2 excepto que no se demora:

:- meta_predicate iwhen(+, 0). iwhen(Cond, G_0) :- when(Cond, ( Called = true, G_0 ) ), ( var(Called) -> throw(error(instantiation_error,_)) ; true ).

Arriba funciona para sistemas que proporcionan when/2 . A continuación es para cualquier sistema de conformidad ISO:

iwhen(Cond, G_0) :- ( when_condition(Cond) -> ( Cond -> G_0 ; throw(error(instantiation_error,_)) ) ; throw(error(domain_error(when_condition, Cond),_)) ). when_condition(C) :- var(C), !, throw(error(instantiation_error,_)). when_condition(ground(_)). when_condition(nonvar(_)). when_condition(?=(_, _)). when_condition(( A, B )) :- when_condition(A), when_condition(B). when_condition(( A ; B )) :- when_condition(A), when_condition(B).

Por otro lado, es bastante frustrante recibir errores de instanciación todo el tiempo en lugar de respuestas reales. Entonces, ¡hagamos que su programa sea realmente puro!

Tu segunda regla

unique(X, [_|Es]) :- unique(X, Es).

lee declarativamente, de derecha a izquierda (que :- es un )

Siempre que X sea ​​un elemento único de la lista Es , entonces X es un elemento único de la lista [_|Es] .

en otras palabras: cada vez que sé que X es único en Es , también será único con cualquier elemento adicional en Es . Esa conclusión no es cierta, ¡considere extender la lista por X ! Necesitas alguna condición extra. Además, tu primera regla debe ser reformulada. Esto usa non_member/2 :

unique(X, [X|Es]) :- non_member(X, Es). unique(X, [E|Es]) :- dif(X, E), unique(X, Es).

Y aquí hay otra forma de usar tfilter/3 :

unique(X, Es) :- tfilter(=(X), Es, [_]).

El más eficiente es probablemente el siguiente que usa if_/3 de la library(reif) :

unique(X, [E|Es]) :- if_(X = E, non_member(E, Es), unique(X, Es) ).