Choisissez la dernière carte d'une main de poker

31

Les mains de poker sont classées du meilleur au pire comme suit:

  1. Quinte flush - cinq cartes de rang séquentiel, toutes de la même couleur
  2. Quatre d'une sorte - quatre cartes de même rang et une carte d'un autre rang
  3. Full house - trois cartes d'un rang et deux cartes d'un autre rang
  4. Flush - cinq cartes toutes de la même couleur
  5. Droit - cinq cartes de rang séquentiel
  6. Trois d'un genre - trois cartes de même rang et deux cartes de deux autres rangs
  7. Deux paires - deux cartes de même rang, deux cartes d'un autre rang et une carte de troisième rang
  8. Une paire - deux cartes de même rang et trois cartes de trois autres rangs
  9. Carte haute - cinq cartes qui ne sont pas toutes de rang séquentiel ou de même couleur, et dont aucune n'est du même rang

  • Rang = Le nombre sur la carte (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Vous pouvez choisir d'utiliser T au lieu de 10.
  • Costume = coeurs (h), pique (s), massues (c) et diamants (d).

Notez que l'As,, Apeut être à la fois le nombre le plus élevé et le plus bas (1 ou 14).

Une carte peut être identifiée par deux lettres As(as de pique), Jc( valet de gourdin ), 7h(7 de cœur) et ainsi de suite.


Défi:

Vous obtenez quatre cartes du croupier (quatre chaînes d'entrée). Trouvez et sortez la meilleure dernière carte possible.

S'il y a des cartes tout aussi bonnes, vous pouvez choisir lesquelles choisir.

Les formats d'entrée et de sortie sont facultatifs, mais les cartes individuelles doivent être identifiées comme indiqué ci-dessus Jcet 2h.


Cas de test:

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)

C'est le golf de code, donc la soumission la plus courte en octets gagne.

Stewie Griffin
la source

Réponses:

13

Pyth, 73 octets

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

C'est assez terrible. Analyser les cartes, trier les valeurs, ... Tout prend tellement de caractères. Mais l'approche est intéressante.

Essayez-le en ligne: démonstration ou suite de tests

Explication:

Je génère les 52 cartes, supprime les quatre cartes de l'entrée, génère un score pour chaque carte (score de la main) et imprime la carte avec le score maximal.

Le score est un peu étrange. Si je compare le score de deux mains complètement différentes, il se peut que le mauvais gagnant soit choisi. Par exemple, une quinte bat 4 as. Mais ça marche, si les 4 premières cartes sont les mêmes dans les deux mains. Et mon score calculé n'est en fait pas une valeur, mais une liste de valeurs:

  • G: Tout d'abord, je regroupe les 5 cartes par rang et prends les longueurs: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Ensuite, j'ajoute 4 moins le nombre de suites différentes à cette liste. Flush -> 3est ajouté, not flush -> 2/1/0est ajouté.
  • S: Ajoutez un autre numéro. 0si ce n'est pas une ligne droite, 4si c'est la ligne droite A2345, ou 5si c'est une ligne droite supérieure.

Ces listes de 4 à 7 numéros sont triées par ordre décroissant et la liste avec la valeur maximale est sélectionnée.

Pourquoi ça marche? Vous voyez ici les configurations possibles pour tous les types. La lettre à côté des chiffres vous indique avec quelle règle ce numéro a été généré.

  • Quinte flush: [5S, 3F, 1G, 1G, 1G, 1G, 1G]ou[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Quatre d'une sorte: [4G, 1G, 0F, 0S]
  • Maison pleine: [3G, 2G, 1F, 0S]ou[3G, 2G, 0F, 0S]
  • Affleurer: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Droit: [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]
  • Brelan: [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • Deux paires: [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • Une paire: [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • Carte haute: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth compare les listes par élément. Il est donc évident qu'une quinte flush battra toujours Four of a kind. La plupart des règles de poker typiques sont évidentes avec ces listes. Certains semblent contradictoires.

  • Un Straight gagnera contre Four of a Kind ou Full House: Pas de problème. Si vous avez une chance d'obtenir un Four of a Kind / Full House avec la carte River, vous ne pouvez pas atteindre une ligne droite en même temps (car vous avez déjà 2 ou 3 suites différentes dans votre main).
  • Une quinte gagnera contre une couleur. Si vous pouvez atteindre une quinte et une quinte avec la carte de la rivière, vous pouvez également atteindre une quinte. Et la quinte flush a un meilleur score que la quinte et la quinte.
  • Une paire [2G, 2F, 1G, 1G, 1G, 0S]gagnera contre quelques mains de deux paires. Pas de problème non plus. Si vous obtenez deux paires avec la carte rivière, alors vous en aviez au moins une paire avant la rivière. Mais cela signifie que vous pouvez vous améliorer en trois, ce qui est mieux. Donc, deux paires ne seront jamais la réponse.
  • La carte haute [2F, 1G, 1G, 1G, 1G, 1G, 0S]gagnera contre quelques mains d'une paire. Si c'est le meilleur score que vous pouvez atteindre, avant la rivière, vous aurez 3 cartes d'une suite et une carte d'une suite différente. Mais ensuite, vous pouvez choisir la carte avec l'une de ces deux suites et avec une valeur qui apparaît déjà, et vous vous retrouverez avec le score [2F, 2G, ...], qui est également meilleur.

Donc, cela choisit le bon type de solution. Mais comment obtenir la meilleure paire (sur 4 possibilités), comment choisir la meilleure ligne droite, ...? Parce que deux solutions d'une paire différentes peuvent avoir le même score.

C'est facile. Pyth garantit un tri stable (en prenant le maximum). Je génère donc simplement les cartes dans l'ordre 2h 2s 2c 2d 3h 3s ... Ad. Ainsi, la carte avec la valeur la plus élevée sera automatiquement le maximum.

Détails d'implémentation

=Zcdivise la chaîne d'entrée et stocke la liste des cartes Z. =T+`M}2Tc4"JQKA"génère la liste des rangs ['2', ..., '10', 'J', 'Q', 'K', 'A']et les stocke dans T. -sM*T..."hscd"Zgénère chaque combinaison de rang avec les suites et supprime les cartes de Z.

o...ordonne ces cartes restantes par: lM.gPkJla longueur des groupes de rangs, +-4l{eMJlMajoute 4 - longueur (suites), +*-5l@\AN}SPMJ+NZSM.:+\AT5ajoute 0/4/5 selon la suite (générer chaque sous-chaîne de longueur 5 de "A" + T, vérifier si la main l'un d'eux (nécessite de trier la main et de trier tous les sous-ensembles), multiplier par 5 - nombre de "A" dans la carte), _Strie la liste décroissante.

e choisissez le maximum et imprimez.

Jakube
la source
2
Très créatif et bonne explication!
Greg Martin
4

JavaScript (ES6), 329 324 317 312 309 octets

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

Comment ça marche

Pour chaque carte restante dans le jeu, nous calculons un score de main S. Plus le score est bas, meilleure est la main.

Variables utilisées pour calculer le score

  • F: fausse si la main est flush
  • c: bitmask des clubs
  • d: bitmask of Diamonds
  • h: bitmask de Hearts
  • s: bitmask of Spades
  • x = c | d: bitmask de Clubs OR Diamonds
  • y = h | s: bitmask de Hearts OR Spades
  • a: bitmask de toutes les combinaisons combinées
  • p = c & d | x & y | h & s: paire bitmask (1)
  • t = c & d & y | h & s & x: masque en bit unique (1)

(1) J'ai écrit ces formules il y a quelques années et les ai utilisées dans plusieurs moteurs de poker. Ils fonctionnent. :-)

Autres formules

  • c & d & h & s: un masque bitmap unique
  • a == 7681: test de la droite spéciale "A, 2, 3, 4, 5" (0b1111000000001)
  • ((j = a / 31) & -j) == j: test pour toutes les autres lignes droites

Tableau des scores

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: Nous n'avons pas à nous soucier des deux paires, ce qui ne peut pas être notre meilleure option. (Si nous avons déjà une paire, nous pouvons la transformer en un modèle unique. Et si nous avons déjà deux paires, nous pouvons les transformer en un Full House.)

Cas de test

Arnauld
la source
3

JavaScript (ES6), 307 349

C'est assez volumineux et je ne suis pas sûr que ce soit la meilleure approche. Peut-être encore un peu golfable.

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)

Moins 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
)

Tester

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
la source
C'est drôle de voir que nos deux approches semblent converger vers des tailles très similaires. :-) En termes de performances, vous êtes définitivement plus rapide.
Arnauld
@Arnauld J'ai réussi à raser encore 4 octets. À votre tour
edc65