I've made a quick rundown of the methods used in the solutions that
got under a score of 80 (as an arbitrary cutoff).

First off, everybody in this group used a hash to collect anagram
sets, generating the key with some moral equivalent of
      join '', sort split //, $_;
the primary trick used here is to prepend some constant string to
force the sort into array context and let the auto-join of hash keys
help out.

Most solutions also presort the input so that the anagram sets will be
collected in sorted order. But a few people chose to collect anagram
sets unsorted and sort them later, allowing the use of -p tricks to
replace "for <>" and print.

I'll go through the main groups of solutions in order of the lowest
scoring member. (Each solution is given with score, time of entry (in
CEST = +0200), and golfer's name).

The first group of course contains the Best of Breed --- these entries
all collect the anagram sets separated by newlines, and then traverse
the whole hash multiple times, each time printing the ones that have a
specific number of words in them. Of course they need to replace all
newlines except the last by a space before the print happens.

One way to do that is to replace only one newline on each traversal,
and printing an anagram set exactly when the last internal newline is
replaced:

  61.44 Apr  8 02:00:00 Best of Breed
        #!perl
        map!s/
        ^/ /m|//||print,sort%/for map$/{_,sort/./g}.=$_,sort<>
  61.46 Apr  7 15:40:43 Lars Mathiesen
        #!perl
        map!s/
        ^/ /m|//||print,sort%0for map$0{0,sort/./g}.=$_,sort<>

The other way is to replace all internal newlines or spaces on each
run, and compare the number of replacements to an external counter:

  67.42 Apr  4 04:55:17 Rick Klement
        #!perl
        map$n^s/\s\b/ /g||print,sort%a,$n++for map$a{r,sort/./g}.=$_,sort<>
  76.46 Apr  7 04:48:06 Yanick Champoux
        #!perl
        map$1{join$|,sort/./g}.=$_,sort<>;map$g^s/\s\b/ /g||print,sort%1while++$g<99
  78.41 Apr  7 16:24:41 Geoff Hubbard
        #!perl
        ++$m^map{$m^s/
        (?!$)/ /g||print}sort%a=%.for map$.{join$m,sort/./g}.=$_,sort<>

The next main group uses an s/// when collecting the sets, to turn
newlines into spaces and add one dummy char at the start of the string
for each word, allowing a single sort to handle the number of words as
well as the words themselves. The final character got squeezed out
here when three people realized that two or more words meant at least
two newlines at the end.

  63.46 Apr  7 19:43:23 Stephen Turner
        #!perl
        $s{o,sort/./g}=~s/.*/~$& $_/for sort<>;print/ (.*
        )
        /for sort%s
  63.46 Apr  7 22:37:54 Ton Hospel
        #!perl
        $_{_,sort/./g}=~s/.*/_$& $_/for sort<>;print/ (.*
        )
        /for sort%_
  63.48 Apr  7 19:08:05 Jasper McCrea
        #!perl
        $o{1,sort/./g}=~s/.*/1$& $_/for sort<>;print/ (.*
        )
        /for sort%o
  64.44 Apr  3 15:19:23 Alma Media Golf Team
        #!perl
        $f{f,sort/./g}=~s/.*/~$& $_/for sort<>;print/~~ (.*
        )/for sort%f
  64.44 Apr  5 11:22:17 Adam Spiers
        #!perl
        $g{g,sort/./g}=~s/.*/~$& $_/for sort<>;print/~~ (.*
        )/for sort%g
  64.44 Apr  3 06:57:38 MeowChow
        #!perl
        $o{_,sort/./g}=~s/.*/_$& $_/for sort<>;print/__ (.*
        )/for sort%o
  66.42 Apr  8 00:32:29 Ari Kauppi
        #!perl
        $p{p,sort/(.)/g}=~s/.*/%$& $_/for sort<>;print/%% (.*
        )/for sort%p
  67.45 Apr  6 23:59:57 Colm Dougan
        #!perl
        map$s{1,sort/./g}=~s/(.*)
        */1$1 $_/,sort<>;map{/11 /;print$'}sort%s
  70.43 Apr  7 19:54:01 Amir Karger
        #!perl
        $o{join"",sort/./g}=~s/.*/~$& $_/for sort<>;print/\w+ .*\n/gfor sort%o
  74.49 Apr  4 22:37:50 Honza Pazdziora
        #!perl
        $h{"@{[sort/./g]}"}=~s/(.*)
        ?/{$1 $_/for sort<>;print grep s/{{+ //,sort%h

The third main way of doing it: Collect anagram sets in an array, one
entry for each set size, and print. Sets are collected with newlines,
which are turned into spaces in the same operation where the set size
is counted.

Finding the set size with split puts the words in @_, and a string
substitution puts in the spaces:

  68.44 Apr  5 15:50:34 Mtv Europe
        #!perl
        map$a{a,sort/./g}.=$_,sort<>;map$p[split].="@_
        "x/
        ./,sort%a;print@p
  72.39 Apr  7 05:14:21 Josef Drexler
        #!perl
        $o{g,sort/./g}.=$_ for sort<>;$g[split].="@_$/"for sort%o;print@g[2..$.]

Turning the newlines into spaces with s/// gives you the count:

  74.41 Apr  7 15:05:50 Keith Calvert Ivey
        #!perl
        map$%{join _,sort/./g}.=$_,sort<>;map$_[s]
        ^] ]gm].=/ /&&$_,sort%%;print@_
  75.41 Apr  7 22:38:15 Andrew Savige
        #!perl
        map$>{o,sort/./g}.=$_,sort<>;@}{s+
        (?=.)+ +g}.=$_ for sort%>;print@}{1..$=}

Note that two solutions filter out the hash keys and one-word 'sets'
before collecting, while the other two have to omit printing the ones
collected. The former approach seems to have an edge.

The fourth main group: Adding a sortable prefix in a separate
operation, showing the set size. All examples of -p tricks are here.
First some that use a fixed-length prefix.

The first one is actually wrong: It just prepends the number of
internal spaces as an integer, which will sort sets with 11 to 20
members between those with 2 and 3. But the test program only has one
case with sets of 2 and 10 members, and some with sets of 11.

  71.38 Apr  7 21:06:01 Terje K
        #!perl
        map$a{a,sort/./g}.=-$_,sort<>;map{/.-/&&print$'}sort map{s/
        -/ /g.$_}%a

Converting the number with chr:

  75.41 Apr  8 01:51:57 Jay Tilton
        #!perl -p
        $h{i,sort/./g}.=$_}for(sort map{chr(@_=sort split)|"h@_
        "}%h){s/i.*|.//s

Adding 8 or 9 to make all numbers from 2 to 15 into two-digit integers:

  76.36 Apr  7 19:37:25 Chris Dolan
        #!perl
        map$a{o,sort/./g}.=_.$_,sort<>;map{s/.._//&&print}sort map{9+s,\n_, ,g.$_}%a
  79.39 Apr  7 18:03:57 John McNamara
        #!perl
        map$j{join"",sort/./g}.=$_,sort<>;print+grep{s/.\d//}sort+map+8+split."@_\n",%j
  79.42 Apr  7 19:34:38 Joost Diepenmaat
        #!perl
        $f{z,sort/./g}.=$_ for<>;s/.\d//&&print for sort map{@r=sort/.+/g;8+@r."@r
        "}%f

Then some more (group four prime, perhaps) that add a variable length
prefix, to get the same picture as group two before the last sort.
More -p tricks here, and some intense obfuscation of that fact by
Juho, using } as the prefix. (It's interesting, FSVO, that only one
solution in group two used { or } as prefix, and here it's only Marko
who doesn't).

  74.38 Apr  5 01:26:50 Juho Snellman
        #!perl -p
        $a{a,sort/./g}.=$_}for(sort map"}"x(@a=sort/.+/g)."@a
        ",%a){/}}+/,$_=$'
  74.39 Apr  6 23:56:50 Eugene van der Pijll
        #!perl
        map$o{o,sort/./g}.=$_,sort<>;map{/}+/.print$'}sort map'}'x s/
        \b/ /g.$_,%o
  74.47 Apr  7 15:14:53 Marko Nippula
        #!perl -p
        $_{1,sort/./g}.=$_}for(sort+map{@_=sort/.+/g;1x$#_."
        @_
        "}%_){s/\C.*
        //
  75.40 Apr  8 00:35:24 Eirik Berg Hanssen
        #!perl
        map$_{_,sort/./g}.=$_,sort<>;print grep{s/}+//}sort map"}"x s/
        \b/ /g.$_,%_
  78.38 Apr  7 16:27:11 Rick Myers
        #!perl
        map$i{a,sort/./g}.=$_,sort<>;map{/{+/,print$'}sort map{'{'x s/
        (?=.)/ /g.$_}%i

In conclusion: There's more than one way to skin a cat, but still only
a finite number. But I was a bit surprised to see that noone else was
using the same method as I was.

I only wonder what the post mortem gamers will manage to do now.

Lars Mathiesen (U of Copenhagen CS Dep) <[EMAIL PROTECTED]> (Humour NOT marked)

Reply via email to