Python 2, 606 584 bytes
Economizou 22 bytes devido ao golfe de Jo King .
from itertools import*
s,S,C,E=sum,sorted,combinations,enumerate
def f(a):a=a.split();a.pop(4);e=a.pop(5)if a[-1]<"$"else 0;b=S("A23456789TJQK".index(i)for i,j in a);d=S(set(b));h=[j for i,j in a];z=len([s(k)for r in range(6)for k in C([[10,k+1][k<10]for k in b],r)if s(k)==15])*2+s(2for i,j in C(b,2)if i==j)+[4*(e<1),5][len(set(h))<2]*(len(set(h[:4]))<2)+(a[4][1]in[j for i,j in a[:4]if i=="J"])+s(reduce(lambda x,y:x*y,[b.count(k)for k in m])*len(m)for m in[d[s(x[:i]):s(x[:i])+j]for x in[[len(list(e))for i,e in groupby(j-i for i,j in E(d))]]for i,j in E(x)if j>2]);return z or 19
Experimente online!
Um pouco mais curto que a resposta do grc e segue uma rota diferente para chegar lá.
Explicação:
# import everything from "itertools" library. We only need "combinations" and "groupby".
from itertools import*
# alias functions to shorter names
s,S,C,E=sum,sorted,combinations,enumerate
# function f which takes the hand+up card+crib string as its argument
def f(a):
# convert space-separated string into list of items.
a=a.split()
# remove the 4th index, which is always "|".
a.pop(4)
# change golfed by Jo King
# if the final item in the list is a "!" (if it is <"$"), remove it from the list and assign it to variable "e".
# otherwise, assign 0 to variable "e".
# a non-empty string will evaluate to True and 0 will evaluate to False in IF checks later.
e=a.pop(5)if a[-1]<"$"else 0
# for each card in the list, split the identifiers into the value(i) and the suit(j).
# return the value's index in the string "A23456789TJQK".
# so, ["5S", "5H", "5D", "JS", "KS"] will return [4, 4, 4, 10, 12].
# using the aliased built-in function sorted(), sort the list numerically ascending.
b=S("A23456789TJQK".index(i)for i,j in a)
# get the unique items in b, then sort the result numerically ascending.
d=S(set(b))
# for each card in the list, split the identifiers into the value(i) and the suit(j).
# return the suits.
h=[j for i,j in a]
# fifteens
# changes golfed by Jo King
# generate pairs of (10, value + 1) for all cards (since they are zero-indexed)
# since True and False evaluate to 1 and 0 in python, return 10 if k>=10
# and reduce all values >10 to 10
# get all unique combinations of cards for 5 cards, 4 cards, 3 cards, 2 cards, and 1 card
# add the values of all unique combinations, and return any that equal 15
# multiply the number of returned 15s by 2 for score
z=len([s(k)for r in range(6)for k in C([[10,k+1][k<10]for k in b],r)if s(k)==15])*2
+
# pairs
# using itertools.combinations, get all unique combinations of cards into groups of 2.
# then, add 2 for each pair where both cards have an identical value.
s(2for i,j in C(b,2)if i==j)
+
# flush
# changes golfed by Jo King
# using list indexing
# [4 * (0 if crib else 1), 5], get item at index [0 if more than one suit in hand+up card else 1]
# -> 4 if not crib and not all suits same
# -> 5 if all cards same
# -> 0 otherwise
# * (0 if more than one suit in hand else 1)
# -> 4 * 0 if not crib and not all suits same
# -> 4 * 1 if not crib and all suits same
# -> 5 * 1 if all cards same
# -> 0 otherwise
[4*(e<1),5][len(set(h))<2]*(len(set(h[:4]))<2)
+
# nobs
# check if the suit of the 5th card (4, zero-indexed) matches the suit of any of the other 4 cards, and if it does is that card a Jack
(a[4][1]in[j for i,j in a[:4]if i=="J"])
+
# runs
s(reduce(lambda x,y:x*y,[b.count(k)for k in m])*len(m)for m in[d[s(x[:i]):s(x[:i])+j]for x in[[len(list(e))for i,e in groupby(j-i for i,j in E(d))]]for i,j in E(x)if j>2])
# since only 0 evaluates to false, iff z==0 return 19, else return z.
print z or 19
Explicação para a lógica de execuções especificamente:
# for each index and value in the list, add the value minus the index
# since the list is sorted and reduced to unique values, this means adjacent values will all be the same value after offset
# ex: "JD 3C 4H 5H | 5S" -> [2, 3, 4, 10] - > [2, 2, 2, 7]
z = []
for i,j in enumerate(d):
z.append(j-i)
# group the values by unique value
# then add the length of the groups to the list
# ex: [2, 2, 2, 7] -> [2:[2,2,2], 7:[7]]
# [2:[2,2,2], 7:[7]] -> [[3], [1]]
w = []
for i,e in groupby(z):
w.append([len(list(e))])
# list is double-nested so that the combined list comprehension leaves "x" available in both places it is needed
z = []
for x in w:
for i,j in enumerate(x):
if j>2:
# if the group length is larger than 2
# slice the list of unique card values to obtain only run values
# since the run can be anywhere in the list, sum the preceding lengths to find the start and end index
a = d[ sum(x[:i]) : sum(x[:i])+j ]
z.append(a)
w = []
for m in z:
# get the number of times the value is in the entire hand
# ex: "JD 3C 4H 5H | 5S" -> [2,3,4,4,10] and (2,3,4) -> [1, 1, 2]
a = [b.count(k)for k in m]
# multiply all values together
# [1, 1, 2] = 1*1*2 = 2
a = reduce(lambda x,y:x*y, a)
# length of the run * number of duplicate values
a *= len(m)
w.append(a)
# sum the results of the runs
return sum(w)