GNU Prolog - создание списка в цикле - PullRequest
1 голос
/ 25 октября 2010

Мне нужно построить новый список с помощью «цикла». По сути, я не могу использовать рекурсию явно, поэтому я использую append для просмотра списков списков.

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

У меня проблема в том, как мне создать совершенно новый список.

Итак, если бы у меня было

[[1,1,1],[2,6,2],[3,3,3]]

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

[[1,1,1],[2,10,2],[3,3,3]].

Сейчас моя главная проблема - просто создать каждую строку. Если я смогу создать каждую строку, я смогу создать список списков.

Итак, чтобы разбить это немного подробнее, давайте просто позаботимся о [1,1,1].

Я просматриваю каждый элемент, добавляя новый элемент в новый список. новый список теперь [1,1,1]

У меня есть это:

set(Row,Col,Bin,TheEntry,Bout) :- 
 append(ListLeft, [R|_], Bin),
  append(ListLeft2, [C|_], R),
   length(ListLeft, LenR),
   length(ListLeft2,LenC),
   CurrRow is LenR + 1,
   CurrCol is LenC + 1,
   getChar(C, Row, Col, CurrRow, CurrCol,TheEntry, NewC),
            appendhere?.

Мне нужно создать новый список с символом, возвращенным из NewC. Не уверен, как это сделать.

Есть какие-нибудь подсказки?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 27 октября 2010

Чтобы дать вам представление о том, как использовать append/3 для извлечения элемента из списка списков, рассмотрим следующий предикат под названием replace/2:

replace(In, Out) :-
    append(LL, [L|RL], In), 
    append(LE, [E|RE], L),
    replaceElement(E, NewE), !,
    append(LE, [NewE|RE], NewL),
    append(LL, [NewL|RL], Out).
replace(In, In).

Этот нерекурсивный предикат принимает, как положено In, список списков и возвратных дорожек, чтобы найти элемент E во внутреннем списке L, который можно заменить с помощью replaceElement/2; если это так, он заменяется сначала созданием внутреннего списка (NewL), а затем использует этот новый список при построении нового внешнего списка (Out), как результат.

Обратите внимание , что это просто служит для демонстрации того, как использовать append/3 для разбиения списка списков для извлечения отдельных элементов по мере необходимости с помощью обратного отслеживания, а не рекурсии, как требуется . Как только элемент E заменяется на NewE через replaceElement/3, он снова используется при построении списка с использованием append/3, как показано.

Также обратите внимание, что это предложение (которое предназначено для того, чтобы помочь вам, а не быть вашим окончательным ответом) также может заменить только один элемент во внутреннем списке, если он вообще есть. Если вы хотите выполнить несколько замен списка ввода за один вызов replace/2 или аналогичного , используя эту технику , то вам почти наверняка понадобится рекурсивное определение или возможность использовать глобальную базу данных с помощью assert. Я рад, что меня поправят, если кто-то другой сможет дать определение в качестве контрпример.

В этом примере предикат replace/2 вместе со, скажем, следующим фактом:

replaceElement(6, 10).

Выполнение следующего дает нам требуемое поведение:

1 ?- replace([[1,1,1],[2,6,2],[3,3,3]], Out).
Out = [[1, 1, 1], [2, 10, 2], [3, 3, 3]] ;
false.

Если вы не можете использовать cut (!), то его можно опустить, но учтите, что второе предложение replace(In, In) приведет к тому, что все вызовы replace/2 будут отменены хотя бы один раз, чтобы вернуть вам список ввода. , Если такое поведение нежелательно, пропуск второго пункта приведет к тому, что replace/2 сразу выйдет из строя, если не будет произведена замена.

0 голосов
/ 26 октября 2010

Если вы не можете использовать рекурсию и делать это с возвратом, вы должны сделать что-то вроде этого: Предположим, что Bin представляет собой список списков (каждый элемент представляет собой полную строку) ~ Разделить входной Bin на три части (список 'left''строки, строка и список оставшихся строк).Это можно сделать с помощью append / 3 с чем-то вроде append (Left, [Item | Rest], Rows). ~ Теперь получите длину «левых» строк. ~ Проверьте длину, используя оператор «is», чтобы проверить, есть ли в левом спискеСтрока - 1 предмет ~ Сделайте то же самое, но теперь с Предметом, то есть разделите его на три части (LeftColums, ColumItem и Rest). Теперь проверьте длину относительно нужного столбца. Теперь у вас есть пункт, который нужно изменить, и все, что вам нужно сделатьэто перестроение списка с использованием двух добавлений (одно для перестроения выбранной строки, а другое для перестройки списка вывода).

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

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