small challenge : limit((x+1)**0.5 for x in itially(2))

A

Azolex

generators challenge
--------------------

define "limit" and "itially"

so that

limit(foo(x) for x in itially(bar))

works out the same as

limit2(foo,bar)

with

def limit2(foo,bar) :
bar1 = foo(bar)
while bar != bar1 :
bar1,bar = foo(bar),bar1
return bar


Note : be careful with your choice of foo and bar, to prevent infinite
loops when the iterated value won't converge.

To think of it, perhaps "abs(bar-bar1)>epsilon" would be more
appropriate than "bar != bar1" in the above loop - I can imagine
roundoff errors leading to tiny oscillations in the least significant
bits of an otherwise convergent computation.

Best, az
 
A

Azolex

Azolex said:
generators challenge
--------------------

define "limit" and "itially"

so that

limit(foo(x) for x in itially(bar))

works out the same as

limit2(foo,bar)

with

def limit2(foo,bar) :
bar1 = foo(bar)
while bar != bar1 :
bar1,bar = foo(bar),bar1

oops, this should read

bar1,bar = foo(bar1),bar1

sorry
 
P

Paul McGuire

Azolex said:
generators challenge
--------------------

define "limit" and "itially"

so that

limit(foo(x) for x in itially(bar))

works out the same as

limit2(foo,bar)

with

def limit2(foo,bar) :
bar1 = foo(bar)
while bar != bar1 :
bar1,bar = foo(bar),bar1
return bar
Howzis?

-- Paul


class Bag:
pass
data = Bag()
data.x = None

def itially(bar):
if data.x is None:
data.x = bar
while 1:
yield data.x

def limit(z):
eps = 1e-10
done = False
z2 = z.next()
z1 = z2 + 1
while abs(z2-z1) > eps:
data.x = z2
z2, z1 = z.next(),z2
print "dbg>",z1,z2
return z1

print limit( x**0.5 for x in itially(2) )



Prints out:
dbg> 1.41421356237 1.189207115
dbg> 1.189207115 1.09050773267
dbg> 1.09050773267 1.04427378243
dbg> 1.04427378243 1.02189714865
dbg> 1.02189714865 1.01088928605
dbg> 1.01088928605 1.00542990111
dbg> 1.00542990111 1.00271127505
dbg> 1.00271127505 1.00135471989
dbg> 1.00135471989 1.00067713069
dbg> 1.00067713069 1.00033850805
dbg> 1.00033850805 1.00016923971
dbg> 1.00016923971 1.00008461627
dbg> 1.00008461627 1.00004230724
dbg> 1.00004230724 1.0000211534
dbg> 1.0000211534 1.00001057664
dbg> 1.00001057664 1.00000528831
dbg> 1.00000528831 1.00000264415
dbg> 1.00000264415 1.00000132207
dbg> 1.00000132207 1.00000066104
dbg> 1.00000066104 1.00000033052
dbg> 1.00000033052 1.00000016526
dbg> 1.00000016526 1.00000008263
dbg> 1.00000008263 1.00000004131
dbg> 1.00000004131 1.00000002066
dbg> 1.00000002066 1.00000001033
dbg> 1.00000001033 1.00000000516
dbg> 1.00000000516 1.00000000258
dbg> 1.00000000258 1.00000000129
dbg> 1.00000000129 1.00000000065
dbg> 1.00000000065 1.00000000032
dbg> 1.00000000032 1.00000000016
dbg> 1.00000000016 1.00000000008
1.00000000016
 
A

Azolex

Paul said:
Howzis?

-- Paul


class Bag:
pass
data = Bag()
data.x = None

def itially(bar):
if data.x is None:
data.x = bar
while 1:
yield data.x

def limit(z):
eps = 1e-10
done = False
z2 = z.next()
z1 = z2 + 1
while abs(z2-z1) > eps:
data.x = z2
z2, z1 = z.next(),z2
print "dbg>",z1,z2
return z1

print limit( x**0.5 for x in itially(2) )

It fits the bill, I'd say. Below is my simplest solution, renaming
"limit" to a more appropriate "fixpoint". Like yours, this solution as
concurrency issues.

Note that (z+1)**0.5 has a more interesting attractive fixpoint that
z**0.5, namely the golden mean 1.618...


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

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

def fixpoint(gen) :
z = echoback(gen).next
while True :
if z()==z() :
return z()

print fixpoint((z+1)**0.5 for z in itially(2))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,292
Messages
2,571,494
Members
48,171
Latest member
EllaHolmwo

Latest Threads

Top