473,773 Members | 2,269 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

how to make a generator use the last yielded value when it regainscontrol

Ok, I wrote this all by myself, which explains why it doesn't work. It
is meant to take a number and generate the next number that follows
according to the Morris sequence. It works for a single number, but what
I'd like it to do is either:

1. repeat indefinitely and have the number of times controlled elsewhere
in the program (e.g., use the morris() generator in a for loop and use
that context to tell it when to stop)

2. just make it a function that takes a second argument, that being the
number of times you want it to repeat itself and create numbers in the
sequence

Here's the code so far, and any general comments are always appreciated
as well:

def morris(seed):
seed = list(str(seed))
grouping = []
nextNum = []
for i in range(len(seed) ):
try:
if seed[i] == seed[i + 1]:
grouping.append (seed[i])
else:
grouping.append (seed[i])
nextNum.append( str(len(groupin g)) + seed[i])
grouping = []
except IndexError:
grouping.append (seed[i])
nextNum.append( str(len(groupin g)) + seed[i])
seed = ''.join(nextNum )
yield seed

I thought the second to last line might rebind 'seed' to the new value,
and it would use that again the next time through, but it seems to just
keep using the original value each time and yielding the same output.
Apr 7 '06 #1
18 1785
John Salerno wrote:
1. repeat indefinitely and have the number of times controlled elsewhere
in the program (e.g., use the morris() generator in a for loop and use
that context to tell it when to stop)

2. just make it a function that takes a second argument, that being the
number of times you want it to repeat itself and create numbers in the
sequence


Well, I suppose I could just do:

num = 1
for x in range(some_limi t):
num = morris(num)
print num,

But that isn't as much of a challenge as the other two options. :) I'd
like the function to do all the work of returning multiple numbers
(which probably means that option 1 isn't the best either)
Apr 7 '06 #2
John Salerno wrote:
2. just make it a function that takes a second argument, that being the
number of times you want it to repeat itself and create numbers in the
sequence


Here's what I've come up with so far. Probably not the most elegant
solution because of the nested function, but it does work! :)

def morris(seed, limit):
num = seed
numberSet = []

def nextNum(num):
num = list(str(num))
grouping = []
nextNum = []
for i in range(len(num)) :
try:
if num[i] == num[i + 1]:
grouping.append (num[i])
else:
grouping.append (num[i])
nextNum.append( str(len(groupin g)) + num[i])
grouping = []
except IndexError:
grouping.append (num[i])
nextNum.append( str(len(groupin g)) + num[i])
return ''.join(nextNum )

for x in range(limit):
numberSet.appen d(int(num))
num = nextNum(num)

return numberSet
Apr 7 '06 #3
The generator in your original post /does/ rebind seed, but only on the
last iteration of the loop. You'll need to wrap that loop in another
loop if you want the generator to yield more than once.

As for "communicat ing" with a generator --- e.g. telling it to stop ---
this might be done by passing some kind of mutable argument to the
generator and then changing the value of that mutable object. However,
it's not a very elegant solution, and in this case there's not really
any reason to do it. Instead, if you want the generator to stop, just
stop asking it to yield:

for number in morris_sequence _generator(seed ):
if it_is_time_to_s top():
break

And:
- No need to convert str(seed) to a list! Strings are indexable.
- Instead of using "try...exce pt IndexError" to detect the end of the
loop, just change the loop to range(len(seed) - 1) and do the yield
after the loop finishes.
- Use xrange instead of range. range is evil.

Bonus points:
Write the generator to work on a seed which is an iterable of unknown
length.

Super bonus points:
Print the Nth element in the sequence without holding more than N
groups of {digit, number of occurences} of state information. You'll
need to do this if you want to get very far: According to Wikipedia,
the 70th term of the look-and-say sequence has 179,691,598 digits.

Apr 7 '06 #4
John Salerno wrote:
It
is meant to take a number and generate the next number that follows
according to the Morris sequence. It works for a single number, but what
I'd like it to do is either:

1. repeat indefinitely and have the number of times controlled elsewhere
in the program (e.g., use the morris() generator in a for loop and use
that context to tell it when to stop)

2. just make it a function that takes a second argument, that being the
number of times you want it to repeat itself and create numbers in the
sequence


Definitely go for (1). The Morris sequence is a great candidate to
implement as a generator. As a generator, it will be more flexible and
efficient than (2).

def morris(num):
"""Generate the Morris sequence starting at num."""
num = str(num)
yield num
while True:
result, cur, run = [], None, 0
for digit in num+'\n':
if digit == cur:
run += 1
else:
if cur is not None:
result.append(s tr(run))
result.append(c ur)
cur, run = digit, 1
num = ''.join(result)
yield num

# Example usage:
from itertools import islice
for n in islice(morris(1 ), 10):
print n

# Output:
"""
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
132113111231131 12211
"""

--Ben

Apr 7 '06 #5
Ben Cartwright wrote:
Definitely go for (1). The Morris sequence is a great candidate to
implement as a generator. As a generator, it will be more flexible and
efficient than (2).


Actually I was just thinking about this and it seems like, at least for
my purpose (to simply return a list of numbers), I don't need a
generator. My understanding of a generator is that you do something to
each yielded value before returning to the generator (so that you might
not return at all), but since I'm not handling the individual numbers,
just getting a list, it seems I don't need them to be yielded. Of
course, a generator would allow the process to be done over and over, I
suppose, which is what I wanted, I just couldn't figure out how to keep
using the new values.
Apr 7 '06 #6
John Salerno wrote:
Actually I was just thinking about this and it seems like, at least for
my purpose (to simply return a list of numbers), I don't need a
generator.
Yes, if it's just a list of numbers you need, a generator is more
flexibility than you need. A generator would only come in handy if,
say, you wanted to give your users the option of getting the next N
items in the sequence, *without* having to recompute everything from
scratch.

My understanding of a generator is that you do something to
each yielded value before returning to the generator (so that you might
not return at all),


A generator is just an object that spits out values upon request; it
doesn't care what the caller does with those values.

There's many different ways to use generators; a few examples:

# Get a list of the first 10
from itertools import islice
m = [n for n in islice(morris(1 ), 10)]

# Prompt user between each iteration
for n in morris(1):
if raw_input('keep going? ') != 'y':
break
print n

# Alternate way of writing the above
g = morris(1)
while raw_input('keep going? ') == 'y':
print g.next()

--Ben

Apr 7 '06 #7
Here's my take on the thing. It only prints one term, though.

http://www.magicpeacefarm.com/lonnie...morris.py.html

(a bit too long to post)

Apr 7 '06 #8
just couldn't help taking the bait...

def morris(seed) :

"""
m = morris('3447221 ')
m.next() '1324172211' m.next() '11131214111722 21' m.next()

'31131112111431 173211'
"""

assert isinstance(seed ,basestring) and seed.isdigit(), "bad seed"

def itially(z) :
feedback.z = z
while True :
yield feedback.z

def feedback(gen) :
while True :
feedback.z = gen.next()
yield feedback.z

def morrisify(numbe r) :
from itertools import groupby
for digit,sequence in groupby(number) :
yield str(len(tuple(s equence)))
yield digit

return feedback(''.joi n(morrisify(num ber))
for number in itially(seed))
Apr 7 '06 #9
Lonnie Princehouse wrote:
Here's my take on the thing. It only prints one term, though.

http://www.magicpeacefarm.com/lonnie...morris.py.html

(a bit too long to post)


yikes, scary! :)

there was always the hint that using itertools might be helpful, as you
guys are doing, but i could never quite figure out how, but looking at
these alternate methods is definitely helpful
Apr 7 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2354
by: Wai Yip Tung | last post by:
I'm attempting to turn some process than uses callback to return result into a more user friendly generator. I'm hitting some road block so any pointer would be appriciated. Let say there is an existing method producer(x, cb). It calls the supplied cb() every time when there is data available. The definititon of cb should be: def cb(data)
5
2254
by: Jerzy Karczmarczuk | last post by:
I thought that the following sequence gl=0 def gen(x): global gl gl=x yield x s=gen(1)
11
1750
by: vbgunz | last post by:
I am afraid that this is the first time in which I would probably need something explained to me as if I were a little child. I am having a hard time getting this through my thick skull. What in the world is wrong with this!? ''' ########################################################### ''' def generatorFunction(sequence=): for item in sequence: yield item
3
3523
by: andy.leszczynski | last post by:
Hi, I might understand why this does not work, but I am not convinced it should not - following: def nnn(): print 'inside' yield 1 def nn():
4
1584
by: Kenneth McDonald | last post by:
I'm trying to write a 'flatten' generator which, when give a generator/iterator that can yield iterators, generators, and other data types, will 'flatten' everything so that it in turns yields stuff by simply yielding the instances of other types, and recursively yields the stuff yielded by the gen/iter objects. To do this, I need to determine (as fair as I can see), what are generator and iterator objects. Unfortunately: <iterator...
3
1330
by: metaperl | last post by:
For this program: def reverse(data): for index in range(len(data)-1, -1, -1): yield data r = reverse("golf") for char in r: print char
10
2446
by: AA Arens | last post by:
I do have a database with customer info in it. To avoid it will be taken out of our office, is it possible to make it not-readable after a certain period? then every let say seven days, I needs to "extend the license", so it will last another week. It consists of queries, forms, and tables, format Access 2003. Bart
3
1908
by: Dieter Maurer | last post by:
I met the following surprising behaviour .... for i in range(3): .... def gen1(): .... yield i .... yield i, gen1() .... .... 0 0 1 1
2
1156
by: psaffrey | last post by:
I'm trying to implement an interactive graph visualisation tool using matplotlib. I want to use a spring layout, where nodes repulse each other and edges act as springs to pull connected nodes together. Usually, this algorithm runs through a number of iterations of attraction/repulsion to allow the nodes to converge to suitable positions. However, rather than running all these iterations to lay out the graph and then rendering it, I...
0
9454
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10264
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10106
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8937
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6717
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5484
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4012
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3610
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2852
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.