2010-04-15 9 views
8

Dies ist keine Hausaufgaben.Helfen Sie mir, diese Python 3.x Self-Challenge zu beenden

Ich sah this article praising Linq library and how great it is für Kombinatorik Zeug, und ich dachte mir: Python kann es in einer lesbareren Weise tun.

Nach einer halben Stunde mit Python tupfte ich fehlgeschlagen. Bitte beenden Sie, wo ich aufgehört habe. Mach es auch möglichst pythonisch und effizient.

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) 

Vielen Dank!

+1

Do Sie möchten die meisten Pythonic oder am effizientesten? Sie können sehr unterschiedliche Dinge sein. :) –

+0

Ich will alles und ich will es jetzt;) Hm ... eins von beiden sowie beides. Es gibt keine beste Antwort, obwohl ich eine auswählen müsste. Bitte geben Sie bei Bedarf einen time-it-liner für Leistungstests an. –

+3

Warum verwenden Sie bitweise XOR in Ihrer teilbaren Funktion? Meinst du ** statt ^? – dan04

Antwort

24

Hier eine kurze Lösung, mit 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) 

Ich habe absichtlich die Teilbarkeit Kontrollen durch 1 und durch 9 weggelassen, da sie immer zufrieden sein werden.

+0

+999 Sehr schön! –

+0

+1; so viel eleganter als die Lösung in dem verlinkten Artikel (trotz LINQs "Enorme Ausdruckskraft") – SingleNegationElimination

2

Hier ist meine Lösung (nicht so elegant wie Mark, aber es funktioniert immer noch):

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

Ich möchte es zeitlich ändern, aber ich sehe Python 2.x-Code, und ich möchte nicht Äpfel und Orangen vergleichen. –

+0

Oh ja, es hat gesagt Python 3.x, oops –

+0

Meine ist nicht annähernd so optimiert, wie es sein könnte .. aber warum auf so etwas zu kümmern? –

1

dies ist meine Lösung, es zu Marks sehr ähnlich ist, aber es läuft etwa doppelt so schnell

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

Hier ist meine Lösung. Ich mag alle Dinge von unten nach oben ;-). Auf meinem Rechner läuft es etwa 580-mal schneller (3,1 ms vs. 1,8 Sekunden) als 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: Auch das funktioniert, und doppelt so schnell (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))