5 ms·
Lets see, what about factorial in constant memory? Exponentiation (a to the power of b, where they are positive integers) in logarithmic time (not using built-
by afc 14y ago
Lets see, what about factorial in constant memory? Exponentiation (a to the power of b, where they are positive integers) in logarithmic time (not using built-in exponentiation functions/syntax)? Anonymously add a constant to a number and return it (in a way that can be passed to a function like 'map' or some such)?
def Factorial(x):
output = 1
for i in xrange(x):
output *= (i + 1)
return output
def Factorial2(x):
return reduce(operator.mul, xrange(1, x + 1), 1)
I provided two versions, both with constant memory, to show how it'd look with explicit iteration and without it.
With this, I get:
>>> Factorial(200)
788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568660226031904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000L
Exponentiation:
def Power(a, b):
if not b:
return 1
if b % 2:
return Power(a, b - 1) * a
x = Power(a, b/2)
return x * x
Add a constant:
lambda x: x + 7
Or, if you want to name it globally:
def TweakValue(x):
return x + 7
How do they look in Perl?
- judofyr 14y agouse bignum; use v5.10; =cut def Factorial(x): output = 1 for i in xrange(x): output *= (i + 1) return output =cut # Direct translation sub factorial { my $x = shift; my $output = 1; for my $i (1 .. $x) { $output *= $i; } return $output; } say factorial(200); =cut def Factorial2(x): return reduce(operator.mul, xrange(1, x + 1), 1) =cut use List::Util "reduce"; sub factorial2 { my $x = shift; reduce { $a * $b } (1 .. $x); } say factorial(200); =cut def Power(a, b): if not b: return 1 if b % 2: return Power(a, b - 1) * a x = Power(a, b/2) return x * x =cut sub power { my $a = shift; my $b = shift // return 1; if ($b % 2) { return power($a, $b - 1) * $a } my $x = power($a, $b/2); return $x * $x; } # lambda x: x + 7 my $plus7 = sub { $_[0] + 7 }; # Or: my $plus7 = sub { my $x = shift; $x + 7 }; say $plus7->(14); =cut def TweakValue(x): return x + 7 =cut sub plus7 { $_[0] + 7 } say plus7(14);
- colomon 14y agoJust in case anyone was wondering, in Perl 6: sub factorial($n) { my $output = 1; for 1..$n -> $i { $output *= $i; } $output; } or sub factorial2($n) { [*] 1..$n; } Pretty anonymous function to add a constant: -> $x { $x + 7 } Really short version: * + 7 Named: sub plus7($x) { $x + 7; }
- jbert 14y agoThanks for that. First one (not 100% sure it's constant memory, I think perl optimises the for to avoid instantiating the (1..$n) list: #!/usr/bin/perl use Modern::Perl; use bigint; say fact(5000); sub fact { my ($n) = @_; my $output = 1; for my $i (1..$n) { $output *= $i; } return $output; } (Took the value up to 5000 to get something which ran long enough to get a measurement, on my laptop it runs (including startup time) in ~1.2s. (Can we compare runtime too? I know we're discussing readability, but I'm interested). The reduce version (again, I'm unsure of const mem req). Comes in at ~1.4s: #!/usr/bin/perl use Modern::Perl; use List::Util qw(reduce); use bigint; say fact(5000); sub fact { my ($n) = @_; return reduce(sub { $a * $b; }, 1, (1..$n)); } The add a constant (true lambda, closing over lexicals in scope, etc etc) is 'sub': sub { my ($x) = @_; $x + 7; } (doesn't have the python lambda limitations). (Be aware that perl GC is refcounted though, so ref cycles are possible). Edit: I think the languages are comparable in terms of features and also readability. People may dislike leading sigils and that's fair, but I dislike python's "no need to declare your vars, just hope you don't typo an assignment" approach to lexicals.
- zem 14y agothat also highlights one of my perl peeves - having to scrape function args out of @_ rather than declaring them as part of the function definition.
- jbert 14y agoYes, that sucks. It's not much extra typing: def function(x, y, z): versus sub function { my ($x, $y, $x) = @_; } The overhead is only really the 'my = @_;' chars, but it is annoying. On the other hand, it does allow you to do things like partially unpack args and pass the rest as a bundle to a super class.
- pyre 14y agoYou can partially unpack in Python too: def method(self, *args): a, b = args[:2] super(self).method(*args[:2]) Perl's lack of using the definition for the variables doesn't necessarily make it 'more powerful.'
- irahul 14y ago> def Factorial(x): output = 1 for i in xrange(x): output = (i + 1) return output Umm, did you mean: def factorial(x): output = 1 for i in xrange(2, x): output *= i return output Here are the perl versions. Such trivial examples are going to look the same in languages which share the same paradigms. use List::Util qw(reduce); # This is how I would write it. sub fact1 { my $num = shift; my $output = 1; $output *= $_ for (2 .. $num); return $output; } # Most people don't prefer inline loops and $_ variable, though # I don't see why not. sub fact2 { my $num = shift; my $output = 1; for my $i (2 .. $num) { $output *= $i; } return $output; } sub fact3 { my $num = shift; return reduce { $a * $b } 2..$num }
- colomon 14y agoBased on the examples, I presume xrange(x) is every integer up to but not including x. ie 1..^$x in Perl 6, don't recall if that's the Perl 5 syntax or not.
- irahul 14y ago> Based on the examples, I presume xrange(x) is every integer up to but not including x Yes. That makes my Python example incorrect(should be xrange(2, num + 1)) > 1..^$x in Perl 6, don't recall if that's the Perl 5 syntax or not. Perl 5 doesn have 1..^$x. I have always used 1..($n - 1) where I needed it - don't know if there is a better alternative.
- afc 14y ago> Yes. That makes my Python example incorrect(should be xrange(2, num + 1)) Or just xrange(num) and then, as in my original code, output *= num + 1. :-)
- irahul 14y ago> Or just xrange(num) and then, as in my original code, output *= num + 1. :-) HN ate your asterisk(it uses asterisk to mark italics), or something wrong with my chrome app for HN. In your post, I saw: def Factorial(x): output = 1 for i in xrange(x): output = (i + 1) return output