Python 2.
Es bastante eficiente porque construye los números (el bucle más interno se ejecuta 4570 veces en total) y bastante corto porque jugué un poco (201 caracteres), pero no estoy realmente seguro de querer explicar esto :)
p=lambda t,a,d:((x,y)for x in range(10)for y in[(t-x-a)%10]if(x not in d)&(y not in d)and x-y)
w=lambda s:[s]if len(s)==10and s[:5]<s[5:]else(m for n in p(2-len(s)/2%2,sum(s[-2:])/10,s)for m in w(s+n))
Sin embargo, los valores devueltos son bastante peculiares: llame w
con una tupla vacía y obtendrá un iterador de 10 tuplas. Estas 10 tuplas son los dígitos de los dos números, por desgracia, al revés y alternativamente , es decir, la tupla
(2, 0, 8, 3, 7, 4, 9, 1, 6, 5)
representa los números 51430 y 69782.
Prueba:
result = list(w(()))
assert len(set(result)) == 192 # found all values
assert len(result) == 192 # and no dupes
for digits in result:
assert all(0 <= d <= 9 for d in digits) # real digits -- zero through nine
assert len(set(digits)) == 10 # all digits distinct
n1 = int("".join(map(str, digits[9::-2])))
n2 = int("".join(map(str, digits[8::-2])))
assert n1 + n2 == 121212 # sum is correct
Aquí está la versión sin golf:
ppcalls = 0 # number of calls to possiblePairs
ppyields = 0 # number of pairs yielded by possiblePairs
ppconstructed = 0 # number of construced pairs; this is the number
# of times we enter the innermost loop
def possiblePairs(theirSumMod10, addition, disallowed):
global ppcalls, ppyields, ppconstructed
ppcalls += 1
for a in range(10):
b = (theirSumMod10 - a - addition) % 10
ppconstructed += 1
if a not in disallowed and b not in disallowed and a != b:
ppyields += 1
yield (a, b)
def go(sofar):
if len(sofar) == 10:
if sofar[:5] < sofar[5:]: # dedupe
yield sofar
digitsum = 2 - (len(sofar) / 2) % 2 # 1 or 2, alternating
for newpair in possiblePairs(digitsum, sum(sofar[-2:]) / 10, sofar):
for more in go(sofar + newpair):
yield more
list(go(())) # iterate
print ppcalls # 457
print ppyields # 840
print ppconstructed # 4570