Подсчет элементов динамического списка и оценка решения (Пролог)

Созданный мной предикат работает некорректно. Предикат должен подсчитывать элементы всех фактов в базе данных и «оценивать» их. (Позже я объясню, что я имею в виду под «оценкой»)

Например. факты таковы:

:- dynamic listitem /1.
listitem(number).
listitem(letter).
listitem(word).
listitem(sentence).

Первый созданный мной предикат собирает все факты в один список:

members(W) :- bagof(X,listitem(X),W).

Теперь я хочу посчитать элементы в списке. Итак, я создал общий предикат для подсчета:

count([],0).
count([_|L],N) :- count(L,N1), N is N1+1.

Мое следующее предположение не работает должным образом. Этот предикат должен подсчитать все элементы приведенных выше фактов.

count_members(U) :- one_list([bagof(X,listitem(X),_W)],U).

Проблема в том, что база данных должна быть динамической, чтобы я мог добавлять и удалять другие элементы. Это означает, что я не могу спросить

?- count([number,letter,word,sentence],N) 

поскольку факты могли измениться.

И последний шаг, который вообще не работает, потому что мой последний предикат неверен, должен быть следующим: Написание пролога all_members (X) должно возвращать оценку. Например. Пролог должен возвращать «X = четыре элемента» для запроса «all_members (X)», если количество элементов в базе данных равно 4. Надеюсь, вы поняли мою проблему. Опять же, предикат, который я ищу, - это «all_members (X)». Другие созданные мной предикаты должны помочь мне в создании самого предиката.

Буду очень рад, если вы поможете мне найти решение моей проблемы! (иначе я не смогу сегодня заснуть ...) Спасибо !!

РЕДАКТИРОВАТЬ:

Извините, я забыл написать свое определение для one_list. Моя мысль заключалась в том, чтобы, например, список выглядит так:

 [[number], [letter], [word]] 

в список следующего вида:

[number, letter, word, list]

one_list(X,[X]) :- \+ is_list(X).
one_list([],[]).
one_list([X|Xs],Zs) :- one_list(X,Y), one_list(Xs,Ys), append(Y,Ys,Zs).

person jazzsuite    schedule 15.12.2013    source источник
comment
Вы действительно чертовски близки к своему решению. Всего две строчки. как определяется one_list? то есть, что вы пробовали до сих пор?   -  person Christian Fritz    schedule 16.12.2013
comment
@ChristianF Я отредактировал свой вопрос. вроде забыл записать определение ^^   -  person jazzsuite    schedule 16.12.2013
comment
Почему так сложно? У вас уже есть свой список (участники (X)), теперь все, что вам нужно сделать, это пересчитать его, не так ли?   -  person Christian Fritz    schedule 16.12.2013
comment
count_members(U) :- members(W), count(W,U). Так составляются предикаты Пролога.   -  person Will Ness    schedule 16.12.2013
comment
Вам не нужен count/2. Вы можете просто использовать встроенный предикат length/2 для длины списка.   -  person lurker    schedule 16.12.2013
comment
Кроме того, в SWI Prolog вы можете использовать flatten/2, который, я думаю, делает то, что вы пытаетесь сделать с one_list/2.   -  person lurker    schedule 16.12.2013


Ответы (1)


Похоже, в вашем вопросе есть некоторая путаница.

Чтобы подсчитать количество facts/1, если ваша база данных (которая работает, как ожидалось, даже если в настоящее время в базе данных нет facts, если facts объявлен как dynamic):

?- findall(X, facts(X), Xs), length(Xs, L).

Обратите внимание, что вы не можете сказать length(findall(...), L), потому что в Прологе есть предикаты, а не функции (как указал Уилл Несс в комментариях к вашему вопросу)!

Создание списка списков странно и ненужно. Я не совсем понимаю, зачем вам это нужно (пожалуйста, поясните, если я упускаю что-то важное).

Использование flatten/2 не является преступлением, но обычно указывает на неудачное дизайнерское решение.

person Community    schedule 16.12.2013