Hold'em ou Fold'em?

17

Seu amigo convidou você para um jogo de pôquer de alto risco no último minuto e, como cientista da computação, decidiu usar suas habilidades para ganhar vantagem no jogo. Sua tarefa será, dada 2 cards(sua mão) e 0, 3, 4 or 5 cards(as cartas distribuídas), você deve decidir qual será a melhor mão possível. Se todas as 7 cartas forem dadas como argumentos, a resposta é bastante clara. Se dado menos, o problema se torna mais complexo. No entanto, isso não é o suficiente para dar a vantagem que você procura, você também deve calcular a melhor mão possível das cartas restantes para entender o que seus oponentes também poderiam ter.


Atualização do Hold'em

Se você não conhece o hold'em, cada jogador no jogo começa com 2 cartas como sua 'mão'. Ao longo de 3 'turnos', revelam-se cartas adicionais para serem compartilhadas entre todos os jogadores. No primeiro turno, 3 cartas são reveladas. A segunda, mais 1 e a terceira vez que uma carta final é revelada. As duas cartas dadas primeiro representam a sua mão, enquanto as últimas representam 0, 3, 4 ou 5 cartas dadas pelos turnos sucessivos.


Números possíveis:

[2,3,4,5,6,7,8,9,T(10),J,Q,K,A]

Possíveis fatos:

[S,C,H,D]

Deck completo:

[2S,3S,4S,5S,6S,7S,8S,9S,TS,JS,QS,KS,AS, # Spades.
 2C,3C,4C,5C,6C,7C,8C,9C,TC,JC,QC,KC,AC, # Clubs.
 2H,3H,4H,5H,6H,7H,8H,9H,TH,JH,QH,KH,AH, # Hearts.
 2D,3D,4D,5D,6D,7D,8D,9D,TD,JD,QD,KD,AD] # Diamonds.

Classificação das mãos:

1:Royal Flush    (A-K-Q-J-10, all from the same suit).
2:Straight Flush (Sequential cards, all from the same suit).
3:Four-of-a-Kind (Self explanatory).
4:Full House     (3-of-a-kind and a 2-of-a-kind).
5:Flush          (All cards are from the same suit).
6:Straight       (Sequential Cards, any suits).
7:3-of-a-Kind    (Self explanatory).
8:2-Pair         (Double 2-of-a-Kind).
9:Pair           (2-of-a-Kind).
10:High Card     (You have absolutely nothing except a single card).

Vamos dar um exemplo ou dois e percorrê-los:

O exemplo simples:

[AS, AC],[AH,AD,9S,9C,9H]-> 3(Quatro), 3(Quatro)

A melhor mão possível que você terá nessa configuração é a mão de quatro tipos. A melhor mão possível que seus oponentes poderiam ter também é a de 4, porque você não pode ter um KQJ10 nas mãos de duas cartas.


[5C,2C],[6C,4C,JH,JD]-> 2(Straight Flush), 3(4-de-um-tipo)

Você corre o risco de um straight flush, mas como você tem o 2 / 5C na sua mão, ninguém mais se deve ao fato de você ter as duas cartas do meio. O melhor que eles podem esperar é ter dois Valetes e um Valete no flop.


[JS,JC],[]-> 1(Royal Flush), 1(Royal Flush)

Nenhuma informação que você possa usar contra eles foi fornecida, tudo o que você pode dizer no momento é que eles só podem ter um royal flush em diamantes / copas, mas é tão possível que você obtenha o royal flush quanto eles. De fato, todas as entradas em que o flop ainda não aconteceu devem resultar em uma resposta de 1 a 1.


[2C,4S],[3C,7S,9D,AH,JD]-> 10(Carta Alta), 7(3)

Este é um exemplo de onde você está absolutamente ferrado, e não há possibilidade de um straight ou um flush dado o river. Significando que a melhor mão aqui são ases, resultando em um 3-de-um-tipo.


Requisitos de E / S

  • A entrada deve ser separada entre o que está na sua mão e o que é conhecimento público; provavelmente será mais fácil assim, independentemente da implementação.
    • Os cartões podem ser tuplas ou cordas, até você.
    • A mão e o campo de jogo podem ser matrizes ou strings delimitadas.
  • A saída deve ser dois índices da lista de ponteiros que eu forneci (EG [2,1]).
    • Pode ser retornado como parte de uma função, impresso no console ou produzido de maneira adequada.
    • Deve haver dois valores distintos, um para a sua melhor mão, outro para a melhor possível.
  • 10 pode ser representado como um Tou como 10, o que fizer sentido para você.
  • As brechas padrão não são permitidas.

Critérios Vencedores

  • Trata-se de , menor contagem de bytes com um desempate da data de postagem.
Urna de polvo mágico
fonte
2
Não deveria haver apenas um Ae 1os possíveis cartões permitidos? Também não acho que exista realmente uma razão convincente para exigir as abreviações de face sobre valores numéricos como 11.
FryAmTheEggman
9
Eu nunca vi um baralho com um Ae um 1. Tudo o resto parece bom.
Isaacg
11
Para nós, jogadores que não são de poker, explique na pergunta que o segundo grupo de cartas é compartilhado entre você e seu oponente, enquanto eles têm suas próprias duas cartas que você não pode ver. Um glossário rápido, definindo os termos pocket , flop e river, seria útil.
DLosc
11
Também é útil: explicar toda a sequência de uma rodada. (Cada jogador começa com duas cartas conhecidas apenas por eles; depois, três cartas são viradas para cima, depois uma quarta e depois uma quinta), momento em que cada jogador forma uma "mão" de cinco cartas dentre as sete visíveis para eles. .) Pode não estar claro para alguém por que existem sete cartas, mas uma mão consiste em cinco.
DLosc

Respostas:

3

Haskell , 433 430 425 bytes

-5 bytes graças a @Laikoni

import Data.List
q="23456789TJQKA"
e=elem
l=length
b=map
r p|z,elem 'A'u,elem 'K'u=1|z=2|e 4t=3|v<3=4|w=5|y=6|e 3t=7|v<4=8|v<5=9|1>0=10where u=[n!!0|n<-p];v=l$nub u;t=b(\n->l[x |x<-u,x==n])q;w=all(==(last$p!!0))[last s|s<-p];y=elem""[u\\s|s<-b(take 5.flip drop('A':q))[0..10]];z=y&&w
0%_=[[]]
n%(x:y)=b(x:)((n-1)%y)++n%y
_%_=[]
h#t|let p=h++t;c i=minimum$b r$concat$b(5%)$b(++i)((7-l i)%([n:[s]|n<-q,s<-"SCHD"]\\p))=(c p,c t)

Experimente online!

Ungolfed (mesma idéia, estrutura ligeiramente diferente):

import Data.List -- for (\\)
numbers = "23456789TJQKA"

e=elem

rank_hand hand
    |royal_flush=1
    |straight_flush=2
    |four_of_a_kind=3
    |full_house=4
    |flush=5
    |straight=6
    |three_kind=7
    |two_pair=8
    |pair=9
    |1>0=10
    where nums = [head n | n<-hand]
          unique = length $ nub nums
          counts = map (\n->length [x | x<-nums, x==n]) numbers
          pair = unique < 5
          two_pair = unique < 4 -- could also be 3 of a kind, but that's ok
          three_kind = e 3 counts
          flush = all (==(last$hand!!0)) [last s|s<-hand]
          straight = elem "" [nums\\s | s <- map (take 5.flip drop ('A':numbers))[0..10]]
          full_house = unique < 3
          four_of_a_kind = e 4 counts
          straight_flush = straight && flush
          royal_flush = straight_flush && elem 'A' nums && elem 'K' nums

-- taken from /codegolf//a/34496/66460
-- k%l finds combinations of size k from a list l
0%_=[[]]
n%(x:y)=map(x:)((n-1)%y)++n%y
_%_=[]

-- find every combination available to each player, and rank each one. 
-- could be golfed a lot more.
h#t=let p=h++t
        a=[n:[s]|n<-numbers,s<-"SCHD"]\\p
        c i=minimum $ map rank_hand $ concat $ map (5%) $ map (++i) ((7-length i)%a)
    in(c p,c t)

Muito lento, já que não há revestimento especial (por exemplo, se nenhuma carta foi mostrada, um royal flush é sempre possível.) A maior parte do meu esforço no golfe foi para a rank_handfunção; #pode ser jogado muito mais combinando mapas e coisas do tipo.

hand#tablecalcula as pontuações ideais para você e seu oponente. Não verifica erros.

vroomfondel
fonte
Eu acho que você esqueceu s/elem/e/gdepois de definir e=elem, de modo que você deve economizar 9 bytes. Eu acho que você também pode remover alguns espaços, particularmente onde identificadores seguem números diretamente
Julian Lobo
@JulianWolf Eu ainda sou novo no Haskell, mas por alguma razão parece com o e=elemtipo inferido Int-> Bool, então não estava compilando quando usei e para chamadas de elem não inteiros. Estou tentando descobrir por que o que era. Obrigado pela dica sobre os espaços!
precisa saber é o seguinte
Ah, você está certo. Haskell tem dificuldade para inferir tipos polimórficos às vezes não tenho certeza fora do topo da minha cabeça se há um reparo fácil, além de adicionar o flexível tipos flag
Julian Lobo
11
h#t=let[...]in[...]pode ser reduzido para h#t|let[...]=[...]. Também head né n!!0. Em um guarda &&pode simplesmente ser ,.
Laikoni