All Source For perl |
Ackermann's Function |
#!/usr/local/bin/perl
# $Id: ackermann.perl,v 1.9 2001/05/04 01:21:38 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
use integer;
# It's prettier but slower to do this
#sub Ack {
# my($M, $N) = @_;
# return( $N + 1 ) if ($M == 0);
# return( Ack($M - 1, 1) ) if ($N == 0);
# Ack($M - 1, Ack($M, $N - 1));
#}
# in our quest for speed, we must get ugly:
# it helps reduce stack frame size a little bit
# from Leif Stensson
sub Ack {
return $_[0] ? ($_[1] ? Ack($_[0]-1, Ack($_[0], $_[1]-1))
: Ack($_[0]-1, 1))
: $_[1]+1;
}
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
my $ack = Ack(3, $NUM);
print "Ack(3,$NUM): $ack\n";
|
Array Access |
#!/usr/local/bin/perl
# $Id: ary3.perl,v 1.1 2001/05/31 02:27:48 doug Exp $
# http://www.bagley.org/~doug/shootout/
# this program is modified from:
# http://cm.bell-labs.com/cm/cs/who/bwk/interps/pap.html
# Timing Trials, or, the Trials of Timing: Experiments with Scripting
# and User-Interface Languages</a> by Brian W. Kernighan and
# Christopher J. Van Wyk.
my $n = @ARGV[0] || 1;
my @X;
my @Y;
my $last = $n - 1;
for my $i (0..$last) {
$X[$i] = $i + 1;
}
for my $k (0..999) {
for my $i (reverse 0..$last) {
$Y[$i] += $X[$i];
}
}
print "$Y[0] $Y[$last]\n";
|
Count Lines/Words/Chars |
#!/usr/local/bin/perl
# $Id: wc.perl,v 1.2 2001/05/16 19:59:52 doug Exp $
# http://www.bagley.org/~doug/shootout/
# this program is modified from:
# http://cm.bell-labs.com/cm/cs/who/bwk/interps/pap.html
# Timing Trials, or, the Trials of Timing: Experiments with Scripting
# and User-Interface Languages</a> by Brian W. Kernighan and
# Christopher J. Van Wyk.
use strict;
my($nl, $nw, $nc);
while(<STDIN>) {
$nc += length;
$nw += scalar(split);
$nl += 1;
# print "$nl $nw $nc\n";
}
print "$nl $nw $nc\n";
exit(0);
while (read(STDIN, $_, 4095)) {
$_ .= <STDIN>;
$nl += scalar(split(/\n/));
$nc += length;
$nw += scalar(split);
}
print "$nl $nw $nc\n";
|
Echo Client/Server |
#!/usr/local/bin/perl
# $Id: echo.perl,v 1.6 2001/05/27 16:44:24 doug Exp $
# http://www.bagley.org/~doug/shootout/
use Socket;
my $DATA = "Hello there sailor\n";
sub server_sock {
local *SS;
socket(SS, PF_INET, SOCK_STREAM, 0) or
die "server/socket ($!)";
setsockopt(SS, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or
die "server/setsockopt ($!)";
bind(SS, sockaddr_in(0, INADDR_LOOPBACK)) or
die "server/bind ($!)";
listen(SS, 2);
return(*SS);
}
sub get_port {
local *SK = shift;
(sockaddr_in(getsockname(SK)))[0];
}
sub client_sock {
my $port = shift;
local *CS;
socket(CS, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or
die "client/socket ($!)";
connect(CS, sockaddr_in($port, INADDR_LOOPBACK)) or
die "client/connect ($!)";
return(*CS);
}
sub echo_client {
my($N, $port) = @_;
local *SOCK = client_sock($port);
select(SOCK);
$| = 1;
for my $i (0..($N-1)) {
print $DATA;
my $ans = <SOCK>;
($ans eq $DATA) or die qq{client: "$DATA" ne "$ans"};
}
close SOCK;
}
sub echo_server {
my($N) = @_;
local *SSOCK = server_sock();
my $port = get_port(*SSOCK);
my $pid = fork;
defined $pid or die "server/fork ($!)";
if ($pid) {
# parent is server
local *CSOCK;
accept(CSOCK, SSOCK) or die "server/accept ($!)";
select(CSOCK);
$| = 1;
my $n = 0;
while (<CSOCK>) {
print $_;
$n += length($_);
}
select(STDOUT);
print "server processed $n bytes\n";
} else {
# child is client
echo_client($N, $port);
}
wait();
}
sub main {
my $N = $ARGV[0] || 1;
echo_server($N);
exit(0);
}
main();
|
Exception Mechanisms |
#!/usr/local/bin/perl
# $Id: except.perl,v 1.5 2001/05/27 00:23:52 doug Exp $
# http://www.bagley.org/~doug/shootout/
use integer;
my $HI = 0;
my $LO = 0;
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
package Lo_Exception;
sub new {
bless({Val => shift}, __PACKAGE__);
}
package Hi_Exception;
sub new {
bless({Val => shift}, __PACKAGE__);
}
package main;
sub some_function {
my $num = shift;
eval {
&hi_function($num);
};
if ($@) {
die "We shouldn't get here ($@)";
}
}
sub hi_function {
my $num = shift;
eval {
&lo_function($num);
};
if (ref($@) eq "Hi_Exception") {
$HI++; # handle
} elsif ($@) {
die $@; # rethrow
}
}
sub lo_function {
my $num = shift;
eval {
&blowup($num);
};
if (ref($@) eq "Lo_Exception") {
$LO++; # handle
} elsif ($@) {
die $@; # rethrow
}
}
sub blowup {
my $num = shift;
if ($num % 2) {
die Lo_Exception->new(Num => $num);
} else {
die Hi_Exception->new(Num => $num);
}
}
$NUM = $ARGV[0];
while ($NUM--) {
&some_function($NUM);
}
print "Exceptions: HI=$HI / LO=$LO\n";
|
Fibonacci Numbers |
#!/usr/local/bin/perl
# $Id: fibo.perl,v 1.4 2001/02/20 02:12:08 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
use integer;
# from Leif Stensson
sub fib {
return $_[0] < 2 ? 1 : fib($_[0]-2) + fib($_[0]-1);
}
my $N = ($ARGV[0] < 1) ? 1 : $ARGV[0];
my $fib = fib($N);
print "$fib\n";
|
Hash (Associative Array) Access |
#!/usr/local/bin/perl
# $Id: hash.perl,v 1.3 2001/05/16 16:11:41 doug Exp $
# http://www.bagley.org/~doug/shootout/
# this program is modified from:
# http:#cm.bell-labs.com/cm/cs/who/bwk/interps/pap.html
# Timing Trials, or, the Trials of Timing: Experiments with Scripting
# and User-Interface Languages</a> by Brian W. Kernighan and
# Christopher J. Van Wyk.
use strict;
my $n = $ARGV[0] || 1;
my %X = ();
my $c = 0;
for my $i (1..$n) {
$X{sprintf('%x', $i)} = $i;
}
for my $i (reverse 1..$n) {
++$c if exists $X{$i};
}
print "$c\n";
|
Hashes, Part II |
#!/usr/local/bin/perl
# $Id: hash2.perl,v 1.3 2001/01/18 23:38:26 doug Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Steve Fink
use strict;
my $n = ($ARGV[0] > 0) ? $ARGV[0] : 1;
my %hash1 = ();
$hash1{"foo_$_"} = $_ for 0..9999;
my %hash2 = ();
my($k, $v);
for (1..$n) {
$hash2{$_} += $hash1{$_} while (defined ($_ = each %hash1));
}
print "$hash1{foo_1} $hash1{foo_9999} $hash2{foo_1} $hash2{foo_9999}\n";
|
Heapsort |
#!/usr/local/bin/perl
# $Id: heapsort.perl,v 1.11 2001/05/08 02:46:59 doug Exp $
# http://www.bagley.org/~doug/shootout/
# Matt Harris suggested passing the array via typeglob
use strict;
use constant IM => 139968;
use constant IA => 3877;
use constant IC => 29573;
use vars qw(@ra);
my $LAST = 42;
sub gen_random { ($_[0] * ($LAST = ($LAST * IA + IC) % IM)) / IM }
sub heapsort ($\@) {
my $n = shift;
# use typeglob ra to refer to array.
local *ra = shift;
my($rra, $i, $j);
my $l = ($n >> 1) + 1;
my $ir = $n;
while (1) {
if ($l > 1) {
$rra = $ra[--$l];
} else {
$rra = $ra[$ir];
# print('ir=1 ', $ir, ' <- ', 1, ' (', sprintf("%.10g", $ra[1]), ')', "\n" );
$ra[$ir] = $ra[1];
if (--$ir == 1) {
# print('1=rra ', 1, ' <- ', sprintf("%.10g", $rra), "\n" );
$ra[1] = $rra;
return;
}
}
$i = $l;
$j = $l << 1;
# print " l=$l i=$i j=$j ir=$ir\n";
while ($j <= $ir) {
$j++ if (($j < $ir) && ($ra[$j] < $ra[$j+1]));
# print(" in2while, j=$j rra=", sprintf("%.10g", $rra), ' ra(j)=', sprintf("%.10g", $ra[$j]), "\n");
if ($rra < $ra[$j]) {
# print('i=j ', $i, ' <- ', $j, ' (', sprintf("%.10g", $ra[$j]), ')', "\n" );
$ra[$i] = $ra[$j];
$j += ($i = $j);
} else {
$j = $ir + 1;
}
}
# print('i=rra ', $i, ' <- ', sprintf("%.10g", $rra), "\n" );
$ra[$i] = $rra;
}
}
my $N = $ARGV[0];
$N = 1 if ($N < 1);
# create an array of N random doubles
my @ary = ();
for (my $i=1; $i<=$N; $i++) {
$ary[$i] = gen_random(1.0);
}
heapsort($N, @ary);
printf("%.10g\n", $ary[-1]);
|
Hello World |
#!/usr/local/bin/perl
# $Id: hello.perl,v 1.1 2001/06/17 22:00:34 doug Exp $
# http://www.bagley.org/~doug/shootout/
print "hello world\n";
|
List Operations |
#!/usr/local/bin/perl
# $Id: lists.perl,v 1.3 2001/05/06 15:50:16 doug Exp $
use strict;
my $SIZE = 10000;
my $ITER = $ARGV[0];
$ITER = 1 if ($ITER < 1);
my $result = 0;
while ($ITER--) {
$result = &test_lists();
}
print "$result\n";
sub test_lists {
# create a list of integers (Li1) from 1 to SIZE
my @Li1 = (1..$SIZE);
# copy the list to Li2 (not by individual items)
my @Li2 = @Li1;
my @Li3 = ();
# remove each individual item from left side of Li2 and
# append to right side of Li3 (preserving order)
push(@Li3, shift @Li2) while (@Li2);
# Li2 must now be empty
# remove each individual item from right side of Li3 and
# append to right side of Li2 (reversing list)
push(@Li2, pop @Li3) while (@Li3);
# Li3 must now be empty
# reverse Li1 in place
@Li1 = reverse @Li1;
# check that first item is now SIZE
return(0) if $Li1[0] != $SIZE;
# compare Li1 and Li2 for equality
my $len1 = scalar(@Li1);
my $len2 = scalar(@Li2);
my $lists_equal = ($len1 == $len2);
return(0) if not $lists_equal;
for my $i (0..($len1-1)) {
if ($Li1[$i] != $Li2[$i]) {
$lists_equal = 0;
last;
}
}
return(0) if not $lists_equal;
# return the length of the list
return($len1);
}
|
Matrix Multiplication |
#!/usr/local/bin/perl
# $Id: matrix.perl,v 1.1 2000/12/29 06:10:10 doug Exp $
# http://www.bagley.org/~doug/shootout/
# This program based on the original from:
# "The What, Why, Who, and Where of Python" By Aaron R. Watters
# http://www.networkcomputing.com/unixworld/tutorial/005/005.html
# modified to pass rows and cols, and avoid matrix size checks
# I've sped up the original quite a bit by removing some loop
# invariants and declaring "use integer"
use strict;
use integer;
my $size = 30;
sub mkmatrix {
my($rows, $cols) = @_;
--$rows; --$cols;
my $count = 1;
my @mx = ();
foreach (0 .. $rows) {
my @row = ();
$row[$_] = $count++ foreach (0 .. $cols);
push(@mx, \@row);
}
return(\@mx);
}
# mmult contributed by Tony Bowden
sub mmult {
my ($rows, $cols, $m1, $m2) = @_;
my $m3 = [];
--$rows; --$cols;
for my $i (0 .. $rows) {
for my $j (0 .. $cols) {
$m3->[$i][$j] += $m1->[$i][$_] * $m2->[$_][$j] for 0..$cols;
}
}
return $m3;
}
#sub mmult {
# my ($rows, $cols, $m1, $m2) = @_;
# my @m3 = ();
# --$rows; --$cols;
# for my $i (0 .. $rows) {
# my @row = ();
# my $m1i = $m1->[$i];
# for my $j (0 .. $cols) {
# my $val = 0;
# for my $k (0 .. $cols) {
# $val += $m1i->[$k] * $m2->[$k]->[$j];
# }
# push(@row, $val);
# }
# push(@m3, \@row);
# }
# return(\@m3);
#}
my $N = $ARGV[0] || 1;
my $m1 = mkmatrix($size, $size);
my $m2 = mkmatrix($size, $size);
my $mm;
while ($N--) {
$mm = mmult($size, $size, $m1, $m2);
}
print "$mm->[0]->[0] $mm->[2]->[3] $mm->[3]->[2] $mm->[4]->[4]\n";
|
Method Calls |
#!/usr/local/bin/perl
# $Id: methcall.perl,v 1.5 2001/05/27 16:44:24 doug Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Ben Tilly
package Toggle;
sub new {
my($class, $start_state) = @_;
bless( { Bool => $start_state }, $class );
}
sub value {
(shift)->{Bool};
}
sub activate {
my $self = shift;
$self->{Bool} ^= 1;
return($self);
}
package NthToggle;
our @ISA = qw(Toggle);
sub new {
my($class, $start_state, $max_counter) = @_;
my $self = $class->SUPER::new($start_state);
$self->{CountMax} = $max_counter;
$self->{Counter} = 0;
return($self);
}
sub activate {
my $self = shift;
if (++$self->{Counter} >= $self->{CountMax}) {
$self->{Bool} ^= 1;
$self->{Counter} = 0;
}
return($self);
}
package main;
sub main {
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
my $val = 1;
my $toggle = Toggle->new($val);
for (1..$NUM) {
$val = $toggle->activate->value;
}
print (($val) ? "true\n" : "false\n");
$val = 1;
my $ntoggle = NthToggle->new($val, 3);
for (1..$NUM) {
$val = $ntoggle->activate->value;
}
print (($val) ? "true\n" : "false\n");
}
main();
|
Nested Loops |
#!/usr/local/bin/perl
# $Id: nestedloop.perl,v 1.2 2000/12/30 21:42:57 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
my $n = ($ARGV[0] > 0) ? $ARGV[0] : 1;
my $x = 0;
my $a = $n;
while ($a--) {
my $b = $n;
while ($b--) {
my $c = $n;
while ($c--) {
my $d = $n;
while ($d--) {
my $e = $n;
while ($e--) {
my $f = $n;
while ($f--) {
$x++;
}
}
}
}
}
}
print "$x\n";
|
Object Instantiation |
#!/usr/local/bin/perl
# $Id: objinst.perl,v 1.6 2001/06/29 23:12:37 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
package Toggle;
sub new {
my($class, $start_state) = @_;
bless( { Bool => $start_state }, $class );
}
sub value {
my $self = shift;
return($self->{Bool});
}
sub activate {
my $self = shift;
$self->{Bool} ^= 1;
return($self);
}
package NthToggle;
@NthToggle::ISA = qw(Toggle);
sub new {
my($class, $start_state, $max_counter) = @_;
my $self = $class->SUPER::new($start_state);
$self->{CountMax} = $max_counter;
$self->{Counter} = 0;
return($self);
}
sub activate {
my $self = shift;
if (++$self->{Counter} >= $self->{CountMax}) {
$self->{Bool} ^= 1;
$self->{Counter} = 0;
}
return($self);
}
package main;
sub main {
my $NUM = ($ARGV[0] > 0) ? $ARGV[0] : 1;
my $toggle = Toggle->new(1);
for (1..5) {
print (($toggle->activate->value) ? "true\n" : "false\n");
}
for (1..$NUM) {
$toggle = Toggle->new(1);
}
print "\n";
my $ntoggle = NthToggle->new(1, 3);
for (1..8) {
print (($ntoggle->activate->value) ? "true\n" : "false\n");
}
for (1..$NUM) {
$ntoggle = NthToggle->new(1, 3);
}
}
main();
|
Producer/Consumer Threads |
#!/usr/local/test/bin/perl
# $Id: prodcons.perl,v 1.2 2001/01/19 04:29:45 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
use Thread qw(cond_wait cond_signal);
my $count = 0;
my $data = 0;
my $produced = 0;
my $consumed = 0;
sub consumer {
my $n = shift;
while (1) {
lock($count);
cond_wait($count) while ($count == 0);
my $i = $data;
$count = 0;
$consumed++;
last if ($i == $n);
cond_signal($count);
}
}
sub producer {
my $n = shift;
for (my $i=1; $i<=$n; $i++) {
lock($count);
cond_wait($count) while ($count == 1);
$data = $i;
$count = 1;
$produced++;
cond_signal($count);
}
}
sub main {
my $n = ($ARGV[0] < 1) ? 1 : $ARGV[0];
my $p = Thread->new(\&producer, $n);
my $c = Thread->new(\&consumer, $n);
$p->join;
$c->join;
print "$produced $consumed\n";
}
&main();
|
Random Number Generator |
#!/usr/local/bin/perl
# $Id: random.perl,v 1.13 2001/05/08 01:51:39 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
use constant IM => 139968;
use constant IA => 3877;
use constant IC => 29573;
my $LAST = 42;
sub gen_random { ($_[0] * ($LAST = ($LAST * IA + IC) % IM)) / IM }
my $result = 0;
my $N = $ARGV[0] || 1;
while ($N--) {
$result = &gen_random(100);
}
printf "%.9f\n", $result;
|
Regular Expression Matching |
#!/usr/local/bin/perl
# $Id: regexmatch.perl,v 1.5 2000/10/07 08:41:43 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
my $re = qr{
(?: ^ | [^\d\(]) # must be preceeded by non-digit
( \( )? # match 1: possible initial left paren
(\d\d\d) # match 2: area code is 3 digits
(?(1) \) ) # if match1 then match right paren
[ ] # area code followed by one space
(\d\d\d) # match 3: prefix of 3 digits
[ -] # separator is either space or dash
(\d\d\d\d) # match 4: last 4 digits
\D # must be followed by a non-digit
}x;
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
my @phones = <STDIN>;
my $count = 0;
my $num;
while ($NUM--) {
foreach (@phones) {
if (/$re/o) {
$num = "($2) $3-$4";
if (0 == $NUM) {
$count++;
print "$count: $num\n";
}
}
}
}
|
Reverse a File |
#!/usr/local/bin/perl
# $Id: reversefile.perl,v 1.4 2001/05/14 01:03:20 doug Exp $
# http://www.bagley.org/~doug/shootout/
undef($/);
print join("\n", reverse split(/\n/, <STDIN>)),"\n";
|
Sieve of Erathostenes |
#!/usr/local/bin/perl
# $Id: sieve.perl,v 1.10 2001/05/06 04:37:45 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
use integer;
# Tony Bowden suggested using 0..8192 to create the array
# and to test for defined instead of the value.
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
my $count;
my @flags = ();
while ($NUM--) {
$count = 0;
my @flags = (0 .. 8192);
for my $i (2 .. 8192 ) {
next unless defined $flags[$i];
# remove all multiples of prime: i
for (my $k=$i+$i; $k <= 8192; $k+=$i) {
undef $flags[$k];
}
$count++;
}
}
print "Count: $count\n";
|
Spell Checker |
#!/usr/local/bin/perl
# $Id: spellcheck.perl,v 1.4 2001/01/23 01:30:42 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
# read dictionary
my %dict = ();
open(DICT, "<Usr.Dict.Words") or
die "Error, unable to open Usr.Dict.Words\n";
while (<DICT>) {
chomp;
$dict{$_} = 1;
}
close(DICT);
while (<STDIN>) {
chomp;
print "$_\n" if (!$dict{$_});
}
|
Statistical Moments |
#!/usr/local/bin/perl
# $Id: moments.perl,v 1.5 2001/01/05 22:36:44 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
my @nums = <STDIN>;
my $sum = 0;
foreach (@nums) { $sum += $_ }
my $n = scalar(@nums);
my $mean = $sum/$n;
my $average_deviation = 0;
my $standard_deviation = 0;
my $variance = 0;
my $skew = 0;
my $kurtosis = 0;
foreach (@nums) {
my $deviation = $_ - $mean;
$average_deviation += abs($deviation);
$variance += $deviation**2;
$skew += $deviation**3;
$kurtosis += $deviation**4;
}
$average_deviation /= $n;
$variance /= ($n - 1);
$standard_deviation = sqrt($variance);
if ($variance) {
$skew /= ($n * $variance * $standard_deviation);
$kurtosis = $kurtosis/($n * $variance * $variance) - 3.0;
}
@nums = sort { $a <=> $b } @nums;
my $mid = int($n/2);
my $median = ($n % 2) ? $nums[$mid] : ($nums[$mid] + $nums[$mid-1])/2;
printf("n: %d\n", $n);
printf("median: %f\n", $median);
printf("mean: %f\n", $mean);
printf("average_deviation: %f\n", $average_deviation);
printf("standard_deviation: %f\n", $standard_deviation);
printf("variance: %f\n", $variance);
printf("skew: %f\n", $skew);
printf("kurtosis: %f\n", $kurtosis);
|
String Concatenation |
#!/usr/local/bin/perl
# $Id: strcat.perl,v 1.4 2001/04/29 06:13:05 doug Exp $
# http://www.bagley.org/~doug/shootout/
use strict;
my $NUM = $ARGV[0];
$NUM = 1 if ($NUM < 1);
my $str = "";
$str .= "hello\n" foreach (1..$NUM);
print length($str),"\n";
|
Sum a Column of Integers |
#!/usr/local/bin/perl
# $Id: sumcol.perl,v 1.4 2000/10/07 08:41:44 doug Exp $
# http://www.bagley.org/~doug/shootout/
use integer;
shift;
while (<>) { $tot += $_ }
print "$tot\n";
|
Word Frequency Count |
#!/usr/local/bin/perl
# $Id: wordfreq.perl,v 1.13 2001/05/16 23:46:40 doug Exp $
# http://www.bagley.org/~doug/shootout/
# Tony Bowden suggested using tr versus lc and split(/[^a-z]/)
use strict;
my %count = ();
while (read(STDIN, $_, 4095) and $_ .= <STDIN>) {
tr/A-Za-z/ /cs;
++$count{$_} foreach split(' ', lc $_);
}
my @lines = ();
my ($w, $c);
push(@lines, sprintf("%7d\t%s\n", $c, $w)) while (($w, $c) = each(%count));
print sort { $b cmp $a } @lines;
|