Reputation: 29
I have a school prompt to create a function that finds out which integer, in the range that the user enters, produces the longest chain. The "chain" consists of:
E.g. if you start with 3, the sequence will be 3-10-5-16-8-4-2-1. The function will print out the number that produces the longest chain and the actual integers in that chain (length of the chain).
This is what I have so far. I can't figure it out.
function chain2()
var startNumber = prompt("Enter starting number of range", "4");
var endNumber = prompt ("Enter ending number of range", "9")
var separator="-";
while (currentNumber>1){
if (currentNumber%2==1){
currentNumber=currentNumber*3+1;
chain+=separator+currentNumber;
}
else if (currentNumber%2==0){
currentNumber=currentNumber/2;
chain+=separator+currentNumber;
}
}
return chain;
}
document.write(chain());
Upvotes: 1
Views: 186
Reputation: 135425
As a homework assignment, I should nudge you rather than just give you the answer. If there's a single point of advice I would give you, it's that you should separate your work into easy-to-understand functions first. Writing one big function that does everything is a recipe for a disaster. The function you have right now
Breaking this into separate parts will make it much easier to reason about your code. I start from the top-level function that I wish would work, and then work my way down from there.
function FindMaxCollatzInRange(x,y) {
// max = ...
// ...
return max;
}
If you find yourself needing other functions, that's perfectly normal. Write them as you need them.
Your basic algorithm should do something like this:
min
and max
(inclusive) ...So here's how I would do this. This is way beyond the scope of a JavaScript homework assignment, but I found it fun to work on.
I'm OK posting this code because I know it can't directly be copy/pasted as an answer for your assignment. My hope is that there will be some things here that will encourage you to explore some of the techniques used.
// compute the collatz chain for a given number, x
const collatz = Y (f=> y=> x=> {
if (x === 1) return append (x) (y);
if (isEven(x)) return f (append (x) (y)) (x/2);
else return f (append (x) (y)) (x*3 + 1);
}) ([]);
// compute the length of a collatz chain
const collatzLen = comp (len) (collatz);
// create a range from minimum, n, to maximum, m
const range = Y (f=> r=> n=> m=> {
if (n > m) return r;
else return f (append (n) (r)) (n+1) (m);
}) ([]);
// compute the maximum collatz chain length for a given range
const maxCollatz = (n,m) =>
comp (foldl (([x,xlen])=> ([y,ylen])=> ylen > xlen ? [y,ylen] : [x,xlen]) ([0,1]))
(map (n=> [n,collatzLen (n)]))
(range (n) (m));
Here's some sample output of the functions so you can see what's going on
collatz (3)
//=> [ 3, 10, 5, 16, 8, 4, 2, 1 ]
collatzLen (3)
//=> 8
range (3) (10)
//=> [ 3, 4, 5, 6, 7, 8, 9, 10 ]
maxCollatz (3,10)
//=> [ 9, 20 ]
The way to read that last output [ 9, 20 ]
is, "The number 9 has the longest Collatz chain length, with a length of 20"
Simply put, each function is responsible for doing exactly one thing. The function that answers your problem is the maxCollatz
function, which computes a list of chain lengths using collatzLen
for each element in the range
. Lastly, the list is reduced to determine which number has the longest chain.
Here are the generic dependencies
const comp = f=> g=> x=> f (g (x));
const mod = x=> y=> y % x;
const eq = x=> y=> y === x;
const isEven = comp (eq (0)) (mod (2));
const prop = x=> y=> y [x];
const len = prop ('length');
const concat = x=> xs=> xs .concat (x);
const append = x=> concat ([x]);
const foldl = f=> y=> xs=> xs .reduce ((x,y)=> f (x) (y), y);
const map = f=> xs=> xs .map (x=> f(x));
// U-combinator
const U = f=> f (f);
// Y-combinator
const Y = U (h=> f=> f (x=> h (h) (f) (x)));
Additional reading:
Upvotes: 1