Почему этот рекурсивный предикат Prolog добавляет в списки некоторые "_1508" числа? - PullRequest
0 голосов
/ 24 апреля 2020

Моя задача - разбить заданный отсортированный список (LSorted) на несколько других, где первый будет содержать значения из LSorted , которые меньше первого простого числа (1 не считается простым) (из списка простых чисел) , второе будет содержать значения из LSorted, меньшие, чем второе простое число, но больше или равные первому простому, et c.

ans(L, Res):-
    max_list(L, X),             /*determine the max value X of L*/
    listPrimes(X, Primes),      /*generate a list of primes up to X and the prime greater than X*/
    msort(L, LSorted),          /*sort L*/
    ans_recur(LSorted, Primes, Res),!.

ans_recur([], _, [[]|[]]).

ans_recur([InH|Input], [PrimeH|Primes], [[InH|Res]|ResT]):-
    InH < PrimeH,
    ans_recur(Input, [PrimeH|Primes], [Res|ResT]).

ans_recur([InH|Input], [_|Primes], [_|ResT]):-
    ans_recur([InH|Input], Primes, ResT).

Когда я запускаю запрос: ans([1,2,3,4], L)., я получаю такой результат:

L = [_1508, [1|_1522], [2|_1534], [3, 4]], тогда как я ожидаю [[1], [2], [3,4]]. Программа «помещает» числа в «правильные» списки, но добавляет некоторые значения, такие как _1508. Насколько я понимаю, причина в том, что Пролог пытается присвоить какое-то значение Res в предикате ans_recur, но почему он это делает?
Tracing:

Call:ans([1, 1, 2, 2, 3, 4], _13636)
 Call:lists:max_list([1, 1, 2, 2, 3, 4], _14050)
 Exit:lists:max_list([1, 1, 2, 2, 3, 4], 4)
 Call:listPrimes(4, _14080)
 Exit:listPrimes(4, [1, 2, 3, 5])
 Call:sort([1, 1, 2, 2, 3, 4], _14224)
 Exit:sort([1, 1, 2, 2, 3, 4], [1, 2, 3, 4])
 Call:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], _13636)
 Call:1<1
 Fail:1<1
 Redo:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], _13636)
 Call:ans_recur([1, 2, 3, 4], [2, 3, 5], _14156)
 Call:1<2
 Exit:1<2
 Call:ans_recur([2, 3, 4], [2, 3, 5], [_14174|_14168])
 Call:2<2
 Fail:2<2
 Redo:ans_recur([2, 3, 4], [2, 3, 5], [_14174|_14168])
 Call:ans_recur([2, 3, 4], [3, 5], _14168)
 Call:2<3
 Exit:2<3
 Call:ans_recur([3, 4], [3, 5], [_14204|_14198])
 Call:3<3
 Fail:3<3
 Redo:ans_recur([3, 4], [3, 5], [_14204|_14198])
 Call:ans_recur([3, 4], [5], _14198)
 Call:3<5
 Exit:3<5
 Call:ans_recur([4], [5], [_14234|_14228])
 Call:4<5
 Exit:4<5
 Call:ans_recur([], [5], [_14252|_14228])
 Exit:ans_recur([], [5], [[]])
 Exit:ans_recur([4], [5], [[4]])
 Exit:ans_recur([3, 4], [5], [[3, 4]])
 Exit:ans_recur([3, 4], [3, 5], [_14204, [3, 4]])
 Exit:ans_recur([2, 3, 4], [3, 5], [[2|_14204], [3, 4]])
 Exit:ans_recur([2, 3, 4], [2, 3, 5], [_14174, [2|_14204], [3, 4]])
 Exit:ans_recur([1, 2, 3, 4], [2, 3, 5], [[1|_14174], [2|_14204], [3, 4]])
 Exit:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], [_14154, [1|_14174], [2|_14204], [3, 4]])
 Exit:ans([1, 1, 2, 2, 3, 4], [_14154, [1|_14174], [2|_14204], [3, 4]])
L = [_1282, [1|_1296], [2|_1308], [3, 4]]

Заранее спасибо.

1 Ответ

0 голосов
/ 25 апреля 2020
ans_recur([InH|Input], [PrimeH|Primes], [[InH|Res]|ResT]):-
    InH < PrimeH,
    ans_recur(Input, [PrimeH|Primes], [Res|ResT]).

ans_recur([InH|Input], [_|Primes], [_|ResT]):-
    ans_recur([InH|Input], Primes, ResT).

То, что вы пытаетесь express в этих пунктах, выглядит примерно так:

  • , если InH меньше следующего простого числа, оно должно быть частью текущей работы результат
  • в противном случае он должен быть частью более позднего результата выполнения

Но в последнем случае «текущий результат выполнения» завершен, в нем больше нет элементов. Так что его хвост, который так далеко открыт, должен быть закрыт. Вам необходимо соответствующим образом изменить заголовок последнего предложения:

ans_recur([InH|Input], [_|Primes], [[]|ResT]):-

Это теперь ведет себя так:

?- ans_recur([1,2,3,4,5,6,7,8,9,10], [2,3,5,7,11], Result).
Result = [[1], [2], [3, 4], [5, 6], [7, 8, 9, 10]] ;
Result = [[1], [2], [3, 4], [5], [6, 7, 8, 9|...]] ;
Result = [[1], [2], [3, 4], [], [5, 6, 7, 8|...]] ;
Result = [[1], [2], [3], [4, 5, 6], [7, 8, 9, 10]] .  % further incorrect answers

Проблема в том, что вы не express в противном случае "условие явно, и Пролог не будет неявно догадываться, что это было то, что вы имели в виду. Вы можете изменить последнее предложение на следующее:

ans_recur([InH|Input], [PrimeH|Primes], [[]|ResT]):-
    InH >= PrimeH,
    ans_recur([InH|Input], Primes, ResT).

И получите только ожидаемый ответ:

?- ans_recur([1,2,3,4,5,6,7,8,9,10], [2,3,5,7,11], Result).
Result = [[1], [2], [3, 4], [5, 6], [7, 8, 9, 10]] ;
false.

Как видите, я имел дело только с вашей реализацией ans_recur/3. В остальной части кода может быть больше ошибок. Мы не можем сказать, потому что код, который вы разместили, является неполным. В будущем, пожалуйста, размещайте только полные программы. Многие участники не будут пытаться завершить ваш вопрос для вас, и вы получите меньше ответов.

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