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.
$c='/usr/bin/cal';($m,$y)=(localtime)[4,5];$m+=1;$y+=1900;$_=$ARGV[0]||''; if($_ eq'now'){$a[1]=[$m,$y]}elsif($_=~/^\d+$/&&$_>=1&&$_<=12){$a[1]=[$_,$y]} else{exec($c,@ARGV)||die($!)}$_=$a[1][0]-1; @{$a[0]}=$_==0?(12,$a[1][1]-1):($_,$a[1][1]);$_=$a[1][0]+1; @{$a[2]}=$_==13?(1,$a[1][1]+1):($_,$a[1][1]); @c=map[map{chomp;$_}`$c @$_`],@a;printf"%-20s %-20s %-20s\n", map shift@$_||'',@c for 1..7
Can you do better?
Update
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:
#!/bin/perl $c='/usr/bin/cal';($m,$y)=(localtime)[4,5];$m++;$y+=1900;$_=$ARGV[0]||''; if(/^now$/){$a[1]=[$m,$y]}elsif(/^\d+$/&&$_>=1&&$_<=12){$a[1]=[$_,$y]} else{exec($c,@ARGV)||die$!}$_=$a[1][0]-1; @{$a[0]}=$_==0?(12,$a[1][1]-1):($_,$a[1][1]);$_=$a[1][0]+1; @{$a[2]}=$_==13?(1,$a[1][1]+1):($_,$a[1][1]); @c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s %-20s %-20s\n", map shift@$_||'',@c for 1..8
Re: Perl golf
$c='/usr/bin/cal';($m,$y)=(localtime)[4,5];$m++;$y+=1900;$_=$ARGV[0]||'';if(/^now$/){$a[1]=[$m,$y]} elsif(/^\d+$/&&$_>=1&&$_<=12){$a[1]=[$_,$y]}else{exec($c,@ARGV)||die$!}$_=$a[1][0]-1; @{$a[0]}=$_==0?(12,$a[1][1]-1):($_,$a[1][1]);$_=$a[1][0]+1;@{$a[2]}=$_==13?(1,$a[1][1]+1):($_,$a[1][1]); @c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s %-20s %-20s\n",map shift@$_||'',@c for 1..8
Re: Perl golf
#!/bin/perl $c='/usr/bin/cal';($m,$y)=(localtime)[4,5];$m++;$y+=1900;$_=$ARGV[0]; $a[1]=[/^now$/?$m:/^\d+$/&&$_>=1&&$_<=12?$_:(exec($c,@ARGV)||die$!),$y];$_=$a[1][0]-1; @{$a[0]}=$_?($_,$a[1][1]):(12,$a[1][1]-1);$_+=2; @{$a[2]}=$_==13?(1,$a[1][1]+1):($_,$a[1][1]); @c=map[map{chop;$_}`$c @$_`],@a;printf"%-20s %-20s %-20s\n",map shift@$_,@c for 1..8
Re: Perl golf
308 and cleaner:
<code>#!/bin/perl $c='/usr/bin/cal';$_=shift;@m=split" ",`date '+%m %Y'`; /^now$/||/^(1[012]?|[2-9])$/&&($m[0]=$1)||exec($c,@ARGV)||die$!; @l=@n=@m;--$l[0]||(--$l[1],$l[0]=12);++$n[0];($n[0]%=13)||(++$n[0],++$n[1]); @c=map[map{chop;$_}`$c @$_`],\(@l,@m,@n);printf"%-20s %-20s %-20s\n",map shift@$_,@c for 1..8</code>