Search code examples
perlcollatz

How can I write a Collatz sequence with List::Gen?


I love the functional-programming paradigm that List::Gen brings to Perl. Writing a Collatz sequence with it should be doable, albeit a little challenging since the length of the list is not known a priori.

I'm missing the final 1 at the end of the sequence with the following code:

use List::Gen '*';
iterate{ $_%2 ? 3*$_+1 : $_/2 }->from( 23 )->while( '!=1' )->say;

which prints:

23 70 35 106 53 160 80 40 20 10 5 16 8 4 2

What I essentially need with this approach is a do-while. The documentation makes mention of a while_, which is a 'look-ahead' version of while, but the interpreter cannot find such a method.


Solution

  • Here is a workaround that tests the element for defined-ness to decide when to end the list. It requires modifying the iterator definition to populate an undef element immediately after it encounters a 1 in the chain:

    iterate{ $_ == 1 ? undef : $_%2  ? 3*$_+1 : $_/2 }->from( 23 )->while( 'defined' )->say;
    

    which prints

    23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1