2010-04-15 20 views
8

Questo non è compito.Aiutami a completare questa auto-sfida Python 3.x

Ho visto this article praising Linq library and how great it is per fare roba combinatoria, e ho pensato a me stesso: Python può farlo in un modo più leggibile.

Dopo mezz'ora di tamponatura con Python ho fallito. Per favore, finisci dove ho lasciato. Inoltre, fallo nel modo più Pythonic ed efficiente possibile per favore.

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) 

Grazie!

+1

Do vuoi più Pythonic o più efficiente? Potrebbero essere cose molto diverse. :) –

+0

Voglio tutto e lo voglio ora;) Hm ... uno di ciascuno e entrambi. Non c'è una risposta migliore allora, anche se dovrei selezionarne una. Si prega di includere timeit one-liner per i test delle prestazioni, se lo si desidera. –

+3

Perché stai utilizzando XOR bit a bit nella funzione divisibile? Intendevi ** invece di ^? – dan04

risposta

24

Ecco una breve soluzione, utilizzando 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) 

Ho volutamente omesso i controlli di divisibilità per 1 e per il 9, dal momento che essi saranno sempre soddisfatti.

+0

+999 Molto bello! –

+0

+1; molto più elegante della soluzione nell'articolo collegato (nonostante la "potenza espressiva Enourmous" di LINQ) – SingleNegationElimination

2

Ecco la mia soluzione (non elegante come Marco, ma funziona ancora):

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

Voglio crearlo, ma vedo il codice Python 2.xe non voglio confrontare mele e arance. –

+0

Oh sì, ha detto Python 3.x, oops –

+0

Il mio non è affatto vicino ottimizzato come potrebbe essere o .. ma perché preoccuparsi di qualcosa di simile? –

1

questa è la mia soluzione, è molto simile a Marks, ma gestisce circa due volte più veloce

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

Ecco la mia soluzione. Mi piacciono tutte le cose dal basso verso l'alto ;-). Sulla mia macchina funziona circa 580 volte più veloce (3.1 msec vs. 1,8 secondi) rispetto ai marchi:

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: Inoltre, questo funziona, e due volte più veloce (1,6 msec):

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