2010-04-15 19 views
8

To nie jest praca domowa.Pomóż mi zakończyć samoczynne wyzwanie w Pythonie 3.x

Widziałem this article praising Linq library and how great it is za wykonywanie rzeczy kombinatorycznych i pomyślałem: Python może to zrobić w bardziej czytelny sposób.

Po półgodzinnej dabbing w Pythonie zawiodłem. Proszę dokończ tam, gdzie skończyłem. Zrób to również w najbardziej Pythoniczny i wydajny sposób, proszę.

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) 

Dzięki!

+1

zrobić chcesz najbardziej Pythonic lub najbardziej wydajne? Mogą to być bardzo różne rzeczy. :) –

+0

Chcę tego wszystkiego i chcę tego teraz;) Hm ... jedno i drugie. Nie ma wtedy najlepszej odpowiedzi, chociaż musiałbym wybrać jedną. W przypadku testowania wydajności prosimy o dołączenie do programu timeit. –

+3

Dlaczego używasz bitowego XOR w swojej funkcji podzielnej? Czy miałeś na myśli ** zamiast ^? – dan04

Odpowiedz

24

Oto krótka rozwiązanie, używając 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) 

ja celowo pominięte kontrole podzielność przez 1 i przez 9, ponieważ zawsze będą spełnione.

+0

+999 Bardzo ładne! –

+0

+1; o wiele bardziej elegancka niż rozwiązanie w połączonym artykule (pomimo LINQ "Enourmous ekspresyjna moc") – SingleNegationElimination

2

Oto moje rozwiązanie (nie tak eleganckie, jak Mark, ale nadal działa):

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

Chcę to czas, ale widzę kod Python 2.x, i nie chcę porównywać jabłek i pomarańczy. –

+0

O tak, powiedział Python 3.x, oops –

+0

Mój nie jest w pobliżu tak zoptymalizowany, jak może być albo .. ale po co zawracać sobie głowę czymś takim? –

1

to jest moje rozwiązanie, jest bardzo podobny do znaków, ale to trwa około dwa razy szybciej

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

Oto moje rozwiązanie. Lubię wszystko od podstaw ;-). Na moim komputerze działa około 580 razy szybciej (3,1 msek vs. 1,8 sek) niż oznaczenia:

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: Także, to działa, i dwa razy szybciej (1,6 msek):

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)) 
Powiązane problemy