In this Kata, you will be given a number and your task will be to rearrange the number so that it is divisible by `25`, but without leading zeros. Return the minimum number of digit moves that are needed to make this possible. If impossible, return `-1` ( `Nothing` in Haskell ).

For example:

More examples in test cases.

Good luck!

Source: codewars | Difficulty: EASY
Tags: Fundamentals

Starter code: def solve(n):
	

Solutions:
def solve(n):
	moves = []
	for (a, b) in ['25', '75', '50', '00']:
		s = str(n)[::-1]
		x = s.find(a)
		y = s.find(b, x + 1 if a == '0' else 0)
		if x == -1 or y == -1:
			continue
		moves.append(x + y - (x > y) - (a == b))
		s = s.replace(a, '', 1).replace(b, '', 1)
		l = len(s.rstrip('0'))
		if l:
			moves[-1] = moves[-1] + (len(s) - l)
		elif s:
			moves.pop()
	return min(moves, default=-1)


def moves(st, ending):
	s = list(st)
	steps = 0
	for i in range(-1, -len(ending) - 1, -1):
		char = ending[i]
		while s[i] != char:
			actual = [j for (j, c) in enumerate(s[:i]) if c == char][-1]
			(s[actual], s[actual + 1]) = (s[actual + 1], s[actual])
			steps += 1
	while s[0] == '0':
		actual = [j for (j, c) in enumerate(s) if c != '0'][0]
		(s[actual - 1], s[actual]) = (s[actual], s[actual - 1])
		steps += 1
	return steps

def solve(n):
	print(f'n: {n}')
	s = str(n)
	(_0, _2, _5, _7) = (s.count('0'), s.count('2'), s.count('5'), s.count('7'))
	best = not_possible = len(s) * 2 + 1
	if _0 > 1:
		best = min(best, moves(s, '00'))
	if _2 and _5:
		best = min(best, moves(s, '25'))
	if _5 and _0:
		best = min(best, moves(s, '50'))
	if _7 and _5:
		best = min(best, moves(s, '75'))
	if best == not_possible:
		best = -1
	return best


def solve(n):

	def inversion(s, a, b):
		(x, y) = (s.rfind(a), s.rfind(b))
		if a == b:
			x = s.rfind(a, 0, y)
		if not x > -1 < y:
			return float('inf')
		inv = len(s) - 2 - x + len(s) - 1 - y + (x > y)
		if not x > 0 < y:
			t = s[1 + ({x, y} == {0, 1}):]
			if t:
				inv += len(s) - len(str(int(t))) - 1 - ({x, y} == {0, 1})
		return inv
	inv = min((inversion(str(n), a, b) for (a, b) in '00 25 50 75'.split()))
	return -1 if inv == float('inf') else inv


from functools import partial

def check(s, tail):
	i = s.find(tail[1])
	if i == -1:
		return float('inf')
	s = s[:i] + s[i + 1:]
	j = s.find(tail[0])
	if j == -1:
		return float('inf')
	s = s[:j] + s[j + 1:]
	if not s:
		return i + j
	if s == '0' * len(s):
		return float('inf')
	return i + j + next((i for (i, c) in enumerate(reversed(s)) if c != '0'))

def solve(n):
	result = min(map(partial(check, str(n)[::-1]), ('00', '25', '50', '75')))
	return -1 if result == float('inf') else result


from collections import Counter as C

def solve(n):
	(c, l, li) = (C(str(n)), len(str(n)) - 1, [])
	for i in '75 50 00 25'.split():
		if not C(i) - c:
			(a, b, cn, t) = (i[0], i[1], 0, list(str(n)))
			bi = l - t[::-1].index(b)
			t.insert(l, t.pop(bi))
			ai = l - t[:-1][::-1].index(a) - 1
			t.insert(l - 1, t.pop(ai))
			li.append(l - bi + (l - ai - 1) + [0, next((k for (k, l) in enumerate(t) if l != '0'))][t[0] == '0'])
	return min(li, default=-1)


def solve(n):
	sn = str(n)
	ret = 0
	if n % 25 == 0:
		return ret
	if not (sn.count('0') >= 2 or ('5' in sn and ('0' in sn or '2' in sn or '7' in sn))):
		return -1
	zeroes = []
	two = -1
	five = -1
	seven = -1
	for c in range(len(sn)):
		if sn[c] == '0':
			zeroes.append(c)
		elif sn[c] == '2':
			two = c
		elif sn[c] == '5':
			five = c
		elif sn[c] == '7':
			seven = c
	minlen = 2 * len(sn)
	if len(zeroes) > 1:
		steps = len(sn) - zeroes[-1] - 1
		steps += len(sn) - zeroes[-2] - 2
		minlen = min(minlen, steps)
	if five != -1:
		if two != -1:
			steps = 2 * len(sn) - five - two - 3
			if five < two:
				steps += 1
			min25 = min(two, five)
			max25 = max(two, five)
			popsn = sn[:min25] + sn[min25 + 1:max25] + sn[max25 + 1:]
			update = False
			while len(popsn) > 0 and popsn[0] == '0':
				steps += 1
				update = True
				popsn = popsn[1:]
			minlen = min(minlen, steps)
		if zeroes != []:
			steps = 2 * len(sn) - five - zeroes[-1] - 3
			if zeroes[-1] < five:
				steps += 1
			min50 = min(zeroes[-1], five)
			max50 = max(zeroes[-1], five)
			popsn = sn[:min50] + sn[min50 + 1:max50] + sn[max50 + 1:]
			update = False
			while len(popsn) > 0 and popsn[0] == '0':
				steps += 1
				update = True
				popsn = popsn[1:]
			minlen = min(minlen, steps)
		if seven != -1:
			steps = 2 * len(sn) - five - seven - 3
			if five < seven:
				steps += 1
			min75 = min(five, seven)
			max75 = max(five, seven)
			popsn = sn[:min75] + sn[min75 + 1:max75] + sn[max75 + 1:]
			update = False
			while len(popsn) > 0 and popsn[0] == '0':
				steps += 1
				update = True
				popsn = popsn[1:]
			minlen = min(minlen, steps)
	return minlen


def spoc(sn, cyfry):
	if sn.endswith(cyfry):
		return 0
	(cp, co) = cyfry
	res = 0
	ico = sn.rfind(co)
	res += len(sn) - ico - 1
	sn = sn[:ico] + sn[ico + 1:]
	icp = sn.rfind(cp)
	res += len(sn) - icp - 1
	sn = sn[:icp] + sn[icp + 1:]
	(lpz, i) = (0, 0)
	if len(sn) > 0 and len(sn) == sn.count('0'):
		return None
	while sn and sn[i] == '0':
		i += 1
		lpz += 1
	return res + lpz

def solve(n):
	print(n)
	(sn, t) = (str(n), [])
	if sn.count('0') > 1:
		t.append(spoc(sn, '00'))
	for (p, d) in ('25', '50', '75'):
		if p in sn and d in sn:
			x = spoc(sn, p + d)
			if x is not None:
				t.append(x)
	return min(t) if t else -1


import re

def difference(n, s):
	n = str(n)[::-1]
	try:
		right_index = n.index(s[1])
		left_index = n.index(s[0], [0, 1 + right_index][s[0] == s[1]])
	except:
		return float('inf')
	upper_index = 1 + max(left_index, right_index) == len(n) and '0' == n[-2] and len(re.search('0*.$', n)[0])
	return right_index + left_index - 1 + (left_index < right_index) + (upper_index and upper_index - 1 - (len(n) <= min(left_index, right_index) + upper_index))

def solve(n):
	removes = min([difference(n, '00'), difference(n, '25'), difference(n, '50'), difference(n, '75')])
	return [-1, removes][int == type(removes)]


def solve(n):
	min_cost = -1
	s = str(n)[::-1]
	for pair in ('00', '25', '50', '75'):
		cost = calculate_ending_pair_cost(s, pair)
		if min_cost == -1 or (cost != -1 and cost < min_cost):
			min_cost = cost
	return min_cost

def calculate_ending_pair_cost(s, pair):
	indices = find_lowest_places(s, pair)
	if indices is None:
		return -1
	cost = 1 if indices[1] > indices[0] else 0
	if cost == 1:
		indices = (indices[1], indices[0])
	cost += indices[0] - indices[1] - 1
	cost += 2 * indices[1]
	if len(s) > 2:
		non_zero_index = first_non_zero_digit_after_indices(s, indices)
		if non_zero_index is None:
			return -1
		cost += len(s) - 1 - non_zero_index
		cost -= 1 if indices[0] > non_zero_index else 0
		cost -= 1 if indices[1] > non_zero_index else 0
	return cost

def find_lowest_places(s, pair):
	(d10, d1) = pair
	try:
		i1 = s.index(d1)
	except:
		return None
	start = 0
	if d1 == d10:
		start = i1 + 1
	try:
		i10 = s.index(d10, start)
	except:
		return None
	return (i10, i1)

def first_non_zero_digit_after_indices(s, indices):
	s = s[::-1]
	indices = [len(s) - 1 - indices[i] for i in range(len(indices))]
	non_zero_index = None
	for i in range(len(s)):
		if i not in indices and s[i] != '0':
			non_zero_index = i
			break
	if non_zero_index is None:
		return None
	return len(s) - 1 - non_zero_index


import re

def solve(n):
	print(n)
	min_moves = []
	n = str(n)
	l = len(n) - 1
	extra = 0
	if '2' in n and '5' in n:
		print('25')
		temp = list(n)
		if n.rindex('2') > n.rindex('5'):
			extra = 1
		temp[n.rindex('2')] = ''
		temp[n.rindex('5')] = ''
		temp = ''.join(temp)
		if temp and temp[0] == '0':
			x = re.search('[1-9]', temp)
			if x:
				extra += x.start()
		min_moves.append(l - 1 - n.rindex('2') + l - n.rindex('5') + extra)
		extra = 0
	if '7' in n and '5' in n:
		print('75')
		temp = list(n)
		if n.rindex('7') > n.rindex('5'):
			extra = 1
		temp[n.rindex('7')] = ''
		temp[n.rindex('5')] = ''
		temp = ''.join(temp)
		print('temp', temp)
		if temp and temp[0] == '0':
			x = re.search('[1-9]', temp)
			if x:
				extra += x.start()
				print('extra', extra)
		min_moves.append(l - 1 - n.rindex('7') + l - n.rindex('5') + extra)
		extra = 0
	if '5' in n and '0' in n:
		print('50')
		if n.rindex('5') > n.rindex('0'):
			extra = 1
		min_moves.append(l - 1 - n.rindex('5') + l - n.rindex('0') + extra)
		extra = 0
	if n.count('0') > 1:
		print('00')
		min_moves.append(l - 1 - n.rindex('0') + l - n.rindex('0', 0, n.rindex('0')))
	print(min_moves)
	if not min_moves:
		return -1
	return min(min_moves)