Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Fun With Perl: Golf

by Boots111 (Hermit)
on Dec 09, 2001 at 00:06 UTC ( [id://130453]=note: print w/replies, xml ) Need Help??


in reply to Fun With Perl: Golf

Monks~

I have seen a few golfs now and respect them quite a bit, but am often stuck looking them and thinking How the hell does that work. Perhaps some more experienced coders could explain exactly what some of these little tid bits do.

Thanks,
Matt

Replies are listed 'Best First'.
Mr. Wizard (Golf Explanations)
by japhy (Canon) on Dec 09, 2001 at 00:35 UTC
    As a blanket statement, please check the FWP archives as most of them are being or have been explained. I'll explain how my five entries worked.
    Here's head.pl, which prints the first 10 lines of a file.
    #!/usr/bin/perl -p 11..exit
    The code expands (loosely) to
    while (<>) { 11..exit; } continue { print }
    The 11..exit is the flip-flop operator, in void context (which is as good as scalar context). It returns true when the left-hand side is true, and continues doing so until the right-hand side is true. Since the left-hand side is a numeric constant, that value is compared to $. (as is documented). So once $. == 11 is true, Perl sees is exit is true, but that has a side-effect of exiting the program. Thus, the print statement is only reached for the first 10 lines.
    Here's tail.pl, which prints the last 10 lines:
    #!/usr/bin/perl print+(<>)[-10..-1]
    Not very exotic. It reads all of the file into a list, and then takes the last 10 elements. There is a one-stroke trick here. print(1+2)*3 happens to parse as (print(1+2))*3, so you often need to do print((1+2)*3). But you can save a stroke with the unary + operator: print+(1+2)*3.

    Here's a more inventive solution of mine:

    #!/usr/bin/perl map--$.>9||print,<>
    This is written more normally as a for-loop:
    for (<>) { print unless --$. > 9; }
    This code reads all of the file into a list to be iterated over (and thus $. is the number of lines read). Then, for each iteration, we subtract one from $. and see if it's greater than 9. If it is, we don't print the line -- otherwise, we do. --$. will be 9 when we get to the 10th-to-last line.
    Here's rev.pl -- it's not mine, since mine is the utterly simplistic print reverse <>. It's the shortest entry, and it's genius.
    #!/usr/bin/perl -p $\=$_.$\}{
    That code expands to:
    while (<>) { $\ = $_ . $\ } {; } continue { print }
    Do you notice how there is an empty block before the continue now? That moves the printing to the very end of the program (where it will only occur once). We place $_ at the BEGINNING of the $\ variable, so we end up getting the lines in reverse order. When we do print, $_ is empty, but we also print $\! Why? Because it's the output record separator... what a clever variable to use!
    Here's mid.pl. It's not the shortest, and it's pretty direct.
    #!/usr/bin/perl @_=<>;print@_[$#_/2..@_/2]
    If the number of lines is odd (13), we only print the ONE middle line. That means $#_/2 is going to be (13-1)/2 = 6, and @_/2 is going to be 13/2 = 6.5. The slice [6 .. 6.5] is as good as [6 .. 6]. However, if there are an even number of lines (20), we print the middle two. $#_/2 is then (20-1)/2 = 9.5, and @_/2 is 20/2 = 10; so our slice is [9.5 .. 10], which is just like [9 .. 10].
    Finally, here's wc.pl, which I won with my first entry.
    #!/usr/bin/perl printf"%010d\n",$.,<>
    This prints the number of lines, zero-padded and right justified, to 10 digits. This makes use of the fact that by the time $. is accessed for its value, the <> has already returned all its lines, so $.'s value reflects that. So we print $. with the format, and "waste" the lines returned by <>.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://130453]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-04-19 08:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found