Re: Sieve of Eratosthenes Golf?
by blokhead (Monsignor) on Apr 07, 2005 at 04:04 UTC
|
Here's 58 57 characters that even does all the printing, though it needs to be run with perl -l:
sub f{@_?($_[0],f(grep$_%$_[0],@_)):()}print for f 2..pop
|
I used a recursive filtering approach to make it much more concise. In fact, the sub that does the work is only 39 characters.
Update: I noticed an easy way to shave a stroke (grep EXPR vs grep BLOCK), so now it's at 57. I also added code tags which I stupidly omitted.
| [reply] [d/l] |
|
The guys above you seem to have proceeded on the assumption that they should write (the contents of) a sub which returned the correct numbers, whereas yours prints them and you've included the sub block too. Not sure what the rules of "golf" are at this point but you're definitely ahead!
($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
=~y~b-v~a-z~s; print
| [reply] |
|
That's a very interesting take on the Sieve. Rewritten to be golfed, it's 33 characters.
@_?($_[0],f(grep$_%$_[0],@_)):()
|
It needs to be called as f(2..$limit) vs. f($limit).
If the requirement is that the signature is f($limit), then it goes to 47 characters
sub x{@_?($_[0],x(grep$_%$_[0],@_)):()}x 2..pop
|
| [reply] [d/l] [select] |
Re: Sieve of Eratosthenes Golf?
by dragonchild (Archbishop) on Apr 07, 2005 at 03:05 UTC
|
I'll start the bidding at 99 characters.
my%x;my$l=pop;for(2..$l){$x{$_}||=0||do{my$m=2*$_;{$x{$m}=1;($m+=$_)<=
+$l&&redo}}}grep!$x{$_},keys%x
|
| [reply] [d/l] |
|
Unneeded variable declaration, 9 stroke penalty!
$x=pop;for(2..$x){$x{$_}||=0||do{$m=2*$_;{$x{$m}=1;($m+=$_)<=$x&&redo}}}grep!$x{$_},keys%x |
| [reply] [d/l] |
Re: Sieve of Eratosthenes Golf?
by BrowserUk (Patriarch) on Apr 07, 2005 at 06:28 UTC
|
It probably won't win the golf, but it will go a lot higher than most. It'll handle upto 1,000,000,000 if you have 1 GB of ram.
sub f{
#23456789 123456789 123456789 123456789 123456789 123456789
$_=1x$_[0];for$n(1..sqrt$_[0]){m[^.{$n}.]g;s[\G(.{$n}).][${1}0]g;}
}
f(pop);
++$i and $1 and print $i while m[(.)]g;
|
And this one will go eight times higher in the same space, and should be relatively quick.
sub f{
$x="\xff"x$_[0];for(2..$_[0]){$n=$_;vec($x,$n,1)=0 while($n+=$_)<$_[0]
+;}
}
f( $ARGV[0]);
vec$x,$_,1 and print $_ for 1..$ARGV[0];
|
You could double that by not storing the evens,
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco.
Rule 1 has a caveat! -- Who broke the cabal?
| [reply] [d/l] [select] |
|
I don't understand those at all really, but the second one did a million in about a minute, so not bad at all.
It did tell me that a million was a prime number though...
($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
=~y~b-v~a-z~s; print
| [reply] |
|
It did tell me that a million was a prime number though...
Due to golfing it, it doesn't handle the very last number correctly.
I don't understand those at all really,
They both work in essentially the same way. The first one creates a string of $limit '1's. It then uses a regex to scan the string substituting '0's for '1's, for all the multiples. It then scans the string, incrementing a counter, looking for the remaining '1's and prints out the counter when it finds a '1'. It just uses the big string as a tally stick and 'crosses off' all the multiples.
The second one does the same thing, but uses vec, and bits instead of bytes, to represent the tally stick.
By avoiding building big lists/arrays, it allows you to go 30/250 or so times higher.
If you're not golfing, it is easy to omit the even bytes/bits and therebye double the range again.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco.
Rule 1 has a caveat! -- Who broke the cabal?
| [reply] |
Re: Sieve of Eratosthenes Golf?
by cog (Parson) on Apr 07, 2005 at 09:50 UTC
|
My first solution, in which I explicitly include the number 100, is at 85 characters, to be run with perl -l.
for(2..100){$n{$y=$_}&&next;$n{$y+=$_}=1 while($_+$y)<=100}for(2..100){$n{$_}||print}
|
More^WLess to come, I hope. | [reply] [d/l] |
|
OK, I know I'm twisting things a little, but I don't consider the problem to be well formed anyway (what is the objective? to print all the prime numbers between 2 and 100? to implement the sieve of Erathosthenes? in a sub? with which output?)
Anyway, here's a basic enhancement, and I also trimmed two characters with s/100/99/ (hey, we all know 100 is not prime, right? O:-) )
for(2..99){$n{$y=$_}&&next;$n{$y+=$_}=1 while($_+$y)<=99;$n{$_}||print |
I'm now at 71 chars.
| [reply] [d/l] |
|
strict and warnings compliant at 77 characters ...
$_{$.=$_}||do{{($_{$.+=$_}=$.+$_<=$,)&&redo}}for@.=2..($,=pop);grep!$_
+{$_},@.
|
| [reply] [d/l] |
Re: Sieve of Eratosthenes Golf?
by tilly (Archbishop) on Apr 07, 2005 at 13:52 UTC
|
sub sieve {
sub p{$_[0],@_>1?p(grep$_%$_[0],@_):()}p 2..pop
}
| [reply] [d/l] |