9 of 18
saved 1 byte
Arnauld
  • 191.9k
  • 20
  • 175
  • 635

#JavaScript (ES7), 130 bytes

Saved 1 byte thanks to @asgallant

Takes input as an array of strings in "Rs" format, where R is the rank and s is the suit. Expects "A" for aces and "T" for 10's. Assumes that aces are low.

a=>(k='A23456789TJQK'+92427**3)[[[r,s],...x]=a.map((c,i)=>[k.search(c[0])+10,c[1],i]),(r-k[x.sort().map(c=>k=k*2|c[2])|k+8])%13]+s

Try it online!

###How?

We first convert each card into an array [R, S, P] where R is a numeric value in [10...22], S is the suit character (unchanged) and P is the original position of the card in [0...3].

[[r, s], ...x] = a.map((c, i) => ['A23456789TJQK'.search(c[0]) + 10, c[1], i])

The rank and suit of the first card are stored in r and s respectively. The three other cards are stored in x[ ].

For instance, ['3c','6h','6c','2s'] becomes:

[ [ 12, 'c', 0 ], [ 15, 'h', 1 ], [ 15, 'c', 2 ], [ 11, 's', 3 ] ]
    r    s        <-------------------- x[] ------------------->

We sort x[ ], which causes an implicit coercion of its entries to strings when they are compared with each other: [ 15, 'h', 1 ] --> '15,h,1'. Because R is guaranteed to have exactly 2 digits and S and P are 1-character each, it is safe to sort in lexicographical order.

In the above example, x[ ] is sorted this way:

[ [ 11, 's', 3 ], [ 15, 'c', 2 ], [ 15, 'h', 1 ] ]

Using the original position of each card, we compute a lookup index by applying the following formula:

.map(c => k = k * 2 | c[2])

Because k is initialized to a string, it is coerced to 0 when the first bitwise OR is applied.

Below are all the possible combinations:

positions | code  | index                    | n | n-10 | -(n-10)
----------+-------+--------------------------+---+------+--------
  1,2,3   | S,M,L | (1 * 2 | 2) * 2 | 3 = 7  | 1 |  -9  |    9
  1,3,2   | S,L,M | (1 * 2 | 3) * 2 | 2 = 6  | 2 |  -8  |    8
  2,1,3   | M,S,L | (2 * 2 | 1) * 2 | 3 = 11 | 3 |  -7  |    7
  3,1,2   | M,L,S | (3 * 2 | 1) * 2 | 2 = 14 | 4 |  -6  |    6
  2,3,1   | L,S,M | (2 * 2 | 3) * 2 | 1 = 15 | 5 |  -5  |    5
  3,2,1   | L,M,S | (3 * 2 | 2) * 2 | 1 = 13 | 6 |  -4  |    4

Hence the lookup string ".89...7.465" which is compressed as 92427**3 = 7[89]580[7]8[465]8483 and initially stored at the end of the string k. The first payload character is the 15th one, so we need to add 8.

Finally, we build the output card using r, s and the above result:

'A23456789TJQK'[
  (
    r - '_____________.89...7.465'[
      x.sort().map(c => k = k * 2 | c[2]) | k + 8
    ]
  ) % 13
] + s
Arnauld
  • 191.9k
  • 20
  • 175
  • 635