Pair et de l'Impair listes
Je suis en train de mettre en œuvre un programme Prolog qui va diviser la liste en deux listes. Le premier contiendra les numéros dans la même positions et la seconde le nombre est impair positions.
E. g.: even_odd([1,2,4,7,5],Even,Odd).
entraînera Even=[2,7].
et Odd=[1,4,5].
J'ai trouvé plus élégant des solutions que le mien googler le problème, cependant je voudrais savoir où se trouve le problème dans mon code (probablement opérateur abus) parce que je pense vraiment que j'ai une très mauvaise compréhension de Prolog opérateurs (en particulier en arithmétique comparaison). Aussi googler il ne fait qu'empirer les choses, chaque site a une toute autre explication.
Mon code:
even_odd([], [], []).
even_odd([H|T], Even, Odd) :-
length([H|T], X),
X mod 2 is 0,
append(Even1, H, Even),
even_odd(T, Even1, Odd).
even_odd([H|T], Even, Odd) :-
length([H|T], X),
X mod 2 is 1,
append(Odd1, H, Odd),
even_odd(T,Even,Odd1).
J'ai essayé de traçage et je sais que le problème réside dans le X mod 2 is 1
ou 0
, aucun d'eux n'est jamais vrai. Si j'ai une liste de trois éléments et de la modification des conditions de X is 3
il est tout à fait acceptable, mais la division semble confus, alors, des idées?
Vous devez vous connecter pour publier un commentaire.
Arithmétiques opérateur d'évaluation (est)/2 effectue une opération arithmétique sur le droit d'expression, et de l'unifier avec ses de gauche argument, et d'appliquer le test à la mauvaise variable. Devrait être
Sinon, il y a (=:=)/2 qui effectue une opération arithmétique sur les deux côtés. Alors peut être
En outre, la façon dont vous traitez les listes n'a pas beaucoup de sens. Vous devez mettre la même valeur dans la liste. Puis quelque chose comme
aurait plus de sens.
Tout CapelliC a la bonne idée sur pourquoi votre code ne fonctionne pas, il a mal compris votre question au sujet de vouloir les paires/impaires positions.
Le problème est, vous êtes le calcul de celles de la fin de la liste, de sorte
even_odd([1,2,4,7],Even,Odd).
entraîneraEven=[1,4].
etOdd=[2,7].
qui n'est pas ce que vous voulez.Une solution serait d'inverser la liste avant le traitement et à inverser les résultats par la suite, ou de prendre une approche différente.
Ici, nous commençons par l'ajout d'un élément à l'étrange liste, puis en alternance entre l'ajout de au même et à l'étrange liste, jusqu'à ce que nous avons atteint la finale de l'élément.
divvy([1,5,4,8,6,4,4,2,0,4], 3, X) ? X = [[1,8,4,4], [5,6,2], [4,4,0]].
?- even_odd(List, [a,b,c], [d,e,f]).
, ce qui n'est pas du tout possible ou conduit à la cessation des problèmes avec moster autres versions et ne fonctionne pas même après avoir appliqué les corrections suggérées.Il existe quelques problèmes.
Première est la @CapelliC souligné, c'est que le
is/2
prédicat instancie une variable simple sur la gauche avec la valeur d'une expression sur le droit. Le code d'origine est l'expression à gauche et la valeur sur le droit et échoue toujours. Donc ceci:Devrait être changé en:
Ou, comme @CapelliC dit,
X mod 2 =:= 1
.Seconde, votre
append
tente d'ajouter un seul élément à une liste.append
ne fonctionne que sur les listes. Donc:Devrait être
Tiers, à l'ordre de
append
et la récursivitéeven_odd
appel va causer un problème:Odd1
est uninstantiated quandappend
est appelé, comme c'estOdd
. Cela génère un nombre infini de solutions pour laappend
avant une réponse acceptable peut être lié par le cas de base, résultant en un débordement de pile. La solution simple pour cela est de les échanger:Cela fonctionne maintenant, mais donne des résultats dans l'ordre inverse:
La chose la plus facile à résoudre qui est à ajouter, plutôt que de l'ajouter. Remplacer
Avec
Ou tout simplement l'inclure dans la tête de la clause. Les clauses finales, avec de tous les correctifs, alors ressembler à ceci:
Rendement
Enfin, il y a un autre problème: la parité sur les listes est déterminée à partir de la fin de la liste, plutôt qu'au début. Cela est dû à la logique de l'aide
length
sur la liste actuelle fragment comme un moyen de détermination de la parité.Pour résoudre ce problème, dans la structure du code (encore une fois, la rétrogradation, la solution plus naturelle que @ATS présenté), vous auriez vraiment besoin de compter/index depuis le début. Le regardant avec beaucoup de détails, qui nous amènerait à une solution comme ceci:
Qui donne:
C'est une solution de travail, mais pas du tout optimal car il ne prend pas avantage de la "connaissance" de la position de la liste dans le code (de manière redondante introduit un nombre ou un indice pour savoir où nous en sommes dans la liste).