10
\$\begingroup\$

Background

Brag is a card game similar in concept to, but simpler than, poker. A hand in brag consists of three cards and is ranked as follows from highest to lowest:

  • Three of a kind - all three cards the same rank. Named as "three Kings" etc.

  • Running flush aka straight flush. All three cards of same suit and of consecutive ranks. The hand is named by the three cards in ascending order followed by the words "on the bounce" to distinguish from a simple run/straight, eg "ten-jack-queen on the bounce". Note an ace is either high or low but not both - "king-ace-two" is not a run.

  • Run aka straight. As above but without the requirement to match suits. Named simply as eg "ten-jack-queen".

  • Flush - all three cards the same suit, named after the highest rank eg "Ace flush".

  • Pair - two cards the same rank together with a third of another version rank. Named as "pair of threes" etc.

  • Any other combination, named after the highest rank eg "ace high".

Challenge

Given three playing cards, output the name of the brag hand they output.

The cards will be input either as three 2-character strings or concatenated as a single 6-character string (whichever your implementation prefers), where the first of each pair is the rank (2...9, T, J, Q, K, A) and the second signifies the suit (H, C, D, S).

Standard golfing rules apply - write a program or function which accepts this input and outputs the name of the hand as detailed above.

You can assume the input will be valid (ranks and suits in the above range, no repeated card) and in whatever case you prefer, but will not be in any particular order.

Output must be either in all capitals, all lower case, or a sensible capitalisation eg title case or sentence case. Numeric ranks should be spelled out eg "tens" not 10s.

Sample inputs & outputs:

2H3C2D => "pair of twos"

TD8C9C => "eight-nine-ten"

4SKS9S => "king flush"

4D4H4S => "three fours"

5H3H2C => "five high"

2D3DAD => "ace-two-three on the bounce"

6D6C6H => "three sixes"

This is my first attempt at a challenge on this site, please do suggest improvements but be gentle :)

\$\endgroup\$
  • 3
    \$\begingroup\$ Related. Related. \$\endgroup\$ – Martin Ender Mar 12 '17 at 13:48
  • 4
    \$\begingroup\$ Welcome to PPCG! I've only skimmed the challenge so far, but it looks decent for a first challenge. That said, writing good challenges is hard and for the future I'd recommend posting ideas in the sandbox first where you can get feedback and improve details of the specification before risking downvotes, close votes and answers that might be invalidated by later changes to the challenge. \$\endgroup\$ – Martin Ender Mar 12 '17 at 13:49
  • \$\begingroup\$ @MartinEnder thanks! I'll certainly have been a look at the sandbox next time. \$\endgroup\$ – IanF1 Mar 12 '17 at 13:50
  • \$\begingroup\$ Can we get input as arrays of tuples? Also, can we shorten output like 'king flush' to 'fk'? \$\endgroup\$ – lol Mar 12 '17 at 14:08
  • 1
    \$\begingroup\$ please add "6D6C6S" as a test case since six is an odd plural \$\endgroup\$ – Not that Charles Mar 16 '17 at 21:39
2
\$\begingroup\$

Ruby, 384, 320

Accepts an array of two-char strings.

Translates the pip values into hex values and identifies hands based on how many distinct pip values there are.

->*d{u=d.map{|x|*u=x[1]}==u*3
g=d.map{|x|(x[0].tr'TJQKA','ABCDE').hex}.sort
g=1,2,3if[2,3,14]==g
_,l,h=a=g.map{|x|%w{king queen jack ten nine eight seven six five four three two ace}[-x%13]}
[*g[0]..2+g[0]]==g ?a*?-+(u ?' on the bounce':''):u ?h+' flush':[h+' high','pair of '+l+=l[?x]?'es':?s,'three '+l][-g.uniq.size]}

Annotated:

->*d{
    # u is "Is this a flush?"" (see if you have more than one suit)
    u=d.map{|x|u=x[1]}==[u]*3

    # g is the sorted card values in integer (convert to base 16)
    g=d.map{|x|x[0].tr('TJQKA','ABCDE').hex}.sort

    # use Ace == 1 if we have a low straight
    g=[1,2,3]if[2,3,14]==g

    # a is the names of all the cards
    a=g.map{|x|%w{ace two three four five six seven eight nine ten jack queen king ace}[x-1]}

    # l is for "plural" - just choose the middle card because we
    #                     only care about plurals for 2s or 3s
    l=a[1].sub(?x,'xe')+?s

    # if [g[0],g[0]+1,g[0]+2] == g, we have a run
    # possibly "on the bounce"
    ([*g[0]..g[0]+2]==g) ? (a * ?-) + (u ? ' on the bounce' : '') :

    # if we have a flush, we can't have three-of-a-kind, so try that first
    u ? a[2]+' flush' :

    # otherwise, dedupe your hand. if there's: 
    # 3 values, x high; 2 values, pair; 1 value, three
    [a[2]+' high','pair of '+l,'three '+l][-g.uniq.size]
}
\$\endgroup\$
3
\$\begingroup\$

Python 2, 788, 715, 559, 556, 554, 546, 568, 522 bytes

*now passes the 'sixes' * thanks to Ben Frankel for saving 46 Bytes!


import re
d,m,n=dict(zip('JQKA',range(10,15))),'pair of %ss','%s-%s-%s'
C=lambda s:int(d.get(s[0],s[0]))
z,x,c=sorted(re.findall('..',raw_input()),key=C)
q,w,e=C(z),C(x),C(c)
A=[0,0,'two','three','four','five','six','seven','eight','nine','ten','jack','queen','king','ace']
I,O,U=A[e],A[w],A[q]
a,k='%s high'%I,e-w+q
if k==13:a=n%(I,U,O)
if k==w:a=n%(U,O,I)
if q==w or e==w or e==q:a=m%O
if k==e==w:a='three %ss'%I
if'x'in a:a=a[:-1]+'es'
if z[-1]==x[-1]==c[-1]:
 if'-'in a:a+=' on the bounce'
 else:a='%s flush'%I
print a

Try it online!

Thanks for a cool first challenge!

\$\endgroup\$
  • 1
    \$\begingroup\$ Some whitespace golfing suggestions: TIO \$\endgroup\$ – math junkie Mar 16 '17 at 12:35
  • \$\begingroup\$ Thanks! I knew the white space was adding a lot of bytes but I thought it required 4 spaces. Edited! @math_junkie \$\endgroup\$ – Stephen Mar 16 '17 at 12:38
  • \$\begingroup\$ @user7686415 Or you could use actual tabs instead. \$\endgroup\$ – mbomb007 Mar 16 '17 at 13:33
  • 1
    \$\begingroup\$ @NotthatCharles fixed it! \$\endgroup\$ – Stephen Mar 17 '17 at 1:40
  • 1
    \$\begingroup\$ @Stephen, Sure. D.get(a, b) means access the value in the dict D at key a, with default value b if the key is not found. It's the same as writing D[a] if a in D else b, which is the same as writing D[a] if a in D.keys() else b. \$\endgroup\$ – Ben Frankel Mar 17 '17 at 4:50
2
\$\begingroup\$

PHP, 413 405 398 409 408 406 398 bytes

Unfortunately, PHP does not support nested array referencing inside strings;
that would have saved another 6 5 bytes.

for(;$a=$argn[$i++];)$i&1?$v[strpos(_3456789TJQKA,$a)]++:$c[$a]++;$k=array_keys($v);sort($k);$n=[two,three,four,five,six,seven,eight,nine,ten,jack,queen,king,ace];echo($m=max($v))<2?($k[!$d=count($c)]+2-($h=$k[2])?$k[1]>1|$h<12?"$n[$h] ".[flush,high][$d++/2]:"ace-two-three":$n[$k[0]]."-".$n[$k[1]]."-$n[$h]").[" on the bounce"][$d^1]:($m<3?"pair of ":"three ").$n[$v=array_flip($v)[$m]].e[$v^4].s;

Run with echo <hand> | php -nR '<code> or test it online.

breakdown

for(;$a=$argn[$i++];)$i&1?      # loop through input
    $v[strpos(_3456789TJQKA,$a)]++  # count values on even positions [0,2,4]
    :$c[$a]++;                      # count colors on odd positions [1,3,5]
$k=array_keys($v);sort($k);     # $k=ascending values
$n=[two,three,four,five,six,seven,eight,nine,ten,jack,queen,king,ace];
echo($m=max($v))<2              # three different values:
?($k[!$d=count($c)]+2-($h=$k[2])    # test normal straight ($d=color count, $h=high card)
    ?$k[1]>1|$h<12                      # test special straight
        ?"$n[$h] ".[flush,high][$d++/2]     # flush if one color, high card if not
                                            #   ($d++ to avoid " on the bounce")
        :"ace-two-three"                    # special straight
    :$n[$k[0]]."-".$n[$k[1]]."-$n[$h]"  # normal straight
).[" on the bounce"][$d^1]          # if straight: straight flush if one color
:($m<3?"pair of ":"three ")     # pair or triplet
    .$n[$v=array_flip($v)[$m]]      # card name
    .e[$v^4].s                      # plural suffix
;

Requires PHP>=5.6 (for e[...])

\$\endgroup\$
  • 1
    \$\begingroup\$ this may fail "sixes" \$\endgroup\$ – Not that Charles Mar 16 '17 at 22:25
  • 1
    \$\begingroup\$ @NotthatCharles: That cost me 11 bytes ... but I golfed them back. :) \$\endgroup\$ – Titus Mar 17 '17 at 18:03
1
\$\begingroup\$

Python 2 - 583 bytes

I'm too new to be able to comment posts, so I just post my version of python solusion.

Fixed issue with 'es' for pair and three of sixes. Thanks to Not that Charles

d={'A':['ace',14],'2':['two',2],'3':['three',3],'4':['four',4],'5':['five',5],'6':['six',6],'7':['seven',7],'8':['eight',8],'9':['nine',9],'T':['ten',10],'J':['jack',11],'Q':['queen',12],'K':['king',13]}
r=input()
j=1
i=lambda x:d[x][j]
v=sorted(r[::2],key=i)
z,y,x=v
s=r[1::2]
e='es'if i(y)==6else's'
j=0
a=i(x)
if z==y or y==x:r="pair of %s"%i(y)+e
if s[0]*3==s:r="%s flush"%a
t="%s-%s"%(i(z),i(y))
j=1
u=" on the bounce"if r[-1]=='h'else ""
if i(z)+i(x)==2*i(y):r=t+"-%s"%a+u
if ''.join(v)=="23A":r="%s-"%a+t+u
if [z]*3==v:r="three %s"%d[z][0]+e
if len(r)==6:r="%s high"%a
print r

A bit more readable with some comments

# first of all we don't need to keep suits
d={'A':['ace',14],'2':['two',2],'3':['three',3],'4':['four',4],'5':['five',5],'6':['six',6],'7':['seven',7],'8':['eight',8],'9':['nine',9],'T':['ten',10],'J':['jack',11],'Q':['queen',12],'K':['king',13]}
r=input()                           # input placed in r, to safely check r[-1] later in code
j=1                                 # j toggles reading from dictionary: 0-string, 1-value
i=lambda x:d[x][j]                  # lambda used to access dictionary
v=sorted(r[::2],key=i)              # take values from input and sort
z,y,x=v                             # variables to compact code
s=r[1::2]                           # take suits from input
e='es'if i(y)==6else's'             # choose ending 'es' for six and 's' for others (for pair and three)
j=0                                 # toggle reading from dictionary to string
a=i(x)                              # get string of top most value
if z==y or y==x:                    # check only two pairs as values are sorted
    r="pair of %s"%i(y)+e
if s[0]*3==s:                       # compact check if all string characters are equal to detect flush
    r="%s flush"%a
t="%s-%s"%(i(z),i(y))               # part of straight output - first two values
j=1                                 # toggle reading from dictionary to values
u=" on the bounce"\                 # addon to output in case of possible straight flush
if r[-1]=='h'else ""                # detected by checking last character in r
                                    # which would be 'h' if flush was detected
if i(z)+i(x)==2*i(y):               # check straight - three sorted numbers a,b,c would be in line if a+c == 2*b
    r=t+"-%s"%a+u                   
if ''.join(v)=="23A":               # check special case with straight, started from Ace
    r="%s-"%a+t+u  
j=0                                 # toggle reading from dictionary to string
if [z]*3==v:                        # check three equal values (almost the same as flush check)
    r="three %s"%d[z][0]+e
if len(r)==6:                       # if r was never modified, then it's just one high card
    r="%s high"%a
print r                             # output r
\$\endgroup\$
  • \$\begingroup\$ Also may change in last rows j=0; if [z]*3==v:r="three %ss"%i(z) to if [z]*3==v:r="three %ss"%d[z][0] But it saves just 1 byte \$\endgroup\$ – Dead Possum Mar 16 '17 at 17:56
  • 1
    \$\begingroup\$ this may fail "sixes" \$\endgroup\$ – Not that Charles Mar 16 '17 at 22:24
  • 1
    \$\begingroup\$ @NotthatCharles Yeah, thank you for noticing. I've added fix \$\endgroup\$ – Dead Possum Mar 17 '17 at 9:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.