### 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
```

Source: codewars | Difficulty: EASY
Tags: Complete search

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)))