Question

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 :)

Was it helpful?

Solution

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

OTHER TIPS

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]

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top