Реализация collatz-списка с использованием Prolog
Я пытаюсь создать функцию под названием collatz_list
в прологе. Эта функция принимает два аргумента, первый из которых является числом, а второй в списке. Этот список будет моим выводом этой функции. Итак, вот моя функция:
collatz_list(1,[1]).
collatz_list(N,[H|T]) :-
N > 1,
N mod 2 =:= 0,
collatz_list(N, [H|T]).
collatz_list(N,[H|T]) :-
N > 1,
N mod 2 =:= 1,
N is N*3 +1,
collatz_list(N,[H|T]).
Я борюсь с созданием списка вывода. Может ли кто-нибудь помочь мне в этом?
Благодарю.
2 ответа
Предполагая, что вы хотите написать collatz_list/2
предикат с параметрами (int, list)
, где list
последовательность Коллатца, начинающаяся с int
и в конечном итоге заканчивается 1
(мы надеемся, что это пока открытая проблема); вам просто нужно закодировать рекурсивное определение декларативным способом.
Вот моя попытка:
/* if N = 1, we just stop */
collatz_list(1, []).
/* case 1: N even
we place N / 2 in the head of the list
the tail is the collatz sequence starting from N / 2 */
collatz_list(N, [H|T]) :-
0 is N mod 2,
H is N / 2,
collatz_list(H, T), !.
/* case 2: N is odd
we place 3N + 1 in the head of the list
the tail is the collatz sequence starting from 3N + 1 */
collatz_list(N, [H|T]) :-
H is 3 * N + 1,
collatz_list(H, T).
Модифицированная версия, включает стартовый номер
Давайте проверим это:
full_list(N, [N|T]) :-
collatz_list(N, T).
collatz_list(1, []).
collatz_list(N, [H|T]) :-
0 is N mod 2,
H is N / 2,
collatz_list(H, T), !.
collatz_list(N, [H|T]) :-
H is 3 * N + 1,
collatz_list(H, T).
?- full_list(27, L).
L = [27, 82, 41, 124, 62, 31, 94, 47, 142|...].
Сначала мы определим простой вспомогательный предикат collatz_next/2
выполнить один шаг Коллатца:
collatz_next(X,Y) :-
X >= 1,
( X =:= 1 -> Y = 1
; X mod 2 =:= 0 -> Y is X // 2
; Y is 3*X + 1
).
Чтобы перейти к фиксированной точке, мы используем мета-предикаты fixedpoint/3
а также fixedpointlist/3
:
?- fixedpoint(collatz_next,11,X).
X = 1. % succeeds deterministically
?- fixedpointlist(collatz_next,11,Xs).
Xs = [11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]. % succeeds deterministically
Оба мета-предиката, использованные в приведенном выше запросе, основаны на монотонной управляющей конструкции if_/3
и предикат равенства (=)/3
и может быть определено следующим образом:
:- meta_predicate fixedpoint(2,?,?).
fixedpoint(P_2, X0,X) :-
call(P_2, X0,X1),
if_(X0=X1, X=X0, fixedpoint(P_2, X1,X)).
:- meta_predicate fixedpointlist(2,?,?).
fixedpointlist(P_2,X0,[X0|Xs]) :-
call(P_2, X0,X1),
if_(X0=X1, Xs=[], fixedpointlist(P_2,X1,Xs)).