| Public Scratchpad | Download, Select Code To D/L |
> $ perl -wle 'print 2**99' > 6.33825300114115e+29 > > $ ruby -wle 'print 2**99' > 633825300114114700748351602688 > > $ perl -wle 'print 9**9**5' > inf > > $ ruby -wle 'print 9**9**5' > 11639648961714476450037112738383513701181195287418707080477275981232 +67112930 > 61110379030497600608981212382961303010194972787269662720493887131941 +28225979 > 02330812909241967408569772612512723188810970249327885348957979540889 +79392032 > 77384285773679535961661261068318224015244212929851142581276122359721 +14773252 > 57783228071854320068415008743325999970986137538251775609647668372776 +37864923 > 85768392264879251737528819108072576866064418380999524740168131677759 +33784942 > and so on [1] > > Though even Ruby gives up after a while. > > $ ruby -wle 'print 9**9**9' > -e:1: warning: in a**b, b may be too big > Infinity > > > [1] Worth noting that Ruby gets this done in about 2.5 seconds while + perl with > bigint takes 30. They're probably using gmp.
The following took about 2.2 seconds (using 5.8.0; I couldn't install Inline::BC on 5.10):
9^9^9 takes more than 350 million digits to write down, and bc refuses to calculate it.#!/usr/bin/perl use strict; use warnings; no warnings 'syntax'; use Inline 'BC'; print x(); __DATA__ __BC__ define x(){ return (9^9^5) }
I think that is good advice in general and even good advice in this particular case, for small N. But I don't think that it is good advice for this problem and large N. The reason is that this problem requires calculating factorials from 1 through N.
With memoized recursion, you need of order N function calls, N memoize lookups and N multiplications. With a straigtfowrawd for loop, you need of order N2 multiplications. Here is some code to demonstrate (I have replaced multiplication with addition to avoid big numbers. That's a change against the recursion camp, as addition is a cheaper operation than multiplication):
use strict; use warnings; use Memoize; $| = 1; memoize('f_fenLisesi'); my $LARGE_N = shift || 10_000; time_this( \&f_fenLisesi, 'fenLisesi' ); time_this( \&f_swampyankee, 'swampyankee'); exit( 0 ); #--------------------------------------------------+ sub time_this { my ($cref, $test_name) = @_; my $start = time(); print "testing $test_name: "; for (1 .. $LARGE_N) { $cref->( $_ ); } printf "%d second(s)\n", time() - $start; } #--------------------------------------------------+ sub f_swampyankee { my ($n) = @_; my $sum = 0; for my $i (1 .. $n) { $sum += $i; } $sum; } ##--------------------------------------------------+ sub f_fenLisesi { my ($n) = @_; return 1 if $n == 1; $n + f_fenLisesi( $n - 1 ); }
On 7/1/07, Mark Jason Dominus <mjd@plover.com> wrote: > >Dave Mitchell: >> NB - It has traditionally been the case that 'local $_' >> was unsafe, and that it was better to do 'local *_' >> instead. Can anyone remind me why this is, and I'm >> wondering whether the assorted local() fixes have made >> this point moot. > > tie $x, "DO_NOT_MODIFY"; > sub DO_NOT_MODIFY::TIESCALAR { bless [] => $_[0] } > sub DO_NOT_MODIFY::FETCH { return rand; } > sub DO_NOT_MODIFY::STORE { > # system("do-bad-stuff"); > die("I told you not to modify this!") > } > > for ($x) { > use_dollar_underbar(); > } > > sub use_dollar_underbar { > local $_; > print "okay...\n"; > $_ = 1; > } > > > use_dollar_underbar() wants to operate on $_ without > tampering with its global value and without causing > any strange action-at-a-distance. So it uses "local $_" > to try to do this. But "local $_" *itself* tampers > with the global value and causes a strange > action-at-a-distance. And more specifically... Changing it to confess() instead of die shows that local $_; calls DO_NOT_MODIFY::STORE(). Yves -- perl -Mre=debug -e "/just|another|perl|hacker/"
# perl -wle 'print 2 ** 128' 3.40282366920938e+38 # perl -Mbigint -wle 'print 2 ** 128' 340282366920938463463374607431768211456 # perl -wle 'print sqrt(2)' 1.4142135623731 # perl -Mbignum -wle 'print sqrt(2)' 1.41421356237309504880168872420969807857 # perl -wle 'print 3/7 ** 77' 2.53847080898319e-65 # perl -Mbigrat -wle 'print 3/7 ** 77' 3/1181813865805958799768684143120019644340385488367699234582870 +39207
... In my current project, I needed to extend the 'convert' functionality of SQL-Abstract-1.22 in order to support two kinds of behavior: 1) convert procedures that take multiple parameters, such as: locale_upper( name, 'en_US' ) 2) convert procedures that apply to some columns only, as in the following snippet: WHERE locale_upper(name,'en_US') LIKE locale_upper($1,'en_US') AND age = 32 The simplest interface extension that I could came up with that supports these requirements was as follows: $criteria->{convert} = ['locale_upper', q('en_US') ]; OR $criteria->{convert} = { proc => ['locale_upper', q('en_US') ], labels => [qw( name description )], }; I was able to hack SQL-Abstract-1.22 today by introducing changes to sub _convert($) {...} only, as you can see in the following patch. After applying this patch, SQL-Abstract-1.22 passes the four tests that come with the distribution, which I hope means that I have not balatantly broken major existing behavior. I am likely to have introduced some new bugs, however, as I have just sewn the patch today and the code has not been reviewed. ... --- SQL-Abstract-1.22-orig.pm 2006-11-30 19:12:14.000000000 +0200 +++ SQL-Abstract-1.22-fenL.pm 2007-03-15 17:53:57.000000000 +0200 @@ -209,10 +209,78 @@ sub _quote { # Conversion, if applicable sub _convert ($) { - my $self = shift; - return @_ unless $self->{convert}; - my $conv = $self->_sqlcase($self->{convert}); - my @ret = map { $conv.'('.$_.')' } @_; + my ($self, @args) = @_; + + return @args unless $self->{convert}; + + if (! $self->{convert_has_been_init}) { + $self->{convert_has_been_init} = 1; + + my $conv = $self->{convert}; + my ($params, $labels) = ([], []); + + if (ref( $conv ) eq 'ARRAY') { + if (! @$conv) { + die q(convert arrayref refers to an empty array); + return @args; + } + ($conv, @$params) = @$conv; + } + elsif (ref( $conv ) eq 'HASH') { + my $proc = $conv->{proc}; + if (defined $conv->{labels}) { + if (ref( $conv->{labels} ) ne 'ARRAY') { + die q(val for key 'labels' must be an arrayref); + ## return @args; + } + $labels = $conv->{labels}; + } + if (! $proc) { + die q(required elem 'proc' missing in convert hash); + ## return @args; + } + if (! ref( $proc )) { + $conv = $proc; + } + elsif (ref( $proc ) eq 'ARRAY') { + if (! @$proc) { + die q(convert proc aref refers to an empty arr); + ## return @args; + } + ($conv, @$params) = @$proc; + } + else { + die q(convert hash elem 'proc' must be scalar/aref); + ## return @args; + } + } + $self->{convert} = $conv; + $self->{convert_params} = $params; + $self->{convert_labels} = { map { uc( $_ ) => 1 } @$labels }; + } + my $conv = $self->{convert}; + $conv = $self->_sqlcase( $conv ); + my @ret = (); + + ARG: + for my $arg (@args) { + if ($arg eq '?') { + if (not defined $self->{convert_current_label}) { + die q(request to convert '?' when no label has been s +een yet); + } + } + else { + $self->{convert_current_label} = $arg; + } + if (keys %{ $self->{convert_labels} }) { + if (not $self->{convert_labels}->{uc $self->{convert_current_label}}) { + warn 'Ignoring _convert() for label ' . $self->{convert_current_label}; + push @ret, $arg; + next ARG; + } + } + push @ret, sprintf '%s(%s%s)', $conv, $arg, map { ",$_" } @{ $self->{convert_params} }; + } return wantarray ? @ret : $ret[0]; }
Do you know me, my lord? Excellent well; you are a Perl Monger.
Imperious Bill Gates, dead and turn'd to clay, Might stop a hole to keep the wind away: O, that that earth, which kept the world in awe, Should patch a Wall to expel the Windows' flaw!
$words, @words, %words.
my $class_name = 'Foo' . '::' . 'Bar'; eval "require $class_name"; if ($@) { warn $@; } $class_name =~ s|::|/|g; eval { require "$class_name.pm"; }; if ($@) { warn $@; }
fenLisesi imagines a damned negative-XP soul, logging in to PM and reading "You have -4 votes left today" Before turn-of-the-day, he has to convince some positive-XP folks to donate votes to him -- which he cannot use -- just to go up to 0 votes, or he gets it
clinton ...condemned forever to being the NodeReaper's assistant...
Moron: "you lost 10 XP, you have another 992 votes to lose before reaching the next level, succubus"
fenLisesi .oO( condemned to read documentation till sunrise, when he "to sulphurous and tormenting flames" must render himself )