Nommez la main de poker - édition de 7 cartes


11

Le défi:

Dans cette question: Nommez la main de poker que vous avez dû prendre une main de poker de cinq cartes et identifiez-la. Cette question est similaire, avec deux rebondissements:

Tout d'abord, la sortie sera en minuscules. Cela permet plus de golf, car vous n'avez pas à vous soucier de la capitalisation flushetstraight

high card
one pair
two pair
three of a kind
straight
flush
full house
four of a kind
straight flush
royal flush

Deuxièmement, avec la popularité du Texas Hold'em et du Stud à 7 cartes, nous, ici, au code golf, devrions pouvoir marquer une main de poker à sept cartes , ai-je raison? Lorsque vous marquez une main de sept cartes, utilisez les cinq meilleures cartes pour votre main et ignorez les deux dont vous n'avez pas besoin.

Référence:

Liste des mains de poker: http://en.wikipedia.org/wiki/List_of_poker_hands

Entrée (relevée directement du fil précédent)

7 cartes provenant d'arguments stdin ou de ligne de commande. Une carte est une chaîne de deux lettres sur le formulaire RS, où R est rang et S est costume. Les rangs sont 2- 9(cartes numérotées), T(dix), J(Jack), Q(Reine), K(Roi), A(As). Les costumes sont S, D, H, Cpour bêches, des diamants, des coeurs et des clubs respectivement.

Exemple de cartes

5H - five of hearts
TS - ten of spades
AD - ace of diamonds

Exemple d'entrée => sortie souhaitée

3H 5D JS 3C 7C AH QS => one pair
JH 4C 2C 9S 4H JD 2H => two pair
7H 3S 7S 7D AC QH 7C => four of a kind
8C 3H 8S 8H 3S 2C 5D => full house
AS KC KD KH QH TS JC => straight

Remarquez que dans le deuxième exemple, il y a en fait trois paires, mais vous ne pouvez utiliser que cinq cartes, donc c'est le cas two pair. Dans le cinquième exemple, il existe à la fois un three of a kindet un straightpossible, mais un straightest meilleur, donc la sortie straight.

Notation

C'est le , donc le code le plus court gagne!

Errata

  1. Vous ne pouvez pas utiliser de ressources externes.
  2. Ace est à la fois haut et bas pour les lignes droites.

Agréable; J'espérais secrètement que quelqu'un ramasserait le ballon. Je voulais juste noter que je n'avais aucune restriction sur la capitalisation dans la question d'origine (clarifiée dans un commentaire), donc vous pouviez (et la plupart / tous l'ont fait) sortir "Straight Flush". IMHO capitalisé semble mieux.
daniero

Vous dites entrée (levée directement du fil précédent) 5 cartes. Je pense que vous vouliez changer cela en 7.
Level River St

@steveverrill Vous pouvez modifier vous-même les publications sur l'échange de pile. Bien que je l'ai fait pour vous ici
durron597

Les ressources externes sont-elles autorisées? Il existe des tables de recherche qui vous permettront de rechercher simplement chaque carte dans la main et d'obtenir une force de main.
Kendall Frey

L'as peut-il être aussi bien bas que haut pour les lignes droites?
Nick T

Réponses:


4

Rubis 353

Cela était basé sur la réponse de Chron à la question d'origine.

Cela prend l'entrée comme arguments de ligne de commande. Fondamentalement, nous répétons simplement toutes les combinaisons de taille 5 pour obtenir le type de main. Chaque type de main a été modifié afin qu'il commence par un nombre. ("royal flush" -> "0royal 4flush", "high card" -> "9high card"). Cela nous permet de trier les chaînes retournées. La première chaîne après le tri est la meilleure main possible. Nous imprimons donc cela après avoir supprimé tous les nombres de la chaîne.

o,p=%w(4flush 1straight)
f=/1{5}|1{4}0+1$/
puts $*.combination(5).map{|z|s=[0]*13;Hash[*z.map{|c|s['23456789TJQKA'.index c[0]]+=1;c[1]}.uniq[1]?[f,'5'+p,?4,'2four'+a=' of a kind',/3.*2|2.*3/,'3full house',?3,'6three'+a,/2.*2/,'7two pair',?2,'8one pair',0,'9high card']:[/1{5}$/,'0royal '+o,f,p+' '+o,0,o]].find{|r,y|s.join[r]}[1]}.sort[0].gsub(/\d/,'')

Agréable. Le gsub à la fin peut juste être un sous-droit?
bazzargh

@bazzargh non, il doit supprimer tous les numéros. Le code concatène 4flush avec 1straight ou 0royal pour obtenir "0royal 4 flush" ou "1straight 4flush". Si nous n'utilisons que sub, le 4 ne serait pas supprimé.
FDinoff

Donne le mauvais résultat pour AS QS JS TS 9S 5H 5D. Ça va vous coûter un personnage!

@ WumpusQ.Wumbley Hmm cela semble être un bug dans le code d'origine. Je vais essayer de comprendre quel est le problème plus tard.
FDinoff

5

Haskell 618 603 598 525 512 504 480 464

Cartes prises comme ligne d'entrée. Je pense que j'ai joué au golf à mort, mais je serai facilement battu par le rubis, etc. en utilisant la même astuce: si vous générez toutes les permutations, vous obtenez les tris vers l'avant que vous souhaitez rechercher en ligne droite, plus les tris inverses que vous voulez pour tester N d'un genre.

import Data.List
m=map
z=take 5
q=m(\x->head[n|(f,n)<-zip"A23456789TJQK"[1..],f==x!!0])
l=m length
v=" of a kind"
w="flush"
y="straight"
c f s p r|f&&r="9royal "++w|f&&s='8':y++" "++w|f='5':w|s||r='4':y|True=case p of 4:_->"7four"++v;3:2:_->"6full house";3:_->"3three"++v;2:2:_->"2two pair";2:_->"1one pair";_->"0high card"
d x=c([5]==l(group$m(!!1)x))(q x==z[head(q x)..])(l$group$q x)$q x==1:[10..13]
k h=tail$maximum$m(d.z)$permutations$words h
main=interact k

Modifié pour "coupler" en ligne et utiliser des préfixes numériques après avoir vu l'entrée de @ FDinoff, a également composé des fonctions de carte pour raser un autre caractère.


Vous pouvez vous sauver quelques personnages (environ 5 je pense) si vous vous débarrassez de u. "one pair","two pair"est alors plus courtu=" pair" ... "one"++u,"two++u
FDinoff

yup, je faisais juste ce changement après avoir lu votre code. De plus, la technique du préfixe numérique me fait gagner encore 5
bazzargh

2

C ++, 622 553 caractères

quatre nouvelles lignes inutiles ajoutées ci-dessous pour plus de clarté.

#include"stdafx.h"
#include"string"
std::string c=" flush",d=" of a kind",e="straight",z[10]={"high card","one pair","two pair","three"+d,e,c,"full house","four"+d,e+c,"royal"+c},
x="CDHSA23456789TJQK";char h[99];int main(){__int64 f,p,t,g,u,v,w,l=1,a=78517370881,b=a+19173960,i,j,q=0;gets_s(h,99);for(i=28;i-->7;){f=p=0;
for(j=7;j--;)if(j!=i%7&j!=(i+i/7)%7){f+=l<<x.find(h[j*3+1])*6;p+=l<<x.find(h[j*3])*3-12;}
v=p&b*2;u=v&v-1;w=p&p/2;g=p*64&p*8&p&p/8&p/64;f&=f*4;t=f&&p==a?9:f&&g?8:p&b*4?7:u&&w?6:f?5:g||p==a?4:w?3:u?2:v?1:0;
q=t>q?t:q;}puts(z[q].c_str());}

Les choses ont changé dans la version golfée:

Rév. 1: toutes les variables numériques ont été remplacées par __int64pour une seule déclaration.

Rev 1: Incrément golfé et état des forboucles

Rev 0: modification des constantes octales en décimales.

Rev 0: ifinstructions modifiées pour les affectations avec opérateur conditionnel. Rev 1: Réarrangé plus loin en une seule expression pour t. Cela nécessitait une nouvelle variable vpour l'une des valeurs intermédiaires

Rev 0: sortie verbeuse supprimée. Ne produit que la meilleure main globale.

Rev 0: J'ai renoncé à compresser le texte de sortie (difficile en C parce que vous ne pouvez pas concaténer des chaînes en utilisant l'opérateur +.) L'écriture de "flush" une seule fois m'a sauvé 12 caractères mais m'a coûté 15, ce qui m'a rendu 3 caractères globalement moins bien. Je l'ai donc écrit 3 fois à la place. Rev 1: utilisé std::stringau lieu de char[]comme suggéré par FDinoff, permettant de concaténer avec +.

Version non golfée, 714 caractères non-commentaire non blancs.

Boucle à travers les 21 mains possibles qui peuvent être faites à partir de 7 cartes et rejette 2 cartes à chaque fois. La couleur et le rang des cinq cartes choisies sont totalisés dans les variables f et p avec un chiffre octal différent pour chaque couleur / rang. Diverses opérations binaires sont effectuées pour déterminer le type de main, qui est ensuite stocké dans t (les 21 possibilités sont sorties dans la version non golfée). Enfin, la meilleure main possible est sortie.

#include "stdafx.h"
#include "string.h"

char x[] = "CDHSA23456789TJQK", h[99], z[10][99] = 
{ "high card", "one pair", "two pair","three of a kind", "straight","flush","full house","four of a kind","straight","royal" };

int main(void)
{
        int i,j,q=0;                  //i,j:loop counters. q:best possible hand of 7 card   
        scanf_s("%s/n", &h, 99); getchar();
        for (i = 7; i < 28; i++){

          //f,p: count number of cards of each suit (2 octal digits) and rank (1 octal digit.)
          //t: best hand for current 5 cards. g:straight flag. u,w: flags for pairs and 3's.   
          //l: constant 1 (64bit leftshift doesn't work on a literal.) 
          //octal bitmasks: a=ace high straight, b=general purpose

            __int64 f=0,p=0,t=0,g,u,w,l=1,a=01111000000001,b=a+0111111110;

           for (j = 0; j < 7; j++){
               if (j != i %7 & j != (i+i/7) %7){

                   f += l << (strchr(x,h[j*3+1])-x)*6;
                   p += l << (strchr(x,h[j*3])-x-4)*3;

                   printf_s("%c%c ",h[j*3], h[j*3+1]);
               }
           }

           w=p&b*2;                          //if 2nd bit set we have a pair
           if (w) t=1;
           u= w & w-1;                       //if there is only one pair w&w-1 evaluates to 0; +ve for 2 pair.
           if (u) t=2;
           w = p & p/2;                      // if 2nd and 1st bit set we have 3 of kind. 
           if (w) t=3;
           g = p*64 & p*8 & p & p/8 & p/64;  // detects all straights except ace high. pattern for ace high in a.
           if (g||p==a) t=4;
           f&=f*4;                           //for a flush we want 5 cards of the same suit, binary 101
           if (f) t=5;
           if (u&&w) t=6;                    //full house meets conditions of 2 pair and 3 of kind
           if (p & b*4) t=7;                 //four of a kind
           if (f && g) t=8;                  //straight flush
           if (f && p==a) t=9;               //royal flush
           printf_s("%s %s \n",z[t],t>7?z[5]:"");
           q=t>q?t:q;
        }   
        printf_s("%s %s",z[q],q>7?z[5]:"");
        getchar();
}

Sortie non golfée

entrez la description de l'image ici


Puisque vous dites que vous utilisez c ++, vous pouvez utiliser <string>ce qui prend en charge + pour la concaténation de chaînes. Ce qui signifie alors que vous pourriez probablement utiliser <iostream>et utiliser coutCependant, je ne sais pas vraiment si l'un de ces éléments conduirait à un plus petit nombre de caractères.
FDinoff

@FDinoff ce que j'ai pu économiser: " pair flush flush straight of a kind"= 35 caractères. Une fois que vous ajoutez des #includeéconomies sont minimes, vous devez alors considérer les ",=+déclarations supplémentaires et les constantes. De plus, je suis nouveau sur C ++ et je lutte avec les paramètres IDE et du compilateur (cela me force à utiliser scanf_set printf_sau lieu des anciennes versions "dangereuses" et l'aide pour le corriger tourne en rond.) coutPourrait aider un peu, c'est à moi de faire la liste, mais probablement pour un autre programme. Ce qui coutme tue , c'est que using namespace stdje ne sais pas s'il y a un moyen d'éviter d'écrire tout ça.
Level River St

Vous ne devriez presque jamais avoir besoin de printf et scanf car vous utilisez c ++. Il y en a d'autres (plus sûr) qui devait faire la même chose. Vous pourriez utiliser std::coutpour vous déplacer leusing namespace std
FDinoff

@FDinoff thx pour la pointe. Dans ma dernière édition, j'ai enregistré 18 octets avec une gestion de chaîne différente: gets_s& puts, plus std::stringpour concaténer, ce qui signifie que je dois convertir char*en sortie. Le golf que j'ai publié fonctionne avec juste stringou simplement iostream.bizarrement, je dois inclure les deux pour utiliser les <<>>opérateurs avec cin/cout& std::strings. Dans l'ensemble, l'utilisation des deux #includes équivaut à 5 octets de moins, même si je peux déclarer en htant que a std::stringet éviter une chardéclaration distincte . On pouvait s'y attendre, je ne peux pas trouver une liste de ce qui est en namespace stdaide (ou une explication sur l'opérateur.)
Level River St

@FDinoff Je suis d'accord, je n'utiliserais pas normalement scanfet gets, sauf pour le golf, où les programmes sont assez dangereux de toute façon. Je pourrais raccourcir de 5 octets -s,99si je pouvais utiliser à la getsplace de gets_s, mais je ne peux pas laisser le compilateur me le permettre. Ce qui me surprend, c'est à quel point le C / C ++ est dangereux en général! Il y a quelques semaines, cela m'aurait choqué de découvrir que cela _int64 x=1<<ydonne la mauvaise réponse pour y supérieur à 31. Mais maintenant, je suis juste un peu ennuyé. Ayant vu des choses avec des indices de tableau sortir des limites sans message d'erreur, je m'y suis habitué. Existe-t-il un moyen d'activer une meilleure vérification?
Level River St

2

perl (> = 5.14), 411 403 400 397 400

Modifier : a inséré un sous qui n'a été appelé qu'une seule fois, économisant 8 caractères.
Édition 2 : a supprimé un .""qui avait été laissé lors d'une première tentative
Édition 3 : au lieu d'une variable temporaire qui préserve l'original $_, utilisez-en une pour la rendre inutile. Gain net 3 caractères.
Edit 4 : correction de l'échec de la détection de la saturation complète (2x 3-of-a-kind). coûte 3 caractères.

Pas tout à fait gagnant, mais le détecteur droit est un concept intéressant, je pense.

sub
j{join"",sort@_}sub
o{j(map{{A=>10}->{$_},11+index(j(2..9).TJQKA,$_)}$h=~/(.(?=@_))/g)=~/.*(..)(??{j
map$1+$_.'.*',1..4})/?$1:()}$h=$_=<>;if(j(/(\S)\b/g)=~/(.)\1{4}/){$w=$_==19?royal:straight
for
o$f=$1}$_=j(/\b(\S)/g)=~s/(.)\1*/length$&/rge;$k=" of a kind";print$w?"$w flush":/4/?four.$k:/3.*2|[23].*3/?"full house":$f?flush:(o".")?straight:/3/?three.$k:/2.*2/?"two pair":/2/?"one pair":"high card"

Version étendue:

# We'll be doing a lot of sorting and joining
sub j {
  return join "", sort @_;
}

# r() expects $_ to contain a rank, and converts it to a numeric code. The
# code starts at 10 so the numbers will sort correctly as strings, and a list
# of 2 values is returned because A is both 10 and 23. All other ranks have
# undef as the first value and their proper 11..22 value as the second value.
sub r {
  return ({A=>10}->{$_}, 11+index(j(2..9).TJQKA,$_));
}

# Sequence-detector. Factored into a sub because it's run twice; once over
# the ranks in the flush suit to find a straight flush and once over all the
# ranks to find a straight. On successful match, returns the lowest rank of
# the straight (in the 10..23 representation).
# Required parameter: the suit to search, or "." for all suits.
sub o {
  j(map r,$h=~/(.(?=@_))/g)          # The list of ranks, in increasing order,
                                     # with ace included at both ends...
    =~                               # ...is matched against...
  /.*(..)(??{j map$1+$_.'.*',1..4})/ # ...a pattern requiring 5 consecutive
                                     # numbers.
  ?$1:()
  # A note about this regexp. The string we're matching is a bunch of numbers
  # in the range 10..23 crammed together like "121314151619" so you might
  # worry about a misaligned match starting on the second digit of one of the
  # original numbers. But since that would make every pair of digits in the
  # match end with a 1 or a 2, there's no way 5 of them will be consecutive.
  # There are no false matches.
  # Another note: if we have a royal flush and also have a 9 in the same
  # suit, we need to return the T rank, not the 9, which is why the regexp
  # starts with a .*
}

# Read a line into $_ for immediate matching with /.../ and also save it into
# $h because $_ will be clobbered later and we'll need the original string
# afterwards.
$h = $_ = <>;

if(j(/(\S)\b/g) =~ /(.)\1{4}/) { # flush detector: sorted list of all suits
                                 # contains 5 consecutive identical chars
  # $f=$1 comes first, so $f will be true later if there's a flush.
  # Then o() is called with the flush suit as arg to detect straight flush.
  # If there's no straight flush, o() returns the empty list and for loop
  # runs 0 times, so $w is not set. If there is a straight flush, the return
  # value of o() is compared to 19 to detect royal flush.
  $w = ($_==19 ? "royal" : "straight")
    for o($f=$1);
}

$_ =
  j(/\b(\S)/g)                 # Get the sorted+joined list of ranks...
    =~ s/(.)\1*/length $&/rge; # ... and turn it into a list of sizes of
                               # groups of the same rank. The /r flag
                               # requires perl 5.14 or newer.

print
  $w             ? "$w flush" :
  /4/            ? "four of a kind" :
  /3.*2|[23].*3/ ? "full house" :
  $f             ? "flush" :
  (o".")         ? "straight" :
  /3/            ? "three of a kind" :
  /2.*2/         ? "two pair" :
  /2/            ? "one pair" :
                   "high card"

1

JavaScript 600

utilisation avec nodeJS: node code.js "7H 3S 7S 7D AC QH 7C"

function a(o){s="";for(k in o)s+=o[k];return s}
b=process.argv[2]
c={S:0,H:0,D:0,C:0}
v={A:0,K:0,Q:0,J:0,T:0,"9":0,"8":0,"7":0,"6":0,"5":0,"4":0,"3":0,"2":0}
d=b.split(" ")
for(i=d.length;i--;){e=d[i];c[e[1]]++;v[e[0]]++}
c=a(c);v=a(v)
f=g=h=j=k=l=m=false
if((st=c.indexOf(5))!=-1)g=!g
if(v.match(/[1-9]{5}/))h=!h
if(st==0)f=!f
if(v.indexOf(4)!=-1)j=!j
if(v.indexOf(3)!=-1)k=!k
if(n=v.match(/2/g))if(n)if(n.length>=2)m=!m;else l=!l
p=" of a kind"
q="Flush"
r="Straight"
console.log(f&&g?"Royal "+q:h&&g?r+" "+q:j?"Four"+p:k&&(l||m)?"Full House":g?q:h?r:k?"Three"+p:m?"Two pairs":l?"Pair":"High card")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.