I know I shouldn’t be … but I am …

[update] a bug in my reasoning (thanks Peter!)

a Perl Golf addict. Not a recovering addict, but one that is active.

What is Perl Golf? Well, as in real golf, you try to provide the minimal number of steps to a solution. In this case, you are to solve the specific puzzle.

Detractors of Perl often make snarky comments about Perl’s equivalency to random line noise and other such nonesense. Sure … if it makes you feel good to say that … I am a fan of terse languages, I wrote programs (if you could call them that) in APL … a while ago. Its a strange sensation when you realize, looking at your code, that you can parse it … and run it … in your head. But I digress.

I ran across this one today.

The problem is:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

Most folks would start off with elegant looking loops, with well spaced and well named code and variables.

This is the antithesis of what you should do in golf and in Perl golf. Try this in the language of your choice.

Here’s my 5 minute version (call it s.pl):

map$s+=(!($_%3)+!($_%5))*$_,1..1E3;print$s
map$s+=(!($_%3)||!($_%5))*$_,1..1E3;print$s

[update] The “+” should be a logical or, otherwise we would double count numbers which are multiples of 15.

To run it

landman@lightning:~$ perl -l s.pl
267333
234168

In octave (Matlab work-alike) …

octave:12> 3*sum(1:333)+5*sum(1:200) 3*sum(1:333)+5*sum(1:200)-15*sum(1:1000/15)
ans = 267333

234168

Thats pretty cool.

Some of my other neat solutions was to solve the LED problem.

You run it like this:

./led.pl SOME_NUMBER

and it generates what looks like an ascii art version of the number. Like this:

landman@crunch-r:~$ ./led.pl 12345987
  # ### ### # # ### ### ### ###
  #   #   # # # #   # # # #   #
  # ### ### ### ### ### ###   #
  # #     #   #   #   # # #   #
  # ### ###   # ### ### ###   #

landman@crunch-r:~$ ./led.pl 21435687
###   # # # ### ### ### ### ###
  #   # # #   # #   #   # #   #
###   # ### ### ### ### ###   #
#     #   #   #   # # # # #   #
###   #   # ### ### ### ###   #

Neat … huh?

So how hard was this? Here’s the code that does it, and it can be improved upon, significantly.

#!/usr/bin/perl
@s=qw(0000 0010 0001 2001 0210 0201 2201 0410);
@c=qw(765321 36 76421 76431 5463 75431 754321 763 7654321 765431 );
$l=shift;$h=0;$p="";
foreach $t(split//,$l)
{foreach$i(0..2){foreach$j(0..4){$d[$j][$i]=" ";}};
foreach$e(split//,$c[$t])
{($x,$y,$i,$j)=split//,$s[$e];foreach$o(0..2){$d[$y+$o*$j][$x+$o*$i]="#";};}
foreach$r(0..4){undef $u[$r];foreach$v(0..2){$u[$r].=$d[$r][$v];}}
if($h){$p=" ";}else{$h=1;}
for($j=4;$j>=0;$j--){$r=join("",$f[$j],$p,$u[$j]);$f[$j]=$r;}}
for($j=4;$j>=0;$j--){print $f[$j],"\n";}

How does it work? Well … I rasterized the characters and encoded the scans as vectors. From there, it was all about assembling the rasterized characters into a 2D character array.

And here’s another one.

landman@crunch-r:~$ perl romancalc2.pl
2011
MMXI

landman@crunch-r:~$ perl romancalc2.pl
2001
MMI

though I didn’t get much into the spirit of the process … it was fun just figuring out how to convert.

#!/usr/bin/perl -a
%r=(I=>1,V=>5,X=>10,L=>50,C=>100,D=>500,M=>1000,IV=>4,IX=>9,XL=>40,XC=>90,CD=>400,CM=>900);
$z=<>;
foreach $g (sort {$b< =>$a} (values %r))
{
while ($z>=$g)
{
print grep {$g == $r{$_}} (keys %r);
$z-=$g
}
}
print"\n";

There was another site dedicated to golfing called codegolf. Sadly, no new challenges.

Maybe we should create an HPC golf. Solve a specific problem with a minimum of code.

Viewed 15638 times by 4301 viewers

Facebooktwittergoogle_plusredditpinterestlinkedinmail