[Question]
  [
This challenge is to score a Cribbage hand. If you don't play Cribbage, you've got some learning to do. We play with a standard poker deck, and a hand consists of four cards plus the "up card". There are two types of hand: normal, and a 'crib hand'.
Cards come in the format `vs` where `v` is one of: `A23456789TJQK` (T for ten) and `s` is one of `SCDH`. A hand will be given in the form (for example)
```
AS 2D 3H JS | 4S
```
where `4S` is the up card. A crib hand will have the format
```
JD 3C 4H 5H | 5S !
```
Face cards have a value of 10, and the ace has a value of 1. Scoring is performed as follows.
* Fifteens: for each subset of five cards whose sum is 15, add two points.
* Pairs: for each pair of cards with the same rank (not value), add two points.
* Runs: for each maximal run of consecutive cards of length longer than 2, add the length of the run in points.
* Flush: if all five cards are the same suit, add five points. Otherwise, if all but the up card are the same suit, add four points. If this is a crib hand, the four-point variant is not counted.
* Nobs: if there is a jack in hand with the same suit of the up card, add one point.
**Notes:**
* Triples and fours of a kind are not special -- there are three pairs in a triple, so a triple is worth 6 points.
* Runs can overlap. For example, `AS AH 2D 3C | 2C` (a double double run) has four runs of length 3 and two pair, so is worth 3+3+3+3+2+2 = 16 points.
* Only maximal runs are counted, so `KS QD JD TC | 9S` is worth 5 points, since it is a run of 5. The sub-runs are not counted.
**House Rule:**
It's impossible to score 19 points in a hand. Instead of zero, report a score of 19.
**Examples:**
```
5S 5H 5D JS | KS
21
AS 2D 3H JS | 4S !
9
JD 3C 4H 5H | 5S
12
9S 8S 7S 6S | 5H !
9
9S 8S 7S 6S | 5H
13
8D 7D 6D 5D | 4D !
14
8D 7D 6D 5D | 4D
14
AD KD 3C QD | 6D
19
```
This is code golf. Shortest solution wins.
  
[Answer]
## C, 364 388 chars
It's big and ugly (though not as big as it once was):
```
char*L="CA23456789TJQKDHS",b[20],p[15],r[5],s[5],v,i=4,t,m,q;
g(j){++p[r[i]=strchr(L,b[j])-L];s[i]=strchr(L,b[j+1])-L;}
f(j,u){u==15?v+=2:++j<5&&f(j,u,f(j,u+(r[j]>9?10:r[j])));}
main(){gets(b);for(g(14);i--;r[i]^11|s[i]^s[4]||++v)g(i*3);
for(f(i,0);++i<15;v+=q?q*q-q:t>2?t*m:0,t=q?t+1:0,m=q?m*q:1)q=p[i];
while(++t<5&&s[t]==*s);v+=t>4-!b[16]?t:0;printf("%d\n",v?v:19);}
```
(Line breaks were added to make it easier to read; those aren't included in the above tally.)
The problem description didn't specify if the code needed to check for invalid input, so naturally I assumed that the program was free to misbehave at will if the input, say, contained extra whitespace.
Here's the ungolfed version:
```
#include <stdio.h>
#include <string.h>
/* A-K correspond to values 1-13. Suit values are arbitrary.
 */
static char const *symbols="CA23456789TJQKDHS";
/* Used as both an input buffer and to bucket cards by rank.
 */
static char buf[20];
/* The cards.
 */
static int rank[5], suit[5];
/* The cards broken down by rank.
 */
static int buckets[15];
static int score;
static int touching, matching, i;
/* Read card number i from buf at position j.
 */
static void getcard(int j)
{
    rank[i] = strchr(symbols, buf[j]) - symbols;
    suit[i] = strchr(symbols, buf[j+1]) - symbols;
    ++buckets[rank[i];
}
/* Recursively find all combinations that add up to fifteen.
 */
static void fifteens(int j, int total)
{
    for ( ; j < 5 ; ++j) {
        int subtotal = total + (rank[j] > 9 ? 10 : rank[j]);
        if (subtotal == 15)
            score += 2;
        else if (subtotal < 15)
            fifteens(j + 1, subtotal);
    }
}
int main(void)
{
    fgets(buf, sizeof buf, stdin);
    score = 0;
    /* Read cards from buf */
    for (i = 0 ; i < 4 ; ++i)
        getcard(i * 3);
    getcard(14);
    /* Score fifteens */
    fifteens(0, 0);
    /* Score any runs and/or pairs */
    touching = 0;
    matching = 1;
    for (i = 1 ; i < 15 ; ++i) {
        if (buckets[i]) {
            score += buckets[i] * (buckets[i] - 1);
            ++touching;
            matching *= buckets[i];
        } else {
            if (touching > 2)
                score += touching * matching;
            touching = 0;
            matching = 1;
        }
    }
    /* Check for flush */
    for (i = 1 ; i < 5 && suit[i] == suit[0] ; ++i) ;
    if (i >= (buf[17] == '!' ? 5 : 4))
        score += i;
    /* Check for hisnob */
    for (i = 0 ; i < 4 ; ++i)
        if (rank[i] == 11 && suit[i] == suit[4])
            ++score;
    printf("%d\n", score ? score : 19);
    return 0;
}
```
[Answer]
## Ruby 1.9, 359 356
It's far too long - almost as much as the C solution.
```
R='A23456789TJQK'
y=gets
f=y.scan /\w+/
o=f.map(&:chr).sort_by{|k|R.index k}
s=0
2.upto(5){|i|o.combination(i){|j|t=0
j.map{|k|t+=k==?A?1:k<?:?k.hex: 10}
(t==15||i<3&&j.uniq!)&&s+=2}}
m=n=l=1
(o+[z=?_]).map{|k|k[z]?n+=1:R[z+k]?(m*=n
l+=n=1):(l>2&&s+=l*m*n
l=n=m=1)
z=k}
x=f.take_while{|k|k[y[1]]}.size
x>(y[?!]?4:3)&&s+=x
y[?J+f[4][1]+' ']&&s+=1
p s>0?s:19
```
[Answer]
# Something to begin with.. Ruby, ~~422 365 355~~ 352
```
c=gets
a,b=c.scan(/(\w)(\w)/).transpose
f=->x{x.uniq.size<2}
s=f[b]?5:!c[/!/]&f[b[0,4]]?4:0
c[/J(.).*\1 ?!?$/]&&s+=1
s+=[5,4,3].map{|i|a.permutation(i).map{|x|'A23456789TJQK'[x*'']?i:0}.inject :+}.find{|x|x>0}||0
a.map{|x|s+=a.count(x)-1}
2.upto(5){|i|s+=2*a.map{|x|x.tr(?A,?1).sub(/\D/,'10').to_i}.combination(i).count{|x|x.inject(:+)==15}}
p s<1?19:s
```
Slightly ungolfed:
```
def t(c)
  s=0
  
  if c.scan(/[SDHC]/).uniq.size<2 # Flush
    s+=5 
  elsif c[0..9].scan(/[SDHC]/).uniq.size<2 && c[-1]!=?! # Flush
    s+=4
  end
  s+=1 if c =~ /J(.).*(\1$|\1\s.$)/ # Nobs
  c=c.scan(/[^ \|]+/).map{|x|x[0]}[0..4]
  d = (3..5).map{|i|c.permutation(i).map{|x| 'A23456789TJQK'.include?(x*'') ? i : 0}.inject(:+)}.reverse.find{|x|x>0} || 0# Runs
  s+=d
  c.map{|x|s+=c.count(x)-1} # Pairs
  c.map!{|x|x.tr('A','1').gsub(/[JQK]/,'10').to_i}
  (2..5).map{|i|s+=2*c.combination(i).count{|x|15==x.inject(:+)}} # 15s
  s<1 ? 19 : s
end
```
Unit tests for golfed version:
```
require "test/unit"
def t(c)
c=gets
a,b=c.scan(/(\w)(\w)/).transpose
f=->x{x.uniq.size<2}
s=f[b]?5:!c[/!/]&f[b[0,4]]?4:0
c[/J(.).*\1 ?!?$/]&&s+=1
s+=[5,4,3].map{|i|a.permutation(i).map{|x|'A23456789TJQK'[x*'']?i:0}.inject :+}.find{|x|x>0}||0
a.map{|x|s+=a.count(x)-1}
2.upto(5){|i|s+=2*a.map{|x|x.tr(?A,?1).sub(/\D/,'10').to_i}.combination(i).count{|x|x.inject(:+)==15}}
p s<1?19:s
end
class Test1 < Test::Unit::TestCase
  def test_simple
    assert_equal 21, t("5S 5H 5D JS | KS")
    assert_equal 21, t("JS 5H 5D 5S | KS")
    assert_equal 12, t("JD 3C 4H 5H | 5S")
    assert_equal 13, t("9S 8S 7S 6S | 5H")
    assert_equal 14, t("8D 7D 6D 5D | 4D")
    assert_equal 19, t("AD KD 3C QD | 6D")
    assert_equal 9, t("AS 2D 3H JS | 4S !")
    assert_equal 9, t("JS 2D 3H AS | 4S !")
    assert_equal 14, t("8D 7D 6D 5D | 4D !")
    assert_equal 9, t("9S 8S 7S 6S | 5H !")
  end
end
```
Results:
```
% ruby ./crib.rb
   Run options: 
# Running tests:
21
21
12
13
14
19
9
9
14
9
.
Finished tests in 0.014529s, 68.8281 tests/s, 688.2813 assertions/s.
1 tests, 10 assertions, 0 failures, 0 errors, 0 skips
```
[Answer]
# Python, 629 characters
I'm only posting mine because no one else has. It's pretty long :(
```
g=range
i=raw_input().split()
r,u=zip(*[tuple(x)for x in i if x not in'!|'])
v=map(int,[((x,10)[x in'TJQK'],1)[x=='A']for x in r])
z=list(set(map(int,[(x,dict(zip('ATJQK',[1,10,11,12,13])).get(x))[x in'ATJQK']for x in r])))
z.sort()
z=[-1]*(5-len(z))+z
s=p=l=0
for a in g(5):
 for b in g(a+1,5):
    s+=2*(v[a]+v[b]==15)
    p+=2*(r[a]==r[b])
    if z[a:b+1]==g(z[a],z[b]+1)and b-a>1:l=max(l,b+1-a)
    for c in g(b+1,5):s+=2*(v[a]+v[b]+v[c]==15)
for d in g(5):s+=2*(sum(v)-v[d]==15)
n=len(set(u))
s+=4*(n==2 and u[-1] not in u[:4] and i[-1]!='!')+5*(n<2)+('J'+u[4]in i[:4])+2*(sum(v)==15)+p+((l*3,l*p)[p<5]or l)
print(s,19)[s<1]
```
[Answer]
### GolfScript, 187 178 174 characters
```
:c"J"c{"SCDH"?)},1/:s-1=+/,([s)-!5*s);)-!4*c"!"?)!*]$-1=+0.14,{c{"A23456789TJQK"?)}%{},:v\{=}+,,.{@*\)}{;.2>**+1 0}if}/;;5-v{{=+}+v\/}/[0]v{.9>{;10}*{1$+}+%}/{15=},,2*+.!19*+
```
Since I never played cribbage I don't know any fancy scoring tricks. Therefore I thought the only way to compete (at least a little bit) is using a golf language. The code is pretty plain GolfScript, the test cases can be found [here](http://golfscript.apphb.com/?c=ewo6YyJKImN7IlNDREgiPyl9LDEvOnMtMT0rLywoW3MpLSE1KnMpOyktITQqYyIhIj8pISpdJC0xPSswLjE0LHtjeyJBMjM0NTY3ODlUSlFLIj8pfSV7fSw6dlx7PX0rLCwue0AqXCl9ezsuMj4qKisxIDB9aWZ9Lzs7NS12e3s9K30rdlwvfS9bMF12ey45Pns7MTB9KnsxJCt9KyV9L3sxNT19LCwyKisuITE5KisKfTpDT0RFOwoKOyI1UyA1SCA1RCBKUyB8IEtTIglDT0RFIHAJIyAyMQo7IkFTIDJEIDNIIEpTIHwgNFMgISIJQ09ERSBwCSMgOQo7IkpEIDNDIDRIIDVIIHwgNVMiCUNPREUgcAkjIDEyCjsiOVMgOFMgN1MgNlMgfCA1SCAhIglDT0RFIHAJIyA5CjsiOVMgOFMgN1MgNlMgfCA1SCIJQ09ERSBwCSMgMTMKOyI4RCA3RCA2RCA1RCB8IDREICEiCUNPREUgcAkjIDE0CjsiOEQgN0QgNkQgNUQgfCA0RCIJQ09ERSBwCSMgMTQKOyJBRCBLRCAzQyBRRCB8IDZEIglDT0RFIHAJIyAxOQo%3D).
The code in a more readable fashion (*reformatted and ungolfed a little*):
```
# Save cards to <c>
:c;
# Is it a non-crib hand? <r>
c"!"?)!:r;
# Values go to <v>
c{"A23456789TJQK"?)}%{},:v;
# Suits go to <s>
c{"SCDH"?)},1/:s;
# Print score for Fifteens
[0]v{.9>{;10}*{1$+}+%}/{15=},,2* .p
# Print score for Pairs
-5v{{=+}+v\/}/ .p
# Print score for Runs
0..14,{v\{=}+,,.{*\)\}{;\.2>**+0 1}if}/;; .p
# Print score for Flush
[s)-!5*s);)-!4*r*]$-1= .p
# And finally print the score for Nobs
c"J"s-1=+/,( .p
# Sum up the sub-scores and if score is zero set to 19
++++
.!19*+
```
*Edit:* Changed logic for fifteens and flushes.
[Answer]
# Python 2, ~~606~~ 584 bytes
Saved 22 bytes due to [Jo King](https://codegolf.stackexchange.com/users/76162/jo-king)'s golfing.
```
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
```
[Try it online!](https://tio.run/##fZLNbqMwFIX3eYpbNAs7caNAIX@EkapQKUpWFbOzvIDgNCZgkDESqfruGUw6UdLF7Ozz3eN7fO3qrI@ldC6XgyoLEJorXZZ5DaKoSqWHg5pEZE3egropSN0pPCX7skiEjLUoZU24bAquYs0HKT/AAcV4GQfxuK5yoRH243FVVsjFPg@uSw@LA8T02WYr65fF85rDxE@CCFmvzovrTWfzxZ/t@84aC5nyFgl8KBUIkoGQEGM/7SprrlGCsX8MaAb3mPmfQc4lojU69T5lZBXLD46mvXAywhpRak/IaWQzelrZE3YjCSPK5DP@ILA9hofOqEbOXZM1SohjakQQZHhE3SHiKxsTj1HT2mQ7Yrxy2BDd9nTpMqPhEYqpy6jNhPwR3ZRcD7W2FsNdU8XTZs9RHhdJGkNLzst2eCY0Ge/LRurvC/apiy6m6VX0UveIkqbdCFq6FAwv/y1GWX/P1uA@ai5qjTj@HjA3J32osqmSM8qexX26N5RizNiD0poZZL8dhn3FdaMkfELH7cWlUkLq7idYXgTeBrwQthF8wS6y8ODGXiNwQnjZXJkbwdM93XZoDe7G@L/Ae3AuIphHMItgapxdwdP/6D2bhzALYRqaSF3P8NH5kz6kDWHXR3o3bNqxy18 "Python 2 – Try It Online")
Slightly shorter than [grc](https://codegolf.stackexchange.com/a/5581/73368)'s answer, and takes a different route to get there.
## Explanation:
```
    # 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
```
## Explanation for runs logic specifically:
```
# 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)
```
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 106 bytes
```
Çí╬Δ╓↔╥.L§º♦½┌§└─»◄G≤n▒HJ♀p$¼♥,Q¢▲»Δ÷♠º≈r↑Vo\b■┌4Üé∟]e:┬A½f║J4σ↔└ΓW6O?╧φ¡╫╠├√├ùß5₧k%5ê╜ò/Φ/7w╠█91I◘┬n≥ìk♂╪
```
[Run and debug online!](https://staxlang.xyz/#p=80a1ceffd61dd22e4c15a704abda15c0c4af1147f36eb1484a0c7024ac032c519b1eaffff606a7f77218566f5c62feda349a821c5d653ac241ab66ba4a34e51dc0e257364f3fcfedadd7ccc3fbc397e1359e6b253588bd952fe82f3777ccdb39314908c26ef28d6b0bd8&i=5S+5H+5D+JS+%7C+KS%0AAS+2D+3H+JS+%7C+4S+%21%0AJD+3C+4H+5H+%7C+5S%0A9S+8S+7S+6S+%7C+5H+%21%0A9S+8S+7S+6S+%7C+5H%0A8D+7D+6D+5D+%7C+4D+%21%0A8D+7D+6D+5D+%7C+4D%0AAD+KD+3C+QD+%7C+6D&a=1&m=2)
Bonus for CP437: See those suits symbol in the packed Stax? Too bad that the clubs do not appear ...
The ASCII equivalent is
```
jc%7<~6(4|@Y{h"A23456789TJQK"I^mXS{{A|mm|+15=_%2=_:u*+f%HxS{{o:-u1]=f{%mc3+|Msn#*+y{H"SHCD"ImY:uc5*s!yNd:u;**HH++yN|Ixs@11#+c19?
```
## Explanation
```
jc%7<~6(4|@Y...X...Y...c19?
j                              Split on space
 c%7<~                         Is it a crib hand? Put it on input stack for later use
      6(                       Remove "!" if it exists
        4|@                    Remove "|"
           Y                   Store list of cards in y
            ...X               Store ranks in x
                ...            Perform scoring for ranks
                   Y           Store suits in y
                    ...        Perform scoring for suits
                       c19?    If the score is 0, change it to 19
{h"..."I^mX
{        m     Map each two character string to
 h             The first character
  "..."I^      1-based index of the character in the string
S{{A|mm|+15=_%2=_:u*+f%H
S                          Powerset
 {                   f%H   Twice the number of elements that satisfy the predicate
  {A|mm                        Value of card. Take the minimum of the rank and 10
       |+15=                   Sum of values equal 15 (*)
            _%2=               Length is 2 (**)
                _:u            All elements are the same (***)
                   *+          ( (***) and (**) ) or (*)
xS{{o:-u1]=f{%mc3+|Msn#*+
xS                                Powerset of ranks
  {        f                      Filter with predicate
   {o                                 Sort
     :-u                              Unique differences between elements
        1]=                           Is [1]
            {%mc                  Length of all runs
                3+|M              Maximum of all the lengths and 3
                    sn#           Number of runs with maximal length
                       *          Multiplied by its length
                        +         Add to score
y{H"SHCD"ImY
y{        mY    For each two character string
  H"SHCD"I      0-based index of the second character in the string "SHCD"
:uc5*s!yNd:u;**HH++
:uc5*                 5 points if all cards have same suit
     s!               Not all cards have same suit (#)
       yNd:u          First four cards have same suit (##)
            ;         Not a crib hand (###)
             **HH++   4 points if (#) and (##) and (###), add to score
yN|Ixs@11#+
yN|I           Index of cards with the same suit of last card (not including itself)
    xs@        The rank at these indices
       11#     Number of Jacks with the same suit of last card
          +    Add to score
```
]