use strict; use warnings; use feature 'say'; use MCE::Flow; sub collatz_choroba { my (\$n) = @_; my @seq = \$n; push @seq, ( \$seq[-1] >> 1, 3 * \$seq[-1] + 1 )[ \$seq[-1] % 2 ] while \$seq[-1] != 1; return scalar @seq; } sub collatz_1nickt { my (\$n) = @_; my @seq = \$n; push @seq, \$n = \$n % 2 ? 3 * \$n + 1 : \$n >> 1 while \$n != 1; return scalar @seq; } sub collatz_compress { my (\$n) = @_; my @seq = \$n; # Notation and compressed dynamics (2:15 into the video) # https://www.youtube.com/watch?v=t1I9uHF9X5Y # consider the map # C(x) = \$n % 2 ? 3 * \$n + 1 : \$n / 2 # compress the map to the dynamically equivalent # T(x) = \$n % 2 ? (3 * \$n + 1) / 2 : \$n / 2 # compress loop iteration when odd sequence push @seq, \$n % 2 ? ( \$n = 3 * \$n + 1, \$n = \$n >> 1 ) : ( \$n = \$n >> 1 ) while \$n != 1; return scalar @seq; } sub collatz_count { my (\$n) = @_; my \$steps = 1; # count using the T(x) notation \$n % 2 ? ( \$steps += 2, \$n = (3 * \$n + 1) >> 1 ) : ( \$steps += 1, \$n = \$n >> 1 ) while \$n != 1; return \$steps; } #*collatz = \&collatz_choroba; # choose collatz here #*collatz = \&collatz_1nickt; #*collatz = \&collatz_compress; *collatz = \&collatz_count; my @sizes; MCE::Flow->init( max_workers => MCE::Util::get_ncpu(), gather => \@sizes, bounds_only => 1, ); mce_flow_s sub { my (\$start, \$end) = @{ \$_[1] }; my @ret = map { [ \$_, collatz(\$_) ] } \$start .. \$end; MCE->gather( ( sort { \$b->[1] <=> \$a->[1] } @ret )[ 0..19 ] ); }, 1, 1e6; MCE::Flow->finish; say "@\$_" for ( sort { \$b->[1] <=> \$a->[1] } @sizes )[ 0..19 ];