class Collatz::HailstoneSequence
Contains the results of computing a hailstone sequence via hailstone_sequence(~).
Attributes
A terminal condition that reflects the final state of the hailstone sequencing, whether than be that it succeeded at determining the stopping time, the total stopping time, found a cycle, or got stuck on zero (or surpassed the max total).
A status value that has different meanings depending on what the terminal condition was. If the sequence completed either via reaching the stopping or total stopping time, or getting stuck on zero, then this value is the stopping/terminal time. If the sequence got stuck on a cycle, then this value is the cycle length. If the sequencing passes the maximum stopping time then this is the value that was provided as that maximum.
The set of values that comprise the hailstone sequence.
Public Class Methods
Initialise and compute a new Hailstone Sequence.
@raise FailedSaneParameterCheck
If p or a are 0.
@param Integer
initial_value The value to begin the hailstone sequence from.
@param Integer
p: Modulus used to devide n, iff n is equivalent to (0 mod p).
@param Integer
a: Factor by which to multiply n.
@param Integer
b: Value to add to the scaled value of n.
@param Integer
max_total_stopping_time: Maximum amount of times to iterate the function, if 1 is not reached.
@param Boolean
total_stopping_time: Whether or not to execute until the “total” stopping time (number of iterations to obtain 1) rather than the regular stopping time (number of iterations to reach a value less than the initial value).
@return HailstoneSequence
An initialised, and computed, hailstone sequence
# File lib/collatz/hailstone_sequence.rb, line 43 def initialize(initial_value, p, a, b, max_total_stopping_time, total_stopping_time) terminate = stopping_time_terminus(initial_value, total_stopping_time) if initial_value.zero? # 0 is always an immediate stop. @values = [0] @terminal_condition = SequenceState::ZERO_STOP @terminal_status = 0 elsif initial_value == 1 # 1 is always an immediate stop, with 0 stopping time. @values = [1] @terminal_condition = SequenceState::TOTAL_STOPPING_TIME @terminal_status = 0 else # Otherwise, hail! min_max_total_stopping_time = [max_total_stopping_time, 1].max pre_values = Array.new(min_max_total_stopping_time+1) pre_values[0] = initial_value for k in 1..min_max_total_stopping_time do next_value = Collatz.function(pre_values[k-1], p: p, a: a, b: b) # Check if the next_value hailstone is either the stopping time, total # stopping time, the same as the initial value, or stuck at zero. if terminate.call(next_value) pre_values[k] = next_value if next_value == 1 @terminal_condition = SequenceState::TOTAL_STOPPING_TIME else @terminal_condition = SequenceState::STOPPING_TIME end @terminal_status = k @values = pre_values.slice(0, k+1) return end if pre_values.include? next_value pre_values[k] = next_value cycle_init = 1 for j in 1..k do if pre_values[k-j] == next_value cycle_init = j break end end @terminal_condition = SequenceState::CYCLE_LENGTH @terminal_status = cycle_init @values = pre_values.slice(0, k+1) return end if next_value.zero? pre_values[k] = 0 @terminal_condition = SequenceState::ZERO_STOP @terminal_status = -k @values = pre_values.slice(0, k+1) return end pre_values[k] = next_value end @terminal_condition = SequenceState::MAX_STOP_OUT_OF_BOUNDS @terminal_status = min_max_total_stopping_time @values = pre_values end end