2013-05-08 2 views
2

sublist(L1,L2,I,J)Пролог - Извлечение подсписка

У меня есть список, L1 передается в, наряду с 2-мя показателями I и J, и я хочу L2 быть включено Подсписок, содержащий элементы между I и J.
Если J находится за пределами границ, я бы хотел, чтобы он пошел от I до конца списка. Аналогично, если I меньше 0, я бы хотел, чтобы он начинал с начала списка до J. I>J возвращает пустой список.

То, что я до сих пор:

sublist(_,[],I,J):- 
    I > J. 
sublist(Xs,Ys,I,Length):- 
    length(Xs,Length), 
    N > L, 
    sublist(Xs,Ys,I,J). 
sublist([X|_],[X],1,1). 
sublist([X|Xs],[X|Ys],1,J):- 
    J > 1, 
    J1 is J - 1, 
    sublist(Xs,Ys,1,J1). 
sublist([_|Xs],Ys,I,J):- 
    I > 1, 
    I1 is I - 1, 
    J1 is J - 1, 
    sublist(Xs,Ys,I1,J1). 
+0

А что не так с *, что у вас есть до сих пор *? Люди здесь не должны давать вам ответы, а скорее объяснения. – Rubens

+0

@Rubens ой, извините, забыли включить. Второй предикат не работает. В настоящее время он нуждается в 'I' и' J', чтобы быть в списке. –

ответ

4

Вы можете решить эту проблему путем переосмысления стратегии.

Во-первых, какие у вас базовые чехлы?

  • Вы в конечном итоге с пустым списком в качестве входных данных
  • Вы имеете I > J

В обоих этих случаях, вы бы добавить пустой список в то, что у вас есть до сих пор, и называть это хорошо ,

Далее, каковы ваши крайние случаи, о которых вы беспокоитесь?

  • J находится за пределами конца списка
  • I есть до начала списка

В первом случае, вы просто пройти до конца списка ввода. Во втором вы начинаете в начале списка ввода.

Хорошо, давайте попробуем и реализуем это, я собираюсь использовать аккумулятор и обернуть его вызовом.

sublist(L1, L2, I, J):- 
    sublist(L1, Temp, I, J, []), 
    !, 
    reverse(Temp, L2). 

Мы входной список L1, переменная унифицировать как наш список L2 вывода, а индексы, I и J. Я использую cut, так что мне не нужно беспокоиться о возврате назад для других решений и отменить его, потому что накопленный список построен в обратном порядке.

Давайте работать на базовых корпусах.

Пустой список в качестве входных данных, просто объедините аккумулятор с нашим выходным списком. На данный момент нас не интересуют индексы. Как оказалось, это также удовлетворяет краевому случаю, где J находится за пределами списка. Поскольку в этот момент мы будем накапливать весь входной список в накопителе и все еще иметь значение J, оставшееся выше.

sublist([], L2, _I, _J, L2). 

I> J, снова, объедините аккумулятор с нашим выходным списком. Мы больше не заботимся о списке входных данных.

sublist(_L1, L2, I, J, L2):- 
    I > J. 

Теперь кромки.

J за пределами конца списка было решено выше.

I до начала списка, просто установите этот индекс в 0 и перейдите к нему.

sublist(L1, L2, I, J, L2):- 
    I < 0, 
    sublist(L1, L2, 0, J, L2). 

Теперь нам просто нужно реализовать фактическую логику. Мы хотим только скопировать, начиная с правильного I. Итак, давайте уменьшим I и выбросим части входного списка, пока мы не доберемся туда, где хотим. Для того, чтобы конец индекса совпал, нам нужно также уменьшить J. Таким образом, мы сохраняем одинаковое расстояние между индексами.

sublist([_L|Ls], L2, I, J, Acc):- 
    I > 0, 
    sublist(Ls, L2, I-1, J-1, Acc). 

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

sublist([L|Ls], L2, I, J, Acc):- 
    sublist(Ls, L2, I, J-1, [L|Acc]). 

Собираем все вместе мы в конечном итоге с:

sublist(L1, L2, I, J):- 
    sublist(L1, Temp, I, J, []), 
    !, 
    reverse(Temp, L2). 
sublist([], L2, _I, _J, L2). 
sublist(_L1, L2, I, J, L2):- 
    I > J. 
sublist(L1, L2, I, J, L2):- 
    I < 0, 
    sublist(L1, L2, 0, J, L2). 
sublist([_L|Ls], L2, I, J, Acc):- 
    I > 0, 
    sublist(Ls, L2, I-1, J-1, Acc). 
sublist([L|Ls], L2, I, J, Acc):- 
    sublist(Ls, L2, I, J-1, [L|Acc]). 

И мы можем проверить это следующим образом:

?- sublist([1,2,3,4,5], S, 0,3). 
S = [1, 2, 3, 4]. 

?- sublist([1,2,3,4,5], S, -1,30). 
S = [1, 2, 3, 4, 5]. 

?- sublist([1,2,3,4,5], S, 3,1). 
S = []. 

?- sublist([1,2,3,4,5], S, 3,3). 
S = [4]. 

?- sublist([1,2,3,4,5], S, 3,4). 
S = [4, 5]. 
+1

+1 Отличный, подробный ответ. Немного обеспокоен отсутствием 'is/2', но, видимо,'/2' работает с арифметическими выражениями. –

+0

Создание результата сверху вниз - это более Prologish, его можно утверждать и могут/должны быть такими же интуитивными. :) В конце концов, в конце концов тоже не нужно реверсировать. –

0

Я думаю, что у вас есть только некоторые опечатку во втором пункте. Попробуйте эту (непроверенную) коррекцию, необходимую для соответствия вашим требованиям

Если J вне границ, я бы хотел, чтобы он переходил от I до конца списка.

sublist(Xs,Ys,I,J):- 
    length(Xs,Length), 
    J > Length, 
    sublist(Xs,Ys,I,Length). 
Смежные вопросы