The PGA was the Perl Golf Apocalypse at the
4th Perl Conference.
Uri Guttman has kindly sent me the questions in order to replay the tournament here at PerlMonks.
The tournament was arranged into 17 "holes". Each hole had a stated level of difficulty and a time limit. The time limit doesn't apply here but they have been left in as an indication of the pressure that the contestants were under.
The holes will be submitted in three rounds over three weeks. The PGA suggested solutions for each round will be published before each new round.
We can also turn this into a competition. Send me a /msg if you wish to take part. I will keep track of the scores over the whole course and setup a leadership table.
Even if you haven't played Perl Golf before you should try one or two of these. Dijkstra notwithstanding, Perl Golf is a good way to learn some of Perl's dustier features and if nothing else it will probably get you to read the perlrun manpage.
Notes:
1. The aim of the tournament is the shortest solution on each hole. You should publish your score with each solution. Counting is as follows:
sub hole{print "hello, world"} For a sub
123456789_123456789_ 20 chars
perl -e 'print "hello, world"' For a one liner
123456789_123456789_123456789_ 30 chars
2. "use strict" and -w are not required.
3. All subroutines which should return a single scalar value will be called in a scalar context.
Thanks again to Uri and the others who contributed to the PGA. Uri's Perl Golf page is here.
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
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
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
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
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
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
They get harder. ;-)
John.
--
Re: PGA Golf, Round 1
by jorg (Friar) on May 24, 2001 at 19:15 UTC
|
right let's kick things off here...
Here is my first Hole, 25chars, took me approx 25 minutes. Makes me wonder if i should've used a Wood number 3 rather than the Iron number 5
sub a{($_[0]=~/\w+/g)[4]}
Update
mincus pointed out to me that there are only 18 chars i should count. How's that for a caddy !
Jorg
"Do or do not, there is no try" -- Yoda | [reply] [d/l] |
|
According to the counting rules (rule 1 above) you only count
the characters inside the subroutine block (for one liners you
count the whole command line). So yours is 18 chars.
Not to spoil anyone's fun, but here's a small tip for shaving
characters --- use pop rather than $_[0],
that gives us a 16 character solution:
sub S {(pop=~/\w+/g)[4]}
123456789_123456 # 16
| [reply] [d/l] [select] |
Re: PGA Golf, Round 1
by jorg (Friar) on May 24, 2001 at 19:43 UTC
|
This second Hole is giving me a freakin headache.. __LINE__ appeared to be a *constant in the true sense so i had to go with
perl -e; -e; -e; -e; -e "goto TPC";
123456789-123456789-123456789-12345
35 big ones in about 1 hour
Update
perl -e; -e; -e; -e; -e "goto TPC"
123456789-123456789-123456789-1234
34 and i'm being downvoted already, just let me have a go at this guys, you can show off your dandy Golf later ok? It's not like I ever mingle into any of the other Golf compo's...
Jorg
"Do or do not, there is no try" -- Yoda | [reply] [d/l] [select] |
|
perl -e'#line 5' -egoto+TPC
123456789_123456789_1234567
japhy --
Perl and Regex Hacker | [reply] [d/l] |
Re: PGA Golf, Round 1
by mr.nick (Chaplain) on May 24, 2001 at 21:15 UTC
|
Okay: here are my entries. They aren't particularly good, but they work which is fine for me.
Hole 1 - 21 chars
(split/[^\w_]/,pop)[4]
1234567890123456789001
Hole 2 - 24 chars
perl -e'\
\
\
\
goto TPC'
Hole 4 - 31 chars
map{chr(hex)}unpack("A2"x11,pop)
1234567890123456789012345678901
Hole 5 - 32 chars
$x=shift;map{$x=$_ if$_<$x}@_;$x
12345678901234567890123456789012
Hole 6 - 53 chars (ugh!)
sort{($a=~/([aeoui])/)[0]cmp($b=~/([aeiou])/)[0]}@_}
1234567890123456789012345678901234567890123456890123
| [reply] [d/l] [select] |
|
I feel so smart... I actually pulled an obscure thing of
my own... in perl // redoes the previous re, so
sub hole{sort{($a=~/([aeiou])/)[0]cmp($b=~//)[0]}@_}
123456789_123456789_123456789_123456789_12
cuts your hole 6 to 42 chars!
my small moment of glory...
Update realized I counted } in sub... actually 42 chars.. not 43...
- Ant | [reply] [d/l] |
Re: PGA Golf, Round 1
by btrott (Parson) on May 24, 2001 at 21:37 UTC
|
Here's my Hole 4, though I feel as if I must be missing something
obvious, either incorrect in my answer or a different solution.
sub h2c{split//,pack"H*",pop}
123456789_123456789_
20 characters.
Update: I realize now that the answer is incorrect because it returns a string rather than a list. Thanks all. :)
Update again: Fixed the answer by adding the split. | [reply] [d/l] |
|
It must be a list of characters.
sub hole{split//,pack"H*",@_}
is optimal (I believe). | [reply] [d/l] |
|
Incorrect in your answer: you need to return a list of characters, not a string.
If God had meant us to fly, he would *never* have give us the railroads.
--Michael Flanders
| [reply] |
Re: PGA Golf, Round 1
by btrott (Parson) on May 24, 2001 at 21:51 UTC
|
Hole 6.
This is really ugly and much too long, but whatever:
sub hole{$r='([aeiou])';sort{($a=~$r)[0]cmp($b=~$r)[0]}@_}
123456789_123456789_123456789_123456789_12345678
48 characters, I think. | [reply] [d/l] |
Re: PGA Golf, Round 1
by da (Friar) on May 24, 2001 at 20:55 UTC
|
Hole 2: I'm working under the assumption that 'one liner' strictly means it is executed as one line; and it's OK to specify I'm using csh otherwise I'm sunk. :-) 25 counting the carriage returns:
perl -e'/
/
/
/
goto TPC'
hmm... specifying sh instead of csh, eliminate the / characters, and that's 21.
Please go easy on me, I'm an amateur.
Of course, scoring it is vaguely impossible according to the rules, so I don't imagine this is a valid play...
---
-DA
update: took me 5 min., plus 5 min. to try and convince myself it might be valid... | [reply] [d/l] [select] |
Re: PGA Golf, Round 1
by ChemBoy (Priest) on May 25, 2001 at 00:27 UTC
|
- Hole 1 (18, or 16 if I can take a free drop on pop)
- sub {(pop=~/\w+/g)[4]}
- Hole 2 (24 in tcsh)
perl -e'\
\
\
goto\
TPC'
Which has been said before, to be sure.
- Hole 3 (20)
- sub {pop=~/^(.+?)\1+$/;$1}
which takes a 1-stroke penalty for the lack of /s, and one for $ instead of \Z. Oh well.
-
Hole 4 (19)
- sub {split//,pack"H*",@_}
or
sub {map{chr hex}pop=~/../g}
for one more stroke and a warmer fuzzier feeling (since I actually got that one done in the time limit).
- Hole 5 (30)
-
sub {$a=pop;for(@_){$a>$_ or$a=$_}$a}
I think this is optimal for Perl 5.004
(tilly can do it better with a more recent revision, I know.)
- Hole 6 (44)
- sub {sub F{pop=~/[aeiou]/;$&}sort{F($a)cmp F$b}@_}
Which is not as cool as some, but is the best I could do without reading the thread.
This gives me an overall score of 155 for six holes, which I think is respectable...
If God had meant us to fly, he would *never* have give us the railroads.
--Michael Flanders
| [reply] [d/l] [select] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: PGA Golf, Round 1
by dooberwah (Pilgrim) on May 24, 2001 at 21:31 UTC
|
| [reply] |
Re: PGA Golf, Round 1
by Anonymous Monk on May 24, 2001 at 22:01 UTC
|
# 1 -- 16 chars
sub g1 { (pop=~/\w+/g)[4] }
# 2 -- 19 chars (23 with newlines)
perl -e'goto\
\
\
\
TPC'
# 3 -- 23 chars
# note: using $ instead of \z is *wrong*
# note: using . without /s is *wrong*
sub g3 { pop=~/^(.*?)\1+\z/s&&$1 }
# 4 -- 12 chars
sub g4 { pack"H*",pop }
# 5 -- 29 chars
sub g5 { $x=pop;$x<$_&&($x=$_)for@_;$x }
# 6 -- 49 chars
sub g6 { sort{($a=~/[aeiou]/g)[0]cmp($b=~/[aeiou]/g)[0]}@_ }
japhy --
Perl and Regex Hacker | [reply] [d/l] |
|
Um, that is my code. My cookie expired or something. Anyway, direct any ++'s here, please.
japhy --
Perl and Regex Hacker
| [reply] |
|
# 4 -- 19 chars
sub g4 { split//,pack"H*",@_ }
# 6 -- 47 chars
sub g6 { sort{($a=~($_='([aeiou])'))[0]cmp($b=~$_)[0]}@_ }
japhy --
Perl and Regex Hacker | [reply] [d/l] |
|
I had similar solutions. But I improved on hole 3 to 20:
sub hole{map/^(.*?)\1+\z/s,@_}
and my solution for hole 5 was also 29 but somewhat different.
sub hole{$,=pop;$,=$,<$_?$_:$,for@_;$,}
However we can improve hole 5 to 28 taking your solution and applying my trick to it.:
sub hole{$,=pop;$_<$,or$,=$_ for@_;$,}
UPDATE
Oops. My test code put hole 3 in the wrong context. My bad. | [reply] [d/l] [select] |
Re: PGA Golf, Round 1
by the_slycer (Chaplain) on May 24, 2001 at 22:24 UTC
|
Well, not fully complete - missing 3 and 6, maybe I'll update those later (I have to actually work now). Here are my attempts.
First time golfing :-)
Hole #1 (score 10):
sub b{(split)[4]}
Hole #2 (score 21): perl -e'
goto TPC '
Hole #4 (score 47):
sub b{$_=reverse;push@_,chr(hex(chop.chop))while$_;@_}
Hole #5 (score 32):
sub b{$t=pop;for(@_){$t=$_ if$_>$t}$t}
Update: Thanks tilly, I would never have noticed hole 5 - though I had some bad feelings about it. I don't know WHAT I was thinking for #1 :-)
update2: changed 5 to a working one now :-) | [reply] [d/l] [select] |
|
| [reply] |
Re: PGA Golf, Round 1
by petral (Curate) on May 25, 2001 at 18:08 UTC
|
I did slightly better in a couple of places, so probably wrong. I'll submit it now, before better solutions show up for everything. (Corrected holes 3 and 4 as per more-careful-readers-of-specs.)
# hole 1: 16
perl -le 'sub h1 {(pop=~/\w+/g)[4]}' -e'print h1"abc ,., de f g
+ hi jk"'
# hole 2: 20
perl -e'
goto
TPC'
# hole 3: 19
perl -le 'sub h3 {pop=~/^(.+?)\1+\z/s}' -e'print h3 join" ",qw(hihi
+hihi)'
# hole 4: 19
perl -le 'sub h4 {split"",pack"H*",@_}' -e'$,=$";print h4"68696C6f"
+'
# hole 5: 22 XXX see below:
perl -le 'sub h5 {$_<$x or$x=$_ for@_;$x}' -e'print h5(3,5,2,8,7)'
# hole 6: 38
perl -le 'sub h6 {grep{s/.//}sort map{/[aeiou]/;$&.$_}@_}' \
-e'$,=$";print h6 qw(book eel hi huge i pe
+a wrap)'
oopsdate: Yes, 5 doesn't work w/o priming the temporary (which makes it 30 chars).
So, here's an overly golfish version that I managed to trim to 32:perl -le'sub x {$_[-1]<$_[0]?pop:shift;$#_?&x:@_}' -e'print x(-3,-5,-2
+,-8,-7)'
(And yes, by the time I posted them, the solutions were all pretty much established. jmcnamara said he wasn't posting answers for a week, so it's a guess between not posting 'spoilers' and getting 'rep' -- especially when others are updating as you collect and cut and paste.  --  Anyway, it is kinda neat that, at least for these first few, the straightforward solutions are the best.)
  p
| [reply] [d/l] [select] |
Re: PGA Golf, Round 1
by srawls (Friar) on May 25, 2001 at 00:38 UTC
|
Hole #5 -- 27 chars (now 34, added $t-pop;):
sub MAX {$t=pop;
(grep{$t<$_?$t=$_:0}@_)[-1]
}
Update:Changed code--it didn't handle negative numbers before. (thanks for the /msg chemboy)
The 15 year old, freshman programmer,
Stephen Rawls | [reply] [d/l] |
Re: PGA Golf, Round 1
by iamcal (Friar) on May 25, 2001 at 12:00 UTC
|
sub hole_one{(pop=~/\w+/g)[4]}
#16 characters
hole two:
perl -e "print STDERR 'Can\'t find label TPC at -e line 5.'"
#60 characters (using tachyon's method)
sub hole_three{pop=~/^(.*?)\1+$/s}
#18 characters (handles carriage returns in the input)
sub hole_four{map{chr hex}(pop=~/(..)/g)}
#26 characters
sub hole_five{$a=pop;(grep{$a=$_ if $_>$a}@_)[-1]}
#35 characters (updated for negetive numbers)
sub hole_six{sort{($a=~/([aeiou])/)[0]cmp($b=~//)[0]}@_}
#42 characters
| [reply] [d/l] |
Re: PGA Golf, Round 1
by tachyon (Chancellor) on May 27, 2001 at 18:00 UTC
|
sub h{pop=~/(?:\w+\W*){4}(\w+)/}
Round 2, 15 sec
print STDERR"Can't find label TPC at -e line 5."
Round 3, 5 mins, Should probably use /s and \z but that's 2 extra chars
sub f{pop=~/^(.*?)\1+$/}
Round 4, 6 mins performance level inversly proportional to level of red in bottle
sub h{$_=pop;s/(..)/chr hex $1/eg;(/../g)}
Round 5, Back on form, 2 minutes
sub g{$m=pop;map{$m=$_ if $_>$m}@_;$m}
Round6, Took too damn long!
sub v{sort{eval'$a=~/([aeiou])/;$1'cmp eval'$b=~/([aeiou])/;$1'}@_}
Please sir can I have some more?
tachyon
Updated with corrections 29052001, and sadly all added length :-( | [reply] [d/l] [select] |
|
I'm afraid that your solutions to 1, 3, 4, and 5 must be disqualified.
Hole 1 specifies returning the fifth word; your solution returns some extra whitespace. Additionally, there may be no whitespace after the fifth word, or after any of the words:
first-second!third+fourth*fifth.
For Hole 3, the entire string must consist of the repeated substring. This was demonstrated in the examples, where 'ababab' results in 'ab' but 'ababaaa' results in ''.
Hole 4 asks for a list of characters, rather than a string. Looks like that one tripped up a lot of people. :)
Hole 5 features a common gotcha; a correct solution must handle the case where all the values in the list are negative. Another one that a lot of people don't catch. :)
We tried to make things a little easier at the actual tournament by providing a test scaffold for each hole, which the participants could use to test their code on sample input. Solving these holes is much harder without that.
| [reply] [d/l] |
Re: PGA Golf, Round 1
by tadman (Prior) on May 25, 2001 at 16:11 UTC
|
My submissions:
Hole 1 (16 characters)
sub f{
(pop=~/w+/g)[4]
}
Hole 2 (31 characters)
perl -e# -e# -e# -e# -egoto+TPC
Hole 3 (46 characters)
If only alphanumeric data will be processed:
sub f{
$p=$_=pop;1while(!/^($p){2,}$/&&$p=~s/.$//);$p
}
If required to support non-alpha, or unusual characters
in the input data (requires \Q...\E), then 51 characters:
sub f{
$p=$_=pop;1while(!/^(\Q$p\E){2,}$/&&$p=~s/.$//s);$p
}
Hole 4 (24 characters)
sub f{
map{chr hex$_}pop=~/../g
}
Hole 5 (30 characters)
sub f{
$x=pop;map{$_>$x?$x=$_:0}@_;$x
}
Hole 6 (39 characters)
sub f{
grep{s/.//}sort map{/[aeiou]/;"$&$_"}@_
}
Update:
Corrected hole 4 (returned string, wanted
list).
Reduced hole 6 (@x=@_ to @_, used $& instead
of memorizing)
Removed first 'version' of hole #5, which didn't handle
negative numbers, leaving the longer second version. | [reply] [d/l] [select] |
|
changing "$&$_" to $&.$_ saves you one stroke... 38 chars
- Ant
| [reply] |
|
|