I’ve been playing around quite a bit with the Collatz Conjecture after watching the latest Coding Train video on the subject. In an effort to keep my J muscles from atrophying, I decided to use the language to implement a Collatz sequence generator.

At its heart, the Collatz sequence is a conditional expression. If the current number is even, the next number in the sequence is the current number divided by two. If the current number is odd, the next number in the sequence is one plus the current number multiplied by three:

We can write each of these branches with some straight-forward J code. Our even case is simply the divide (`%`

) verb bonded (`&`

) to `2`

:

```
even =: %&2
```

And our odd case is a “monadic noun fork” of `1`

plus (`+`

) `3`

bonded (`&`

) to multiply (`*`

):

```
odd =: 1 + 3&*
```

We can tie together those two verbs and use agenda (`@.`

) to pick which one to call based on whether the argument is even:

```
next =: even`odd@.pick
```

Our `pick`

verb is testing for even numbers by checking if `1:`

equals (`=`

) `2`

bonded to the residue verb (`|`

).

```
pick =: 1:=2&|
```

We can test our `next`

verb by running it against numbers with known next values. After `3`

, we’d expect `10`

, and after `10`

, we’d expect `5`

:

```
next 3
10
next 10
5
```

Fantastic!

J has an amazing verb, power (`^:`

), that can be used to find the “limit” of a provided verb by continuously reapplying that verb to its result until a repeated result is encountered. If we pass power boxed infinity (`<_`

) as an argument, it’ll build up a list of all the intermediate results.

This is exactly what we want. To construct our Collatz sequence, we’ll find the limit of `next`

for a given input, like `12`

:

```
next^:(<_) 12
```

**But wait, there’s a problem!** A loop exists in the Collatz sequences between `4`

, `2`

, and `1`

. When we call `next`

on `1`

, we’ll receive `4`

. Calling `next`

on `4`

returns `2`

, and calling `next`

on `2`

returns `1`

. Our `next`

verb never converges to a single value.

To get over this hurdle, we’ll write one last verb, `collatz`

, that checks if the argument is `1`

before applying `next`

:

```
collatz =: next`]@.(1&=)
```

Armed with this new, converging `collatz`

verb, we can try finding our limit again:

```
collatz^:(<_) 12
12 6 3 10 5 16 8 4 2 1
```

Success! We’ve successfully implemented a Collatz sequence generator using the J programming langauge. Just for fun, let’s plot the sequence starting with `1000`

:

```
require 'plot'
plot collatz^:(<_) 1000
```

Posted on by:

## Discussion