95 lines
2.5 KiB
Plaintext
95 lines
2.5 KiB
Plaintext
:- object(hailstone).
|
|
|
|
:- public(generate_sequence/2).
|
|
:- mode(generate_sequence(+natural, -list(natural)), zero_or_one).
|
|
:- info(generate_sequence/2, [
|
|
comment is 'Generates the Hailstone sequence that starts with its first argument. Fails if the argument is not a natural number.',
|
|
argnames is ['Start', 'Sequence']
|
|
]).
|
|
|
|
:- public(write_sequence/1).
|
|
:- mode(write_sequence(+natural), zero_or_one).
|
|
:- info(write_sequence/1, [
|
|
comment is 'Writes to the standard output the Hailstone sequence that starts with its argument. Fails if the argument is not a natural number.',
|
|
argnames is ['Start']
|
|
]).
|
|
|
|
:- public(sequence_length/2).
|
|
:- mode(sequence_length(+natural, -natural), zero_or_one).
|
|
:- info(sequence_length/2, [
|
|
comment is 'Calculates the length of the Hailstone sequence that starts with its first argument. Fails if the argument is not a natural number.',
|
|
argnames is ['Start', 'Length']
|
|
]).
|
|
|
|
:- public(longest_sequence/4).
|
|
:- mode(longest_sequence(+natural, +natural, -natural, -natural), zero_or_one).
|
|
:- info(longest_sequence/4, [
|
|
comment is 'Calculates the longest Hailstone sequence in the interval [Start, End]. Fails if the interval is not valid.',
|
|
argnames is ['Start', 'End', 'N', 'Length']
|
|
]).
|
|
|
|
generate_sequence(Start, Sequence) :-
|
|
integer(Start),
|
|
Start >= 1,
|
|
sequence(Start, Sequence).
|
|
|
|
sequence(1, [1]) :-
|
|
!.
|
|
sequence(N, [N| Sequence]) :-
|
|
( N mod 2 =:= 0 ->
|
|
M is N // 2
|
|
; M is (3 * N) + 1
|
|
),
|
|
sequence(M, Sequence).
|
|
|
|
write_sequence(Start) :-
|
|
integer(Start),
|
|
Start >= 1,
|
|
sequence(Start).
|
|
|
|
sequence(1) :-
|
|
!,
|
|
write(1), nl.
|
|
sequence(N) :-
|
|
write(N), write(' '),
|
|
( N mod 2 =:= 0 ->
|
|
M is N // 2
|
|
; M is (3 * N) + 1
|
|
),
|
|
sequence(M).
|
|
|
|
sequence_length(Start, Length) :-
|
|
integer(Start),
|
|
Start >= 1,
|
|
sequence_length(Start, 1, Length).
|
|
|
|
sequence_length(1, Length, Length) :-
|
|
!.
|
|
sequence_length(N, Length0, Length) :-
|
|
Length1 is Length0 + 1,
|
|
( N mod 2 =:= 0 ->
|
|
M is N // 2
|
|
; M is (3 * N) + 1
|
|
),
|
|
sequence_length(M, Length1, Length).
|
|
|
|
longest_sequence(Start, End, N, Length) :-
|
|
integer(Start),
|
|
integer(End),
|
|
Start >= 1,
|
|
Start =< End,
|
|
longest_sequence(Start, End, 1, N, 1, Length).
|
|
|
|
longest_sequence(Current, End, N, N, Length, Length) :-
|
|
Current > End,
|
|
!.
|
|
longest_sequence(Current, End, N0, N, Length0, Length) :-
|
|
sequence_length(Current, 1, CurrentLength),
|
|
Next is Current + 1,
|
|
( CurrentLength > Length0 ->
|
|
longest_sequence(Next, End, Current, N, CurrentLength, Length)
|
|
; longest_sequence(Next, End, N0, N, Length0, Length)
|
|
).
|
|
|
|
:- end_object.
|