2010-04-15 9 views
8

Esto no es tarea.Ayúdame a terminar este auto desafío de Python 3.x

Vi this article praising Linq library and how great it is por hacer cosas combinatorias, y pensé para mí mismo: Python puede hacerlo de una manera más legible.

Después de media hora de pintar con Python falle. Por favor termina donde lo dejé. Además, hágalo de la manera más pitonica y eficiente posible, por favor.

from itertools import permutations 
from operator import mul 
from functools import reduce 
glob_lst = [] 
def divisible(n): return (sum(j*10^i for i,j in enumerate(reversed(glob_lst))) % n == 0) 
oneToNine = list(range(1, 10)) 
twoToNine = oneToNine[1:] 
for perm in permutations(oneToNine, 9): 
    for n in twoToNine: 
     glob_lst = perm[1:n] 
     #print(glob_lst) 
     if not divisible(n): 
      continue 
    else: 
     # Is invoked if the loop succeeds 
     # So, we found the number 
     print(perm) 

Gracias!

+1

Do ¿Quieres más Pythonic o más eficiente? Bien pueden ser cosas muy diferentes. :) –

+0

Lo quiero todo y lo quiero ahora;) Hm ... uno de cada uno, así como ambos. No hay mejor respuesta entonces, aunque tendría que seleccionar una. Por favor incluya timeit one-liner para pruebas de rendimiento si lo hace. –

+3

¿Por qué usa XOR bit a bit en su función divisible? ¿Quisiste decir ** en lugar de ^? – dan04

Respuesta

24

Aquí es una solución a corto, utilizando itertools.permutations:

from itertools import permutations 

def is_solution(seq): 
    return all(int(seq[:i]) % i == 0 for i in range(2, 9)) 

for p in permutations('123456789'): 
    seq = ''.join(p) 
    if is_solution(seq): 
     print(seq) 

he omitido deliberadamente los controles de divisibilidad por 1 y 9, ya que siempre estarán satisfechos.

+0

+999 ¡Muy bien! –

+0

+1; mucho más elegante que la solución en el artículo vinculado (a pesar del "poder expresivo enorme" de LINQ) – SingleNegationElimination

2

aquí está mi solución (no tan elegante como Marcos, pero todavía funciona):

from itertools import permutations 

for perm in permutations('123456789'): 
    isgood = 1 
    for i in xrange(9): 
     if(int(''.join(perm[:9-i])) % (9-i)): 
      isgood = 0 
      break 
    if isgood: 
     print ''.join(perm) 
+0

Quiero cronometrarlo, pero veo el código de Python 2.x y no quiero comparar manzanas y naranjas. –

+0

Oh sí, sí dijo Python 3.x, oops –

+0

La mina no está tan optimizada como podría ser ... ¿pero por qué molestarse en algo como esto? –

1

esta es mi solución, que es muy similar a las marcas, pero se ejecuta dos veces más rápido

from itertools import permutations 

def is_solution(seq): 
    if seq[-1]=='9': 
     for i in range(8,1,-1): 
      n = -(9-i) 
      if eval(seq[:n]+'%'+str(i))==0: 
       continue 
      else:return False 
     return True 
    else:return False 
for p in permutations('123456789'): 
    seq = ''.join(p) 
    if is_solution(seq): 
     print(seq) 
3

Aquí está mi solución. Me gustan todas las cosas de abajo hacia arriba ;-). En mi máquina que funciona con cerca de 580 veces más rápido (3,1 milisegundos frente a 1,8 segundos) que las marcas:

def generate(digits, remaining=set('123456789').difference): 
    return (n + m 
     for n in generate(digits - 1) 
      for m in remaining(n) 
       if int(n + m) % digits == 0) if digits > 0 else [''] 

for each in generate(9): 
    print(int(each)) 

EDIT: Además, esto funciona, y dos veces más rápido (1,6 mseg):

from functools import reduce 

def generate(): 
    def digits(x): 
     while x: 
      x, y = divmod(x, 10) 
      yield y 
    remaining = set(range(1, 10)).difference 
    def gen(numbers, decimal_place): 
     for n in numbers: 
      for m in remaining(digits(n)): 
       number = 10 * n + m 
       if number % decimal_place == 0: 
        yield number 
    return reduce(gen, range(2, 10), remaining()) 

for each in generate(): 
    print(int(each)) 
Cuestiones relacionadas