Chọn lá bài cuối cùng trong ván bài xì phé


31

Tay bài xì phé được xếp hạng từ tốt nhất đến tệ nhất như sau:

  1. Xả thẳng - năm thẻ xếp hạng liên tiếp, tất cả đều giống nhau
  2. Bốn loại một - bốn thẻ cùng cấp và một thẻ cấp bậc khác
  3. Nhà đầy đủ - ba thẻ một cấp bậc và hai thẻ cấp bậc khác
  4. Flush - năm thẻ tất cả cùng một bộ
  5. Straight - năm thẻ xếp hạng liên tiếp
  6. Ba loại một - ba thẻ cùng cấp và hai thẻ của hai cấp khác
  7. Hai cặp - hai thẻ cùng cấp, hai thẻ hạng khác và một thẻ hạng ba
  8. Một cặp - hai thẻ cùng cấp và ba thẻ của ba cấp bậc khác
  9. Thẻ cao - năm thẻ không phải là tất cả các thứ hạng liên tiếp hoặc của cùng một bộ đồ, và không có thẻ nào có cùng cấp bậc

  • Xếp hạng = Số trên thẻ (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Bạn có thể chọn sử dụng T thay vì 10.
  • Suit = heart (h), spades (s), club (c) và diamonds (d).

Lưu ý rằng Ace, Acả hai có thể là số cao nhất và thấp nhất (1 hoặc 14).

Một thẻ có thể được xác định bằng hai chữ cái As(Ace of spades), Jc(Jack of club), 7h(7 of heart), v.v.


Thử thách:

Bạn nhận được bốn thẻ từ đại lý (bốn chuỗi đầu vào). Tìm và xuất thẻ cuối cùng tốt nhất có thể bạn có thể nhận được.

Nếu có những thẻ tốt như nhau thì bạn có thể chọn thẻ nào để chọn.

Các định dạng đầu vào và đầu ra là tùy chọn, nhưng các thẻ riêng lẻ phải được xác định như được hiển thị ở trên Jc2h.


Các trường hợp thử nghiệm:

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)

Đây là mã golf, vì vậy việc gửi byte ngắn nhất sẽ giành chiến thắng.

Câu trả lời:


13

Bình thường, 73 byte

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

Điều này là khá khủng khiếp. Phân tích cú pháp thẻ, sắp xếp các giá trị, ... Mọi thứ cần rất nhiều ký tự. Nhưng cách tiếp cận là thú vị.

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Giải trình:

Tôi tạo tất cả 52 thẻ, loại bỏ bốn thẻ của đầu vào, tạo điểm cho mỗi thẻ (điểm của tay) và in thẻ với số điểm tối đa.

Điểm số hơi kỳ quặc. Nếu tôi so sánh điểm của hai tay hoàn toàn khác nhau, nó có thể chọn sai người chiến thắng. Ví dụ, một đường thẳng sẽ đánh bại 4 con át chủ bài. Nhưng nó hoạt động, nếu 4 thẻ đầu tiên giống nhau ở cả hai tay. Và điểm số được tính toán của tôi thực sự không phải là một giá trị, mà là một danh sách các giá trị:

  • G: Đầu tiên tôi nhóm 5 thẻ theo thứ hạng và lấy độ dài: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Sau đó, tôi thêm 4 trừ số lượng bộ khác nhau vào danh sách này. Flush -> 3được nối thêm, not flush -> 2/1/0được nối thêm.
  • S: Thêm một số khác. 0nếu nó không phải là một đường thẳng, 4nếu nó là đường thẳng A2345hoặc 5nếu nó là đường thẳng cao hơn.

Các danh sách gồm 4-7 số này được sắp xếp theo thứ tự giảm dần và danh sách có giá trị tối đa được chọn.

Tại sao điều này làm việc? Ở đây bạn thấy các cấu hình có thể cho tất cả các loại. Chữ bên cạnh các số, cho bạn biết quy tắc nào số này đã được tạo.

  • Thẳng tuôn ra: [5S, 3F, 1G, 1G, 1G, 1G, 1G]hoặc[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Bốn trong số các loại: [4G, 1G, 0F, 0S]
  • Nhà đầy đủ: [3G, 2G, 1F, 0S]hoặc[3G, 2G, 0F, 0S]
  • Tuôn ra: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Thẳng: [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]
  • Ba của một loại: [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • Hai cặp: [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • Một cặp: [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • Thẻ cao: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth so sánh danh sách các yếu tố khôn ngoan. Vì vậy, rõ ràng là một tuôn thẳng sẽ luôn đánh bại Four of a kind. Hầu hết các quy tắc poker điển hình là rõ ràng với các danh sách này. Một số có vẻ mâu thuẫn.

  • Một Straight sẽ giành chiến thắng trước Four of a kind hoặc Full house: Không thành vấn đề. Nếu bạn có cơ hội nhận được Four of a kind / Full house bằng thẻ sông, hơn là bạn không thể đi thẳng cùng một lúc (vì bạn đã có 2 hoặc 3 bộ khác nhau trong tay).
  • Một Straight sẽ giành chiến thắng chống lại một tuôn ra. Nếu bạn có thể đạt được một lần xả và một đường thẳng với thẻ sông, thì bạn cũng có thể đạt được một đường thẳng. Và xả thẳng có điểm tốt hơn cả thẳng và xả.
  • Một cặp [2G, 2F, 1G, 1G, 1G, 0S]sẽ giành chiến thắng trước một số hai tay đôi. Cũng không có vấn đề. Nếu bạn nhận được một cặp với thẻ sông, hơn bạn đã có ít nhất một cặp trước sông. Nhưng điều này có nghĩa là, bạn có thể cải thiện thành ba loại, tốt hơn. Vì vậy, một cặp đôi thực sự sẽ không bao giờ là câu trả lời.
  • Thẻ cao [2F, 1G, 1G, 1G, 1G, 1G, 0S]sẽ giành chiến thắng trước một số tay đôi. Nếu đây là điểm số tốt nhất bạn có thể đạt được, trước khi ra sông, bạn sẽ có 3 thẻ của một bộ và một thẻ của một bộ khác. Nhưng sau đó, bạn có thể chọn thẻ có một trong hai bộ này và với giá trị đã xuất hiện, và bạn sẽ kết thúc với điểm số [2F, 2G, ...], điều này cũng tốt hơn.

Vì vậy, điều này chọn đúng loại giải pháp. Nhưng làm thế nào để tôi có được một cặp tốt nhất (trong số 4 khả năng), làm thế nào để tôi chọn được một cặp tốt nhất, ...? Bởi vì hai giải pháp một cặp khác nhau có thể có cùng số điểm.

Điều đó thật dễ dàng. Pyth đảm bảo phân loại ổn định (khi lấy tối đa). Vì vậy, tôi đơn giản tạo ra các thẻ theo thứ tự 2h 2s 2c 2d 3h 3s ... Ad. Vì vậy, thẻ có giá trị cao nhất sẽ tự động là tối đa.

Chi tiết thực hiện

=Zcchia chuỗi đầu vào và lưu danh sách thẻ vào Z. =T+`M}2Tc4"JQKA"tạo danh sách các cấp bậc ['2', ..., '10', 'J', 'Q', 'K', 'A']và lưu trữ chúng trong T. -sM*T..."hscd"Ztạo ra mỗi kết hợp xếp hạng với các bộ và loại bỏ các thẻ của Z.

o...sắp xếp các thẻ còn lại bằng cách: lM.gPkJchiều dài của các nhóm xếp hạng, +-4l{eMJlMnối thêm 4 chiều dài (bộ), +*-5l@\AN}SPMJ+NZSM.:+\AT5nối thêm 0/4/5 tùy theo bộ (tạo từng chuỗi con có độ dài 5 của "A" + T, kiểm tra xem tay có một trong số chúng (yêu cầu sắp xếp tay và sắp xếp tất cả các tập hợp con), nhân với 5 - số chữ "A" trong thẻ), _Ssắp xếp danh sách giảm dần.

e chọn tối đa và in.


2
Rất sáng tạo, và giải thích tuyệt vời!
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

Làm thế nào nó hoạt động

Đối với mỗi thẻ còn lại trong bộ bài, chúng tôi tính điểm số tay S. Điểm càng thấp, tay càng tốt.

Các biến được sử dụng để tính điểm

  • F: giả mạo nếu bàn tay là một tuôn ra
  • c: bitmask của các câu lạc bộ
  • d: bitmask của Kim cương
  • h: bitmask của trái tim
  • s: bitmask của Spades
  • x = c | d: bitmask của Câu lạc bộ HOẶC Kim cương
  • y = h | s: bitmask của Hearts HOẶC Spades
  • a: bitmask của tất cả các bộ đồ kết hợp
  • p = c & d | x & y | h & s: cặp bitmask (1)
  • t = c & d & y | h & s & x: ba trong số một loại bitmask (1)

(1) Tôi đã viết những công thức này vài năm trước và sử dụng chúng trong một số công cụ poker. Họ làm việc. :-)

Các công thức khác

  • c & d & h & s: bốn trong số một bitmask
  • a == 7681: kiểm tra độ thẳng đặc biệt "A, 2, 3, 4, 5" (0b1111000000001)
  • ((j = a / 31) & -j) == j: kiểm tra cho tất cả các căng thẳng khác

Biểu đồ tỷ số

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

Lưu ý: Chúng tôi không phải quan tâm đến Two-Pair có thể không phải là lựa chọn tốt nhất của chúng tôi. (Nếu chúng ta đã có một cặp, chúng ta có thể biến nó thành Three of a Kind. Và nếu chúng ta đã có hai cặp, chúng ta có thể biến chúng thành Full House.)

Các trường hợp thử nghiệm


3

JavaScript (ES6), 307 349

Điều này khá cồng kềnh và tôi không chắc đó là cách tiếp cận tốt nhất. Vẫn có thể chơi golf một chút.

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)

Ít chơi gôn

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
)

Kiểm tra

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>


Thật buồn cười khi thấy cả hai cách tiếp cận của chúng tôi dường như hội tụ về các kích thước rất giống nhau. :-) Hiệu suất khôn ngoan, mặc dù bạn chắc chắn nhanh hơn.
Arnauld

@Arnauld Tôi quản lý để cạo thêm 4 byte. Đến lượt bạn
edc65
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.