perl -E'sub w{join"",sort pop=~/./g}$w=w pop;($w~~w$_)&&print for<>' .
+/dict.txt acert
But, hell, we can go shorter. Let's switch from the join"",... construct with the babycart operator inside an interpolated string... "@{[...]}". Can't remember why I did this - doesn't actually reduce the size of the code, but I think it was necessary for some of the later stuff.
perl -E'sub w{"@{[sort pop=~/./g]}"}$w=w pop;($w~~w$_)&&print for<>' .
+/dict.txt acert
Next, we stop passing a parameter to the w function, and use $_ instead. This means that we can take advantage of the fact that regular expressions get applied to $_ by default, giving us massive savings inside the function. Outside the function it's a mixed blessing. We need to assign that pop to $_ giving us a whole new statement. But we don't need to pass anything to w on either of its invocations, and we can drop the parentheses around the smart match comparison.
perl -E'sub w{"@{[sort/./g]}"}$_=pop;$w=w;$w~~w&&print for<>' ./dict.t
+xt acert
Those two assignments in the middle started to grind my gears. I figured there must be a way to ditch the semicolon between them... and there is! The w function no longer cares about what parameters it's passed.
perl -E'sub w{"@{[sort/./g]}"}$w=w$_=pop;$w~~w&&print for<>' ./dict.tx
+t acert
I could go two characters shorter, but only swapping from print to say which adds unsightly blank lines to the output.
UPDATE: five characters more. Smart match can deal with arrayrefs!
perl -E'sub w{[sort/./g]}$w=w$_=pop;$w~~w&&print for<>' ./dict.txt ace
+rt
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
|