On Tue, Jun 15, 2010 at 9:26 AM, Ian Kelly <ian.g.ke...@gmail.com> wrote:
> On Tue, Jun 15, 2010 at 6:21 AM, Alain Ketterlin > <al...@dpt-info.u-strasbg.fr> wrote: > > You compute i**2 too many times (7/5 times more than necessary) and > > twice too many modulos. I suggest: > > > > c = { 0:1, 1:1, 2:1, 3:-1, 4:-1 } > > #or, why not: c = lambda i : +1 if (i%5) < 3 else -1 > > > > s = 0 > > for i in range(1,2011): > > s += c[(i-1)%5]*(i**2) > > print s > > In fact, most of them are unnecessary: > > from itertools import izip, cycle > > def squares(start, stop): > square = start * start > step = start * 2 + 1 > for root in xrange(start, stop): > yield square > square += step > step += 2 > > print sum(sign * square for sign, square in izip(cycle([1,1,1,-1,-1]), > squares(1, 2011))) > > Now, anybody know how to make that version a one-liner without making > it go quadratic in run-time? > > Cheers, > Ian > -- > http://mail.python.org/mailman/listinfo/python-list > I don't really consider long one liners that pythonic - they're often not that clear. Here's something I do consider pythonic, which uses the algorithm Ian mentions. It's far from the shortest, but it's quite clear, IMO: #!/usr/bin/python import itertools def signs(): while True: yield 1 yield 1 yield 1 yield -1 yield -1 # take advantage of the property that a perfect square is the sum of odd integers to get a radical speed boost # 1, 4, 9, 16, 25 # 4 - 1 is 3 # 9 - 4 is 5 # 16 - 9 is 7 # and so on. IOW, if you build a square and then build onto two of the sides to increase the dimensions by one unit, you're always # adding the next odd integer - you can do it nicely with a child's blocks. def squares(): oddno = 1 square = oddno while True: yield square oddno += 2 square += oddno for squareno, sign, square in itertools.izip(xrange(20), signs(), squares()): # what you want to do with these is your business :) print squareno, sign, square
-- http://mail.python.org/mailman/listinfo/python-list