Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
176 views
in Technique[技术] by (71.8m points)

Is there a way to 'pause' or partially consume a generator in Python, then resume consumption later where left off?

There is a related question here. I am attempting to do this project Euler challenge on HackerRank. What it requires is that you are able to derive the nth permutation of a string "abcdefghijklm". There are 13! permutations.

I tried a simple solution where I used for num, stry in zip(range(1, math.factorial(13)), itertools.permutations("abcdefghijklm"):. That works, but it times out.

What would be really nice is to store each value in a dict as I go along, and do something like this:

import itertools
import math

strt = "abcdefghijklm"

dic = {}

perms_gen = itertools.permutations(strt)
idxs_gen = range(1, math.factorial(13))

curr_idx = 0

test_list = [1, 2, 5, 10]

def get_elems(n):
  for num, stry in zip(idxs_gen, perms_gen):
    print(num) # debug
    str_stry = "".join(stry)
    dic[num] = str_stry
    if num == n:
      return str_stry

for x in test_list:
  if curr_idx < x:
    print(get_elems(x))
  else:
    print(dic[x])

This doesn't work. I get this output instead:

1
abcdefghijklm
1
2
abcdefghijlkm
1
2
3
4
5
abcdefghikjml
1
2
3
4
5
6
7
8
9
10
abcdefghilmkj

As I was writing this question, I apparently found the answer... to be continued.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Pausing is built-in functionality for generators. It's half the point of generators. However, range is not a generator. It's a lazy sequence type.

If you want an object where iterating over it again will resume where you last stopped, you want an iterator over the range object:

idsx_iter = iter(range(1, math.factorial(13)))

However, it would be simpler to save the zip iterator instead of two underlying iterators. Better yet, use enumerate:

indexed_permutations = enumerate(itertools.permutations(strt))

You've got a lot more things that don't make sense in your code, though, like curr_idx, which just stays at 0 forever, or your range bounds, which produce 13!-1 indices instead of 13! indices, and really, you should be using a more efficient algorithm. For example, one based on figuring out how many permutations you skip ahead by setting the next element to a specific character, and using that to directly compute each element of the permutation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...