Perl
Saya memutuskan untuk menjadi sedikit anti persaingan, dan menunjukkan bagaimana Anda biasanya mengkodekan masalah seperti itu di Perl.
Ada juga entri golf kode karakter 46 (total) di akhir.
Tiga contoh pertama ini semuanya dimulai dengan tajuk ini.
#! /usr/bin/env perl
use Modern::Perl;
# which is the same as these three lines:
# use 5.10.0;
# use strict;
# use warnings;
while( <> ){
chomp;
last unless $_;
Collatz( $_ );
}
Versi rekursif sederhana
use Sub::Call::Recur;
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
die 'Integer values only' unless $n == int $n;
say $n;
given( $n ){
when( 1 ){}
when( $_ % 2 != 0 ){ # odd
recur( 3 * $n + 1 );
}
default{ # even
recur( $n / 2 );
}
}
}
Versi iteratif sederhana
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
die 'Integer values only' unless $n == int $n;
say $n;
while( $n > 1 ){
if( $n % 2 ){ # odd
$n = 3 * $n + 1;
} else { #even
$n = $n / 2;
}
say $n;
}
}
Versi iteratif yang dioptimalkan
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
die 'Integer values only' unless $n == int $n;
#
state @next;
$next[1] //= 0; # sets $next[1] to 0 if it is undefined
#
# fill out @next until we get to a value we've already worked on
until( defined $next[$n] ){
say $n;
#
if( $n % 2 ){ # odd
$next[$n] = 3 * $n + 1;
} else { # even
$next[$n] = $n / 2;
}
#
$n = $next[$n];
}
say $n;
# finish running until we get to 1
say $n while $n = $next[$n];
}
Sekarang saya akan menunjukkan bagaimana Anda akan melakukan contoh terakhir dengan versi Perl sebelum v5.10.0
#! /usr/bin/env perl
use strict;
use warnings;
while( <> ){
chomp;
last unless $_;
Collatz( $_ );
}
{
my @next = (0,0); # essentially the same as a state variable
sub Collatz{
my( $n ) = @_;
$n += 0; # ensure that it is numeric
die 'invalid value' unless $n > 0;
# fill out @next until we get to a value we've already worked on
until( $n == 1 or defined $next[$n] ){
print $n, "\n";
if( $n % 2 ){ # odd
$next[$n] = 3 * $n + 1;
} else { # even
$next[$n] = $n / 2;
}
$n = $next[$n];
}
print $n, "\n";
# finish running until we get to 1
print $n, "\n" while $n = $next[$n];
}
}
Tolok ukur
Pertama, IO akan selalu menjadi bagian yang lambat. Jadi, jika Anda benar-benar membandingkannya apa adanya, Anda harus mendapatkan kecepatan yang sama dari masing-masing.
Untuk mengujinya, saya membuka pegangan file ke /dev/null
( $null
), dan mengedit setiap file say $n
untuk dibaca say {$null} $n
. Ini untuk mengurangi ketergantungan pada IO.
#! /usr/bin/env perl
use Modern::Perl;
use autodie;
open our $null, '>', '/dev/null';
use Benchmark qw':all';
cmpthese( -10,
{
Recursive => sub{ Collatz_r( 31 ) },
Iterative => sub{ Collatz_i( 31 ) },
Optimized => sub{ Collatz_o( 31 ) },
});
sub Collatz_r{
...
say {$null} $n;
...
}
sub Collatz_i{
...
say {$null} $n;
...
}
sub Collatz_o{
...
say {$null} $n;
...
}
Setelah menjalankannya 10 kali, berikut adalah contoh keluaran yang representatif:
Nilai Recursive Iterative Optimized
Rekursif 1715 / s - -27% -46%
Iteratif 2336 / s 36% - -27%
Dioptimalkan 3187 / s 86% 36% -
Akhirnya, entri kode-golf nyata:
perl -nlE'say;say$_=$_%2?3*$_+1:$_/2while$_>1'
46 total karakter
Jika Anda tidak perlu mencetak nilai awal, Anda dapat menghapus 5 karakter lagi.
perl -nE'say$_=$_%2?3*$_+1:$_/2while$_>1'
41 karakter total
31 karakter untuk bagian kode sebenarnya, tetapi kode tidak akan berfungsi tanpa -n
sakelar. Jadi saya memasukkan seluruh contoh dalam hitungan saya.