Skip to content

Instantly share code, notes, and snippets.

@ihercowitz
Created February 23, 2012 00:35
Show Gist options
  • Save ihercowitz/1888724 to your computer and use it in GitHub Desktop.
Save ihercowitz/1888724 to your computer and use it in GitHub Desktop.
The 3n + 1 Problem
/*
* The 3n + 1 Problem
*Consider the following algorithm to generate a sequence of numbers. Start with an
*integer n. If n is even, divide by 2. If n is odd, multiply by 3 and add 1. Repeat this
*process with the new value of n, terminating when n = 1. For example, the following
*sequence of numbers will be generated for n = 22:
*22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
*It is conjectured (but not yet proven) that this algorithm will terminate at n = 1 for
*every integer n. Still, the conjecture holds for all integers up to at least 1, 000, 000.
*For an input n, the cycle-length of n is the number of numbers generated up to and
*including the 1. In the example above, the cycle length of 22 is 16. Given any two
*numbers i and j, you are to determine the maximum cycle length over all numbers
*between i and j, including both endpoints.
*
*Input
*The input will consist of a series of pairs of integers i and j, one pair of integers per
*line. All integers will be less than 1,000,000 and greater than 0.
*
*Output
*For each pair of input integers i and j, output i, j in the same order in which they
*appeared in the input and then the maximum cycle length for integers between and
*including i and j. These three numbers should be separated by one space, with all three
*numbers on one line and with one line of output for each line of input.
*
* Sample Input Sample Output
* 1 10 1 10 20
* 100 200 100 200 125
* 201 210 201 210 89
* 900 1000 900 1000 174
*/
function solve(number, step) {
if (number === 1) return step;
var tmp;
if (number % 2 === 0) {
tmp = number /2;
} else {
tmp = (number * 3) + 1;
}
return solve(tmp, ++step);
}
function maximum_cycle_in(start, end) {
var max_cycle = 0;
for (var i=start; i <= end; i++) {
var tmp = solve(i, 1);
if (tmp > max_cycle)
max_cycle = tmp;
}
return max_cycle;
}
var start = 1
var end = 1000000
print(start+" "+end+" "+maximum_cycle_in(start, end));
@berserker1996
Copy link

berserker1996 commented Jun 26, 2020

Nice solution!! But, can You please explain me your code?

@MarkMoretto
Copy link

Not OP, but I'll try my best to help.

/**
 * Main solver function.
 * This uses recursion to count the number of steps required for solving the following algorithm:
 * 
 * `If n is even, divide by 2. If n is odd, multiply by 3 and add 1.`
 * 
 * @param (number) number The current integer for evaluation
 * @param (number) step An increment counter.  The '++' prefix in the return function increments the value before assigning it.
*/
function solve(number, step) {
    // Return step, which will be at it's highest level if number === 1.
    // This also terminates the function.
    if (number === 1) return step; 

    // Temporary variable for holding values of the original number
    var tmp;

    // First part of the algorithm: `If n is even, divide by 2.`
    if (number % 2 === 0) {
       tmp = number /2;

    // Second part of the algorithm: `If n is odd, multiply by 3 and add 1.`
    } else {
       tmp = (number * 3) + 1;
    }

    // Call the function again with the updated number value 
    // and increment step before doing so.
    return solve(tmp, ++step);
}

/**
 * Driver function.
 * This function runs the solve() function and evaluates each result against a local maximum number.
 * The loop domain is from start to end, inclusive.
 * 
 * @param (number) start The smaller number in a two-number set.
 * @param (number) end The larger number in a two-number set.
*/
function maximum_cycle_in(start, end) {
    // Variable to hold the latest maximum cycle from the solve() function
    // if that result is greater than the current maximum value.
    var max_cycle = 0;

    // Standard looping procedure which includes the start and end variables.
    for (var i=start; i <= end; i++) {
        // Variable to hold cycle (step) count of each number.
        var tmp = solve(i, 1);

        // Evaluation of whether the latest cycle (step) count is greater than
        // the current maximum count.  If so, update the local variable.
        if (tmp > max_cycle)
            max_cycle = tmp;
    }
    // Outout the max cycle (step) count once the for-loop concludes
    return max_cycle;
}

// Start and end variables
var start = 1
var end = 1000000
print(start+" "+end+" "+maximum_cycle_in(start, end));

 // Alt method
//  var start = 1
//  var end = 1000000
//  let og_start = start; // My addition. Stores original start value for output.
//  let og_end = end; // My addition. Stores original end value for output.
//  hotswap(start, end); // My addition. See below.
//  print(og_start+" "+og_end+" "+maximum_cycle_in(start, end));


/**
 * Function to set variables in proper order if entered incorrectly.
 * Using start and end as parameters will update those values in-place.
 * 
 * @param (number) low Lower valued variable of two variables used in this solution.
 * @param (number) high Higher valued variable of two variables used in this solution.
*/
hotswap = function(low, high) {
    // If `low` is actually a larger number than `high`
    if (low > high) {
        // Set `low` to a temporary variable
        let tmp_low = low;
        // Set `low` to the `high` value.
        low = high;
        // Set `high` to the `low` value.
        high = tmp_low;        
    }

    // Set our `start` and `end` variables to their new values.
    // Note: If low is actually the lower value, having the variables
    // update here is still okay.
    start = low;
    end = high;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment