1
$\begingroup$

I know this is pretty fundamental, but I'm trying to learn Mathematica on my own and this is stumping me.

I know 5 is wondrous and it takes 5 steps to reach one, but I can't figure out the input to evaluate at the last output value. Here's what I have:

n = 5;
For[n = 5, n <= 20, n++,
 If[EvenQ[n], Print[n/2], Print[3 n + 1]]]

I know that n++ will just keep evaluating until n=20, but this is the only thing that gave me an output.

$\endgroup$
2
  • $\begingroup$ Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) take the introductory Tour now, 2) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 3) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 4) give help too, by answering questions in your areas of expertise. $\endgroup$
    – bbgodfrey
    Commented Sep 4, 2015 at 0:03
  • 1
    $\begingroup$ You will find a lot about your project by searching this site on "collatz" -- the sequences you are generating are often referred to as Collatz sequences. $\endgroup$
    – m_goldberg
    Commented Sep 4, 2015 at 0:16

2 Answers 2

3
$\begingroup$
NestWhileList[If[EvenQ[#], #/2, 3 # + 1] &, 5, # != 1 &]

(* {5, 16, 8, 4, 2, 1} *)
$\endgroup$
3
$\begingroup$

Taking advantage of the 4, 2, 1 cycle. (Assuming the conjecture is correct.)

step = If[EvenQ@#, #/2, 3 # + 1] &;
step3 = Rest@NestList[step, Last@#, 3] &;
Flatten@FixedPointList[step3, {5}] ~Drop~ -3
(* {5, 16, 8, 4, 2, 1} *)

This is a needlessly complicated solution intended to highlight some of Mathematica's functionality and syntax.


For Reals: some notes about using a loop (which you shouldn't use in Mathematica: see belisarius's correct solution) to solve this problem.

First: n is the index of your sequence of numbers. They just tell you where you are in the sequence. You need to have a variable that represents the value, and you update that variable at every step. So:

val = 5;
For[n = 1, n <= 20, n++,
  If[EvenQ[val], val = val/2, val = 3*val + 1]
]

will construct the sequence. Unfortunately, it doesn't Print out the values, and it doesn't keep the values either. For this, you can do a number of things. For instance,

val = 5;
For[n = 1, n <= 8, n++
  , If[EvenQ[val], val = val/2, val = 3*val + 1]; 
  Print[val]
 ]

This will print the numbers to the screen. Now, we can do better. Perhaps we want to write the numbers to a list?

vals = {5};
For[n = 1, n <= 8, n++, 
   If[EvenQ[Last@vals], AppendTo[vals, Last@vals/2], AppendTo[vals, 3*Last@vals + 1]]]
vals
(* {5, 16, 8, 4, 2, 1, 4, 2, 1} *)

This is standard sort of programming stuff: building a list by appending values to the list (albeit dynamically, which is not usually where people start when they first start learning programming). However, once again, this is decidedly not the best way to do things in Mathematica.

We can use recursion and memoization:

step[n_] := step[n] = If[EvenQ@step[n - 1], step[n - 1]/2, 3 step[n - 1] + 1]
step[1] = 5;
Array[step, 9]
(* {5, 16, 8, 4, 2, 1, 4, 2, 1} *)

Look up the function Array in the documentation.

Alternatively, we can define a function which takes an element of the sequence and spits out the next one:

f[x_Integer] := If[EvenQ[x], x/2, 3x + 1]

Then, we can Nest this function (Nest essentially performs function composition f[f[f[5]]]):

NestList[f, 5, 8]
(* {5, 16, 8, 4, 2, 1, 4, 2, 1} *)

Alternatively, we can define this as a pure function, which is how belisarius did it, who is also taking advantage of the fact that we "know" (read: suspect) that this sequence always eventually reaches 1 for any initial input. In that case, he used NestWhileList which will go until some condition is met. (FixedPointList is a variant of this that will keep calculating until the result doesn't change anymore.)

$\endgroup$
5
  • $\begingroup$ Ha! The OP is still struggling with For loops :D +1 $\endgroup$ Commented Sep 4, 2015 at 0:14
  • $\begingroup$ @belisarius. I considered posting a working For version. Perhaps I should, since perhaps this solution is too snarky. $\endgroup$
    – march
    Commented Sep 4, 2015 at 0:15
  • 1
    $\begingroup$ In any case, don't post bad code without a BIG warning :) $\endgroup$ Commented Sep 4, 2015 at 0:16
  • $\begingroup$ @belisarius. You're right. Should be a comment anyway. $\endgroup$
    – march
    Commented Sep 4, 2015 at 0:17
  • $\begingroup$ @belisarius. There! I think I salvaged it :) $\endgroup$
    – march
    Commented Sep 4, 2015 at 0:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.