Разбор списка списков в Прологе - PullRequest
0 голосов
/ 23 января 2019

Я новичок в Prolog.Рассмотрим следующий пример:

MainList =  [["A","a","0"],["A","b","0"],["B","a","0"],["B","b","0"],["A","a","1"],["B","b","1"],["C","c","1"],["C","a","0"]]
SubList = ["A","b","-']

Формат MainList: в первом индексе это должна быть большая буква, во втором индексе - маленькая буква, а в третьем - цифра.MainList может содержать другие форматы (и длины), но я выбираю этот формат, потому что его легче объяснить.Я просто хочу объяснить, что там индексы каждого подсписка делятся на категории - первый элемент каждого списка принадлежит category1, второй элемент category2 и так далее.Символ "-" означает, что мы знаем о связи этого элемента с другими элементами.

Отношение, которое я хотел бы создать, должно пройти через MainList и удалить все подсписки, которые не следуютSubList.Для приведенного выше примера он должен вернуть:

Output =  [["A","b","0"],["B","a","0"],["C","c","1"],["C","a","0"]]

Объяснение: "A" работает вместе с "b", поэтому следует проверять все подсписки, содержащие один из этих элементов.если они оба существуют, тогда все в порядке (без дубликатов).В противном случае, если существует только один из них, это не нормально, и мы не должны вставлять его в список Output.

Другой пример (MainList немного отличается от предыдущего):

MainList =  [["A","a","0"],["A","b","0"],["B","a","0"],["B","b","0"],["A","b","1"],["B","b","1"],["C","c","1"],["C","a","0"]]
SubList = ["C","a","0"]
Output = [["A","b","1"],["B","b","1"],["C","a","0"]]

Я понимаю алгоритм - мы должны пройти через каждый подсписок MainList и проверить, работает ли соединение ввода-подсписка, если так, мы вставим его в список Output.Проблема в том, что я не понимаю, как правильно это реализовать.Что если подсписок содержит более 2 соединений (как показано во втором примере)?Как мне относиться к подсписку иначе?

РЕДАКТИРОВАТЬ: Я попытаюсь объяснить немного больше.Место каждого элемента имеет важное значение.Каждое место представляет отдельную категорию.Например, первое место может представлять большие буквы, второе место - маленькие буквы, а третье - цифры (может быть больше категорий).Мы получаем sublist, который представляет связь между двумя или более элементами.Например, у нас есть связь между "A" и "b": ["A","b","-"].Мы должны перебрать подсписки MainList и проверить, содержит ли каждый из этих подсписков один из этих элементов ("A" и "b").Если это произойдет, мы должны проверить правильность связи.Например, если у нас есть подсписок, который имеет A (в первом индексе, конечно), то мы должны перейти ко второму индексу и проверить, есть ли "b".если его там нет, мы не должны вставлять его в список Output, в противном случае мы вставим.Например, у нас есть облигация ["A","b","-"], и мы попали в подсписки MainList, которые выглядят следующим образом: ["A","a","0"] или ["B","b","2"].Мы не будем инертировать эти списки в Output.Но если мы получим такие списки, как: ["A","b","1"] и ["A","b","2"] и ["B","a","1"], мы вставим эти списки в Output.

1 Ответ

0 голосов
/ 23 января 2019

Я написал код, который удовлетворяет условиям вывода для приведенных вами примеров, но не пробовал другие случаи и не рассматривал эффективность кода, так что вы можете улучшить его. Вот код:

subList(List,SubL,Out):-
    (member("-",SubL),
     select("-",SubL,SubRem)
    ;
    \+ member("-",SubL),
    SubRem = SubL),
    findall(L,((member(L,List),checkEq(SubRem,L));
           (member(L,List),checkNeq(SubRem,L))),Out).

checkEq([],_).
checkEq([S|Rest],[E|List]):-
    S == E,
    checkEq(Rest,List).

checkNeq([],_).
checkNeq([S|Rest],List) :-
    \+ member(S,List),
    checkNeq(Rest,List).

Объяснение: Я сделал следующее: сначала я удалил символ "-" из подмассива (если он существует), чтобы облегчить вычисления. Затем я либо проверяю условие, что каждый элемент в SubList находится в порядке с элементами выбранного подсписка MainList . Если это не удается, я проверяю, не содержится ли ни один из элементов SubList в выбранном подсписке. Если обе проверки не пройдены, я перехожу к следующему подсписку. Используя предикат findall / 3, я нахожу все комбинации, которые удовлетворяют любому из этих условий, и группирую их в списке Out

EDIT: добавить дополнительное предложение для предиката checkEq:

checkEq([S|Rest],[E|List]):-
    S \= E,
    member(S,List),
    checkEq([S|Rest],List).

Итак, окончательная версия:

checkEq([],_).
checkEq([S|Rest],[E|List]):-
    S == E,
    checkEq(Rest,List).

checkEq([S|Rest],[E|List]):-
    S \= E,
    member(S,List),
    checkEq([S|Rest],List).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...