Прологовые места в таблице

У меня есть данный список, который представляет собой двумерный список x. Эта таблица содержит два «пятна» по 1, как вы можете видеть в примере ниже:

xxxxxxxxxxxxxxxx
xx1111xxxx111xxx
xxx1111xxxx11xxx
x1111xxxxxx111xx

Мне нужно изменить ТОЛЬКО второе место с 1 на 2, как в примере ниже:

xxxxxxxxxxxxxxxx
xx1111xxxx222xxx
xxx1111xxxx22xxx
x1111xxxxxx222xx

Мне нужен предикат с именем separate(L,M), который возьмет первый список L и создаст вторую таблицу M.

Было бы отлично, если бы мы могли решить эту проблему без использования какого-либо стандартного предиката, такого как «findall» и т. д. …


person user1118501    schedule 05.01.2012    source источник
comment
Непонятно, как представлены эти таблицы; не могли бы вы привести пример? Далее, как определить, какое место первое, а какое второе? А как определить место?   -  person Scott Hunter    schedule 05.01.2012
comment
эти таблицы - списки, их элементы - списки. Пятна - это элементы, которые являются соседями и имеют значение 1 . Я хочу разделить два пятна, повернув элементы одного пятна только с 1 на 2   -  person user1118501    schedule 05.01.2012
comment
Нет, не нашел, извините.   -  person Mostowski Collapse    schedule 08.01.2012


Ответы (3)


Вы можете использовать грамматику определенных предложений (DCG) для реализации преобразователя с конечным состоянием. Хотя DCG не выполняют много композиционных операций на стороне производства, они достаточно хороши для реализации стороны распознавания.

Итак, вы хотите распознать два разных типа прогонов единиц. Итак, в основном я предполагаю, что строка ввода выглядит следующим образом в расширенной форме Бэкуса-Наура (EBNF):

line :== exs run1 exs run2 exs | exs.
exs  :== { "x" } "x".
run1 :== { "1" } "1".
run2 :== { "1" } "1".

Для решения проблемы распознавания вы можете написать DCG без атрибутов (далее следует текст Пролога, который вы можете поместить в файл или напрямую обратиться к нему через ?- [пользователь]):

line --> exs, run1, exs, run2, exs | exs.

run1 --> "1", run1.
run1 --> "1".

run2 --> "1", run2.
run2 --> "1".

exs --> "x", exs.
exs --> "x".

Вот несколько примеров запусков:

?- phrase(line,"xxx").
Yes 
?- phrase(line,"xxx111xxx111xxx").
Yes 
?- phrase(line,"xxx111xxx"). 
No

Для производственной задачи вы можете просто добавить атрибуты в DCG. Использование списка различий работает проще всего:

line(I,O) --> exs(I,H), run1(H,J), exs(J,K), run2(K,L), exs(L,O) | exs(I,O).

run1([0'1|I],O) --> "1", run1(I,O).
run1([0'1|H],H) --> "1".

run2([0'2|I],O) --> "1", run2(I,O).
run2([0'2|H],H) --> "1".

exs([0'x|I],O) --> "x", exs(I,O).
exs([0'x|H],H) --> "x".

Вот несколько примеров запусков:

?- phrase(line(R,[]),"xxx").
R = [120, 120, 120] 
?- phrase(line(R,[]),"xxx111xxx111xxx").
R = [120, 120, 120, 49, 49, 49, 120, 120, 120, 50, 50, 50, 120, 120, 120] 
?- phrase(line(R,[]),"xxx111xxx").
No

Примечание. 0' — это нотация Пролога для кода символа. В ascii мы имеем 0'x = 120, 0'1 = 49, 0'2 = 50, что объясняет результат. Вышеописанное должно работать на большинстве систем Prolog, поскольку они поддерживают DCG.

Пока

Грамматика определенного предложения
http://en.wikipedia.org/wiki/Definite_clause_grammar

Преобразователь конечного состояния
http://en.wikipedia.org/wiki/Finite_state_transducer

person Mostowski Collapse    schedule 08.01.2012

Мы можем применить специальную транслитерацию (только для «горизонтальных» списков):

transliteration(Matrix, Translit) :-
  maplist(transliteration(not_seen), Matrix, Translit).

transliteration(_State, [], []).
transliteration(State, [X|Xs], [Y|Ys]) :-
  transliteration(State, X, NewState, Y),
  transliteration(NewState, Xs, Ys).

% handle only required state change
transliteration(not_seen, 0'1, seen_first, 0'1).
transliteration(seen_first, C, seen_last, C) :- C =\= 0'1.
transliteration(seen_last, 0'1, seen_last, 0'2).
% catch all, when no change required
transliteration(State, C, State, C).
person CapelliC    schedule 08.01.2012
comment
для этого: транслитерация([[0,0,0,0,0],[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1 ,0],[0,0,0,0,0]],L). я получаю сообщение об ошибке - person user1118501; 09.01.2012
comment
cat и вставьте свой код, у меня тоже выдает ошибку, но, похоже, в тексте есть какой-то странный символ! Если переписать, например, то нормально...:- транслитерация([ [0,0,0,0,0], [0,1,0,0,0], [0,1,0,1, 0], [0,0,0,1,0], [0,0,0,0,0] ], L), writeln(L). дает [[0,0,0,0,0],[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0], [0,0,0,0,0]] - person CapelliC; 14.01.2012

Похоже на решение, предложенное @chac, но более прямое.

walk(L, R) :- walk(s0, L, R).
walk(_, [], []). % finish
walk(s0, [0'1|T], [0'1|R]) :- walk(s1, T, R).
walk(s1, [0'x|T], [0'x|R]) :- walk(s2, T, R).
walk(s2, [0'1|T], [0'2|R]) :- walk(s2, T, R).
walk(S, [H|T], [H|R]) :- walk(S, T, R). % keep state and do nothing
person ony    schedule 08.01.2012
comment
я не получаю правильный результат, который я дал это: прогулка([[x,x,x,x,x],[x,1,x,x,x],[x,1,x,1,x] ,[х,х,х,1,х],[х,х,х,х,х]],L). но я получаю тот же список, что и дал - person user1118501; 09.01.2012
comment
walk("xxx11xx11x",L). Вы должны использовать его для каждой строки. Если вы собираетесь использовать атомы x и 1 вместо символов 0'x и 0'1. Замените их в соответствующих местах. Также вы можете немного узнать о Прологе - это очень интересный язык. Я желаю, чтобы люди встречали его при других обстоятельствах, а не домашнем задании... - person ony; 09.01.2012
comment
Я изучал Пролог, но в примечаниях учителя ничего не говорится об этих упражнениях. И я пытаюсь найти решение, чтобы быть готовым к экзаменам. когда я даю walk([0,1,0,0,1,1,1],L), я получаю ответ «нет». Я хочу, чтобы первый элемент предиката был списком, а второе место превратилось в 2 - person user1118501; 09.01.2012
comment
Он должен объединить L с тем же списком, который указан в первом аргументе walk/2. Если нет других ограничений на L, то он не должен создавать no. Какую систему Пролога вы используете? Я не думаю, что в этом упражнении есть что-то специфичное для Пролога, за исключением его реализации на языке Пролог. Я считаю, что используемый здесь подход называется хвостовой рекурсивной реализацией. Каждая цель walk/3 требует достижения другой цели walk/3, пока не будет достигнут конец списка. Обратите внимание, что в главах walk/3 вы найдете, с какими атомами происходит объединение (то есть 0'1 и 0'x вместо 1 и 0). - person ony; 10.01.2012
comment
Ах... Да, это что-то вроде конечного автомата с 3 состояниями и 7 переходами (4 круговых - последние два правила, 2 - прямые, 3-е и 4-е правило посередине, 3 завершения - второе правило). - person ony; 10.01.2012