Ce que je dois faire est d'écrire un prédicat Multiplication / 3, dont le premier argument est un entier, le deuxième argument est une liste et le troisième argument est le résultat de la multiplication de l'entier avec la liste, par exemple:

? -Multiplication (3, [2,7,4], Résultat).

Devrait revenir

Résultat = [6,21,12].

Voici mon code:

Multiplication(X,[],Result).

Multiplication(X,[Head|Tail],Result) :-
    Y is X*Head,
    append([Result], [Y], L),
    append([],L,Result),  // HERE
    Multiplication(X,Tail,Result).

Et j'obtiens l'erreur suivante:

Erreur de domaine: "acyclic_term" attendu, trouvé "@ (lists: append ([], S_1, S_1), [S_1 = [S_1,1]])"

Sur le deuxième appel d'ajout.

Si quelqu'un sait pourquoi je reçois l'erreur, comment la corriger ou une autre façon de résoudre ce problème, je suis ouvert aux idées.

3
George Cernat 20 avril 2017 à 18:26

3 réponses

Meilleure réponse

Dans votre code d'origine:

Multiplication(X,[Head|Tail],Result) :-
    Y is X*Head,
    append([Result], [Y], L),
    append([],L,Result),  // HERE
    Multiplication(X,Tail,Result).

Vous obtenez un "cycle" parce que vous ajoutez Result à quelque chose pour obtenir L, puis ajoutez quelque chose à L pour obtenir Result. Ce n'est pas bon. Vous avez également un nom de prédicat en majuscule, ce qui est une erreur de syntaxe. (Je suppose que, depuis que vous avez exécuté votre code, il n'a pas été mis en majuscule dans la version originale.)

Votre nouvelle solution proposée est trop compliquée. Pourquoi avez-vous besoin du 4e argument? De plus, votre cas de base pour return (qui est return(X, [], Result) n'a pas de sens, car il doit singleton des variables. L'utilisation de append/3 est excessive car la récursivité gère l'itération dans la liste éléments pour vous.

En partant du haut, vous avez un modèle commun dans Prolog où vous souhaitez exécuter une requête sur les éléments correspondants de deux listes ou plus. Une solution récursive simple ressemblerait à ceci:

multiplication(_, [], []).    % Multiplying anything by the empty list is the empty list
multiplication(M, [X|Xs], [XX|XXs]) :-
    XX is M * X,
    multiplication(M, Xs, XXs).

Une autre façon d'implémenter ce type de modèle dans Prolog est d'utiliser maplist/3. Vous pouvez d'abord définir la requête sur les éléments correspondants:

multiply(X, Y, Product) :- Product is X * Y.

Ensuite, utilisez maplist/3:

multiplication(M, List, Result) :-
    maplist(multiply(M), List, Result).

Maplist fera un call(multiply(M), ...) sur chaque paire correspondante d'éléments de List et Result.

2
lurker 20 avril 2017 à 17:21

J'ai édité le code et j'ai trouvé ceci:

multiplication(X,[],Result,Result).

multiplication(X,[Head|Tail],List,Result) :-
    Y is X*Head,
    append(List, [Y], L),
    multiplication(X,Tail,L,Result).

return(X,[],Result).

return(X,L,Result) :-
    multiplication(X,L,_,Result).

Et la requête:

return (2, [1,2], Résultat).

Après la première exécution, il semble renvoyer le résultat comme il se doit, mais il s'exécute pour toujours.

0
George Cernat 20 avril 2017 à 16:51

Vos deux objectifs append([Result], [Y], L), append([],L,Result) sont exactement les mêmes que:

L = [Result,Y], L = Result.

Ou encore plus simple:

L = [L,Y]

Ce qui aboutirait soit à un échec silencieux, soit à un terme infini. Au lieu de cela, votre Prolog produit une erreur, afin que vous puissiez corriger votre programme.

3
false 20 avril 2017 à 15:59