Module: Collatz

Defined in:
lib/collatz.rb,
lib/collatz/version.rb,
lib/collatz/function.rb,
lib/collatz/constants.rb,
lib/collatz/utilities.rb,
lib/collatz/tree_graph.rb,
lib/collatz/hailstone_sequence.rb

Overview

rubocop:disable Style/Documentation

Defined Under Namespace

Modules: SaneParameterErrMsg, SequenceState Classes: FailedSaneParameterCheck, HailstoneSequence, TreeGraph, TreeGraphNode

Constant Summary collapse

VERSION =

The current semver version.

"1.0.0"
KNOWN_CYCLES =

The four known cycles for the standard parameterisation.

[
  [1, 4, 2], [-1, -2], [-5, -14, -7, -20, -10],
  [-17, -50, -25, -74, -37, -110, -55, -164, -82, -41, -122, -61, -182, -91, -272, -136, -68, -34]
].each(&:freeze).freeze
VERIFIED_MAXIMUM =

The current value up to which the standard parameterisation has been verified.

295147905179352825856
VERIFIED_MINIMUM =

The current value down to which the standard parameterisation has been verified.

-272 # TODO: Check the actual lowest bound.

Class Method Summary collapse

Class Method Details

.function(n, p: 2, a: 3, b: 1) ⇒ Object

Returns the output of a single application of a Collatz-esque function.

Parameters:

  • +Integer+

    n: The value on which to perform the Collatz-esque function.

  • +Integer+

    p: Modulus used to devide n, iff n is equivalent to (0 mod p).

  • +Integer+

    a: Factor by which to multiply n.

  • +Integer+

    b: Value to add to the scaled value of n.

Returns:

  • Integer The result of the function

Raises:

  • FailedSaneParameterCheck If p or a are 0.



49
50
51
52
# File 'lib/collatz/function.rb', line 49

def function(n, p: 2, a: 3, b: 1)
  assert_sane_parameterisation(p, a, b)
  (n%p).zero? ? (n/p) : ((a*n)+b)
end

.hailstone_sequence(initial_value, p: 2, a: 3, b: 1, max_total_stopping_time: 1000, total_stopping_time: true) ⇒ Object

rubocop:disable Layout/LineLength



151
152
153
154
155
156
157
# File 'lib/collatz/hailstone_sequence.rb', line 151

module_function def hailstone_sequence(initial_value, p: 2, a: 3, b: 1, max_total_stopping_time: 1000, total_stopping_time: true) # rubocop:disable Layout/LineLength
  # Prior to starting the hailstone, which has some magic case handling,
  # call the function to trigger any assert_sane_parameterisation flags.
  _throwaway = function(initial_value, p: p, a: a, b: b)
  # Return the hailstone sequence.
  HailstoneSequence.new(initial_value, p, a, b, max_total_stopping_time, total_stopping_time)
end

.reverse_function(n, p: 2, a: 3, b: 1) ⇒ Object

Returns the output of a single application of a Collatz-esque reverse function. If only one value is returned, it is the value that would be divided by p. If two values are returned, the first is the value that would be divided by p, and the second value is that which would undergo the multiply and add step, regardless of which is larger.

Parameters:

  • +Integer+

    n: The value on which to perform the reverse Collatz function.

  • +Integer+

    p: Modulus used to devide n, iff n is equivalent to (0 mod p).

  • +Integer+

    a: Factor by which to multiply n.

  • +Integer+

    b: Value to add to the scaled value of n.

Raises:

  • FailedSaneParameterCheck If p or a are 0.



70
71
72
73
74
75
76
77
# File 'lib/collatz/function.rb', line 70

def reverse_function(n, p: 2, a: 3, b: 1)
  assert_sane_parameterisation(p, a, b)
  if ((n-b)%a).zero? && ((n-b)%(p*a)).nonzero?
    [p*n, (n-b)/a]
  else
    [p*n]
  end
end

.stopping_time(initial_value, p: 2, a: 3, b: 1, max_stopping_time: 1000, total_stopping_time: false) ⇒ Object

rubocop:disable Layout/LineLength



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/collatz/hailstone_sequence.rb', line 188

module_function def stopping_time(initial_value, p: 2, a: 3, b: 1, max_stopping_time: 1000, total_stopping_time: false) # rubocop:disable Layout/LineLength
  # Although the "max_~_time" for hailstones is named for "total stopping" time
  # and the "max_~_time" for this "stopping time" function is _not_ "total",
  # they are handled the same way, as the default for "total_stopping_time"
  # for hailstones is true, but for this, is false. Thus the naming difference.
  # rubocop:disable Layout/HashAlignment
  hail = hailstone_sequence(initial_value, p: p, a: a, b: b,
                            max_total_stopping_time: max_stopping_time,
                            total_stopping_time: total_stopping_time)
  # rubocop:enable Layout/HashAlignment
  # For total/regular/zero stopping time, the value is already the same as
  # that present, for cycles we report infinity instead of the cycle length,
  # and for max stop out of bounds, we report None instead of the max stop cap
  { SequenceState::TOTAL_STOPPING_TIME => hail.terminal_status,
    SequenceState::STOPPING_TIME => hail.terminal_status,
    SequenceState::CYCLE_LENGTH => Float::INFINITY,
    SequenceState::ZERO_STOP => hail.terminal_status,
    SequenceState::MAX_STOP_OUT_OF_BOUNDS => nil
  }.fetch(hail.terminal_condition, nil)
end

.tree_graph(initial_value, max_orbit_distance, p: 2, a: 3, b: 1) ⇒ Object

Returns a directed tree graph of the reverse function values up to a maximum nesting of max_orbit_distance, with the initial_value as the root.

function. There is no natural termination to populating the tree graph, equivalent to the termination of hailstone sequences or stopping time attempts, so this is not an optional argument like max_stopping_time / max_total_stopping_time, as it is the intended target of orbits to obtain, rather than a limit to avoid uncapped computation.

Parameters:

  • +Integer+

    initial_value: The root value of the directed tree graph.

  • +Integer+

    max_orbit_distance: Maximum amount of times to iterate the reverse

  • +Integer+

    p: Modulus used to devide n, iff n is equivalent to (0 mod p).

  • +Integer+

    a: Factor by which to multiply n.

  • +Integer+

    b: Value to add to the scaled value of n.

Returns:

  • TreeGraph The branches of the tree graph as determined by the reverse function.

Raises:

  • FailedSaneParameterCheck If p or a are 0.



177
178
179
180
181
182
# File 'lib/collatz/tree_graph.rb', line 177

module_function def tree_graph(initial_value, max_orbit_distance, p: 2, a: 3, b: 1)
  # Prior to starting the tree graph, which has some magic case handling, call
  # the reverse_function to trigger any assert_sane_parameterisation flags.
  _throwaway = reverse_function(initial_value, p: p, a: a, b: b)
  TreeGraph.new(initial_value, max_orbit_distance, p, a, b)
end