Comparez deux mains de poker

14

Défi:

Étant donné deux mains de cinq cartes, déterminez laquelle gagne en fonction du classement standard des mains de poker .

Contribution:

Dix cartes séparées par des espaces de stdin ou comme arguments de ligne de commande, selon votre préférence. Les cinq premières cartes sont la main du joueur 1 tandis que les cinq dernières sont la main du joueur 2. Chaque carte sera une chaîne de deux lettres de la forme RS où R est rang et S est couleur. Les rangs vont de 2 à 9, T pour dix, et J, Q, K et A pour Jack, Queen, King et Ace respectivement. Les combinaisons sont H, D, C, S pour Hearts, Diamonds, Clubs et Spades respectivement. Vous devez afficher le numéro du joueur qui gagne: «1» ou «2».

Exemples de cartes:

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

Exemples d'entrée à sortie:

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

Explication: le joueur 1 a une paire de cinq tandis que le joueur 2 a une paire de huit.

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

Explication: Aucun des joueurs n'a quelque chose de spécial, mais la carte haute du joueur 1 est un as tandis que la carte haute du joueur 2 est une reine.

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

Explication: le joueur 1 a trois as, le joueur 2 a une couleur de diamants.

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

Explication: Les deux joueurs ont une paire de reines, mais la deuxième carte la plus haute du joueur 1 est un neuf tandis que le joueur 2 est un sept.

Règles et clarifications:

  • Reportez-vous au classement standard des mains de poker pour plus de détails sur la comparaison des mains.
  • Vous pouvez supposer qu'il n'y a pas de cartes répétées dans chaque paire de mains.
  • Vous pouvez supposer qu'il y a un gagnant certain dans chaque cas.
  • Le costume n'entre pas en ligne de compte dans le classement d'une main. Par exemple, deux quintes flush royales de couleurs différentes sont égales (donc toute entrée où les deux joueurs ont une quinte flush est invalide par la règle précédente).
  • Comme il s'agit du code golf, la réponse la plus courte l'emporte.

Remarques:

commando
la source
Toutes mes excuses s'il y a quelque chose que j'ai manqué! Ceci est ma première question de golf de code.
commando
Ceci est similaire à cette récente question codegolf.stackexchange.com/q/23743/15599 et à la version à 5 cartes référencée. Cependant, ces questions ne demandaient qu'à nommer le type de main. Une grande différence ici est que si les deux joueurs ont le même type de main, nous devons déterminer laquelle est la meilleure par rang de carte (par exemple pour deux paires, qui a la meilleure première paire, la deuxième paire et, si nécessaire, une seule carte). ce n'est pas un doublon. Recherchez toujours des questions similaires, reliez-les (je vois que vous l'avez fait) et soyez prêt à défendre pourquoi il ne s'agit pas d'un double avant de publier.
Level River St
Et si le flop et la main sont identiques?
Ismael Miguel
@IsmaelMiguel Il n'y a pas de flop dans cette version. Il y a simplement deux mains distinctes qui doivent être évaluées l'une par rapport à l'autre.
commando
1
Précédemment résolu pour 10 cartes ici
Hasturkun

Réponses:

2

Haskell - 352 339 caractères

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

Exécute:

& 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

Non-golfé et commenté, vous pouvez donc voir la 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
la source
2

Python - 774 722 707 698 685 caractères

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

J'ai choisi de générer une chaîne pour chaque main qui la représente, en commençant par un caractère pour le type de main, suivi de caractères décrivant la variation particulière du type (par exemple, de quelle carte en aviez-vous seulement 4?), Suivi de les valeurs des cartes restantes en cas d'égalité (si les deux joueurs ont la même double paire, la 5ème carte devra décider qui gagne). Je l'ai testé assez longuement, mais je ne joue pas vraiment au poker, donc j'espère avoir bien compris. De plus, je sais que ce n'est pas encore complètement joué, je peux probablement raser quelques dizaines de caractères plus tard.

Tal
la source
Tuez 5 caractères avec _=lambda c:chr(97+c). De plus, vous avez des espaces inutiles après :s et =s. Enfin, utilisez ;au lieu de nouvelles lignes pour séparer les instructions afin de réduire les espaces utilisés pour l'indentation.
user12205
Joli avec le lambda, merci!
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)}

usage:

a("5H 5C 6S 7S KD 2C 3S 8S 8D TD");

non golfé:

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

la source

Alex
la source
1

perl, 801 733 caractères

Je pense que c'est une mise en œuvre assez simple. Fondamentalement, pour chaque main, nous trions les costumes et les visages séparément. Ensuite, nous faisons une autre copie des visages avec des as comptant bas afin que nous puissions vérifier les lignes droites avec des as bas. Ensuite, nous déterminons si nous avons une couleur ou une quinte, et quelle est la carte haute. Ensuite, nous vérifions simplement les matchs par ordre de score (nous vérifions d'abord les quinte flush, puis quatre types, etc.). Le score réel est juste la concaténation du type de main suivi des valeurs faciales des cartes dans l'ordre où elles comptent (c'est _s () dans la version non golfée, u () dans la version golfée). C'est ici:

@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

Et voici l'équivalent le moins 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
la source
AH 2C 3S 4S 5D 6C 7S 7C 7D TDproduit un résultat de 2, mais je pense qu'une ligne droite bat trois en son genre
r3mainer