Dick Moores wrote:
> At 07:34 PM 8/22/2007, Kent Johnson wrote:
>> FWIW here is my fastest solution:
>>
>> 01 from itertools import chain
>> 02 def compute():
>> 03      str_=str; int_=int; slice_=slice(None, None, -1)
>> 04     for x in chain(xrange(1, 1000001, 10), xrange(2, 1000001, 10),
>> 05 xrange(3, 1000001, 10), xrange(4, 1000001, 10), xrange(5, 1000001, 10),
>> 06 xrange(6, 1000001, 10), xrange(7, 1000001, 10), xrange(8, 1000001, 10),
>> 07 xrange(9, 1000001, 10)):
>> 08          rev = int_(str_(x)[slice_])
>> 09          if rev>=x: continue
>> 10         if not x % rev:
>> 11              print x,
>> 12 compute()

> And at first I thought your use of str_, int_, and slice_ were pretty 
> weird; instead of your line 08, why not just use the straightforward
> 
> rev = int(str(x)[::-1])
> 
> but on upon testing I see they all make their respective 
> contributions to speed.
> 
> But I don't understand why. Why is your line 08 faster than "rev = 
> int(str(x)[::-1])"?

Two reasons. First, looking up a name that is local to a function is 
faster than looking up a global name. To find the value of 'str', the 
interpreter has to look at the module namespace, then the built-in 
namespace. These are each dictionary lookups. Local values are stored in 
an array and accessed by offset so it is much faster.

Second, the slice notation [::-1] actually creates a slice object and 
passes that to the __getitem__() method of the object being sliced. The 
slice is created each time through the loop. My code explicitly creates 
and caches the slice object so it can be reused each time.
> 
> BTW I also thought that
> 
> for x in chain(xrange(1, 1000001, 10), xrange(2, 1000001, 10),
> xrange(3, 1000001, 10), xrange(4, 1000001, 10), xrange(5, 1000001, 10),
> xrange(6, 1000001, 10), xrange(7, 1000001, 10), xrange(8, 1000001, 10),
> xrange(9, 1000001, 10)):
>      pass
> 
> MUST take longer than
> 
> for x in xrange(1000000):
>      pass
> 
> because there appears to be so much more going on, but their timings 
> are essentially identical.

Well for one thing it is looping 9/10 of the number of iterations. Also, 
chain() doesn't have to do much, it just forwards the values returned by 
the underlying iterators to the caller, and all the itertools methods 
are written in C to be fast. If you read comp.lang.python you will often 
see creative uses of itertools in optimizations.

Kent
_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to