Vergleichen Sie zwei Pokerhände

14

Herausforderung:

Bestimmen Sie bei zwei Fünf-Karten-Händen anhand der Standardrangfolge der Pokerblätter , welche gewinnt .

Eingang:

Zehn durch Leerzeichen von stdin oder als Befehlszeilenargumente getrennte Karten, je nachdem, was Sie bevorzugen. Die ersten fünf Karten sind die Hand von Spieler 1, während die letzten fünf die Hand von Spieler 2 sind. Jede Karte besteht aus zwei Buchstaben der Form RS, wobei R Rang und S Farbe ist. Die Ränge reichen von 2-9, T für zehn und J, Q, K und A für Jack, Queen, King und Ace. Die Farben sind H, D, C, S für Herzen, Diamanten, Keulen und Pik. Sie müssen die Nummer des Spielers ausgeben, der gewinnt: '1' oder '2'.

Beispiele für Karten:

AS - the Ace of Spades
QD - the Queen of Diamonds
2C - the Two of Clubs
TH - the Ten of Hearts

Input to Output Beispiele:

5H 5C 6S 7S KD 2C 3S 8S 8D TD -> 2

Erklärung: Spieler 1 hat ein Paar Fünfer, während Spieler 2 ein Paar Acht hat.

5D 8C 9S JS AC 2C 5C 7D 8S QH -> 1

Erläuterung: Keiner der Spieler hat etwas Besonderes, aber die hohe Karte von Spieler 1 ist ein Ass, während die hohe Karte von Spieler 2 eine Dame ist.

2D 9C AS AH AC 3D 6D 7D TD QD -> 2

Erklärung: Spieler 1 hat drei Asse, Spieler 2 hat einen Flush of Diamonds.

4D 6S 9H QH QC 3D 6D 7H QD QS -> 1

Erläuterung: Beide Spieler haben ein Paar Damen, aber die zweithöchste Karte von Spieler 1 ist eine Neun, während die von Spieler 2 eine Sieben ist.

Regeln und Erläuterungen:

  • Weitere Informationen zum Vergleichen von Händen finden Sie in der Standardrangliste der Pokerblätter.
  • Sie können davon ausgehen, dass es keine wiederholten Karten in jedem Paar Hände gibt.
  • Sie können davon ausgehen, dass es jeweils einen konkreten Gewinner gibt.
  • Die Farbe berücksichtigt nicht die Rangfolge einer Hand. Zum Beispiel sind zwei Royal Flushes unterschiedlicher Farben gleich (daher ist jede Eingabe, bei der beide Spieler einen Royal Flush haben, nach der vorstehenden Regel ungültig).
  • Da dies Codegolf ist, gewinnt die kürzeste Antwort.

Anmerkungen:

Kommando
quelle
Entschuldigung, wenn ich etwas verpasst habe! Dies ist meine erste Code Golf Frage.
Kommando
Dies ähnelt der aktuellen Frage codegolf.stackexchange.com/q/23743/15599 und der 5-Karten-Version, auf die darin verwiesen wird. Diese Fragen werden jedoch nur benötigt, um die Art der Hand zu benennen. Ein großer Unterschied besteht darin, dass wir, wenn beide Spieler die gleiche Art von Hand haben, anhand des Kartenrangs bestimmen müssen, welche besser ist (z. B. für zwei Paare, wer das beste erste Paar, zweite Paar und gegebenenfalls eine einzelne Karte hat) Es ist kein Duplikat. Suchen Sie immer nach ähnlichen Fragen, verknüpfen Sie sie (ich sehe, dass Sie es getan haben) und seien Sie bereit, vor dem Posten zu verteidigen, warum es kein Duplikat ist.
Level River St
Was ist, wenn der Flop und die Hand gleich sind?
Ismael Miguel
@IsmaelMiguel In dieser Version gibt es keinen Flop. Es gibt einfach zwei separate Hände, die gegeneinander bewertet werden müssen.
Kommando
1
Zuvor für 10 Karten hier
Hasturkun

Antworten:

2

Haskell - 352 339 Zeichen

import Data.List
v h=10*(sum$map(\l->l*l)g)+b g:k where
  (g,k)=unzip$reverse$sort$map(\r->(length r,head r))$group$sort$map(maybe 0 id.(`elemIndex`"23456789TJQKA").head)h
  b(1:_)=f(map(!!1)h)+t k;b _=0
f(y:z)|all(==y)z=75;f _=0
t[y,_,_,_,z]|y-z==4=70;t[12,3,2,1,0]=65;t _=0
w(a,b)|v a>v b="1\n";w _="2\n"
main=interact$w.splitAt 5.words

Läuft:

& echo "5H 5C 6S 7S KD 2C 3S 8S 8D TD" | runhaskell 25056-Poker.hs 
2

& echo "5D 8C 9S JS AC 2C 5C 7D 8S QH" | runhaskell 25056-Poker.hs 
1

& echo "2D 9C AS AH AC 3D 6D 7D TD QD" | runhaskell 25056-Poker.hs 
2

& echo "4D 6S 9H QH QC 3D 6D 7H QD QS" | runhaskell 25056-Poker.hs 
1

Ungolf'd und kommentierte, so dass Sie das techinque sehen können:

import Data.List

value :: [String] -> [Int]
value hand = 10 * (sum $ map (\l->l*l) groups) + bonus groups : kicker
    -- ^ Value of a hand is 10 times the sum of the squares of the group lengths
    -- plus the straight & flush bonus, followed by the kicker (to break ties)
    -- This 10 * sum-of-squares + bonus works out to put the hands in category
    -- order, and then they only need to be ordered by card ranks.
  where
    -- | The cards are sorted into groups by matching rank, then the groups
    -- sorted by length and rank: For example: "7C 7D 7H QS 2S" will becomes
    -- [(3,7),(1,Q),(1,2)]. This is like a run-length encoding. Finally, the
    -- groups lengths, and the kicker ranks are taken apart into two lists.
    -- N.B: kicker here includes the ranks of the groups, unlike the poker term.

    (groups,kicker) = unzip             -- split apart
        $ reverse $ sort                -- reverse sort by (length,rank)
        $ map (\r->(length r,head r))   -- turn groups into (length,rank) pairs
        $ group $ sort                  -- group sorted ranks
        $ map (maybe 0 id . (`elemIndex`"23456789TJQKA") . head) hand
            -- take first letter of each card in the hand, and map to [0..12]

    -- | Give a bonus for flush and straight to hands with five cards,
    -- or equivalently hands where the largest group length is just 1
    bonus (1:_ ) = flush (map (!!1) hand)   -- flush takes the suits of the hand
                   + straight kicker        -- straight takes the ranks
    bonus _      = 0

    -- | A flush is if all suits match the first suit
    flush (y:z) | all (==y) z = 75
                | otherwise   =  0

    -- | There are two kinds of straight.
    -- N.B: If there are five groups, then there are no duplicate ranks
    straight [y,_,_,_,z] | y-z == 4 = 70    -- normal, high to low
    straight [12,3,2,1,0]           = 65    -- ace is low, but it sorts high
    straight _                      =  0

wins :: ([String], [String]) -> String
wins (a,b) | value a > value b = "1\n"
           | otherwise         = "2\n"

main = interact $ wins . splitAt 5 . words
MtnViewMark
quelle
2

Python - 774 722 707 698 685 Zeichen

import sys
t,q,e,u='--23456789TJQKA','SDCH',enumerate,len
_=lambda c,i=0:chr(97+c[i])
def j(s):
 v,g,l=[0]*15,[0]*4,''
 for c in s:
  r,s=c[0],c[1];v[t.find(r)]+=1;g[q.find(s)]+=1
 c,h,k,m,f=0,0,[0,0,[],[],[]],0,0
 for x,i in e(v):
  for b in[2,3,4]:
   if i==b:k[b]+=[x]
 v[1]=v[14]
 for x,i in e(v):
  if i:
   c+=1
   if c==5:m,h=1,x
   if i==1:l+=_([x])
  else:c=0
 f,l,d=max(g)//5*2,l[::-1],'';z=f+m
 if z==3:d='z'+l
 if k[4]:d='y'+_(k[4])+l
 if k[2] and k[3]:d='x'+_(k[3])+_(k[2])
 if z==2:d='w'+l
 if z==1:d='v'+_([h])
 if k[3]:d='u'+_(k[3])+l
 if u(k[2])>1:d='t'+_(k[2],1)+_(k[2])+l
 if u(k[2])==1>u(k[3]):d='s'+_(k[2])+l
 return d or l
p=sys.argv
print(1+(j(p[1:6])<j(p[6:])))

Ich habe mich entschieden, für jede Hand eine Zeichenfolge zu generieren, die sie repräsentiert, beginnend mit einem Zeichen für den Handtyp, gefolgt von Zeichen, die die jeweilige Variation des Typs beschreiben (z. B. welche Karte hatten Sie gerade 4?), Gefolgt von die Werte der verbleibenden Karten im Falle eines Gleichstands (wenn beide Spieler dasselbe Doppelpaar haben, muss die 5. Karte entscheiden, wer gewinnt). Ich habe es ziemlich ausgiebig getestet, aber ich spiele eigentlich nicht Poker, also hoffe ich, dass ich es richtig gemacht habe. Außerdem weiß ich, dass es noch nicht voll besetzt ist. Ich kann wahrscheinlich ein paar Dutzend Zeichen später abschneiden.

Tal
quelle
Töte 5 Zeichen mit _=lambda c:chr(97+c). Außerdem haben Sie nach :s und =s unnötige Leerzeichen . Verwenden Sie ;abschließend anstelle von neuen Zeilen Anweisungen, um das für Einrückungen verwendete Leerzeichen zu reduzieren.
user12205
Schön mit dem Lambda, danke!
Tal
2

JavaScript - 526 508

function a(b){b=b.split(" ");var c=b.splice(5,5),d=[],e=[],r=[8,9,5,6,1,2,3,10,4,7],A=14,K=13,Q=12,J=11,S={"S":1,"C":2,"H":4,"D":8};for(i=0;i<5;i++){d.push(b[i].split('')[1]);b[i]=b[i].split('')[0];e.push(c[i].split('')[1]);c[i]=c[i].split('')[0]}function p(w,m){var v,i,o,s=1<<w[0]|1<<w[1]|1<<w[2]|1<<w[3]|1<<w[4];for(i=-1,v=o=0;i<5;i++,o=Math.pow(2,w[i]*4)){v+=o*((v/o&15)+1)}v=v%15-((s/(s&-s)==31)||(s==0x403c)?3:1);v-=(m[0]==(m[1]|m[2]|m[3]|m[4]))*((s==0x7c00)?-5:1);return r[v]}alert(p(b,d)>p(c,e)?1:2)}

Verwendung:

a("5H 5C 6S 7S KD 2C 3S 8S 8D TD");

ungolfed:

function a(b) {
b = b.split(" ");
var c=b.splice(5,5),
        d=[],
        e=[],
        r=[8,9,5,6,1,2,3,10,4,7],
        A=14,
        K=13,
        Q=12,
        J=11,
        S={"S":1,"C":2,"H":4,"D":8};

    for (i=0;i<5;i++) {
        d.push(b[i].split('')[1]);
        b[i] = b[i].split('')[0];
        e.push(c[i].split('')[1]);
        c[i] = c[i].split('')[0];   
    }

function p(w,m){
  var v, i, o, s = 1<<w[0]|1<<w[1]|1<<w[2]|1<<w[3]|1<<w[4];
  for (i=-1, v=o=0; i<5; i++, o=Math.pow(2,w[i]*4)) {v += o*((v/o&15)+1);}
  v = v % 15 - ((s/(s&-s) == 31) || (s == 0x403c) ? 3 : 1);
  v -= (m[0] == (m[1]|m[2]|m[3]|m[4])) * ((s == 0x7c00) ? -5 : 1);
  return r[v];
}

alert(p(b,d)>p(c, e)?1:2);
}

Quelle

Alex
quelle
1

Perl, 801 733 Zeichen

Ich glaube, das ist eine ziemlich direkte Implementierung. Grundsätzlich sortieren wir für jede Hand die Anzüge und die Gesichter getrennt. Dann machen wir eine weitere Kopie der Gesichter mit niedrigen Assen, damit wir nach Geraden mit niedrigen Assen suchen können. Dann stellen wir fest, ob wir einen Flush oder eine Straße haben und wie hoch die Karte ist. Dann suchen wir nach Übereinstimmungen in der Reihenfolge des Ergebnisses (zuerst suchen wir nach Straight Flushes, dann nach Vierergruppen usw.). Die tatsächliche Punktzahl ist nur die Verkettung der Art der Hand, gefolgt von den Nennwerten der Karten in der Reihenfolge, in der sie wichtig sind (das ist _s () in der ungolfed-Version, u () in der golfed-Version). Hier ist es:

@l{2..9,qw(T J Q K A)}=2..14;sub u{join"",map{$_>9?$_:"0$_"}shift,ref$_[0]?$$_[0]:map{$h[$_]}@_}sub e{$p[$_[0]-1]-1==$p[$_[0]]}sub f{@p=@_;e(1)&&e(2)&&e(3)&&e 4}sub h{$h[$_[0]]==$h[$_[1]]}sub i{h(@_[0,1])&&h @_[2,3]}sub t{@s=sort map{substr($_,1)}@_;$f=$s[0]eq$s[4];@l=@h=sort{$b<=>$a}map{$l{substr($_,0,1)}}@_;@l=(@l[1..4],1)while$l[0]==14;$s=0;if(f@l){$s=1;$h=$l[0]}else{$h=$h[0];$s=1 if f@h}$f&&$s?u 9,\$h:h(4,1)?u 7,4,0:h(3,0)?u 7,3,4:i(4,3,2,0)?u 6,0,4:i(4,2,1,0)?u 6,4,0:$f?u 5,0:$s?u 4,\$h:h(4,2)?u 3,4,0,1:h(3,1)?u 3,3,0,4:h(2,0)?u 3,2..4:i(4,3,2,1)?u 2,2,4,0:i(4,3,1,0)?u 2,1,4,2:i(3,2,1,0)?u 2,1,3,4:h(4,3)?u 1,4,0,1,2:h(3,2)?u 1,3,0,1,4:h(2,1)?u 1,2,0,3,4:h(1,0)?u 1,1..4:u 0,0..4}print t(@ARGV[0..4])gt t(@ARGV[5..9])?1:2

Und hier ist das Äquivalent für weniger Golfspieler:

use strict;
use warnings;

# ace high or low in straights, otherwise high
# T = ten, J = jack, Q = queen, K = king, A = ace

# 0 high card
# 1 one pair
# 2 two pair
# 3 3 of a kind
# 4 straight
# 5 flush
# 6 full house
# 7 four of a kind
# 9 straight flush (royal flush a subclass of straight flush)

my %l;@l{2..9,qw(T J Q K A)}=2..14;
sub score {
  my @suits = sort map { substr($_,1) } @_;
  my @faces_h = sort { $b <=> $a } map { $l{substr($_,0,1)} } @_;
  my @faces_l = @faces_h;
  @faces_l = (@faces_l[1..4], 1) while $faces_l[0] eq 14;
  my $is_flush = $suits[0] eq $suits[4];
  my ($is_straight, $high_card);
  if($faces_l[0]-1==$faces_l[1] &&
     $faces_l[1]-1==$faces_l[2] &&
     $faces_l[2]-1==$faces_l[3] &&
     $faces_l[3]-1==$faces_l[4]) {
    $is_straight=1;
    $high_card = $faces_l[0];
  } else {
    $high_card = $faces_h[0];
    if($faces_h[0]-1==$faces_h[1] &&
       $faces_h[1]-1==$faces_h[2] &&
       $faces_h[2]-1==$faces_h[3] &&
       $faces_h[3]-1==$faces_h[4]) {
      $is_straight=1;
    }
  }
  return _s(9, \$high_card) if $is_flush && $is_straight;
  return _s(7, 4,0) if $faces_h[4] == $faces_h[1];
  return _s(7, 3,4) if $faces_h[3] == $faces_h[0];
  return _s(6, 0,4) if $faces_h[4] == $faces_h[3] && $faces_h[2] == $faces_h[0];
  return _s(6, 4,0) if $faces_h[4] == $faces_h[2] && $faces_h[1] == $faces_h[0];
  return _s(5, 0) if $is_flush;
  return _s(4, \$high_card) if $is_straight;
  return _s(3, 4,0,1) if $faces_h[4] == $faces_h[2];
  return _s(3, 3,0,4) if $faces_h[3] == $faces_h[1];
  return _s(3, 2,3,4) if $faces_h[2] == $faces_h[0];
  return _s(2, 2,4,0) if $faces_h[4] == $faces_h[3] && $faces_h[2] == $faces_h[1];
  return _s(2, 1,4,2) if $faces_h[4] == $faces_h[3] && $faces_h[1] == $faces_h[0];
  return _s(2, 1,3,4) if $faces_h[3] == $faces_h[2] && $faces_h[1] == $faces_h[0];
  return _s(1, 4,0,1,2) if $faces_h[4] == $faces_h[3];
  return _s(1, 3,0,1,4) if $faces_h[3] == $faces_h[2];
  return _s(1, 2,0,3,4) if $faces_h[2] == $faces_h[1];
  return _s(1, 1,2,3,4) if $faces_h[1] == $faces_h[0];
  return _s(0, 0..4);
}

sub _s {
  join "", map { $_ > 9 ? $_ : "0$_" } shift,
    ref $_[0] ? $$_[0] : map { $faces_h[$_] } @_
  # my @a=@_;
  #  if(ref $a[1]) {
  #    $a[1]=${$a[1]};
  #  } else {
  #    $a[$_]=$faces_h[$a[$_]] for 1..$#a;
  #  }
  #  join "", map { $_ < 10 ? "0$_" : $_ } @a;
}

my @p1 = @ARGV[0..4];
my @p2 = @ARGV[5..9];

my $s1 = score(@p1);
my $s2 = score(@p2);
print $s1 gt $s2 ? 1 : 2;
Skibrianski
quelle
AH 2C 3S 4S 5D 6C 7S 7C 7D TDproduziert ein Ergebnis von 2, aber ich denke, ein Straight schlägt drei
Gleiche