Pilih kartu terakhir di tangan poker

31

Tangan poker diurutkan dari yang terbaik ke yang terburuk sebagai berikut:

  1. Straight flush - lima kartu dengan peringkat berurutan, semuanya dengan jenis yang sama
  2. Empat kartu sejenis - empat kartu dengan peringkat yang sama dan satu kartu dengan peringkat lain
  3. Rumah penuh - tiga kartu dari satu peringkat dan dua kartu dari peringkat lain
  4. Flush - lima kartu semua jenis yang sama
  5. Lurus - lima kartu peringkat berurutan
  6. Tiga kartu sejenis - tiga kartu dengan peringkat yang sama dan dua kartu dengan dua peringkat lainnya
  7. Dua pasangan - dua kartu dengan peringkat yang sama, dua kartu dengan peringkat lain dan satu kartu dengan peringkat ketiga
  8. Satu pasang - dua kartu dengan peringkat yang sama dan tiga kartu dengan tiga peringkat lainnya
  9. Kartu tinggi - lima kartu tidak semua peringkat berurutan atau jenis yang sama, dan tidak ada yang memiliki peringkat yang sama

  • Rangking = Angka pada kartu (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Anda dapat memilih untuk menggunakan T daripada 10.
  • Suit = hati (h), sekop, klub (c) dan berlian (d).

Perhatikan bahwa Ace,, Adapat berupa angka tertinggi dan terendah (1 atau 14).

Kartu dapat diidentifikasi dengan dua huruf As(Ace of spades), Jc(Jack of Clubs), 7h(7 of hearts) dan sebagainya.


Tantangan:

Anda mendapatkan empat kartu dari dealer (empat string input). Temukan dan hasilkan kartu terakhir sebaik mungkin yang bisa Anda dapatkan.

Jika ada kartu yang sama baiknya maka Anda dapat memilih mana yang akan dipilih.

Format input dan output adalah opsional, tetapi masing-masing kartu harus diidentifikasi seperti yang ditunjukkan di atas Jcdan 2h.


Kasus uji:

Ah Kh Jh 10h
Qh

7d 8h 10c Jd
9d (or 9h, 9c, 9s)

Js 6c 10s 8h
Jc (or Jh, Jd)

Ac 4c 5d 3d
2h (or 2d, 2c, 2s)

5s 9s Js As
Ks

2h 3h 4h 5h
6h

Js Jc Ac Ah
As (or Ad)  <- Note that AAAJJ is better than AAJJJ because A is higher than J

10d 9d 5h 9c
9h (or 9s)

Ah Ac Ad As
Ks (or Kd, Kh, Kc)

4d 5h 8c Jd
Jc (or Js, Jh)

Ini adalah kode golf, jadi pengiriman terpendek dalam byte menang.

Stewie Griffin
sumber

Jawaban:

13

Pyth, 73 byte

eo_S+*-5l@\AN}SPMJ+NZSM.:+\AT5+-4l{eMJlM.gPkJ-sM*=T+`M}2Tc4"JQKA""hscd"=Zc

Ini sangat mengerikan. Mem-parsing kartu, menyortir nilai-nilai, ... Semuanya membutuhkan banyak karakter. Tapi pendekatannya menarik.

Cobalah online: Demonstrasi atau Test Suite

Penjelasan:

Saya menghasilkan semua 52 kartu, mengeluarkan empat kartu dari input, menghasilkan skor untuk setiap kartu (skor tangan), dan mencetak kartu dengan skor maksimal.

Skornya sedikit aneh. Jika saya membandingkan skor dua tangan yang sama sekali berbeda, itu mungkin memilih pemenang yang salah. Misalnya lurus akan mengalahkan 4 ace. Tapi berhasil, jika 4 kartu pertama sama di kedua tangan. Dan skor saya yang dihitung sebenarnya bukan nilai, tetapi daftar nilai:

  • G: Pertama saya mengelompokkan 5 kartu berdasarkan peringkat dan mengambil panjang: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Lalu saya tambahkan 4 dikurangi jumlah suite yang berbeda ke daftar ini. Flush -> 3akan ditambahkan, not flush -> 2/1/0akan ditambahkan.
  • S: Tambahkan nomor lain. 0jika tidak lurus, 4jika lurus A2345, atau 5jika lurus lebih tinggi.

Daftar nomor 4-7 ini disortir dalam urutan menurun dan daftar dengan nilai maksimal dipilih.

Mengapa ini bekerja? Di sini Anda melihat konfigurasi yang mungkin untuk semua jenis. Huruf di sebelah angka, memberi tahu Anda aturan mana nomor ini dihasilkan.

  • Straight flush: [5S, 3F, 1G, 1G, 1G, 1G, 1G]atau[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Empat jenis: [4G, 1G, 0F, 0S]
  • Rumah penuh: [3G, 2G, 1F, 0S]atau[3G, 2G, 0F, 0S]
  • Menyiram: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Lurus: [5S, 2F, 1G, 1G, 1G, 1G, 1G], [5S, 1F, 1G, 1G, 1G, 1G, 1G], [5S, 1G, 1G, 1G, 1G, 1G, 0F], [4S, 2F, 1G, 1G, 1G, 1G, 1G], [4S, 1F, 1G, 1G, 1G, 1G, 1G],[4S, 1G, 1G, 1G, 1G, 1G, 0F]
  • Tiga dari jenis: [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • Dua pasang: [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • Satu pasang: [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • Kartu tinggi: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth membandingkan daftar elemen-bijaksana. Jadi sudah jelas bahwa Straight flush akan selalu mengalahkan Four of a kind. Sebagian besar aturan poker khas jelas dengan daftar ini. Beberapa tampak saling bertentangan.

  • A Straight akan menang melawan Four of a kind atau Full house: Tidak masalah. Jika Anda memiliki kesempatan untuk mendapatkan Four of a kind / Full house dengan kartu sungai, daripada Anda tidak dapat mencapai lurus pada saat yang sama (karena Anda sudah memiliki 2 atau 3 suite yang berbeda di tangan Anda).
  • Straight akan menang melawan flush. Jika Anda dapat mencapai flush dan lurus dengan kartu sungai, maka Anda juga dapat mencapai flush lurus. Dan straight flush memiliki skor yang lebih baik daripada straight dan flush.
  • Satu pasang [2G, 2F, 1G, 1G, 1G, 0S]akan menang melawan dua pasang tangan. Juga tidak masalah. Jika Anda mendapatkan dua pasangan dengan kartu sungai, daripada Anda memiliki setidaknya satu pasangan sebelum sungai. Tetapi ini berarti, Anda dapat meningkatkan ke tiga jenis, yang lebih baik. Jadi dua pasangan sebenarnya tidak akan pernah menjadi jawabannya.
  • Kartu tinggi [2F, 1G, 1G, 1G, 1G, 1G, 0S]akan menang melawan sepasang tangan yang berpasangan. Jika ini adalah skor terbaik yang dapat Anda capai, sebelum sungai Anda akan memiliki 3 kartu satu suite dan satu kartu suite yang berbeda. Tetapi kemudian Anda dapat memilih kartu dengan salah satu dari dua suite ini dan dengan nilai yang sudah muncul, dan Anda akan berakhir dengan skor [2F, 2G, ...], yang juga lebih baik.

Jadi ini memilih jenis solusi yang tepat. Tapi bagaimana cara mendapatkan satu-pasangan terbaik (dari 4 kemungkinan), bagaimana cara memilih yang terbaik, ...? Karena dua solusi satu pasangan berbeda dapat memiliki skor yang sama.

Itu mudah. Pyth menjamin penyortiran stabil (saat mengambil maksimum). Jadi saya sederhana menghasilkan kartu dalam urutan 2h 2s 2c 2d 3h 3s ... Ad. Jadi kartu dengan nilai tertinggi secara otomatis akan menjadi maksimum.

Detail implementasi

=Zcmemisahkan string input dan menyimpan daftar kartu Z. =T+`M}2Tc4"JQKA"menghasilkan daftar peringkat ['2', ..., '10', 'J', 'Q', 'K', 'A']dan menyimpannya dalam T. -sM*T..."hscd"Zmenghasilkan setiap kombinasi peringkat dengan suite, dan menghapus kartu Z.

o...memesan kartu-kartu yang tersisa ini dengan: lM.gPkJpanjang grup dari peringkat, +-4l{eMJlMmenambahkan 4-panjang (suite), +*-5l@\AN}SPMJ+NZSM.:+\AT5menambahkan 0/4/5 tergantung pada suite (menghasilkan setiap substring panjang 5 dari "A" + T, periksa apakah tangan salah satu dari mereka (perlu menyortir tangan dan menyortir semua himpunan bagian), kalikan dengan 5 - nomor "A" di kartu), _Smengurutkan daftar menurun.

e pilih yang maksimal dan cetak.

Jakube
sumber
2
Sangat kreatif, dan penjelasan yang bagus!
Greg Martin
4

JavaScript (ES6), 329 324 317 312 309 byte

H=>[..."cdhs"].map(Y=>[...L="AKQJT98765432"].map(X=>~H.indexOf(X+=Y)||([...H,X].map(([R,S])=>a|=eval(S+'|=1<<L.search(R)',F|=S!=H[0][1]),F=a=c=d=h=s=0),x=c|d,y=h|s,c&=d,h&=s,p=c|x&y|h,t=c&y|h&x,(S=a-7681?((j=a/31)&-j)-j?F?c&h?2e4+a:t?t^p?3e4+t:7e4:p?8e4+p:M:4e4+a:F?5e4+a:a:F?6e4:1e4)<M&&(R=X,M=S))),M=1/0)&&R

Bagaimana itu bekerja

Untuk setiap kartu yang tersisa di geladak, kami menghitung skor tangan S. Semakin rendah skor, semakin baik tangan.

Variabel yang digunakan untuk menghitung skor

  • F: falsy jika tangan adalah flush
  • c: bitmask Clubs
  • d: bitmask of Diamonds
  • h: bitmask of Hearts
  • s: bitmask of Spades
  • x = c | d: bitmask Clubs ATAU Intan
  • y = h | s: bitmask of Hearts ATAU Spades
  • a: bitmask dari semua pakaian gabungan
  • p = c & d | x & y | h & s: pair bitmask (1)
  • t = c & d & y | h & s & x: three of a kind bitmask (1)

(1) Saya menulis formula ini beberapa tahun yang lalu dan menggunakannya di beberapa mesin poker. Mereka berhasil. :-)

Formula lainnya

  • c & d & h & s: empat bitmask jenis
  • a == 7681: tes untuk straight khusus "A, 2, 3, 4, 5" (0b1111000000001)
  • ((j = a / 31) & -j) == j: tes untuk semua lurus lainnya

Grafik skor

Value    | Hand
---------+--------------------------------------------
0   + a  | Standard Straight Flush
1e4      | Special Straight Flush "A, 2, 3, 4, 5"
2e4 + a  | Four of a Kind
3e4 + t  | Full House
4e4 + a  | Flush
5e4 + a  | Standard Straight
6e4      | Special Straight "A, 2, 3, 4, 5"
7e4      | Three of a Kind
8e4 + p  | Pair
Max.     | Everything else

NB: Kami tidak perlu peduli dengan Dua-Pasangan yang tidak mungkin menjadi pilihan terbaik kami. (Jika kita sudah memiliki satu pasang, kita dapat mengubahnya menjadi Tiga Jenis. Dan jika kita sudah memiliki dua pasang, kita dapat mengubahnya menjadi Rumah Penuh.)

Uji kasus

Arnauld
sumber
3

JavaScript (ES6), 307 349

Ini cukup besar dan saya tidak yakin itu pendekatan terbaik. Mungkin masih sedikit golf.

h=>(r='_23456789TJQKAT',R=x=>r.search(x[0]),M=i=>[...'hcds'].some(s=>h.indexOf(j=h[i][0]+s)<0)&&j,[u,v,w,y]=h.sort((a,b)=>R(a)-R(b)).map(x=>R(x)),[,,d,e,f,g,k]=[...new Set(h+h)].sort(),q=10-u-v-w,s=(z=y>12)&q>0?q:y-u<5&&u*5+q-y,d>r?z?'Kh':'Ah':f>r?M((e>r?v<w:u<v)+1):s?r[s]+g:k?M(3):r[13-z-(w>11)-(v>10)]+g)

Kurang golf

h=>(
  // card rank, 1 to 13, 0 unused
  // fake rank 14 is T, to complete a straight JQKA?
  // as I always try to complete a straight going up
  r = '_23456789TJQKAT', 

  // R: rank a card
  R = x => r.search(x[0]),  

  // M: find a missing card (to complete a same-rank set like a poker)
  // look for a card with the same rank of the card at position i
  // but with a suit not present in the hand
  M = i => [...'hcds'].some(s => h.indexOf(j=h[i][0]+s) < 0) && j,
  h.sort((a, b) => R(a)-R(b) ), // sort hand by rank
  [u,v,w,y] = h.map(x=>R(x)),   // rank of cards 0..3 in u,v,w,y

  // Purpose: look for duplicate rank and/or duplicate suits
  // Put values and suits in d,e,f,g,k, with no duplicates and sorted
  // suits are lowercase and will be at right end
  [,,d,e,f,g,k] = [...new Set(h+h)].sort(),

  // Only if all ranks are different: find the missing value to get a straight
  // or 0 if a straight cannot be obtained
  // The first part manages the A before a 2
  q = 10-u-v-w, s = y>12&q>0 ? q : y - u < 5 && u * 5 + q - y,

  d > r // d is lowercase -> all cards have the same rank
    ? u < 13 ? 'Ah' : 'Kh' // add a K to a poker of A, else add an A
    : e > r // e is lowercase -> 2 distinct ranks
      ? M(v<w ? 2 : 1) // go for a poker or a full house
      : f > r // f is lowercase -> 3 distinct ranks, we have a pair
        ? M(u<v ? 2 : 1) // find the pair and go for 3 of a kind
        : s // all different ranks, could it become a straight?
          ? r[s] + g // if there is only a suit, it will be a flush straight too
          : k // if there are 2 or more different suits
            ? M(3) // go for a pair with the max rank
            : r[13-(y>12)-(w>11)-(v>10)]+g // flush, find the max missing card
)

Uji

F=
h=>(r='_23456789TJQKAT',R=x=>r.search(x[0]),M=i=>[...'hcds'].some(s=>h.indexOf(j=h[i][0]+s)<0)&&j,[u,v,w,y]=h.sort((a,b)=>R(a)-R(b)).map(x=>R(x)),[,,d,e,f,g,k]=[...new Set(h+h)].sort(),q=10-u-v-w,s=(z=y>12)&q>0?q:y-u<5&&u*5+q-y,d>r?z?'Kh':'Ah':f>r?M((e>r?v<w:u<v)+1):s?r[s]+g:k?M(3):r[13-z-(w>11)-(v>10)]+g)

output=x=>O.textContent+=x+'\n'

;`Ah Kh Jh Th -> Qh
7d 8h Tc Jd -> 9d 9h 9c 9s
Js 6c Ts 8h -> Jc Jh Jd
Ac 4c 5d 3d -> 2h 2d 2c 2s
5s 9s Js As -> Ks
2h 3h 4h 5h -> 6h
Js Jc Ac Ah -> As Ad
Td 9d 5h 9c -> 9h 9s
Ah Ac Ad As -> Ks Kd Kh Kc
4d 5h 8c Jd -> Jc Js Jh`
.split('\n')
.forEach(s=>{
  var o = s.match(/\w+/g) // input and output
  var h = o.splice(0,4) // input in h, output in o
  var hs = h+''
  var r = F(h)
  var ok = o.some(x => x==r)
  
  output((ok?'OK ':'KO ')+ hs + ' -> ' + r)
})
<pre id=O></pre>

edc65
sumber
Lucu melihat bahwa kedua pendekatan kami tampaknya menyatu ke ukuran yang sangat mirip. :-) Kinerja bijaksana, Anda pasti lebih cepat.
Arnauld
@Arnauld saya berhasil mencukur lebih dari 4 byte. Giliran Anda
edc65