포커 패에서 마지막 카드를 선택하십시오


31

포커 핸드는 다음과 같이 최고에서 최악으로 분류됩니다.

  1. 스트레이트 플러시-순차적 등급의 5 장의 카드, 모두 같은 수트
  2. 같은 종류의 카드 4 장과 다른 등급의 카드 1 장
  3. 풀 하우스-한 등급의 세 카드와 다른 등급의 두 카드
  4. 플러시-같은 카드 5 장
  5. 연속-연속 순위의 5 장의 카드
  6. 같은 종류의 3 장의 카드와 다른 2 가지 등급의 2 장의 카드
  7. 두 쌍-같은 등급의 두 카드, 다른 등급의 두 카드 및 세 번째 등급의 한 카드
  8. 한 쌍-같은 등급의 두 카드와 다른 등급의 세 카드
  9. 높은 카드-5 개의 카드가 모두 순차적 등급이 아니거나 같은 수의 카드가 아니며 동일한 등급이 아닌 카드

  • 순위 = 카드 번호 (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). 10 대신 T를 사용하도록 선택할 수 있습니다.
  • 슈트 = 하트 (h), 스페이드 (s), 클럽 (c) 및 다이아몬드 (d).

Ace A는 가장 높고 가장 낮은 수 (1 또는 14) 일 수 있습니다.

카드는 두 글자 As(스페이드 에이스), Jc(클럽 잭), 7h(마음 7 ) 등 으로 식별 할 수 있습니다 .


도전:

딜러로부터 4 개의 카드를받습니다 (4 개의 입력 문자열). 가장 좋은 마지막 카드를 찾아서 출력하십시오.

똑같이 좋은 카드가 있으면 선택할 카드를 선택할 수 있습니다.

입력 및 출력 형식은 선택 사항이지만 각각의 카드는 위 그림과 같이 확인해야 Jc하고 2h.


테스트 사례 :

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)

이것은 코드 골프이므로 바이트 단위의 최단 제출이 이깁니다.

답변:


13

Pyth, 73 바이트

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

이것은 꽤 끔찍하다. 카드를 파싱하고 값을 정렬하는 등 모든 것이 너무 많은 문자를 사용합니다. 그러나 그 접근법은 흥미 롭습니다.

온라인으로 사용해보십시오 : 데모 또는 테스트 스위트

설명:

52 장의 카드를 모두 생성하고, 입력 한 카드 4 장을 제거하고, 각 카드에 대한 점수 (손의 점수)를 생성 한 후 최대 점수로 카드를 인쇄합니다.

점수는 조금 이상합니다. 완전히 다른 두 손의 점수를 비교하면 잘못된 승자를 선택할 수 있습니다. 예를 들어 스트레이트는 4 에이스를 이길 것입니다. 그러나 처음 4 장의 카드가 양손에 동일하면 효과가 있습니다. 그리고 내 계산 점수는 실제로 값이 아니라 값 목록입니다.

  • G : 먼저 5 장의 카드를 순위별로 묶고 길이를 가져옵니다. 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F : 그런 다음이 목록에 다른 스위트 수를 뺀 4를 추가합니다. Flush -> 3추가되고 not flush -> 2/1/0추가됩니다.
  • S : 다른 번호를 추가하십시오. 0직선이 아닌 4경우, 직선 A2345이거나 5높은 직선 인 경우.

이 4-7 숫자 목록은 내림차순으로 정렬되며 최대 값을 가진 목록이 선택됩니다.

왜 이것이 작동합니까? 다음은 모든 유형에 가능한 구성입니다. 숫자 옆의 문자는이 숫자가 생성 된 규칙을 알려줍니다.

  • 스트레이트 플러시 : [5S, 3F, 1G, 1G, 1G, 1G, 1G]또는[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • 네 종류 : [4G, 1G, 0F, 0S]
  • 풀 하우스 : [3G, 2G, 1F, 0S]또는[3G, 2G, 0F, 0S]
  • 플러시: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • 스트레이트 [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]
  • 세 종류 : [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • 두 쌍 : [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • 한 쌍 : [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • 높은 카드 : [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth는리스트를 요소별로 비교합니다. 따라서 스트레이트 플러시는 항상 종류의 4를 이길 것입니다. 일반적인 포커 규칙의 대부분은이 목록에서 분명합니다. 일부는 상충되는 것 같습니다.

  • 스트레이트는 4 가지 종류 또는 풀 하우스에서 승리합니다. 문제 없습니다. 리버 카드로 4 종류 / 풀 하우스를 얻을 수있는 기회가있는 경우, 동시에 직선에 도달 할 수없는 것보다 (손에 이미 2 개 또는 3 개의 다른 스위트가 있기 때문에).
  • 플러시는 상대편이 이깁니다. 강 카드로 플러시 및 직선에 도달 할 수 있으면 스트레이트 플러시에 도달 할 수도 있습니다. 그리고 스트레이트 플러시는 스트레이트 및 플러시보다 점수가 더 높습니다.
  • 한 쌍 [2G, 2F, 1G, 1G, 1G, 0S]은 두 쌍의 손에 이길 것입니다. 또한 문제 없습니다. 강 카드로 두 쌍을 얻는다면 강보다 적어도 한 쌍을 가진 것보다. 그러나 이것은 당신이 세 가지 종류로 향상시킬 수 있다는 것을 의미합니다. 따라서 두 쌍은 실제로 답이 될 수 없습니다.
  • [2F, 1G, 1G, 1G, 1G, 1G, 0S]한 쌍의 손에 대해 높은 카드 가 이깁니다. 이것이 당신이 도달 할 수있는 최고의 점수라면, 강 전에는 한 스위트의 3 장의 카드와 다른 스위트의 1 장의 카드를 갖게됩니다. 그러나이 두 가지 스위트 중 하나와 이미 표시된 값으로 카드를 선택할 수 있으며 점수가 올라가면 [2F, 2G, ...]더 좋습니다.

따라서 올바른 유형의 솔루션을 선택합니다. 그러나 어떻게 최고의 1 쌍을 구할 수 있습니까 (4 가지 가능성 중), 어떻게 최선의 직선을 선택합니까? 서로 다른 두 개의 단일 쌍 솔루션의 점수가 같을 수 있기 때문입니다.

쉽습니다. Pyth는 안정적인 정렬을 보장합니다 (최대 값을 사용할 때). 그래서 순서대로 카드를 간단하게 생성합니다 2h 2s 2c 2d 3h 3s ... Ad. 따라서 가장 높은 값을 가진 카드가 자동으로 최대가됩니다.

구현 세부 사항

=Zc입력 문자열을 분할하고에 카드 목록을 저장합니다 Z. =T+`M}2Tc4"JQKA"순위 목록을 생성하여에 ['2', ..., '10', 'J', 'Q', 'K', 'A']저장합니다 T. -sM*T..."hscd"Z스위트와 등급의 각 조합을 생성하고의 카드를 제거합니다 Z.

o...남은 카드의 순서 : lM.gPkJ순위 그룹의 +-4l{eMJlM길이 , 4-길이 (스위트), 스위트 +*-5l@\AN}SPMJ+NZSM.:+\AT5에 따라 0/4/5 추가 ( "A"+ T의 길이 5의 각 하위 문자열 생성, 핸드 여부 확인) 그 중 하나 (손을 정렬하고 모든 부분 집합을 정렬해야 함)에 5-카드의 "A"수를 곱 _S하면 목록이 감소합니다.

e 최대 값을 선택하고 인쇄하십시오.


2
매우 창의적이고 훌륭한 설명!
Greg Martin

4

자바 스크립트 (ES6), 329 324 317 312 309 바이트

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

작동 원리

갑판에 남아있는 카드마다 핸드 스코어를 계산합니다 S. 점수가 낮을수록 손이 좋아집니다.

점수를 계산하는 데 사용되는 변수

  • F: 손이 플러시 인 경우 허위
  • c: 클럽의 비트 마스크
  • d: 다이아몬드 비트 마스크
  • h: 하트 비트 마스크
  • s: 스페이드의 비트 마스크
  • x = c | d: 클럽 또는 다이아몬드의 비트 마스크
  • y = h | s: 하트 또는 스페이드의 비트 마스크
  • a: 모든 결합 된 슈트의 비트 마스크
  • p = c & d | x & y | h & s: 쌍 비트 마스크 (1)
  • t = c & d & y | h & s & x: 친절한 비트 마스크 3 개 (1)

(1) 몇 년 전에이 공식을 작성하여 여러 포커 엔진에 사용했습니다. 그들은 일한다. :-)

다른 공식

  • c & d & h & s: 친절한 비트 마스크 4 개
  • a == 7681: 특수 직선 "A, 2, 3, 4, 5"에 대한 테스트 (0b1111000000001)
  • ((j = a / 31) & -j) == j: 다른 모든 스트레이트에 대한 테스트

스코어 차트

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

주의 : 우리는 최선의 선택이 될 수없는 2 쌍에 대해 신경 쓸 필요가 없습니다. (이미 한 쌍이 있다면 3 가지 종류로 바꿀 수 있습니다. 이미 두 쌍이 있으면 풀 하우스로 바꿀 수 있습니다.)

테스트 사례


3

자바 스크립트 (ES6), 307 (349)

이것은 매우 부피가 크며 이것이 최선의 방법인지 확실하지 않습니다. 여전히 약간 골프를 칠 수 있습니다.

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)

덜 골프

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
)

테스트

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>


우리의 두 가지 접근 방식이 매우 비슷한 크기로 수렴하는 것처럼 보입니다. :-) 성능면에서는 확실히 빠릅니다.
Arnauld

@ Arnauld 나는 4 바이트를 더 면도 할 수있었습니다. 당신의 차례
edc65
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.