2017-05-08 3 views
2

Je suis en train de développer le code dans Prolog pour capturer des éléments avec la fréquence 0. Regardez l'exemple, le tuple:valeurs de capture d'une liste en Prolog et ajouter à une autre liste

[[1,31],[2,0],[3,21],[4,0],[5,0]] 

où chaque élément est quelque chose d'autre avec 2 éléments chacun, donc les éléments qui devraient être couverts sont 2, 4 et 5, pour la fréquence 0. le code ci-dessous représente l'idée:

match([],_). 
match([[A,Y]|Tail],[A|Tail2]):- Y==0,match(Tail,[Tail2|A]),!. 
match([[_,_]|Tail],X):- match(Tail,X). 

Deux paramètres sont passés: Un tuple contenant l'ensemble des valeurs cibles et fréquences,

(["Target value", "frequency"], ["target value", "frequency"], ...] 

Et un deuxième paramètre qui est une variable, il reçoit les éléments cibles. Cependant, l'abstraction que j'avais pour développer le code n'est pas correcte, parce que les résultats ne sont pas comme prévu. J'ai fait le tour pas à pas pour comprendre, modifié plusieurs choses et le résultat est toujours le même ... Une liste avec seulement 2 éléments est renvoyée dans tous les cas (même s'il n'y a qu'une seule cible avec une fréquence de 0).

Exemple avec 3 cibles de fréquence 0:

?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X). 
X = [2|4]. 

Résultat attendu pour ce cas: X = [2,4,5].

exemple avec une cible de fréquence 0:

?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X). 
X = [2|_9998]. 

résultat escompté pour ce cas: X = [2].

Quelqu'un peut-il m'aider?

Répondre

1

Vous êtes très proche! Juste deux petits problèmes:

  • Actuellement, quand une liste vide est passée, vous dites que le résultat peut être quelque chose (_). Je doute fortement que ce soit ce que tu veux; la sortie d'une liste vide doit également être une liste vide.
  • L'appel récursif dans la deuxième clause n'est pas correct. Ce que vous voulez que le résultat soit A suivi du résultat de l'appel récursif (Tail2). Cependant, pour une raison quelconque, vous avez écrit l'appel récursif avec aussi A. Je ne peux pas vraiment dire comment vous êtes arrivé à cela, mais vous devriez juste obtenir Tail2 seul.

De plus, vous pouvez éviter d'écrire Y==0 en l'écrivant directement dans l'en-tête de la clause. Le code résultant ressemble alors à ceci:

match([],[]). 
match([[A,0]|Tail], [A|Tail2]) :- match(Tail, Tail2), !. 
match([[_,_]|Tail], X) :- match(Tail, X). 

?- match([[1,31],[2,0],[3,312],[4,0],[5,0]],X). 
X = [2, 4, 5] 

?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X). 
X = [2] 
+0

Wow, merci beaucoup! Je commence pour l'instant dans le prologue et l'utilisation de la récursivité dans la programmation logique est quelque chose de nouveau pour moi. Parfois, il est si difficile de comprendre ce que je dois faire. –

2

Vous pouvez choisir de décrire la liste résultante avec DCG comme ceci:

match(Pairs,ZFs) :-   % the items with frequency 0 
    phrase(zeros(Pairs),ZFs). % are described by zeros//1 

zeros([]) -->     % the empty list 
    [].      % contains no items 
zeros([[I,0]|Is]) -->   % if the frequency is 0 
    [I],      % the item is in the list 
    zeros(Is).     % the same for the remaining items 
zeros([[I,F]|Is]) -->   % if the frequency 
    {dif(F,0)},    % is not 0, the item isn't in the list 
    zeros(Is).     % the same for the remaining items 

Ainsi, les deux exemples de requêtes dans votre post donnent les résultats souhaités:

?- match([[1,31],[2,0],[3,21],[4,0],[5,0]],X). 
X = [2,4,5] ? ; 
no 
    ?- match([[1,31],[2,0],[3,312],[4,312],[5,123]],X). 
X = [2] ? ; 
no