Perl golf

My friend Stephen has posted a little challenge over on his blog. Basically it's to put a wrapper arond cal(1) so that if it is given a single argument between 1 and 12 or 'now' it prints a 3-month calendar centered around that month in the year, rather than the default behaviour which is to print a calendar for the year 1 through 12 - duh!

I of course took it as a perl golf challenge to produce the smallest (and therefore most unreadable) version possible. I know a few of my friends in perl-land read this blog, so perhaps you can come up with something even smaller than my current 404-byte version? To be fair, obvious hacks such as removing the die or shortening the /usr/bin/cal path are considered to be cheating ;-)

Here's my current effort, line breaks added to stop it sending your browser mental.

if($_ eq'now'){$a[1]=[$m,$y]}elsif($_=~/^\d+$/&&$_>=1&&$_<=12){$a[1]=[$_,$y]}
@c=map[map{chomp;$_}`$c @$_`],@a;printf"%-20s   %-20s   %-20s\n",
map shift@$_||'',@c for 1..7

Can you do better?


Thanks to Jason Santos for spotting a bug, and being devious enough to get the count down even further - here's the latest version, see if you can spot the differences:

@c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s   %-20s   %-20s\n",
map shift@$_||'',@c for 1..8
Tags : , ,
Categories : Tech, Perl, Work

Re: Perl golf

I've shortened yours a bit (384 bytes), and fixed an error (you only printed out the first seven lines, but some months have eight lines... e.g., your version omits Haloween this year!):
@c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s   %-20s   %-20s\n",map shift@$_||'',@c for 1..8

Re: Perl golf

Oops, thanks for catching the error! I like the use of a RE against the default $_ operand instead of eq, and the substitution of chop for chomp was *very* sneaky ;-)

Re: Perl golf

How about this one, in 353 bytes.
@c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s   %-20s   %-20s\n",map shift@$_,@c for 1..8

Re: Perl golf

Yep, that works for me, thanks! I suspect there isn't much more fat left to be trimmed...

Re: Perl golf

308 and cleaner:

$c='/usr/bin/cal';$_=shift;@m=split" ",`date '+%m %Y'`;
@c=map[map{chop;$_}`$c @$_`],\(@l,@m,@n);printf"%-20s   %-20s   %-20s\n",map shift@$_,@c for 1..8</code>