двоичный предикат в квадратный список и подсписки в прологе - PullRequest
0 голосов
/ 08 ноября 2011

Я новичок в прологе и пытался создать двоичный предикат, который даст список, в котором все числа в квадрате, в том числе в подсписках. например,

?-dcountSublists([a,[[3]],b,4,c(5),4],C).
  C=[a,[[9]],b,c(5),16]

Может кто-нибудь направить меня, как я могу это сделать. Благодарю вас. Ответ с фрагментом приветствуется

Ответы [ 2 ]

0 голосов
/ 10 ноября 2011

Это легко достигается с помощью рекурсии в Прологе.Помните, что все в Прологе является либо переменной, либо термином (атомы - это просто 0-арные термины), поэтому термин , подобный следующему:

[a,[[3]],b,4,c(5),4]

... легкодеконструированный (также обратите внимание, что синтаксис списка [..] является сахаром для двоичного предиката ./2).Prolog предлагает ряд предикатов для тестирования для определенных типов терминов, таких как числа, строки или составные термины (такие как compound/1).

Чтобы построить предикат, который вам нужен, я рекомендую написать его, используя несколько предикатов, таких как:

dcountSublists(In, Out) :-
  % analyze type of In
  % based on type, either: 
  %   1. split term into subterms for recursive processing
  %   2. term cannot be split; either replace it, or pass it through

Вот пример, который поможет вам начать работу, которая решает сложную задачу.Следующее распознает составные термины и разбивает их на части с помощью термина de / constructor =../2:

dcountSublists(In, Out) :-
  % test if In has type compound term
  compound(In),
  % cut to exclude backtracking to other cases below this predicate
  !, 
  % deconstruct In into functor and an argument list
  In =.. [Func|Args],
  % apply dcountSublists/2 to every argument, building new args
  maplist(dcountSublists, Args, NewArgs),
  % re-construct In using the new arguments
  Out =.. [Func|NewArgs].

dcountSublists(In, Out) :-
  % test if In has type atom
  atom(In), !, 
  % pass it through
  Out = In.

Тестирование:

?- dcountSublists([a,[[e]],b,a,c(s),a], L).
L = [a, [[e]], b, a, c(s), a].

Обратите внимание, что это не работает, есливходной термин имеет числа, потому что у него нет предиката для распознавания и обработки с ними.Я оставлю это на ваше усмотрение.

Удачи!

0 голосов
/ 08 ноября 2011

SWI-Prolog имеет предикат maplist / [2-5] , который позволяет отображать предикат по некоторым спискам.Используя это, вам нужно только создать предикат, который возведет в квадрат число или числа в списке и оставит все остальное таким же.Предикаты number / 1, is_list / 1 имеют значение true, если их аргумент является числом или списком.

Следовательно:

    square(N,NN):-
            integer(N),
            NN is N*N.

    square(L,LL):-
            is_list(L),
            dcountSublists(square,L,LL).

    square(Other,Other):-
            \+ number(Other),
            \+ is_list(Other).

    dcountSublists(L,LSquared):-
            maplist(square,L,LSquared).

с отрицанием в конечном предикате, которого мы избегаем многократным (неправильно) решения: например, dcountSublists([2],X) вернет X=[4] и X=[2] в противном случае.Этого можно было бы избежать, если бы мы использовали структуру if-then-else для квадрата or once/1 для вызова square/2.

Если это домашняя работа, возможно, вам не следует использовать maplist, поскольку (вероятно) цель упражнениянаучиться строить рекурсивную функцию;в любом случае я бы предложил написать эквивалентный предикат без maplist.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...