Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

comment on

( [id://3333] : superdoc . print w/replies, xml ) Need Help??

These are the results of the PGA Golf Round 1.

Since the first round I've learned that Ronald Kimball, aka chipmunk, was one of the organisers of the the Perl Golf Apocalypse. He has also, very graciously, provided me with the commentary to the solutions below. Thanks Ronald. :-)

The full organising and judging committee of the Perl Golf Apocalypse were: Uri Guttman, Brand Hilton, Ronald Kimball, Larry Rosler and Damian Conway.

Special mention goes to tachyon who actually tried to complete the holes in the allotted time. A bottle of red wine thwarted his efforts however and he got 4 of the 6 holes wrong on the first pass. The motto there: "Don't drink and drive". :-|

ROUND 1: - Holes 1-6

Hole 1 - Fifth Word

Write a Perl subroutine which returns the fifth word in a string. A word is any sequence of letters, numbers, and/or underscores. The string will be passed as the sole argument and will contain at least 5 words.

* Difficulty: Easy

* Time: 3 minutes

* Solutions:
sub hole{(pop=~/\w+/g)[4]} # 16

* Commentary

This was intended as a practice hole for the tournament. This hole provides some hints to help with the later holes. If there's one argument in @_, pop is the shortest way to get at it; and many golf problems can be solved with a short regular expression.

This hole also shows how tricky these golf holes can be. A correct solution should return the word 'fifth' for the following string: '!first@@second#third$$fourth%fifth^^sixth'. In this string, the words are not broken by whitespace; the words are broken by multiple non-word characters; and the first word is preceeded by a non-word character.

Hole 2 - Error Message

Write a Perl one-liner that prints the following to STDERR:
Can't find label TPC at -e line 5.

* Difficulty: Easy

* Time: 3 minutes

* Solutions:
perl -e"die qq{Can't find label TPC at -e line 5.\n}" # 53 perl -e '' -e '' -e '' -e '' -e'goto TPC' # 41 perl -e0 -e, -e, -e';' -e'goto TPC' # 35 perl -e{ -e{ -e} -e} -e'goto TPC' # 33 perl -e'#line 5' -e'goto TPC' # 29 perl -e'#line 5' -egoto+TPC # 27

* Commentary

This hole was really just to see if people know about the somewhat obscure #line direction. It was used as a practice hole at the tournament.

We decided to disallow the following clever solution, because it's not strictly a one-liner. This solution works because sh allows quotes to span multiple lines.
perl -e" goto TPC"
jmcnamara: I actually counted solutions of this nature. The #line solution is interesting. I tried this but I added the -P switch because I thought it needed to be preprocessed. It doesn't.

Hole 3 - Smallest Repeating Pattern

Write a subroutine that accepts a string which may consist of a repeating pattern, and returns the smallest repeating substring. If the string does not consist of a repeating pattern, the subroutine should return undef or the empty string. e.g.:
input output 'aaaaaa' 'a' 'ababab' 'ab' 'aabaab' 'aab' 'ababaa' ''
* Difficulty: Easy

* Time: 4 minutes

* Solutions:
sub hole{pop=~/^(.+?)\1+$/;$1} #20

* Commentary

This hole is tricky, because the subroutine is being called in scalar context. Otherwise the result of the pattern match could be returned directly. The obvious way to work around that is with (pop=~/^(.+?)\1+$/)[0]) but changing to the solution shown above saves... one whole character! :)

A shorter solution is pop=~/^(.+?)\1+$/;$1 but that depends on $1 already being empty when the subroutine is called, which may not be the case. This possibility was accounted for in the test data at the conference.

jmcnamara: This was the hole that most people avoided.

Hole 4 - Hex to Char

Write a subroutine which, given a string consisting entirely of hexadecimal digits, converts pairs of digits to their ASCII character equivalents and returns the result as a list of characters. The hexadecimal digits A-F may appear in upper or lower case. There will be an even number of digits in the string. e.g.
5065726c206861636b6572 -> ('P', 'e', 'r', 'l', ' ', 'h', 'a', 'c', 'k', 'e', 'r')
* Difficulty: Easy

* Time: 4 minutes

* Solutions:
sub hole{grep$_=$_&&chr hex,split/(..)/,pop} # 34 sub hole{$_=pop;s/../chr hex$&/ge;/./g} # 29 sub hole{map{chr hex}pop=~/../g} # 32 sub hole{split//,pack'H*',@_} # 19 sub hole{(pack'H*',@_)=~/./g} # 19 sub hole{$_=pack'H*',@_;/./g} # 19

* Commentary

Ronald came up with this hole because he wanted to be clever with split and grep. Then someone posted one of the pack solutions. Doh! But he redeemed himself slightly by coming up with another of the pack variants shown above.

Hole 5 - Max without Sort

Write a subroutine that accepts a list of numbers, and returns the maximum number from the list, without using Perl's built-in sort.

* Difficulty: Easy

* Time: 4 minutes

* Solutions:
sub hole{$m=pop;$m=($m,$_)[$m<$_]for@_;$m} # 32 sub hole{$m=pop;$_>$m&&($m=$_)for@_;$m} # 29 sub hole{$m=pop;$_>$m?$m=$_:1for@_;$m} # 28

* Commentary

This one is a nice, straightforward golf problem. Except for one thing; a correct solution requires initializing max with an element of the list. Otherwise, the subroutine fails when all the elements are negative.

At the tournament, one team tried initializing max to -999,999, but that wasn't low enough to fool the judging script. Sorry, no points!

Hole 6 - Vowel Sort

Write a subroutine that accepts a list of words, and returns the list sorted by the first *vowel* that appears in each word. If two words have the same first vowel, it does not matter which is sorted first. Words will be in lowercase and will always contain at least one vowel. (Vowels are a, e, i, o, and u.)
e.g.: hole('dog', 'cat', 'fish', 'duck', 'lemur') returns: ('cat', 'lemur', 'fish', 'dog', 'duck')

* Difficulty: Easy

* Time: 5 minutes

* Solutions:
sub hole{map{$_->[0]}sort{$a->[1]cmp$b->[1]}map{[$_,m/[aeiou]/g]}@_} + # 58 sub hole{sort{($a=~/([aeiuo])/)[0]cmp($b=~/([aeiou])/)[0]}@_} # 51 sub hole{sort{($a=~($v='([aeiou])'))[0]cmp($b=~$v)[0]}@_} # 47 sub hole{map{substr$_,1}sort map{/[aeiou]/;$&.$_}@_} # 42 sub hole{map/.(.+)/,sort map/[aeiou]/&&$&.$_,@_} # 38

* Commentary

There are several possible approaches to this problem. The first solution above uses a classic Schwartzian Transform, a map sort map with array references. The second and third pull out the vowels every time the comparison sub is called; the third saves keystrokes by assigning the regex to a variable. The fourth and fifth use the method written about by Uri Guttman and Larry Rosler in their Sort::Fields paper; a map sort map using the default comparison function.


In reply to PGA Golf, Round 1 - Results by jmcnamara

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.