Bandingkan dua tangan poker

14

Tantangan:

Diberi dua kartu lima tangan, tentukan yang satu menang dengan peringkat standar tangan poker .

Memasukkan:

Sepuluh kartu dipisahkan oleh spasi dari stdin atau sebagai argumen baris perintah, mana yang Anda inginkan. Lima kartu pertama adalah kartu Player 1 sedangkan kartu terakhir adalah kartu Player 2. Setiap kartu akan berupa string dua huruf dari bentuk RS di mana R adalah peringkat dan S sesuai. Jajarannya berkisar 2-9, T untuk sepuluh, dan J, Q, K, dan A untuk Jack, Queen, King, dan Ace. Setelannya masing-masing adalah H, D, C, S untuk Hati, Berlian, Klub, dan Sekop. Anda harus menampilkan jumlah pemain yang menang: '1' atau '2'.

Contoh Kartu:

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

Contoh Input ke Output:

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

Penjelasan: Player 1 memiliki Pair of Fives sementara Player 2 memiliki Pair of Eights.

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

Penjelasan: Tidak ada Player yang memiliki sesuatu yang istimewa, tetapi kartu tinggi Player 1 adalah Ace sedangkan kartu tinggi Player 2 adalah Queen.

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

Penjelasan: Player 1 memiliki Three Aces, Player 2 memiliki Flush of Diamonds.

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

Penjelasan: Kedua pemain memiliki Pair of Queens, tetapi kartu tertinggi kedua Player 1 adalah Sembilan sedangkan Player 2 adalah Tujuh.

Aturan dan Klarifikasi:

  • Lihat peringkat standar tangan poker untuk rincian membandingkan tangan.
  • Anda dapat mengasumsikan bahwa tidak ada kartu berulang di setiap pasang tangan.
  • Anda dapat berasumsi bahwa ada pemenang yang pasti dalam setiap kasus.
  • Gugatan tidak menjadi faktor dalam peringkat tangan. Misalnya, dua flush royal dari suit yang berbeda sama (oleh karena itu setiap input di mana kedua pemain memiliki flush royal tidak valid oleh aturan sebelumnya).
  • Karena ini adalah kode golf, jawaban terpendek menang.

Catatan:

komando
sumber
Permintaan maaf jika ada sesuatu yang saya lewatkan! Ini adalah pertanyaan golf kode pertama saya.
commando
Ini mirip dengan pertanyaan ini codegolf.stackexchange.com/q/23743/15599 dan versi 5-kartu yang direferensikan di dalamnya. Namun pertanyaan-pertanyaan itu hanya diperlukan untuk menyebutkan jenis tangan. Perbedaan besar di sini adalah bahwa jika kedua pemain memiliki jenis tangan yang sama, kita harus menentukan mana yang lebih baik berdasarkan peringkat kartu (misalnya untuk dua pasangan, yang memiliki pasangan pertama terbaik, pasangan kedua, dan jika perlu kartu tunggal.) Oleh karena itu itu bukan duplikat. Selalu mencari pertanyaan serupa, tautkan, (saya lihat Anda tahu) dan bersiaplah untuk membela mengapa itu bukan duplikat sebelum memposting.
Level River St
Bagaimana jika kegagalan dan tangan sama?
Ismael Miguel
@IsmaelMiguel Tidak ada kegagalan dalam versi ini. Hanya ada dua tangan yang terpisah yang harus dievaluasi satu sama lain.
commando
1
Sebelumnya diselesaikan untuk 10 kartu di sini
Hasturkun

Jawaban:

2

Haskell - 352 339 karakter

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

Berjalan:

& 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

Tidak dikomentari dan dikomentari, sehingga Anda dapat melihat techinque:

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
sumber
2

Python - 774 722 707 698 685 karakter

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

Saya memilih untuk membuat string untuk masing-masing tangan yang mewakilinya, dimulai dengan karakter untuk jenis tangan, diikuti oleh karakter yang menggambarkan variasi jenis tertentu (misalnya, kartu apa yang baru Anda miliki 4?), Diikuti oleh nilai kartu yang tersisa dalam kasus seri (jika kedua pemain memiliki pasangan ganda yang sama, kartu ke-5 harus memutuskan siapa yang menang). Saya sudah mengujinya secara ekstensif, tetapi saya tidak benar-benar bermain poker, jadi saya harap saya bisa melakukannya dengan benar. Juga, saya tahu itu belum sepenuhnya golf, saya mungkin bisa mencukur beberapa lusin karakter di kemudian hari.

Tal
sumber
Bunuh 5 karakter dengan _=lambda c:chr(97+c). Juga, Anda memiliki spasi putih yang tidak perlu setelah :s dan =s. Akhirnya, gunakan ;bukan baris baru untuk memisahkan pernyataan untuk mengurangi spasi putih yang digunakan untuk indentasi.
user12205
Bagus dengan lambda, terima kasih!
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)}

pemakaian:

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

sumber

Alex
sumber
1

perl, 801 733 karakter

Saya percaya ini adalah implementasi yang sangat mudah. Pada dasarnya, untuk masing-masing tangan, kami menyortir jas dan wajah secara terpisah. Kemudian kita membuat salinan lain dari wajah-wajah dengan ace menghitung rendah sehingga kita dapat memeriksa lurus dengan ace rendah. Kemudian kita menentukan apakah kita memiliki flush atau lurus, dan apa kartu tinggi itu. Kemudian kami hanya memeriksa pertandingan dalam urutan skor (pertama kami memeriksa straight flushes, kemudian empat dari jenis, dll.). Skor aktual hanyalah gabungan dari jenis tangan yang diikuti oleh nilai nominal kartu sesuai urutannya (itu _s () dalam versi yang tidak dikoleksi, u () dalam versi golf). Ini dia:

@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

Dan inilah yang kurang setara golf:

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
sumber
AH 2C 3S 4S 5D 6C 7S 7C 7D TDmenghasilkan hasil 2, tapi saya pikir lurus mengalahkan tiga sejenis
r3mainer