Write a function that takes a positive integer and returns the next smaller positive integer containing the same digits.

For example:

```python
next_smaller(21) == 12
next_smaller(531) == 513
next_smaller(2071) == 2017
```

Return -1 (for `Haskell`: return `Nothing`, for `Rust`: return `None`), when there is no smaller number that contains the same digits. Also return -1 when the next smaller number with the same digits would require the leading digit to be zero.

```python 
next_smaller(9) == -1
next_smaller(135) == -1
next_smaller(1027) == -1  # 0721 is out since we don't write numbers with leading zeros
```
```ruby 
next_smaller(9) == -1
next_smaller(135) == -1
next_smaller(1027) == -1  # 0721 is out since we don't write numbers with leading zeros
```

 * some tests will include very large numbers.
 * test data only employs positive integers.

*The function you write for this challenge is the inverse of this kata: "[Next bigger number with the same digits](http://www.codewars.com/kata/next-bigger-number-with-the-same-digits)."*

Difficulty: MEDIUM
Tags: String algorithms

Mathematics

Starter code:
def next_smaller(n):
	

Solutions:
def next_smaller(n):
	s = list(str(n))
	i = j = len(s) - 1
	while i > 0 and s[i - 1] <= s[i]:
		i -= 1
	if i <= 0:
		return -1
	while s[j] >= s[i - 1]:
		j -= 1
	(s[i - 1], s[j]) = (s[j], s[i - 1])
	s[i:] = reversed(s[i:])
	if s[0] == '0':
		return -1
	return int(''.join(s))


def next_smaller(n):
	numbers = [int(i) for i in str(n)]
	for i in range(len(numbers) - 1, 0, -1):
		if numbers[i] < numbers[i - 1]:
			rearrange_list = numbers[i - 1:]
			original_list = numbers[:i - 1]
			less_than_values = []
			for i in rearrange_list:
				if i < rearrange_list[0]:
					less_than_values.append(i)
			original_list.append(max(less_than_values))
			rearrange_list.remove(max(less_than_values))
			original_list += sorted(rearrange_list, reverse=True)
			output = int(''.join([str(num) for num in original_list]))
			if len(str(output)) < len(str(n)):
				return -1
			else:
				return output
	return -1


def swap(s, a, b):
	s = list(s)
	(s[a], s[b]) = (s[b], s[a])
	return ''.join(s)

def maximized_range(s, left):
	return s[:left] + ''.join(sorted(s[left:], reverse=True))

def next_smaller(n):
	s = str(n)
	k = len(s)
	for i in range(k - 1, -1, -1):
		for j in range(k - 1, i, -1):
			if s[j] < s[i]:
				t = swap(s, i, j)
				if t[0] != '0':
					return int(maximized_range(t, i + 1))
	return -1


from operator import itemgetter

def next_smaller(n):
	s = str(n)
	LR_Pairs = list(enumerate(zip(s, s[1:])))
	(iP, pivot) = next(((i, l) for (i, (l, r)) in reversed(LR_Pairs) if l > r), (-1, -1))
	if iP == -1:
		return -1
	(iM, mx) = max(((i, c) for (i, c) in enumerate(s[iP + 1:], iP + 1) if c < pivot), key=itemgetter(1))
	nextS = s[:iP] + mx + ''.join(sorted(s[iP:iM] + s[iM + 1:], reverse=True))
	return int(nextS) if nextS[0] != '0' else -1


import itertools

def next_smaller(n):
	print(n)
	a = list(str(n))
	b = len(a)
	if b == 1:
		return -1
	for j in range(b - 2, -1, -1):
		if a[j] > a[j + 1]:
			t = a[j:]
			m = max([x for x in t if x < t[0]])
			t.remove(m)
			c = []
			while len(t) > 0:
				d = max(t)
				c.append(d)
				t.remove(d)
			a[j:] = [m] + c
			if a[0] == '0':
				return -1
			return int(''.join(a))
	return -1


def next_smaller(n):
	nums = list(map(int, list(str(n))))
	seen = []
	for i in reversed(range(1, len(nums))):
		if nums[i - 1] > nums[i]:
			seen.append(nums[i])
			seen.append(nums[i - 1])
			seen = sorted(seen, reverse=True)
			for j in range(len(seen)):
				if seen[j] < nums[i - 1]:
					winner = seen.pop(j)
					break
			if winner == 0 and i == 1:
				return -1
			nums = nums[:i - 1]
			nums.append(winner)
			nums.extend(seen)
			return int(''.join(map(str, nums)))
		else:
			seen.append(nums[i])
	return -1


def f(s):
	if ''.join(sorted(s)) == s:
		return ''
	ss = s[1:]
	if ''.join(sorted(ss)) == ss:
		xs = sorted(s, reverse=True)
		next_1st_digit = max((x for x in set(xs) if x < s[0]))
		xs.remove(next_1st_digit)
		return next_1st_digit + ''.join(sorted(xs, reverse=True))
	return s[0] + str(f(ss))

def next_smaller(n):
	s = f(str(n))
	return int(s) if s and (not s.startswith('0')) else -1


def next_smaller(n):
	s = str(n)
	i = next((i for i in range(len(s) - 1, 0, -1) if s[i - 1] > s[i]), len(s))
	j = next((j for j in range(len(s) - 1, i - 1, -1) if s[i - 1] > s[j]), -1)
	s = s[:i - 1] + s[j] + (s[i:j] + s[i - 1] + s[j + 1:])[::-1]
	return [int(s), -1][s[0] == '0' or j < 0]


def next_smaller(n):
	num = list(str(n))
	try:
		pivot = next((i for i in reversed(range(len(num) - 1)) if num[i] > num[i + 1]))
	except StopIteration:
		return -1
	swap = next((i for i in reversed(range(len(num))) if num[pivot] > num[i]))
	(num[pivot], num[swap]) = (num[swap], num[pivot])
	num[pivot + 1:] = reversed(num[pivot + 1:])
	if num[0] == '0':
		return -1
	return int(''.join(num))


def next_smaller(n):
	list_number = list(map(lambda x: int(x), str(n)))
	center = None
	for i in range(len(list_number) - 1, 0, -1):
		if list_number[i] < list_number[i - 1]:
			center = list_number[i - 1]
			left = list_number[:i - 1]
			right = list_number[i:len(list_number)]
			break
	if center is None:
		return -1
	else:
		right.sort(reverse=True)
		for i in right:
			if i < center:
				right.append(center)
				center = i
				right.remove(i)
				right.sort(reverse=True)
				left.append(center)
				left.extend(right)
				if left[0] == 0:
					return -1
				return int(''.join((str(n) for n in left)))