Nomear a mão de poker - edição de 7 cartas


11

O desafio:

Nesta pergunta: Nomeie a mão de pôquer que você teve que pegar uma mão de cinco cartas e identifique-a. Esta pergunta é semelhante, com duas reviravoltas:

Primeiro, a saída será minúscula. Isso permite mais golfe, pois você não precisa se preocupar com a capitalização flushestraight

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

Em segundo lugar, com a popularidade do Texas Hold'em e do 7 card stud, nós do code golf poderemos marcar uma mão de sete cartas, certo? Ao marcar uma mão de sete cartas, use as cinco melhores cartas para sua mão e ignore as duas que você não precisa.

Referência:

Lista de mãos de pôquer: http://en.wikipedia.org/wiki/List_of_poker_hands

Entrada (levantada diretamente do encadeamento anterior)

7 cartas dos argumentos stdin ou da linha de comando. Um cartão é uma sequência de duas letras no formulário RS, onde R é a classificação e S é o naipe. As fileiras são 2- 9(cartas de número), T(dez), J(Valete), Q(Rainha), K(Rei), A(Ás). Os ternos são S, D, H, Cpara pás, diamantes, corações e clubes, respectivamente.

Exemplo de cartões

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

Exemplo de entrada => saída desejada

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 no segundo exemplo, na verdade, existem três pares, mas você só pode usar cinco cartas, por isso é two pair. No quinto exemplo, há a three of a kinde a straightpossível, mas a straighté melhor, portanto, saída straight.

Pontuação

Isso é , então o código mais curto vence!

Errata

  1. Você não pode usar recursos externos.
  2. O ás é alto e baixo para retas.

Agradável; Eu secretamente esperava que alguém pegasse a bola. Só queria observar que eu não tinha nenhuma restrição de capitalização na pergunta original (esclarecida em um comentário), para que você pudesse (e quase tudo) produziu "Straight Flush". IMHO capitalizado parece melhor.
Daniero 11/0314

Você diz que a entrada (levantada diretamente do segmento anterior) 5 cartões. Eu acho que você pretendia mudar isso para 7. #
Level River St

@steveverrill Você pode editar suas postagens na troca de pilhas. Embora eu tenha feito isso por você aqui #
durron597

Recursos externos são permitidos? Existem tabelas de pesquisa que permitem que você pesquise cada carta na mão e obtenha força na mão.
Kendall Frey

O ás pode ser baixo e alto para retas?
Nick T

Respostas:


4

Ruby 353

Isso foi baseado na resposta de Chron da pergunta original.

Isso leva a entrada como argumentos de linha de comando. Basicamente, iteramos todas as combinações de tamanho 5 para obter que tipo de mão é. Cada tipo de mão foi modificado para que comece com um número. ("royal flush" -> "0royal 4flush", "high card" -> "9high card"). Isso nos permite classificar as strings que foram retornadas. A primeira corda após a classificação é a melhor mão possível. Então, imprimimos isso após remover todos os números da string.

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/,'')

Agradável. O gsub no final pode ser apenas um sub, certo?
bazzargh

@bazzargh não, ele precisa remover todos os números. O código concatena 4flush com 1straight ou 0royal para obter "0royal 4 flush" ou "1straight 4flush". Se usarmos apenas o sub, os 4 não serão removidos.
FDinoff

Dá o resultado errado para AS QS JS TS 9S 5H 5D. Isso vai te custar um personagem!

@ WumpusQ.Wumbley Hmm, isso parece ser um bug no código original. Vou tentar descobrir qual é o problema mais tarde.
FDinoff

5

Haskell 618 603 598 525 512 504 480 464

Cartões tomados como uma linha de entrada. Eu acho que joguei isso até a morte, mas será facilmente derrotado por rubi, etc. usando o mesmo truque: se você gerar todas as permutações, obterá o tipo de avanço que deseja procurar em linha reta, mais o tipo de inversão que deseja para testar N de um tipo.

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 "par" embutido e usar prefixos numéricos depois de ver a entrada de @ FDinoff, também compôs funções de mapa para raspar mais um caractere.


Você pode salvar alguns personagens (cerca de 5 eu acho) se você se livrar de você. "one pair","two pair"é menor entãou=" pair" ... "one"++u,"two++u
FDinoff 12/03/2014

Sim, eu estava fazendo essa alteração depois de ler seu código. Além disso, a técnica de número de prefixo me salva outros 5
bazzargh

2

C ++, 622 553 caracteres

quatro novas linhas desnecessárias adicionadas abaixo para maior clareza.

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

As coisas mudaram na versão golfed:

Rev 1: Alteradas todas as variáveis ​​numéricas para __int64para uma única declaração.

Rev 1: Incremento de golfe e condição de forloops

Rev 0: Constantes octais alteradas para decimal.

Rev 0: Instruções alteradas ifpara atribuições com operador condicional. Rev 1: Reorganizado ainda mais em uma única expressão para t. Isso exigiu nova variável vpara um dos valores intermediários

Rev 0: Saída detalhada excluída. Somente produz a melhor mão geral.

Rev 0: Desistiu de compactar o texto de saída (difícil em C porque você não pode concatenar seqüências de caracteres usando o operador +.) Escrever "flush" apenas uma vez me salvou 12 caracteres, mas me custou 15, fazendo com que eu sofresse três caracteres em geral. Então, eu apenas escrevi 3 vezes. Rev 1: usado em std::stringvez de char[]sugerido por FDinoff, possibilitando concatenar com +.

Versão não-gasta, 714 caracteres não-espaço em branco que não são comentários.

Loops através de todas as 21 mãos possíveis que podem ser feitas de 7 cartas e rejeita 2 cartas de cada vez. O naipe e o ranking das cinco cartas escolhidas são totalizados nas variáveis ​​fe ep com um dígito octal diferente para cada naipe / ranking. Várias operações de bit são executadas para determinar o tipo de ponteiro, que é armazenado em t (todas as 21 possibilidades são produzidas na versão não-gravada). Finalmente, a melhor mão possível é produzida.

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

Saída não destruída

insira a descrição da imagem aqui


Como você diz que está usando c ++, você pode usar o <string>que suporta + para concatenação de strings. O que significa que você provavelmente poderia usar <iostream>e usar. coutNo entanto, não sei se algum deles levaria a uma contagem menor de caracteres.
FDinoff 17/03/2014

@FDinoff o que eu poderia economizar: " pair flush flush straight of a kind"= 35 caracteres. Depois de adicionar #includeeconomias, o mínimo é necessário considerar ",=+declarações extras e de constantes. Também sou novo em C ++ e luto com as configurações do IDE e do compilador (ele me obriga a usar scanf_se, em printf_svez das antigas versões "inseguras", e a ajuda para corrigi-lo circula em círculos.) coutPode ajudar um pouco, é meu dever lista, mas provavelmente para outro programa. O que coutme mata é using namespace stdque não sei se há uma maneira de evitar escrever tudo isso.
Level River St

Você quase nunca precisará de printf e scanf, pois está usando o c ++. Há outro (mais seguro) era fazer a mesma coisa. Você poderia usar std::coutpara contornar ousing namespace std
FDinoff

@FDinoff thx pela dica. Na minha edição mais recente, salvei 18 bytes com manipulação de string diferente: gets_s& puts, mais std::stringpara concatenar, o que significa que devo converter char*em saída. O golfe que publiquei funciona com o Bizarrely, com apenas stringou apenas com o qual iostream.devo incluir ambos, para usar os <<>>operadores com o cin/cout& std::strings. No geral, o uso de #includes funciona 5 bytes pior, embora eu possa declarar hcomo ae std::stringevitar uma chardeclaração separada . Previsivelmente, não consigo encontrar uma lista do que está em namespace stdajuda (ou uma explicação sobre o operador.) #
Level River St

@FDinoff Eu concordo, normalmente não usaria scanfe gets, exceto no golfe, onde os programas são bastante inseguros. Eu poderia reduzir em 5 bytes -s,99se pudesse usar em getsvez de gets_s, mas não consigo o compilador me permitir. O que me surpreende é como o C / C ++ é inseguro em geral! Algumas semanas atrás, teria me chocado ao descobrir que _int64 x=1<<ydá a resposta errada para y maior que 31. Mas agora estou levemente aborrecido. Tendo visto coisas com subscritos de matriz saindo dos limites sem nenhuma mensagem de erro, eu me acostumei. Existe alguma maneira de ativar uma verificação melhor?
Level River St

2

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

Editar : inline um sub que foi chamado apenas uma vez, economizando 8 caracteres.
Edit 2 : removeu um .""que sobrou de uma tentativa inicial
Edit 3 : em vez de uma variável temporária que preserva o original $_, use um para torná-lo desnecessário. Ganho líquido de 3 caracteres.
Edição 4 : falha corrigida na detecção de full house cheio (2 em 3). custa 3 caracteres.

Não é um vencedor, mas o detector reto é um conceito interessante, eu acho.

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"

Versão expandida:

# 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

uso com 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")
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.