Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: Perl Golf idea

by thundergnat (Deacon)
on Apr 30, 2012 at 20:01 UTC ( #968142=note: print w/replies, xml ) Need Help??

in reply to Perl Golf idea

Here's a kind of half-assed one. Feed it the path to the dictionary file and a word and it will return all the matches.


perl -e"sub w{join'',sort@_[0]=~/./g};$w=w pop;($w eq w$_)&&print for<>" ./dict.txt acert



(with the dict.txt file I had. YMMV).

Replies are listed 'Best First'.
Re^2: Perl Golf idea
by tobyink (Abbot) on Apr 30, 2012 at 22:51 UTC

    Nice. I've managed to knock off twelve characters though...

    • @_[0] can be replaced with pop. This needs whitespace before it, but it's still shorter. Savings: 1 character.
    • eq can be replaced by the smart match operator, allowing the whitespace around it to be dropped. Savings: 2 characters.
    • Semicolon after sub definition not needed. Savings: 1 character.

    Now we've got:

    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'
      One character less:
      perl -nlE'sub w{[sort/./g]}INIT{$w=w$_=pop}$w~~w&&say' ./dict.txt acer +t
      And if you don't mind the (second) argument getting printed, another 3 chars less:
      perl -nlE'sub w{[sort/./g]}$w||=w$_=pop;$w~~w&&say' ./dict.txt acert
        And if you don't mind the (second) argument getting printed, another 3 chars less:
        perl -nlE'sub w{[sort/./g]}$w||=w$_=pop;$w~~w&&say' ./dict.txt acert

        This one is wrong (only) if the first line of 'dict.txt' contains a valid word (different from arg2).


        $ cat dict.txt one neo noe bad $ perl -nlE'sub w{[sort/./g]}$w||=w$_=pop;$w~~w&&say' ./dict.txt oen oen neo noe

        First word is missing. Anyway, this is a very beautiful version: ++

        UPDATE: with an extra newline

        perl -E'@a=sort pop=~/./g;say grep@a~~[sort/./g],<>' ./dict.txt acert

        UPDATE2: one char useless

        perl -E'@a=sort pop=~/./g;say grep@a~~[sort//g],<>' ./dict.txt acert

      Umm. Wow. I knew there was room for improvement reduction but... tobyink++

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://968142]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2017-01-20 20:16 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (177 votes). Check out past polls.