2010-04-15 4 views
8

Ce ne sont pas des devoirs.Aidez-moi à terminer cet auto-défi Python 3.x

J'ai vu this article praising Linq library and how great it is pour faire des trucs combinatoires, et je me suis dit: Python peut le faire d'une manière plus lisible. Après une demi-heure de tamponnage avec Python j'ai échoué

S'il vous plaît finir où je me suis arrêté. Aussi, faites-le de la manière la plus pythonique et efficace possible s'il vous plaît.

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) 

Merci!

+1

Do vous voulez le plus Pythonic ou le plus efficace? Ils peuvent bien être des choses très différentes. :) –

+0

Je veux tout et je le veux maintenant;) Hm ... un de chaque ainsi que les deux. Il n'y a pas de meilleure réponse alors, bien que je devrais en choisir un. S'il vous plaît inclure time-liner pour les tests de performance si vous le souhaitez. –

+3

Pourquoi utilisez-vous XOR bit à bit dans votre fonction divisible? Vouliez-vous dire ** au lieu de ^? – dan04

Répondre

24

est ici une solution à court, en utilisant 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) 

J'ai été délibérément omis les contrôles de divisibilité par 1 et par 9, car ils seront toujours satisfaits.

+0

+999 Très bien! –

+0

+1; tellement plus élégant que la solution dans l'article lié (malgré le "pouvoir expressif Enourmous" de LINQ) – SingleNegationElimination

2

Voici ma solution (pas aussi élégant que Marc, mais il fonctionne encore):

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

Je veux le chronométrer, mais je vois le code Python 2.x, et je ne veux pas comparer des pommes et des oranges. –

+0

Oh oui, il a dit Python 3.x, oops –

+0

Mine est loin d'être aussi optimisé que cela pourrait être .. mais pourquoi s'embêter avec quelque chose comme ça? –

1

c'est ma solution, il est très similaire à Marks, mais il tourne deux fois plus vite

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

Voici ma solution. J'aime toutes les choses bottom-up ;-). Sur ma machine, il fonctionne environ 580 fois plus rapide (3,1 ms contre 1,8 secondes) que Marks:

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: En outre, cela fonctionne, et deux fois plus rapide (1,6 ms):

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