from math import factorial
T = factorial( 52 ) // factorial( 4 ) **13
idx2card = "23456789TJQKA"
card2idx = { c:i for i, c in enumerate ( idx2card) }
def deal2vec( cards) :
return [ card2idx[ c] for c in cards if c in card2idx]
def vec2deal( vec) :
return "" .join ( idx2card[ i] for i in vec)
def encode( vec) :
a = [ 4 ] * 13
cards = sum ( a)
n = T
k = 0
for idx in vec:
k += sum ( a[ :idx] ) * n // cards
n = a[ idx] * n // cards
a[ idx] -= 1
cards -= 1
return k
def decode( k) :
vec = [ ]
a = [ 4 ] * 13
cards = sum ( a)
n = T
while cards > 0 :
i = cards * k // n
accum = 0
for idx in range ( len ( a) ) :
if i < accum + a[ idx] :
k -= accum * n // cards
n = a[ idx] * n // cards
a[ idx] -= 1
vec.append ( idx)
break
accum += a[ idx]
cards -= 1
return vec
for deal in [ "54A236J87726Q33969AAAQJK7T9292Q36KJ57T8TKJ448Q8T55K4"
, "92TAJ9KA8J7353364Q67JQJTK9A947QK7882TK25836462A5T45Q"
, "T87JK457855QJ432QKAA2KQ7T62TA86985349AK364Q997J3T6J2"
, "A829J6K6Q274J4563AQ48K7AT576Q539J33QT782T4989KKAT52J"
, "349272TKQ36A9TQKK8JQQ295T89665JJ485A377KA78J6424T53A"
, "5Q462TJ33498ATK3J8K589727JQ6Q3T4766J789AK24T9AQ5A5K2"
, "6J98QKJTQ5753AT93T429KJTK59327367Q6J88478A54462AKQA2"
] :
round_trip = vec2deal( decode( encode( deal2vec( deal) ) ) )
print ( deal + ": " + ( "OK" if deal == round_trip else "**FAIL**" ) )
ZnJvbSBtYXRoIGltcG9ydCBmYWN0b3JpYWwKVCA9IGZhY3RvcmlhbCg1MikgLy8gZmFjdG9yaWFsKDQpKioxMwoKaWR4MmNhcmQgPSAiMjM0NTY3ODlUSlFLQSIKY2FyZDJpZHggPSB7YzppIGZvciBpLGMgaW4gZW51bWVyYXRlKGlkeDJjYXJkKX0KCmRlZiBkZWFsMnZlYyhjYXJkcyk6CiAgICByZXR1cm4gW2NhcmQyaWR4W2NdIGZvciBjIGluIGNhcmRzIGlmIGMgaW4gY2FyZDJpZHhdCmRlZiB2ZWMyZGVhbCh2ZWMpOgogICAgcmV0dXJuICIiLmpvaW4oaWR4MmNhcmRbaV0gZm9yIGkgaW4gdmVjKQoKZGVmIGVuY29kZSh2ZWMpOgogICAgYSA9IFs0XSAqIDEzCiAgICBjYXJkcyA9IHN1bShhKQogICAgbiA9IFQKICAgIGsgPSAwCiAgICBmb3IgaWR4IGluIHZlYzoKICAgICAgICBrICs9IHN1bShhWzppZHhdKSAqIG4gLy8gY2FyZHMKICAgICAgICBuID0gYVtpZHhdICogbiAvLyBjYXJkcwogICAgICAgIGFbaWR4XSAtPSAxCiAgICAgICAgY2FyZHMgLT0gMQogICAgcmV0dXJuIGsKCmRlZiBkZWNvZGUoayk6CiAgICB2ZWMgPSBbXQogICAgYSA9IFs0XSAqIDEzCiAgICBjYXJkcyA9IHN1bShhKQogICAgbiA9IFQKICAgIHdoaWxlIGNhcmRzID4gMDoKICAgICAgICBpID0gY2FyZHMgKiBrIC8vIG4KICAgICAgICBhY2N1bSA9IDAKICAgICAgICBmb3IgaWR4IGluIHJhbmdlKGxlbihhKSk6CiAgICAgICAgICAgIGlmIGkgPCBhY2N1bSArIGFbaWR4XToKICAgICAgICAgICAgICAgIGsgLT0gYWNjdW0gKiBuIC8vIGNhcmRzCiAgICAgICAgICAgICAgICBuID0gYVtpZHhdICogbiAvLyBjYXJkcwogICAgICAgICAgICAgICAgYVtpZHhdIC09IDEKICAgICAgICAgICAgICAgIHZlYy5hcHBlbmQoaWR4KQogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgYWNjdW0gKz0gYVtpZHhdCiAgICAgICAgY2FyZHMgLT0gMQogICAgcmV0dXJuIHZlYwoKZm9yIGRlYWwgaW4gWyAiNTRBMjM2Sjg3NzI2UTMzOTY5QUFBUUpLN1Q5MjkyUTM2S0o1N1Q4VEtKNDQ4UThUNTVLNCIKCQkJLCAiOTJUQUo5S0E4SjczNTMzNjRRNjdKUUpUSzlBOTQ3UUs3ODgyVEsyNTgzNjQ2MkE1VDQ1USIKCQkJLCAiVDg3Sks0NTc4NTVRSjQzMlFLQUEyS1E3VDYyVEE4Njk4NTM0OUFLMzY0UTk5N0ozVDZKMiIKCQkJLCAiQTgyOUo2SzZRMjc0SjQ1NjNBUTQ4SzdBVDU3NlE1MzlKMzNRVDc4MlQ0OTg5S0tBVDUySiIKCQkJLCAiMzQ5MjcyVEtRMzZBOVRRS0s4SlFRMjk1VDg5NjY1Sko0ODVBMzc3S0E3OEo2NDI0VDUzQSIKCQkJLCAiNVE0NjJUSjMzNDk4QVRLM0o4SzU4OTcyN0pRNlEzVDQ3NjZKNzg5QUsyNFQ5QVE1QTVLMiIKCQkJLCAiNko5OFFLSlRRNTc1M0FUOTNUNDI5S0pUSzU5MzI3MzY3UTZKODg0NzhBNTQ0NjJBS1FBMiIKCQkJXToKCXJvdW5kX3RyaXAgPSB2ZWMyZGVhbChkZWNvZGUoZW5jb2RlKGRlYWwydmVjKGRlYWwpKSkpCglwcmludChkZWFsICsgIjogIiArICgiT0siIGlmIGRlYWwgPT0gcm91bmRfdHJpcCBlbHNlICIqKkZBSUwqKiIpKQ==