Word Poker, quem ganha?

13

A entrada será duas palavras de cinco letras. Na verdade, eles não precisam ser palavras do dicionário, apenas cinco letras cada, todas minúsculas ou maiúsculas, à sua escolha. Somente AZ aparecerá nas palavras de entrada e elas sempre terão 5 caracteres.

Seu programa é pontuar os dois como se fossem mãos de pôquer e gerar a mão mais alta. É claro que naipes não se aplicam aqui, apenas classificações, para que não haja flushes.

O sistema de classificação de pôquer típico é: '1 par', '2 pares', '3 do mesmo tipo', 'straight', 'full house', '4 do tipo', '5 do tipo' e, é claro existe a possibilidade de a mão (ou palavra neste caso) não valer nada.

No caso de empate , as letras mais próximas de A são consideradas mais altas, então um par de As vence um par de Bs. Em alguns casos, ambas as mãos podem ser idênticas, mas em uma ordem diferente (ou não); nesse caso, produzem uma mão ou uma versão mais recente.

Esta página externa contém informações sobre como identificar o vencedor e, principalmente, aborda os laços nos rankings específicos, caso você não esteja familiarizado com a pontuação das mãos de poker.

No caso de retas : as letras devem estar adjacentes ao alfabeto e não podem ser contornadas. Então 'defgh' em qualquer ordem é uma sequência, 'xyzab' não é.

Exemplos de como marcar uma única mão:

word   | scored as
---------------------
ccccc  | 5 of a kind     <-- highest ranking
woooo  | 4 of a kind
opopo  | full house
vurst  | straight
vovvu  | 3 of a kind
ppoww  | 2 pairs
upper  | 1 pair
kjsdf  | high card only (in this case D) <-- lowest ranking

Portanto, o programa realmente produzirá resultados como este:

input        |  output
-----------------------
voviu,kjsdf  |  voviu     because a pair beats nothing 
opoqo,upper  |  opoqo     because 3 of a kind beats a pair
woooo,ggegg  |  ggegg     because 4 Gs beats 4 Os
queue,hopup  |  queue     because 2 pairs beats 1 pair
lodpl,ddkop  |  ddkop     because pair DD beats pair LL
huhyg,hijht  |  huhyg     both have pair HH, but G beats I
ddffh,ccyyz  |  ccyyz     both have 2 pairs, but CC(yyz) beats DD(ffh)
okaok,nkunk  |  nkunk     KK ties with KK, but NN beats OO
abcdf,bcdef  |  bcdef     because it is a straight
qtery,retyq  |  qtery     identical! so doesnt matter
abedc,vyxwz  |  abedc     because it is a "higher" straight
hhhij,hijkl  |  hijkl     because straight beats 3 of a kind
aaabb,zzzzz  |  zzzzz     because nothing beats 5 of a kind

A ordem das letras na entrada e na saída é irrelevante; portanto, a ordem na saída pode ser diferente da entrada, mas o mesmo inventário de letras precisa estar presente.

A saída deve conter exatamente cinco letras - nem mais nem menos.

As regras usuais do codegolf se aplicam. O menor código vence.

Polvo
fonte

Respostas:

4

JavaScript ( 224 218 213 bytes)

s=>t=>(v=s=>(o={},l=n=0,z=3.5,[...s].sort().map(c=>(n+=o[c]=-~o[c],z*=!l|l+1==(l=c.charCodeAt()))),[n+z,Object.keys(o).sort((a,b)=>o[b]-o[a]||(o[b]>o[a]?1:-1))]),w=v(s),x=v(t),w[0]>x[0]||w[0]==x[0]&&w[1]<x[1]?s:t)

Ungolfed:

s=>t=>(
  v=s=>(
    o={},
    l=n=0,
    z=3.5,
    [...s].sort().map(c=>(
      n+=o[c]=-~o[c],
      z*=!l|l+1==(l=c.charCodeAt())
    )),
    [n+z,Object.keys(o).sort((a,b)=>o[b]-o[a]||(o[b]>o[a]?1:-1))]
  ),
  w=v(s),x=v(t),
  w[0]>x[0] || w[0]==x[0] && w[1]<x[1] ? s : t
)

Depois de map() rodadas, n + zdetermina a classificação de uma mão:

insira a descrição da imagem aqui

(Você pode entender por que eu inicializei zpara 3.5.)

Em caso de empate, Object.keys(o).sort()é usado para determinar a mão de classificação mais alta.

Snippet:

f=

s=>t=>(v=s=>(o={},l=n=0,z=3.5,[...s].sort().map(c=>(n+=o[c]=-~o[c],z*=!l|l+1==(l=c.charCodeAt()))),[n+z,Object.keys(o).sort((a,b)=>o[b]-o[a]||(o[b]>o[a]?1:-1))]),w=v(s),x=v(t),w[0]>x[0]||w[0]==x[0]&&w[1]<x[1]?s:t)

console.log(/voviu/.test(f('voviu')('kjsdf')))       //because a pair beats nothing 
console.log(/opoqo/.test(f('opoqo')('upper')))       //because 3 of a kind beats a pair
console.log(/ggegg/.test(f('woooo')('ggegg')))       //because 4 Gs beats 4 Os
console.log(/queue/.test(f('queue')('hopup')))       //because 2 pairs beats 1 pair
console.log(/ddkop/.test(f('lodpl')('ddkop')))       //because pair DD beats pair LL
console.log(/huhyg/.test(f('huhyg')('hijht')))       //both have pair HH, but G beats I
console.log(/ccyyz/.test(f('ddffh')('ccyyz')))       //both have 2 pairs, but CC(yyz) beats DD(ffh)
console.log(/nkunk/.test(f('okaok')('nkunk')))       //KK ties with KK, but NN beats OO
console.log(/bcdef/.test(f('abcdf')('bcdef')))       //because it is a straight
console.log(/qtery|retyq/.test(f('qtery')('retyq'))) //identical! so doesnt matter
console.log(/abedc/.test(f('abedc')('vyxwz')))       //because it is a "higher" straight
console.log(/hijkl/.test(f('hhhij')('hijkl')))       //because straight beats 3 of a kind
console.log(/zzzzz/.test(f('aaabb')('zzzzz')))       //because nothing beats 5 of a kind

Rick Hitchcock
fonte
3

Gelatina ,  28 27 29  27 bytes

+2 e -2 corrigem um erro e depois re-golf.

FI=1ȦḤW
OµNĠLÞṚịµL€+Ç,N
ÇÞṪ

Um link monádico que pega uma lista de "mãos" e retorna (um dos) vencedores.

Funciona para todas as letras maiúsculas ou minúsculas.
(... mas não misturado, pois isso antecede a linha final com Œlou Œu).

Experimente online! ou veja a suíte de testes .

Quão?

FI=1ȦḤW - Link 1, straight offset: grouped and reverse sorted hand ordinals
        -                     e.g. [[-101],[-100],[-99],[-98],[-97]]
F       - flatten                  [-101,-100,-99,-98,-97]
 I      - increments               [1,1,1,1]
  =1    - equal 1? (vectorises)    [1,1,1,1]
    Ȧ   - any and all?             1
     Ḥ  - double                   2
      W - wrap in a list           [2]
        -   The purpose of this is so that when "a" from Link 2 represents a straight we
        -   get [2], whereas for any other hand we get [0]. Adding the [2] to [1,1,1,1,1]
        -   (the lengths of a straight's groups) yields [3,1,1,1,1], placing it between
        -   three of a kind, [3,1,1], and a full house, [3,2], as required.

OµNĠLÞṚịµL€+Ç,N - Link 2, hand rank key function: list of characters       e.g. "huhyg"
O               - cast to ordinals                                [104,117,104,121,103]
 µ              - monadic chain separation, call that o
  N             - negate (to give them a reverse-sort order) [-104,-117,-104,-121,-103]
   Ġ            - group indices by value                            [[4],[2],[1,3],[5]]
     Þ          - sort by key function:
    L           -   length                                          [[4],[2],[5],[1,3]]
      Ṛ         - reverse                                           [[1,3],[5],[2],[4]]
       ị        - index into o                       [[-104,-104],[-103],[-117],[-121]]
        µ       - monadic chain separation (call that a)
         L€     - length of €ach                                              [2,1,1,1]
            Ç   - call last link (2) as a monad -> [isStraight? * 2]                [0]
           +    - addition (vectorises)                                       [2,1,1,1]
              N - negate o                                [[104,104],[103],[117],[121]]
             ,  - pair                        [[2,1,1,1],[[104,104],[103],[117],[121]]]
                -   now sorting by this will first be comparing the hand class, and if
                -   and only if they match comparing the card values in the required order.

ÇÞḢ - Main link: list of lists of characters (list of hands)
 Þ  - sort by key function:
Ç   -   last link (2) as a monad
  Ṫ - tail (best or an equal-best hand)
Jonathan Allan
fonte
Estupidamente curto em comparação com o que estou fazendo no JS 0.o
Stephen
3
@StephenS Bem-vindo ao PPCG, onde você cria algo em alguma linguagem que não seja golfe e, em seguida, alguém cria algo em Jelly, 05AB1E, Pyth, CJam, etc., que é mais curto que o nome do seu idioma: I: P
HyperNeutrino
1
@StephenS - JS deve competir com JS. Não deixe que os idiomas do golfe o impeçam de enviar soluções bem pensadas em outros idiomas!
Jonathan Allan
@ JonathanAllan me impede de me esforçar demais para pensar demais e abstrair um problema que pode ser resolvido em ~ 25 caracteres, eis o violino em que eu estava trabalhando - escrevi todo o boilerplate e nenhum código real
Stephen
Isso é incrível, mas recentemente adicionei um caso de teste que não calcula, especificamente ["hhhij", "hijkl"]. Eu acho que é por causa da maneira como você classifica uma sequência como [3,1,1,1,1]?
Oct
3

JavaScript ( 250 247 232 bytes)

S=d=>(x={},l=99,h=s=0,[...d].map(v=>x[v]=-~x[v]),Object.keys(x).map(v=>(c=91-v.charCodeAt(),t=x[v],s+=1e4**t,c<x[t]?0:x[t]=c,g=(h=c>h?c:h)-(l=c<l?c:l))),[5,4,3,2,1].map(v=>s+=0|x[v]**v),s+(s<5e7&&g<5?1e13:0)),C=a=>b=>(S(a)>S(b)?a:b)

Código ungolfed e casos de teste no JSFiddle: https://jsfiddle.net/CookieJon/8yq8ow1b/

Salvei alguns bytes graças a @RickHitchcock. @StephenS & @Arnauld

Irregular
fonte
Era isso que eu estava tentando fazer, mas não tinha idéia de como fazer.
26517 Stephen
Nem fiz até depois que comecei! :-)
Acidentado
s=0,h=0=> s=h=0Eu acredito
Stephen
1
Corrigido agora depois de muito puxar o cabelo. Determinar o desempate nos casos em que a mão é a mesma E os caracteres mais baixos do primeiro e do segundo maiores grupos eram os mesmos do assassino (mais ou menos 33 bytes APENAS para isso !?) :-(
Acidentado
x[v]=x[v]?++x[v]:1pode se tornar x[v]=(x[v]|0)+1, economizando 3 bytes.
Rick Hitchcock
2

Python 2.7, 242 223 bytes

from collections import*
s=sorted
f=lambda x,y:s(map(lambda h:(lambda (r,n):((3,1.5)if len(r)==5 and ord(r[0])+4==ord(r[4])else n,[-ord(d) for d in r],h))(zip(*s(Counter(h).items(),key=lambda z:(-z[1],z[0])))),(x,y)))[1][2]

Semelhante no conceito básico aos exemplos de javascript (classifique por força da mão, com exceção de retas; depois por classificação); mas aproveitando collections.CounterInfelizmente,.most_common não tem o comportamento desejado; então tive que adicionar uma chave de classificação personalizada.

Editar: um pouco mais de código de golfe para reduzir 19 bytes.

Código não golfe

from collections import Counter

def convertHand(h):
    # first get item counts, appropriately ordered; e.g. cbabc -> (('b',2), ('c',2),('a',1))
    sortedPairs = sorted(Counter(h).items(),key=lambda x:(-x[1],x[0]))

    # 'unzip' the tuples to get (('b','c','a'), (2,2,1))
    ranks, numberFound = zip(*sortedPairs) 

    if len(ranks)==5:
        # no pairs; is it a straight? well, since they are in increasing order...
        if ord(ranks[0])+4 == ord(ranks[4]):
            # replace numberFound with something that will sort above 3 of a kind but below full house
            numberFound = (3,1.5)

    # invert the values of the ranks, so they are in decreasing, rather then increasing order
    ranks = [-ord(r) for r in ranks]

    # arrange tuples so we can sort by numberFound, and then ranks; and keep a reference to the hand
    return (numberFound, ranks, h)

# put it all together...
def f(x,y):
    hands = [convertHand(h) for h in (x,y)]
    rankedHands = sorted(hands)
    return rankedHands[1][2]
Chas Brown
fonte
1

Mathematica, 635 bytes

H[x_]:=Block[{t},T=Sort@ToCharacterCode[x];L=Last/@Tally@T;t=0;S=Count;If[S[L,2]==1,t=1];If[S[L,2]==2,t=2];If[S[L,3]==1,t=3];If[S[Differences@T,1]==4,t=4];If[S[L,2]==1&&S[L,3]==1,t=5];If[S[L,4]==1,t=6];If[S[L,5]==1,t=7];t];F[K_,v_]:=First@Flatten@Cases[Tally@K,{_,v}];B=ToCharacterCode;(Z=Sort@B@#1;Y=Sort@B@#2;a=H[#1];b=H[#2];If[a>b,P@#1,If[a<b,P@#2]]If[a==b&&a==0,If[Z[[1]]<Y[[1]],P@#1,P@#2]];If[a==b&&(a==1||a==2),If[F[Z,2]<F[Y,2],P@#1,If[F[Z,2]==F[Y,2],If[F[Z,1]<F[Y,1],P@#1,P@#2],P@#2]]];If[a==b&&(a==3||a==5),If[F[Z,3]<F[Y,3],P@#1,P@#2]];If[a==b&&a==6,If[F[Z,4]<F[Y,4],P@#1,P@#2]];If[a==b&&(a==7||a==4),If[Tr@Z<Tr@Y,P@#1,P@#2]])&

.
.
Formulário de entrada

["abcde", "kkekk"]

J42161217
fonte
Existe uma maneira de testar isso online?
Octopus
1
sandbox.open.wolframcloud.com/app/objects colar com ctrl + v adicionar a entrada no final do código e correr com Shift + Enter
J42161217