ooboo
ooboo

Reputation: 17109

Generate from generators

I have a generator that takes a number as an argument and yields other numbers. I want to use the numbers yielded by this generator and pass them as arguments to the same generator, creating a chain of some length.

For example, mygenerator(2) yields 5, 4 and 6. Apply mygenerator to each of these numbers, over and over again to the numbers yielded. The generator always yields bigger numbers than the one passed as argument, and for 2 different numbers will never yield the same number.

mygenerator(2): 4 5 mygenerator(4) : 10 11 12 mygenerator(5): 9 300 500

So the set (9,10,11,12,300,500) has "distance" 2 from the original number, 2. If I apply it to the number 9, I will get a set of numbers with distance "3" from the original 2.

Essentially what I want is to create a set that has a specified distance from a given number and I have problems figuring out how to do that in Python. Help much appreciated :)

Upvotes: 2

Views: 766

Answers (3)

yairchu
yairchu

Reputation: 24814

This solution does not require to keep all results in memory: (in case it doesn't fit in memory etc)

def grandKids(generation, kidsFunc, val):
  layer = [val]
  for i in xrange(generation):
    layer = itertools.chain.from_iterable(itertools.imap(kidsFunc, layer))
  return layer

Example:

def kids(x): # children indices in a 1-based binary heap
  yield x*2
  yield x*2+1

>>> list(grandKids(3, kids, 2))
[16, 17, 18, 19, 20, 21, 22, 23]

Btw, solution in Haskell:

grandKids generation kidsFunc val =
  iterate (concatMap kidsFunc) [val] !! generation

Upvotes: 2

aks
aks

Reputation: 25377

I have just started learning Python so bear with me if my answer seems a tad amateurish. What you could do is use a list of lists to populate the values returned from the myGenerator function.

So for eg. with 2 as the starting argument your data-structure would resemble something like

resDataSet = [[2], 
              [4, 5],
              [9, 10, 11, 12, 300 , 500]
              ...
             ]

The row index should give you the distance and you can use methods like extend to add on more data to your list.

Upvotes: 0

Anurag Uniyal
Anurag Uniyal

Reputation: 88845

Suppose our generator yields square and cube of given number that way it will output unique so if we want to get numbers at dist D in simplest case we can recursively get numbers at dist D-1 and then apply generator to them

def mygen(N):
    yield N**2
    yield N**3

def getSet(N, dist):
    if dist == 0:
        return [N]

    numbers = []
    for n in getSet(N, dist-1):
        numbers += list(mygen(n))

    return numbers

print getSet(2,0)
print getSet(2,1)
print getSet(2,2)
print getSet(2,3)

output is

[2]
[4, 8]
[16, 64, 64, 512]
[256, 4096, 4096, 262144, 4096, 262144, 262144, 134217728]

Upvotes: 3

Related Questions