Solve in Python:
Print an ordered cross table of a round robin tournament that looks like this:

```
 #  Player            1  2  3  4  5  6  7  8  9 10 11 12 13 14  Pts   SB
==========================================================================
 1  Nash King            1  0  =  1  0  =  1  1  0  1  1  1  0  8.0  52.25
 2  Karsyn Marks      0     1  1  =  1  =  =  1  0  0  1  1  0  7.5  49.75
 3  Yandel Briggs     1  0     =  0  =  1  1  1  =  0  1  0  1  7.5  47.25
    Luka Harrell      =  0  =     1  1  1  =  0  0  1  1  0  1  7.5  47.25
    Pierre Medina     0  =  1  0     =  1  =  1  1  =  0  1  =  7.5  47.25
 6  Carlos Koch       1  0  =  0  =     =  =  1  1  =  0  =  1  7.0  43.50
 7  Tristan Pitts     =  =  0  0  0  =     1  0  1  =  1  1  1  7.0  40.75
    Luke Schaefer     0  =  0  =  =  =  0     1  =  =  1  1  1  7.0  40.75
 9  Tanner Dunn       0  0  0  1  0  0  1  0     1  1  =  1  1  6.5  37.25
10  Haylee Bryan      1  1  =  1  0  0  0  =  0     1  0  0  1  6.0  39.25
11  Dylan Turner      0  1  1  0  =  =  =  =  0  0     1  =  =  6.0  38.75
12  Adyson Griffith   0  0  0  0  1  1  0  0  =  1  0     1  1  5.5  31.75
13  Dwayne Shaw       0  0  1  1  0  =  0  0  0  1  =  0     1  5.0  30.50
14  Kadin Rice        1  1  0  0  =  0  0  0  0  0  =  0  0     3.0  22.25
```

The `#` column contains the rank. Ranks may be tied.  
A colum with index numbers `i` contains the match against the player on line `i`. `1` / `=` / `0` means win / draw / loss.  
The `Pts` column contains the score, 1 for each win, 0.5 for each draw.  
The `SB` column contains the Sonneborn-Berger score (see below).  

The rank is determined by the score, the Sonneborn-Berger score is used to break ties.
Players with the same score and the same SB score share the same rank.
In the cross table those tied players are ordered by their surenames.

# Sonneborn-Berger score

The Sonneborn-Berger score (`SB`) (sometimes also called Neustadtl Sonneborn–Berger or Neustadtl score) is a system to break ties in tournaments.
This score is based on the...
def crosstable(players, scores):
    points, le = {j:sum(k or 0 for k in scores[i]) for i, j in enumerate(players)}, len(players)
    SB = {j:sum(points[players[k]] / ([1, 2][l == 0.5]) for k, l in enumerate(scores[i]) if l) for i, j in enumerate(players)}

    SORTED, li = [[i, players.index(i)] for i in sorted(players, key=lambda x: (-points[x], -SB[x], x.split()[1]))], []

    ps = [format(i, '.1f') for i in points.values()]
    Ss = [format(i, '.2f') for i in SB.values()]
    
    digit = len(str(le))
    name = len(max(players, key=len))
    pts = len(str(max(ps, key=lambda x: len(str(x)))))
    sb = len(str(max(Ss, key=lambda x: len(str(x)))))

    for i, j in enumerate(SORTED):
        ten_ = [" ", "  "][le >= 10]
        index = [str(i + 1), " "][points[j[0]] == points[SORTED[i - 1][0]] and SB[j[0]] == SB[SORTED[i - 1][0]]].rjust(digit)
        name_ = j[0].ljust(name)
        team = ten_.join(['1=0 '[[1, 0.5, 0, None].index(scores[j[1]][l])] or '_' for k, l in SORTED])
        pt = str(format(points[j[0]], ".1f")).rjust(pts)
        Sb = str(format(SB[j[0]], ".2f")).rjust(sb)
        li.append(f'{index}  {name_}{["  ", "   "][le >= 10]}{team}  {pt}  {Sb}')
    
    fline = ' '.join(['#'.rjust(digit) + '  ' +
                    'Player'.ljust(name) +
                    ['  ', '   '][len(players) >= 10] +
                    ''.join([[' ', '  '][i < 10 and le >= 10] + str(i) for i in range(1, le + 1)]).strip() + '  ' +
                    'Pts'.center(pts) + '  ' +
                    'SB'.center(sb - [0, 2][sb & 1])]).rstrip()
    return '\n'.join([fline, '=' * len(max(li, key=len))] + li)