tags:

views:

361

answers:

4

Hi! I'm creating a ladder system for some games and I've encountered a problem regarding the clan base system. You see, every player who joins are parsed and put into a players table. Like this:

chelsea | gordon 
chelsea | jim
chelsea | brad

OR...

CLANTAG|> jenna
CLANTAG|> jackson
CLANTAG|> irene

So, what I want: I wanna grab the CLANTAG, which is at the same place and identical in every players name, which are on that team. But, the separator could be anything from whitespace to nothing (clan player1, clan player2 OR clanplayer1, clanplayer2).

Any ideas on how to do this?

Thanks in advance.

+1  A: 

Taking a wild stab here, is this what you want?

#! /usr/bin/perl

use strict;
use warnings;

while (<DATA>)
{
  if (/^(\w+) \| (\w+)$/     ||
      /^\[(\w+)\] \. (\w+)$/ ||
      /^(\w+)-(\w+)$/)
  {
    print "tag=$1, name=$2\n";
  }
}

exit 0;

__DATA__
team1 | foo
team1 | bar

[another] . user
[another] . player

more-james
more-brown

Because it generates:

tag=team1, name=foo
tag=team1, name=bar
tag=another, name=user
tag=another, name=player
tag=more, name=james
tag=more, name=brown
Paul Beckingham
Not exactly, because the separator varies. It could be anything from whitespace to nothing at all, just like TEAMplayer1, TEAMplayer2. And I also wanna grab the TAG, not the player name. :)
Okay, if you're a bit more specific about the format, the answer will be closer to what you need.
Paul Beckingham
The format? Like I said, it can be everything, the only thing we know is that it's an equal part of every team members name.
Ah, I see - you're looking for something on the left side that is common across multiple lines. That's a little harder...
Paul Beckingham
Yes that's correct! But is it possible..?
Yes, it's possible. You just need to look for the leftmost longest common substring between arbitrary groups of lines. It's not easy though.
Paul Beckingham
Well, it's not something you'd want to solve with a regex, so it's going to diverge from your question. You might have more success editing this question so that it no longer specifies regex.
Chad Birch
Well, then I have to know what to solve it with.. if I'm going to specify something else.
You don't have to specify, just describe the problem. For example, do all players (I'm assuming this is games) use an identical clan tag? Or will some do [IDL] and some do IDL| ? Are all the names of people on the same team already grouped, or do you have to make the program do the grouping as well?
Chad Birch
+1  A: 

Edit: re-read question and comments..

This works for the example, but may not work for names with spaces or punctuation, and possibly other scenarios:

while ( <DATA> )
{
    if ( /(\w+).*?(\w+)$/ )
    {
        print "$1, $2\n";
    }
}


__DATA__
team1 | foo
team1 | bar

[another] . user
[another] . player

more-james
more-brown

Gives:

team1, foo
team1, bar
another, user
another, player
more, james
more, brown
Chris J
Please read my comments on the first answer.. thanks!
Ah, missed the no-separator case. If you have teamjones and teamjoe, then there's no way to know if the team name is "team", "teamj", "teamjo", etc.
Chris J
That's not bad, that in fact worked on every team I had stored in the database. If we perhaps add a little fail-safe to that, it might be just what I need.. :) Thanks
A: 

If you're just running the regex on one player's name at a time, I would suggest:

/(\w+)\W+(\w+)$/

In English, this means "at least one word character, followed by at least one non-word character, followed by at least one word character, and then the end of the line"

"Word character" is letters, numbers, and underscores. So if people ever use anything other than those characters in their tags/nicks, it'll need modification. For example, if people might also have hyphens in their nicks you'd need:

/(\w+)\W+([\w-]+)$/

As far as I know, people always use punctuation-type characters (and/or whitespace) for the separation between their clan and their nick, so the \W+ there should be fine.

As for the case you gave with no separator (clanplayer1, clanplayer2), there's no way to solve this without looking at multiple players' names that you know are in the same clan, and figuring out at which point their names start to differ, so it can't be solved with a regex alone.

Chad Birch
I think he wants to derive the team name, so for "fooA" and "fooB" he wants "foo" extracted, ie longest leftmost commonality, and of course ignoring any formatting/separator junk.
Paul Beckingham
+4  A: 

Here's a shot:

use strict;
use warnings;

my($strip) = shift || 0;

print FindTeamName("TEAMJimBob", "TEAMJoeBob", "TEAMBillyBob"), "\n";
print FindTeamName("TEAM|JimBob", "TEAM|JoeBob", "TEAM|BillyBob"), "\n";
print FindTeamName("TEAM | JimBob", "TEAM | JoeBob", "TEAM | BillyBob"), "\n";
print FindTeamName("TEAMJimBob", "TEAM|JoeBob", "TEAM - BillyBob"), "\n";

sub FindTeamName
{
    my(@players) = @_;

    my($team) = shift;
    foreach my $player (@players) {
     $team = FindCommonString($team, $player);
    }

    $team =~ s{\W+$}{} if $strip;

    $team;
}

sub FindCommonString
{
    my($str1, $str2) = @_;

    my(@arr1) = split(//, $str1);
    my(@arr2) = split(//, $str2);

    my($common) = "";

    while (@arr1 && @arr2) {
     my($letter1) = shift(@arr1);
     my($letter2) = shift(@arr2);

     if ($letter1 eq $letter2) {
      $common .= $letter1;
     }
     else {
      last;
     }
    }

    $common;
}

which gives the following:

C:\temp>perl test.pl
TEAM
TEAM|
TEAM |
TEAM

C:\temp>perl test.pl 1
TEAM
TEAM
TEAM
TEAM

C:\temp>
Joe Casadonte
There ya go. Nice.
Paul Beckingham
That's brilliant, thanks! =)