If you like cryptography and playing cards, have also a look at the kata [Card-Chameleon, a Cipher with Playing cards](http://www.codewars.com/kata/card-chameleon-a-cipher-with-playing-cards).
As a secret agent, you need a method to transmit a message to another secret agent. But an encrypted text written on a notebook will be suspicious if you get caught. A simple deck of playing cards, however, is everything but suspicious...
With a deck of 52 playing cards, there are `52!` different possible permutations to order it. And `52!` is equal to `80658175170943878571660636856403766975289505440883277824000000000000`. That's a number with [68 digits](https://www.wolframalpha.com/input/?i=52!)!
There are so many different possible permutations, we can affirm that if you shuffle the cards well and put them back together to form a deck, you are the first one in history to get this particular order. The number of possible permutations in a deck of cards is higher than the estimated number of atoms in planet Earth (which is a number with about [50 digits](https://www.wolframalpha.com/input/?i=number+of+atoms+in+earth)).
With a way to associate a permutation of the cards to a sequence of characters, we can hide a message in the deck by ordering it correctly.
---
# Correspondence between message and permutation
## Message
To compose our message, we will use an alphabet containing 27 characters: the space and the letters from A to Z. We give them the following values:
`" " = 0, A = 1, B = 2, ..., Z = 26`
We now have a [numeral system](https://en.wikipedia.org/wiki/Numeral_system) with a base equal to 27. We can compute a numeric value corresponding to any message:
`"A " = 27`
`"AA" = 28`
`"AB" = 29`
`"ABC" = 786`
etc.
## Permutation
Now we need a way to attribute a unique number to each of the possible [permutations](https://en.wikipedia.org/wiki/Permutation) of our deck of playing cards.
There are few methods to [enumerate permutations](https://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations) and [assign a number](https://en.wikipedia.org/wiki/Permutation#Numbering_permutations) to each of them, we will use the [lexicographical order](https://en.wikipedia.org/wiki/Lexicographical_order). With three cards, A, B, and C, as an example, it gives:
`ABC = 0`
`ACB = 1`
`BAC = 2`
`BCA = 3`
`CAB = 4`
`CBA = 5`
So the first arrangement is ABC, and the last one is CBA. With our 52 playing cards – ranks sorted from the Ace to the King, and suits in alphabetical order (Clubs, Diamonds, Hearts, Spades) – the first arrangement (number `0`) is:
and the last one (number `52! - 1`) is:
To transmit a message, we will compute the permutation for which the unique number is the numeric value of the message.
---
# Your task
Write two functions:
* ```python
encode(message)
```
```if:java
Which takes a message as argument and returns a deck of playing cards ordered to hide the message (or `null` if the message contains invalid characters or has a numeric value greater than or equal to `52!`).
```
```if:python
Which takes a String containing a message, and returns an array of Strings representing a deck of playing cards ordered to hide the message (or `None` if the message contains invalid characters or has a numeric value greater than or equal to `52!`).
```
```if:elixir
Which takes a string containing a message, and returns a list of strings representing a deck of playing cards ordered to hide the message (or `nil` if the message contains invalid characters or has a numeric value greater than or equal to `52!`).
```
* ```python
decode(deck)
```
```if:java
Which takes a deck of playing cards as argument and returns the message hidden inside (or `null` if the deck contains invalid cards, more than one time a single card, or doesn't contain 52 cards).
```
```if:python
Which takes an array of Strings representing a deck of playing cards, and returns the message that is hidden inside (or `None` if the deck contains invalid cards, more than one time a single card, or doesn't contain 52 cards).
```
```if:elixir
Which takes a list of strings representing a deck of playing cards, and returns the message that is hidden inside (or `nil` if the deck contains invalid cards, more than one time a single card, or doesn't contain 52 cards).
```
Each card name, in a deck, is written with a two characters String: the rank followed by the suit. So the first arrangement of the deck is represented like:
`AC 2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC` for the Clubs  
`AD 2D 3D 4D 5D 6D 7D 8D 9D TD JD QD KD` for the Diamonds  
`AH 2H 3H 4H 5H 6H 7H 8H 9H TH JH QH KH` for the Hearts  
`AS 2S 3S 4S 5S 6S 7S 8S 9S TS JS QS KS` for the Spades
For your convenience, a preloaded method allows you to easily print a deck to the output:
```python
printDeck(deck, unicode)
```
The first argument is the deck to print, the second one is a boolean value allowing you to choose between simple text or Unicode display. (For Unicode, you need to have a font, on your system, that contains the playing cards Unicode characters.)
---
# Examples
## Encoding
```python
playingCards.encode("ATTACK TONIGHT ON CODEWARS")
```
should return an array of 52 Strings containing:
```python
[
    "AC", "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "TC", "JC", "QC", "KC",
    "AD", "2D", "3D", "4D", "5D", "6D", "JD", "9D", "7S", "9S", "QD", "5S", "TH",
    "7D", "TS", "QS", "2H", "JS", "6H", "3S", "6S", "TD", "8S", "2S", "8H", "7H",
    "4S", "4H", "3H", "5H", "AS", "KH", "QH", "9H", "KD", "KS", "JH", "8D", "AH"
]
```
## Decoding
```python
playingCards.decode([
    "AC", "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "TC", "JC", "QC", "KC",
    "AD", "2D", "3D", "4D", "5D", "6D", "7D", "8D", "9D", "TD", "JD", "QD", "KD",
    "AH", "2H", "3H", "4H", "8H", "9S", "3S", "2S", "8S", "TS", "QS", "9H", "7H",
    "KH", "AS", "JH", "4S", "KS", "JS", "5S", "TH", "7S", "6S", "5H", "QH", "6H"
])
```
should return a String containing:
```python
"ATTACK APPROVED"
```
---
# Further readings
## Logarithm
With the logarithm function, we can know how many digits, in a numeral system of a certain base, are needed to represent a number. For example, `log base 2 of 52! = 225.58`, so we can store 225 bits of information in a deck of cards (and 226 bits are needed to represent the value of `52!`). Also, `log base 27 of 52! = 47.44`, so we can store [47](https://www.wolframalpha.com/input/?i=log+base+27+of+52!) characters of our alphabet in a deck of cards (and some message with 48 characters, but not all of them).
class PlayingCards:
    CARDS=['AC', '2C', '3C', '4C', '5C', '6C', '7C', '8C', '9C', 'TC', 'JC', 'QC', 'KC',
            'AD', '2D', '3D', '4D', '5D', '6D', '7D', '8D', '9D', 'TD', 'JD', 'QD', 'KD',
            'AH', '2H', '3H', '4H', '5H', '6H', '7H', '8H', '9H', 'TH', 'JH', 'QH', 'KH',
            'AS', '2S', '3S', '4S', '5S', '6S', '7S', '8S', '9S', 'TS', 'JS', 'QS', 'KS']
    S=len(CARDS)
    
    def __init__(self):
        self.f=[0]*self.S
        self.f[0]=1
        for k in range(1,self.S):
            self.f[k]=self.f[k-1]*k
            
        self.CARD_index={c:self.CARDS.index(c)for c in self.CARDS}
        
    def baseEncode(self,s):
        r=0
        for c in s:
            r*=27
            r+=ord(c)%32
        return r

    def baseDecode(self,n):
        s=''
        while n:
            n,c=divmod(n,27)
            s=(chr(64+c)if c else' ')+s
        return s
    
    def permute(self,n):
        S=52
        p=[0]*S
        for k in range(S):
            p[k],n=divmod(n,self.f[S-1-k])
        for k in range(S-1,0,-1):
            for j in range(k-1,-1,-1):
                if p[j]<=p[k]:
                    p[k]+=1
        return [self.CARDS[i]for i in p]
        
    # Takes a String containing a message, and returns an array of Strings representing
    # a deck of playing cards ordered to hide the message, or None if the message is invalid.
    def encode(self, message):
        if not all(c==' 'or 'A'<=c<='Z' for c in message):return
        n=self.baseEncode(message)
        if n>=80658175170943878571660636856403766975289505440883277824000000000000:return
        p=self.permute(n)
        return p

    # Takes an array of Strings representing a deck of playing cards, and returns
    # the message that is hidden inside, or None if the deck is invalid.
    def decode(self, deck):
        if set(deck)!=set(self.CARDS):return
        
        i,j=0,1
        perm=[self.CARD_index[c]for c in deck]
        for p in range(50,-1,-1):
            s=0
            for q in range(p+1,52):
                if perm[p]>perm[q]:s+=1
            i+=s*self.f[j]
            j+=1
        return self.baseDecode(i)

class PlayingCards:
    CARDS=['AC', '2C', '3C', '4C', '5C', '6C', '7C', '8C', '9C', 'TC', 'JC', 'QC', 'KC',
            'AD', '2D', '3D', '4D', '5D', '6D', '7D', '8D', '9D', 'TD', 'JD', 'QD', 'KD',
            'AH', '2H', '3H', '4H', '5H', '6H', '7H', '8H', '9H', 'TH', 'JH', 'QH', 'KH',
            'AS', '2S', '3S', '4S', '5S', '6S', '7S', '8S', '9S', 'TS', 'JS', 'QS', 'KS']
    S=len(CARDS)
    
    def __init__(self):
        self.f=[0]*self.S
        self.f[0]=1
        for k in range(1,self.S):
            self.f[k]=self.f[k-1]*k
            
        self.CARD_index={c:self.CARDS.index(c)for c in self.CARDS}
        
    def baseEncode(self,s):
        r=0
        for c in s:
            r*=27
            r+=ord(c)%32
        return r

    def baseDecode(self,n):
        s=''
        while n:
            n,c=divmod(n,27)
            s=(chr(64+c)if c else' ')+s
        return s
    
    def permute(self,n):
        S=52
        p=[0]*S
        for k in range(S):
            p[k],n=divmod(n,self.f[S-1-k])
        for k in range(S-1,0,-1):
            for j in range(k-1,-1,-1):
                if p[j]<=p[k]:
                    p[k]+=1
        return [self.CARDS[i]for i in p]
        
    # Takes a String containing a message, and returns an array of Strings representing
    # a deck of playing cards ordered to hide the message, or None if the message is invalid.
    def encode(self, message):
        if not all(c==' 'or 'A'<=c<='Z' for c in message):return
        n=self.baseEncode(message)
        if n>=80658175170943878571660636856403766975289505440883277824000000000000:return
        p=self.permute(n)
        return p

    # Takes an array of Strings representing a deck of playing cards, and returns
    # the message that is hidden inside, or None if the deck is invalid.
    def decode(self, deck):
        if set(deck)!=set(self.CARDS):return
        
        i,j=0,1
        perm=[self.CARD_index[c]for c in deck]
        for p in range(50,-1,-1):
            s=0
            for q in range(p+1,52):
                if perm[p]>perm[q]:s+=1
            i+=s*self.f[j]
            j+=1
        return self.baseDecode(i)
