Porównaj dwie ręce pokera

14

Wyzwanie:

Biorąc pod uwagę dwa pięciokartowe układy, określ, które z nich wygrywają, poprzez standardowy ranking układów pokera .

Wejście:

Dziesięć kart oddzielonych spacjami od standardowego wejścia lub jako argumenty wiersza poleceń, w zależności od tego, co wolisz. Pierwsze pięć kart to ręka Gracza 1, a ostatnie pięć to Ręka Gracza 2. Każda karta będzie dwuliterowym ciągiem postaci RS, w której R ma rangę, a S ma kolor. Rangi wahają się od 2-9, T dla dziesięciu oraz J, Q, K i A odpowiednio dla Jacka, Królowej, Króla i Asa. Kolorami są odpowiednio H, D, C, S dla kier, karo, trefl i pik. Musisz podać numer zwycięskiego gracza: „1” lub „2”.

Przykłady kart:

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

Przykłady danych wejściowych:

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

Objaśnienie: Gracz 1 ma parę piątek, podczas gdy gracz 2 ma parę ósemek.

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

Objaśnienie: Żaden z graczy nie ma nic specjalnego, ale najwyższą kartą gracza 1 jest as, a wysoką kartą gracza 2 jest królowa.

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

Objaśnienie: Gracz 1 ma trzy asy, gracz 2 ma kolor diamentów.

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

Objaśnienie: Obaj gracze mają parę królowych, ale drugą najwyższą kartą Gracza 1 jest Dziewiątka, a Gracza 2 Siódemka.

Zasady i wyjaśnienia:

  • Szczegółowe informacje na temat porównywania rąk można znaleźć w standardowym rankingu rąk pokerowych .
  • Możesz założyć, że w każdej parze nie ma powtarzających się kart.
  • Możesz założyć, że w każdym przypadku jest określony zwycięzca.
  • Kolor nie bierze udziału w rankingu ręki. Na przykład dwa królewskie kolory w różnych kolorach są równe (w związku z tym wszelkie dane wejściowe, w których obaj gracze mają kolor królewski, są nieważne zgodnie z powyższą regułą).
  • Ponieważ jest to kod golfowy, wygrywa najkrótsza odpowiedź.

Uwagi:

komandos
źródło
Przepraszam, jeśli coś mi umknęło! To jest moje pierwsze pytanie dotyczące golfa.
komandos
Jest to podobne do tego ostatniego pytania codegolf.stackexchange.com/q/23743/15599 i wersji 5- kartowej w nim zawartej . Jednak te pytania wymagały jedynie podania rodzaju ręki. Duża różnica tutaj polega na tym, że jeśli obaj gracze mają ten sam typ ręki, musimy ustalić, która z nich jest lepsza według rangi karty (np. Dla dwóch par, która ma najlepszą pierwszą parę, drugą parę, a jeśli to konieczne jedną kartę). to nie jest duplikat. Zawsze szukaj podobnych pytań, łącz je (i widzę, że tak zrobiłeś) i bądź przygotowany na obronę, dlaczego nie jest duplikatem przed opublikowaniem.
Level River St
Co jeśli flop i ręka są takie same?
Ismael Miguel
@IsmaelMiguel W tej wersji nie ma flopa. Są po prostu dwie oddzielne ręce, które należy ocenić względem siebie.
komandos
1
Uprzednio rozwiązany przez 10 kart tutaj
Hasturkun

Odpowiedzi:

2

Haskell - 352 339 znaków

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

Działa:

& 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 i skomentował, dzięki czemu można zobaczyć technikę:

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
źródło
2

Python - 774 722 707 698 685 znaków

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:])))

Postanowiłem wygenerować ciąg znaków dla każdej reprezentującej go ręki, zaczynając od znaku dla rodzaju ręki, po którym następują znaki opisujące konkretną odmianę rodzaju (na przykład, którą kartę miałeś 4 z?), A następnie wartości pozostałych kart w przypadku remisu (jeśli obaj gracze mają tę samą podwójną parę, piąta karta będzie musiała zdecydować, kto wygra). Testowałem to dość obszernie, ale tak naprawdę nie gram w pokera, więc mam nadzieję, że mam rację. Wiem też, że nie jest jeszcze w pełni golfa, prawdopodobnie później mogę zgolić kilkadziesiąt znaków.

Tal
źródło
Zabij 5 znaków za pomocą _=lambda c:chr(97+c). Ponadto masz trochę niepotrzebnych białych znaków po :s i =s. Na koniec użyj ;zamiast nowych wierszy do oddzielenia instrukcji, aby zmniejszyć białe znaki używane do wcięć.
user12205
Niezły z lambda, dzięki!
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)}

stosowanie:

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

bez golfa:

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);
}

źródło

Alex
źródło
1

perl, 801 733 znaków

Uważam, że jest to dość prosta implementacja. Zasadniczo dla każdej ręki sortujemy kolory i twarze osobno. Następnie tworzymy kolejną kopię twarzy z asami liczącymi niskie, abyśmy mogli sprawdzić stritów z niskimi asami. Następnie ustalamy, czy mamy kolor, czy strit i jaka jest wysoka karta. Następnie sprawdzamy tylko mecze w kolejności punktacji (najpierw sprawdzamy, czy są to kolory, a potem cztery rodzaje itp.). Rzeczywisty wynik jest tylko połączeniem rodzaju ręki, po której następuje wartość nominalna kart w kolejności, w jakiej się liczą (to _s () w wersji bez golfa, u () w wersji golfowej). Oto on:

@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

A oto odpowiednik mniej golfa:

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
źródło
AH 2C 3S 4S 5D 6C 7S 7C 7D TDdaje wynik 2, ale myślę, że strita bije trójkę
r3mainer