saber - obtener elemento de una lista c#
Prolog: ¿cómo verificar si una lista incluye ciertos elementos? (1)
Estoy probando Prolog por primera vez y estoy teniendo dificultades para usar listas.
Digamos que tengo una lista de elementos. Quiero verificar que la lista tenga los siguientes elementos:
Todos: A1, A2, A3, A4, A5
Uno de: B1, B2, B3, B4
Dos de: C1, C2, C3, C4, C5, C6
Por ejemplo, [A1, A2, B2, C1, A3, A4, C4, A5] cumple los requisitos y [A2, A1, C1, B1, A3, A4] no.
¿Cómo podría escribir algo que devuelva Sí / Verdad si una lista cumple con los requisitos y No / Falso de lo contrario? Del mismo modo, ¿qué hay de escribir algo que devuelva los valores que faltan de la lista necesaria para cumplir con los requisitos?
¡Has hecho muchas preguntas! Permítame comenzar con algunos predicados que resuelven la mayoría de sus requisitos.
Primero abordemos el caso de verificar que todas las entradas de una lista también estén en la otra lista:
subset([ ],_).
subset([H|T],List) :-
member(H,List),
subset(T,List).
Esta recursión simple hace uso del predicado miembro / 2 familiar para verificar que cada entrada en la lista especificada por el primer argumento del subconjunto / 2 también esté en la lista especificada por el segundo argumento. [Por simplicidad, he supuesto que las entradas de esta lista son distintas. Sería necesaria una versión más elaborada si quisiéramos verificar que varias instancias de una entrada de la primera lista coinciden al menos con tantas instancias en la segunda lista.]
De acuerdo, ¿qué tal un cheque que (al menos) uno de una primera lista pertenece también a la segunda lista? Obviamente, este es un predicado diferente al anterior. En lugar de todos los elementos en la primera lista, el objetivo es satisfacerse si existe un elemento en la primera lista que pertenece a la segunda lista.
intersects([H|_],List) :-
member(H,List),
!.
intersects([_|T],List) :-
intersects(T,List).
Esta recursión falla si alcanza una lista vacía para el primer argumento, pero tiene éxito si en algún momento anterior se encuentra un miembro de la primera lista que pertenece a la segunda lista. [Este predicado funcionaría bien incluso si ocurrieran múltiples instancias de un elemento en cualquiera de las listas. Sin embargo, necesitaríamos refinar la lógica si quisiéramos comprobar que un solo elemento de la primera lista pertenece a la segunda lista, y eso implicaría preocuparse sobre si las instancias múltiples son consistentes o contrarias al recuento exacto de una.]
¿Qué sucede si queremos generalizar esta verificación para verificar que (al menos) N elementos de la primera lista estén en la segunda? El predicado resultante requerirá un tercer argumento:
intersectsAtLeast(_,_,N) :- N <= 0, !.
intersectsAtLeast([H|T],L,N) :-
member(H,L),
!,
M is N-1,
intersectsAtLeast(T,L,M).
intersectsAtLeast([_|T],L,N) :-
intersectsAtLeast(T,L,N).
Esta recursión funciona a través de la lista, decrementando el tercer argumento por uno cada vez que un elemento en la primera lista también está en la segunda lista, y teniendo éxito una vez que el recuento se reduce a 0 (o menos). [De nuevo, el código aquí necesita más trabajo si las listas pueden tener repeticiones.]
Finalmente, pregunta por escribir algo que "devuelva los valores que faltan" para cumplir los requisitos. Esto no está bien definido en el caso de verificar uno o más elementos en ambas listas, ya que un "valor perdido" podría ser uno cualquiera de una serie de elementos posibles. En el caso especial en el que solicitamos que todos los elementos de la primera lista pertenezcan a la segunda lista, se pueden determinar los "valores faltantes" (si los hay).
missingValues([ ],_,[ ]).
missingValues([H|T],L,K) :-
member(H,L),
!,
missingValues(T,L,K).
missingValues([H|T],L,[H|K]) :-
missingValues(T,L,K).
Aquí, la recursividad "mueve" elementos de la lista de entrada primero a la tercera lista de "elementos faltantes" de salida si y solo si no aparecen en la segunda lista.
Una nota final sobre sus preguntas se refiere a la notación. En Prolog las variables son identificadores que comienzan con una letra mayúscula o un guión bajo, por lo que el uso de A1, A2, etc. como elementos en la lista se dirige a problemas si se tratan como "incógnitas" en lugar de (como supongo que quiso decir ) átomos distintos (constantes). Cambiar a letras minúsculas resolvería eso.