### self_converge
`Goal`: Given a number (with a minimum of 3 digits), return the number of iterations it takes to arrive at a derived number that converges on to itself, as per the following [Kaprekar][Kaprekar] routine. As a learning exercise, come up with a solution that uses recursion. The
following steps would be applicable to a number that originally had
exactly 4 digits.

0. Initialize a counter to count the number of iterations
1. Take any four-digit number `n`, using at least two different digits.
2. Arrange the digits in descending and then in ascending order to get two four-digit numbers, adding leading zeros if necessary. 
    - Add as many zeroes so that the width of the original number is maintained.
3. Subtract the smaller number from the bigger number. Let us call this `nseq`.
4. Check if `nseq` (the remainder) from Step 4 equals the previous value of `n`. If not, increment the iteration counter and go back to step 2 and perform it on the `nseq`. 

If the number of digits to start with was more than 4, convergence occurs on to a `cycle` of numbers. Therefore in Step 5, detect this cycle by comparing to not only the previous value, but to all previous values of `n`.
  - If there is a match, then return the count of iterations
  - If the sequence_number collapses to zero, then return -1 

[Kaprekar]: http://mathworld.wolfram.com/KaprekarRoutine.html

### Converge values  
While 3-digit numbers converge to the same unique number `k` which is also 3 digits long, all 4-digit numbers also converge to the same unique value `k1` which is 4 digits long. However, 5 digit numbers converge to any one of the following values: `53955, 59994, 61974, 62964, 63954, 71973, 74943, 75933, 82962, 83952`.

### Example
`1234`  ->   `4`
```
1. 4321 - 1234 =  3087 /   
2. 8730 - 378  =  8352 /   
3. 8532 - 2358 =  6174 /   
4. 7641 - 1467 =  6174 // same as previous
```
`414` -> `5`
```
1. 441 - 144 =  297 /   
2. 972 - 279 =  693 /   
3. 963 - 369 =  594 /
4. 954 - 459 =  495 /
5. 954 - 459 =  495 // same as previous
```
`50000` -> `4`
```
1. 50000 - 5      =  49995 /   
2. 99954 - 45999  =  53955 /  # first 
3. 95553 - 35559  =  59994 /
4. 99954 - 45999  =  53955 /  # 2nd time
```

Difficulty: introductory

Starter code:

def self_converge(number):
	

Solutions:
def self_converge(number):
    n, cycle = str(number), set()
    while n not in cycle:
        cycle.add(n)
        s = ''.join(sorted(n))
        n = '%0*d' % (len(n), int(s[::-1]) - int(s))
    return -1 if not int(n) else len(cycle)

def self_converge(n, seen=None):
    s, seen = "".join(sorted(str(n))), set() if seen is None else seen
    s = f"{int(s[::-1]) - int(s):0{len(s)}d}"
    return len(seen) + 1 if int(s) and s in seen else self_converge(s, seen | {s}) if int(s) else -1


def self_converge(n):
    s, seen = str(n), set()
    while not s in seen:
        seen.add(s)
        s = "".join(sorted(s))
        s = f"{int(s[::-1]) - int(s):0{len(s)}d}"
    return len(seen) if int(s) else -1


def self_converge(number):
    digits_num = len(str(number))
    count = 0
    prev = []
    while number not in prev:
        prev.append(number)
        digits = [c for c in str(number)]
        n_asc = int(''.join(sorted(digits, reverse=False)))
        n_desc = int(''.join(sorted(digits, reverse=True)))
        while len(str(n_desc))<digits_num:
            n_desc *=10
        number = n_desc-n_asc
        if number==0:
            return -1
        count += 1
    return count

def self_converge(number, seen=None):
    number = str(number)
    digits = ''.join(sorted(number))
    result = '{{:0{}}}'.format(len(number)).format(int(digits[::-1]) - int(digits))
    if int(result) == 0:
        return -1
    elif seen and result in seen:
        return len(seen) + 1
    else:
        return self_converge(result, (seen or []) + [result])

def self_converge(number):
  digits = len(str(number))
  if digits < 3 or number % int('1' * digits) == 0: return -1
  fmtstr = '%%0%dd' % digits
  log = [ number ]
  while True:
    nstr = fmtstr % number
    low = int(''.join(sorted(nstr)))
    high = int(''.join(sorted(nstr, reverse=True)))
    nextn = high - low
    if nextn in log: return len(log)
    log.append(nextn)
    number = nextn



def self_converge(number):
    def sub_converge(n, l, min_length):
        digits = [d for d in str(n)]
        while len(digits) < min_length:
            digits.append('0')
        asc = sorted(digits)
        desc = asc[::-1]
        if asc == desc:
            return -1
        next = int("".join(desc)) - int("".join(asc))
        if next in l:
            return len(l) + 1
        else:
            return sub_converge(next, l + [next], min_length)
    return sub_converge(number, [], len(str(number)))

from itertools import count

def self_converge(p):
    width = len(str(p))
    previous = set()
    for i in count(1):
        s = sorted(str(p).ljust(width, '0'))
        n = int(''.join(reversed(s))) - int(''.join(s))
        if n is 0:
            return -1
        if n in previous:
            return i
        p = n
        previous.add(n)


def rec(n, seen):
    if n == '0'*len(n): return -1
    seen.add(n)
    res = str(int(''.join(sorted(n, reverse=True))) - int(''.join(sorted(n)))).zfill(len(n))    
    if res in seen: return len(seen)
    return rec(res, seen)
    
def self_converge(number):
    return rec(str(number), set())

def self_converge(number,z=0,counter=0,previous=[]): return (lambda sol: -1 if sol==0 else counter if number in previous else self_converge(sol,len(str(number)) if z==0 else z,counter+1,previous+[number]))((lambda n: int("".join(sorted(n,reverse=True)))-int("".join(sorted(n))))(str(number).zfill(z)))
#one-liner and recursive solution: KAME-HAME-HAA!!!!