Nombra la mano de póker - edición de 7 cartas

11

El reto:

En esta pregunta: Nombre la mano de póker que tuvo que tomar una mano de póker de cinco cartas e identifíquela. Esta pregunta es similar, con dos giros:

Primero, la salida será en minúsculas. Esto permite más golf, ya que no tiene que preocuparse por la capitalización flushystraight

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

En segundo lugar, con la popularidad de Texas Hold'em y 7 card stud, aquí en code golf deberíamos poder anotar una mano de póker de siete cartas, ¿verdad? Al anotar una mano de siete cartas, use las cinco mejores cartas para su mano e ignore las dos que no necesita.

Referencia:

Lista de manos de póker: http://en.wikipedia.org/wiki/List_of_poker_hands

Entrada (levantada directamente del hilo anterior)

7 cartas de argumentos estándar o de línea de comandos. Una tarjeta es una cadena de dos letras en el formulario RS, donde R es rango y S es palo. Los rangos son 2: 9(tarjetas de números), T(diez), J(Jack), Q(Reina), K(Rey), A(As). Los trajes son S, D, H, Cde picas, diamantes, corazones y clubes respectivamente.

Ejemplo de cartas

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

Ejemplo de entrada => salida deseada

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

Observe que en el segundo ejemplo en realidad hay tres pares, pero solo puede usar cinco cartas, así que es two pair. En el quinto ejemplo, hay a three of a kindy a straightposibles, pero a straightes mejor, por lo tanto, la salida straight.

Puntuación

Este es el , ¡el código más corto gana!

Erratas

  1. No puede usar recursos externos.
  2. As es tanto alto como bajo para las rectas.
durron597
fuente
Agradable; Secretamente esperaba que alguien recogiera la pelota. Solo quería señalar que no tenía ninguna restricción sobre la capitalización en la pregunta original (aclarada en un comentario), por lo que podría (y la mayoría / todos lo hicieron) producir "Straight Flush". En mi humilde opinión capitalizado se ve mejor.
daniero
Dices entrada (levantada directamente del hilo anterior) 5 cartas. Creo que querías cambiar eso a 7.
Level River St
@steveverrill Puede editar publicaciones usted mismo en el intercambio de pila. Aunque lo hice por ti aquí
durron597
¿Se permiten recursos externos? Hay tablas de búsqueda que le permitirán simplemente buscar cada carta en la mano y obtener fuerza en la mano.
Kendall Frey
¿Puede ser tanto bajo como alto para los rectos?
Nick T

Respuestas:

4

Rubí 353

Esto se basó en la respuesta de Chron de la pregunta original.

Esto toma la entrada como argumentos de línea de comando. Básicamente, simplemente iteramos sobre todas las combinaciones de tamaño 5 para obtener qué tipo de mano es. Cada tipo de mano se modificó para que comience con un número. ("escalera real" -> "0royal 4flush", "carta alta" -> "carta 9high"). Esto nos permite ordenar las cadenas que se devolvieron. La primera cadena después de ordenar es la mejor mano posible. Entonces imprimimos eso después de eliminar todos los números de la cadena.

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/,'')
FDinoff
fuente
Agradable. El gsub al final puede ser un sub ¿verdad?
bazzargh
@bazzargh no, necesita eliminar todos los números. El código concatena 4flush con 1sight o 0royal para obtener "0royal 4 flush" o "1straight 4flush". Si solo usáramos sub, el 4 no se eliminaría.
FDinoff
Da el resultado incorrecto para AS QS JS TS 9S 5H 5D. ¡Eso te costará un personaje!
@ WumpusQ.Wumbley Hmm esto parece ser un error en el código original. Trataré de averiguar cuál es el problema más adelante.
FDinoff
5

Haskell 618 603 598 525 512 504 480 464

Tarjetas tomadas como una línea de entrada. Creo que he jugado al golf hasta la muerte, pero será fácilmente derrotado por el rubí, etc. con el mismo truco: si genera todas las permutaciones, obtendrá el tipo de avance que desea buscar rectas, más el tipo de reverso que desea para probar N de una especie.

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

Editado para "emparejar" en línea y usar prefijos de números después de ver la entrada de @ FDinoff, también compuso funciones de mapa para afeitar un carácter más.

bazzargh
fuente
Puedes ahorrarte un par de personajes (unos 5, creo) si te deshaces de ti. "one pair","two pair"es más corto entoncesu=" pair" ... "one"++u,"two++u
FDinoff
Sí, estaba haciendo ese cambio después de leer tu código. También la técnica de prefijo numérico me ahorra otros 5
bazzargh
2

C ++, 622 553 caracteres

cuatro líneas nuevas innecesarias agregadas a continuación para mayor claridad.

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

Las cosas cambiaron en la versión de golf:

Rev 1: Se cambiaron todas las variables numéricas para __int64una sola declaración.

Rev 1: Incremento de golf y condición de forbucles

Rev 0: Cambió las constantes octales a decimal.

Rev 0: Cambió las ifdeclaraciones a asignaciones con operador condicional. Rev 1: Reorganizado aún más en una sola expresión para t. Esto requirió una nueva variable vpara uno de los valores intermedios

Rev 0: salida detallada eliminada. Solo genera la mejor mano en general.

Rev 0: me di por vencido al comprimir el texto de salida (difícil en C porque no se pueden concatenar cadenas con el operador +). Escribir "vaciar" solo una vez me salvó 12 caracteres, pero me costó 15, empeorando en general 3 caracteres. Así que lo escribí 3 veces en su lugar. Rev 1: se utiliza en std::stringlugar de char[]lo sugerido por FDinoff, lo que hace posible concatenar con +.

Versión sin golf, 714 caracteres sin espacios en blanco sin comentarios.

Recorre las 21 manos posibles que se pueden hacer con 7 cartas y rechaza 2 cartas cada vez. El palo y el rango de las cinco cartas elegidas se totalizan en las variables f y p con un dígito octal diferente para cada palo / rango. Se realizan varias operaciones de bits para determinar el tipo de mano, que luego se almacena en t (las 21 posibilidades se emiten en la versión sin golf). Finalmente, se emite la mejor mano posible.

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

Salida sin golf

ingrese la descripción de la imagen aquí

Level River St
fuente
Como dice que está usando c ++, podría usar el <string>que admite + para la concatenación de cadenas. Lo que significa que probablemente podría usar <iostream>y usar coutSin embargo, en realidad no sé si alguno de ellos conduciría a un recuento de caracteres más pequeño.
FDinoff
@FDinoff lo que podría guardar: " pair flush flush straight of a kind"= 35 caracteres. Una vez que agregue los #includeahorros son mínimos, entonces debe considerar extra ",=+y declaraciones de constantes. Además, soy nuevo en C ++ y tengo dificultades con la configuración de IDE y del compilador (me obliga a usar scanf_sy, en printf_slugar de las viejas versiones "inseguras" y la ayuda para solucionarlo va en círculos.) coutPodría ayudar un poco, depende de mí lista, pero probablemente para otro programa. Lo que coutme mata es using namespace stdque no sé si hay una manera de evitar escribir todo eso.
Level River St
Casi nunca debería necesitar printf y scanf ya que está utilizando c ++. Hay otros (más seguros) para hacer lo mismo. Podrías std::coutmoverte por elusing namespace std
FDinoff
@FDinoff thx por la propina. En mi última edición, guardé 18 bytes con diferente manejo de cadenas: gets_s& puts, además std::stringde concatenar, lo que significa que debo convertir char*a salida. El golf que publiqué funciona con solo stringo iostream.extrañamente. Debo incluir ambos para usar <<>>operadores con cin/cout& std::strings. En general, usar ambos #includes funciona 5 bytes peor, a pesar de que puedo declarar hcomo ay std::stringevitar una chardeclaración por separado . Como era de esperar, no puedo encontrar una lista de lo que está en namespace stdayuda (o una explicación sobre el operador).
Level River St
@FDinoff Estoy de acuerdo, normalmente no usaría scanfy gets, a excepción del golf, donde los programas son bastante inseguros de todos modos. Podría acortar en 5 bytes -s,99si pudiera usar en getslugar de gets_s, pero no puedo conseguir que el compilador me lo permita. ¡Lo que me sorprende es lo inseguro que es C / C ++ en general! Hace unas semanas me habría sorprendido descubrir que _int64 x=1<<yda una respuesta incorrecta para mayores de 31 años. Pero ahora estoy un poco molesto. Habiendo visto cosas con subíndices de matriz fuera de límites sin mensaje de error, me he acostumbrado. ¿Hay alguna forma de mejorar el control?
Level River St
2

Perl (> = 5,14), 411 403 400 397 400

Editar : en línea un sub que solo se llamó una vez, ahorrando 8 caracteres.
Edición 2 : eliminó un .""sobrante de un intento anterior
Edición 3 : en lugar de una variable temporal que conserva el original $_, use uno para que sea innecesario. Ganancia neta 3 caracteres.
Edición 4 : error solucionado para detectar la casa completa demasiado llena (2x 3 de su tipo). cuesta 3 caracteres

No es un gran ganador, pero creo que el detector directo es un concepto interesante.

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"

Versión ampliada:

# 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"

fuente
1

JavaScript 600

uso con 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")
guy777
fuente