Re: Pattern Matching Query
by BrowserUk (Patriarch) on Sep 17, 2002 at 12:46 UTC
|
Update: Added missing brackets and an afterthought at the bottom. And corrected the error blakem pointed out below.
You don't need a regex, a simple index will do fine. This has the additional benefit that $run will give you a comparative value for determining the value of the hand.
if (($run = index('abcdefghijklm', $sorted_values,0)) > -1)
{
# Do stuff...
}
In fact, if you arranged for your sort of the cards to sort aces above kings, then you could use the $run values to determine which run has the higher scoring value. (I think. I'm not much of a card player :^)
Well It's better than the Abottoire, but Yorkshire! | [reply] [d/l] |
|
A return value of 0 from index actually means it found the substr at position 0. An rv of -1 indicates failure. Therefore:
if (index('abcdefghijklm', $sorted_values) > -1)
{
# Do stuff...
}
-Blake
| [reply] [d/l] |
Re: Pattern Matching Query
by blakem (Monsignor) on Sep 17, 2002 at 12:49 UTC
|
How about using $sorted_values as the regex?
if ("abcdefghijklm" =~ /$sorted_values/) {
...
}
Update Or index would work as well.
-Blake
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
Re: Pattern Matching Query
by davorg (Chancellor) on Sep 17, 2002 at 12:52 UTC
|
Regexes aren't always the answer. This solution uses substr and the magical autoincrement properties of strings.
#!/usr/bin/perl -w
use strict;
while (<DATA>) {
chomp;
my $card = substr $_, 0, 1;
my $run = 1;
foreach my $x (1 .. 4) {
++$card ne substr $_, $x, 1 and $run = 0, last;
}
print "$_ - ", $run ? 'yep' : 'nope', "\n";
}
__DATA__
abcde
abcef
fghij
acghm
Update: Argh! Or either of the previous answers would probably be better :(
--
<http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [d/l] |
Re: Pattern Matching Query
by rob_au (Abbot) on Sep 17, 2002 at 13:51 UTC
|
In the spirit of TMTOWTDI ...
my @matches = (
'abcde', 'bcdef', 'cdefg', 'defgh', 'efghi', 'fghij', 'ghijk', 'hi
+jkl', 'ijklm'
);
if ( grep { $sorted_values eq $_ } @matches ) {
# ...
}
This approach makes for easy maintenence, particularly, if there a number of points in the code where matching is to be carried out. However, this method should prove to be slower compared to other methods in that it executes in O(n), where n is the number of elements in @matches.
YMMV
| [reply] [d/l] [select] |
Re: Pattern Matching Query
by Solo (Deacon) on Sep 17, 2002 at 12:54 UTC
|
I think you want the qr{} operator. See perldoc perlop.
use warnings;
use strict;
my $hand = 'defgh';
my @tests = ( qr/abcde/,
qr/bcdef/,
qr/cdefg/,
qr/defgh/,
);
for my $test (@tests) {
if ($hand =~ /$test/) {
# do stuff
# print "Got a straight\n";
}
}
Update: As others have suggested in the full thread there are more elegant ways to do this.
--
May the Source be with you.
You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.
| [reply] [d/l] [select] |
Re: Pattern Matching Query
by thunders (Priest) on Sep 17, 2002 at 20:50 UTC
|
similar to some of the above and limited to only the cases you mentioned
if ('abcdefghijklm' =~ qr/$sv/ && $sv =~/^[a-m]{5}$/){
&do_stuff
}
| [reply] [d/l] |
|
if (join('','a'..'m') =~ qr/$sv/ && $sv =~/^[a-m]{5}$/){
print "Matched\n";
}
Which just means you don't need to specify the whole of the range, just the start and end, you could sub it like this:
sub match_range {
my ($string, $start, $end, $length) = @_;
if (join('',$start .. $end) !~ qr/$string/) { return 0; }
if ($string !~ /^[${start}-${end}]{$length}$/) { return 0; }
return 1;
}
| [reply] [d/l] [select] |
|
Nice, but since boolean operators shortcircuit anyway (ie the right operand of && won't even be evaluated if the left one is already false), you just added a lot of blocks for no gain. Also, return 0 is a bad meme, if you want to return false then just return (which is equivalent to return wantarray ? () : undef).
sub match_range {
my ($string, $start, $end, $length) = @_;
my $range = join '', $start .. $end;
return
$range =~ /$string/
&& $string =~ /^[$range]{$length}$/;
}
Just a bit of nitpickery.. :-)
Makeshifts last the longest. | [reply] [d/l] |
|
|
|
Re: Pattern Matching Query
by Lexicon (Chaplain) on Sep 17, 2002 at 17:14 UTC
|
Yay, another poker module!
I wrote a fairly efficient Classify_Hand subroutine in my Poker Probability Processor. It works on arbitrarily large hands and returns a string indicating the rank of the hand. It, and the rest of the module, might be worth looking at. I had originally intended to extend it to calculate odds of winnning various types of poker, including Texas Holdem', but after all the time writing the Combinator module, I was done. ;)
| [reply] |
|
Hi Lexicon,
Interesting stuff - I wish I'd searched PM before I started in on this! Although I probably would have written my version anyway as I have really improved my Perl over the past week or so.
One of the things that I noticed was that you can use a lot of cheats rather than look for the exact hand (mine only work for five cards though) - for example, if a unique list of the card values has only two elements then it must be either a full house or a four-of-a-kind. This reduces by a long way the amount of work to be done. I've also realised that I can rank the hand using the standard gt, lt and eq operators because of the way I set out how the hand's score is formatted.
The version I'm working on at the moment uses an object oriented (something I'm trying to get a handle on) interface to handle the card-related functions: Shuffling, dealing, flopping, turn, river and who wins. I've also added a sethand function so that it can be used for basic statistical analyses. The next thing for me to write is an overlying game & betting manager so that it can be used as the basis for some kind of AI Poker competition or game.
Thanks, Elgon
"What this book tells me is that goose-stepping morons, such as yourself, should read books instead of burning them."
- Dr. Jones Snr, Indiana Jones and the Last Crusade
| [reply] [d/l] [select] |
|
Tis very try, but we played some three card games like Pineapple and some seven card games like Anaconda and 7 Card Stud. Plus, since I wasn't prepared to write an AI, it gives some indication of hand frequency when playing optimal 5 card draw.
I originally was writing the module to be object oriented, but do to the sheer speed requirements, I went this direction. As I recall, method calls are an order of magnatude slower than mere subroutine calls. Can anyone verify that? Unless you're planning an exhaustive search of the hand space, there's not much need for that kind of speed though. And a poker AI isn't going to be a branching tree search like Go or Chess, I'd imagine it would be mostly statistics based, also not so speed dependent.
The poker project drastically improved my Perl and general programming skills and math skills as well, especially the Math::Combinatorics::Combinator module, which required a heafty amount of analysis and then a heafty amount of optimization, and led to a couple of researching side projects like Fundamental Benchmarks.
So yeah, I love this kind of useless project (well, mine was useless :).
| [reply] |
|
Re: Pattern Matching Query
by perlguy (Deacon) on Sep 17, 2002 at 17:03 UTC
|
more in the spirit of TMTOWTDI:
UPDATE: I should have used the character class
[a-z] instead of \l\w in the first part of the regex, that way numbers, uppercase characters and underscores wouldn't be matched. it would still work either way, though.
if (/(\l\w)(?{local $lastchar = ord $1;})(??{chr(++$lastchar)}){4}/) {
# INSERT YOUR CODE HERE
}
| [reply] [d/l] [select] |