Questions: While And List Comprehension

Ian ian.g.kelly at gmail.com
Wed Nov 10 22:10:24 EST 2010


On 11/10/2010 4:36 AM Felipe Vinturini said...
> 2.* *I would like to know another way, a more pythonic way, to write the
> following:
> ===================================================================================
> import sys
>
> def Z(iNumber):
>      sum=0
>      while (iNumber>=5):
>          iNumber=iNumber/5
>          sum = sum + iNumber
>      print sum
>
> def factorialCountZeros2():
>      sysStdinReadLine = sys.stdin.readline
>      numValues = int(sysStdinReadLine())
>      [ Z(int(sysStdinReadLine())) for x in xrange(numValues) ]
>
> if __name__ == '__main__':
>      factorialCountZeros2()
> ===================================================================================
> To be more specific, I would like to know about the Z function, is there a
> way to rewrite that while with list comprehension?

Probably not in a way that's more efficient than what you're already
doing.  One thing you should do is to use the // operator instead
of /.  Apart from being more portable (/ no longer does integer
division in Python 3), it's also significantly faster:

$ python -m timeit "12 / 5"
10000000 loops, best of 3: 0.0711 usec per loop

$ python -m timeit "12 // 5"
10000000 loops, best of 3: 0.028 usec per loop

Also, don't use a list comprehension for your looping construct in
factorialCountZeros2().  The list comprehension has to build up a list
containing all the None objects returned by the Z() method, which
wastes time and space.  Because of that, it would be faster just to
write it out the for loop.  Besides the speed improvement, it's also
bad style to use a list comprehension for a loop where you're only
interested in the side effects.

Another thing to consider is that function calls are expensive.  Your
Z() function gets called once for every line of input, which could add
up.  While it will make the code a bit less readable (CodeChef is
definitely not the place to go if you want to learn to write *clear*
code), you might see some improvement if you wrap that function into
the factorialCountZeros2() function.

Finally, one thing that really tends to help a lot in these puzzles is
to do all your input at once and all your output at once.  I/O is
crazy expensive, but you can cut a lot of that out by minimizing the
number of reads and writes that you have to do.

After the first readline, you can do something like "input =
sys.stdin.read().strip().split('\n')" to pull everything into a single
list, then iterate over the list instead of stdin.  For output, append
all your results to a list instead of printing them immediately, then
use '\n'.join() to generate something suitable for printing.

Cheers,
Ian

P.S. CodeChef and SPOJ both have the psyco module available.  If you
just can't seem to get a problem solved in the time limit, you can
always turn it on for a major speed boost.  It's more fun to try to
solve the problems without it, though.



More information about the Python-list mailing list