Hi All,

Somone posted what seemed like a homework question here. I replied in a golfish format, and mentioned the fact to the CB. Chemboy suggested posting it as a real golf, wherupon CheeseLord stepped in and said that in a similer reply, which also called for Golf, tachyon had provided an even better answer than mine.

Seemed like an interesting problem, so I present the Nth annual rangify function golf contest!

Problem
Given an unsorted list of unique positive integers convert this list into a "rangeified" form, where all consequtive sequences of numbers are coded into a BEGIN-END format.

For instance, the list 1089,3,4,0,5,6,7,99,832,1087,831,1088
would become 0,3-7,99,831-832,1087-1089

In order to keep it interesting answers in three catagories will be allowed, also code _must_ be strict safe.

  1. Returns a stringified version of the list
  2. Returns a list
  3. Does *not* use map()
So to start things off I present my solution, rather big I must say at 105 chars, for catagories 1 and 3 as the following code:
# 1 2 3 4 5 6 # 01234567890123456789012345678901234567890123456789012345678901234567 +890 sub demerphq{ @0=sort{$a<=>$b}@_;$_=":@0";1 while s/:((\d+)(-(\d+))?) (\d+)/ $5-$2-1&&$5-$4-1?"$1,:$5":":$2-$5"/e;y/://d;$_ }
Thanks and apologies (for mispelling his name) to CheeseLord for a couple of tips. But from what I've heard it wont help me much....

:-)

Yves
--
You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

Replies are listed 'Best First'.
Re: (Golf) Rangify Array
by japhy (Canon) on Sep 27, 2001 at 08:14 UTC
    From List-to-Range generation... oh, and {$a-$b} sorts the same way that {$a<=>$b} does, in two fewer characters.
    # 27 * 3 - 1 = 80 chars sub num2range { #23456789012345678901234567 my$x=join',',sort{$a-$b}@_; $x=~s/(?<!\d)(\d+)(?:,((??{ $++1})))+(?!\d)/$1-$+/g;$x }

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

      You don't need to make that a non-capturing parenthesis, nor resort to lookahead/lookbehind trickery; a simple word boundary will do. Very nice trick with $+, though ;)
      # 27 + 40 + 2 = 69 dude! sub num2range { #234567890123456789012345678901234567890 my$x=join',',sort{$a-$b}@_; $x=~s/\b(\d+)(,((??{$++1})))+\b/$1-$+/g; $x }
        Hmm, good point. The capturing parens are fine. The reason I had look-ahead/behind was because I was looking at a larger problem which doesn't actually exist since we're dealing with numbers. Good move.

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

How I learned to stop worrying and love $1. (boo)
by boo_radley (Parson) on Sep 27, 2001 at 20:50 UTC
    3 attempts, the shortest weighing in at 77 characters(!), using japhys sort trick. I'm quite fond of the last two.

    my @d=(1089,3,4,0,5,6,7,99,832,1087,831,1088,10000); print "\nfirst try\n\n"; @ary= boo(@d); print "@ary"; print "\n\nsecond try\n\n"; @ary=boo2(@d); print "@ary"; print "\n\nthird try (stringify)\n\n"; $list=boo3(@d); print $list; sub boo { # 1 2 3 4 5 6 7 + 8 9 A B C #234567890123456789012345678901234567890123456789012345678901234567890 +1234567890123456789012345678901234567890123456789012345 @_=sort{$a-$b}@_;$a[0]=$_[0];map{$q=$_[$_-1];$_[$_]==$q+1||do{$a[-1].= +"-$q";push@a,$_[$_]};$a[-2]=~s/(\d+)-\1/$1/}(1..$#_);@a } sub boo2 { # 1 2 3 4 5 6 7 + 8 #234567890123456789012345678901234567890123456789012345678901234567890 +123456789012345678 $_=join$",sort{$a-$b}@_;while(/(\d+)/g){$e=$1+1;s/($1) $e/$1-$e/;s/-\d ++-/-/}split" " } sub boo3 { # stringify # 1 2 3 4 5 6 7 + #234567890123456789012345678901234567890123456789012345678901234567890 +1234567 $_=join$",sort{$a-$b}@_;while(/(\d+)/g){$e=$1+1;s/($1) $e/$1-$e/;s/-$1 +-/-/}$_ }
Re: (Golf) Rangify Array
by japhy (Canon) on Jan 31, 2004 at 04:44 UTC
    Since I just replied to someone's post, and directed them to my List-to-Range node, I thought I'd rehash this one, and pare it down by ONE stroke (from the best answer given).
    # 30 + 38 = 68 sub num2range { #2345678901234567890123456789012345678 local$_=join',',sort{$a-$b}@_; s/\b(\d+)(,((??{$++1})))+\b/$1-$+/g;$_ }
    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;