Every number from 1,2,5,6,9,10... is divisible by 4 with remainder 1 or 2.
>>> ','.join(str(i) for i in xrange(100) if i % 4 in (1,2))
'1,2,5,6,9,10,13,14,...'
Answer from Aleksei astynax Pirogov on Stack OverflowEvery number from 1,2,5,6,9,10... is divisible by 4 with remainder 1 or 2.
>>> ','.join(str(i) for i in xrange(100) if i % 4 in (1,2))
'1,2,5,6,9,10,13,14,...'
>>> ','.join('{},{}'.format(i, i + 1) for i in range(1, 100, 4))
'1,2,5,6,9,10,13,14,17,18,21,22,25,26,29,30,33,34,37,38,41,42,45,46,49,50,53,54,57,58,61,62,65,66,69,70,73,74,77,78,81,82,85,86,89,90,93,94,97,98'
That was a quick and quite dirty solution.
Now, for a solution that is suitable for different kinds of progression problems:
def deltas():
while True:
yield 1
yield 3
def numbers(start, deltas, max):
i = start
while i <= max:
yield i
i += next(deltas)
print(','.join(str(i) for i in numbers(1, deltas(), 100)))
And here are similar ideas implemented using itertools:
from itertools import cycle, takewhile, accumulate, chain
def numbers(start, deltas, max):
deltas = cycle(deltas)
numbers = accumulate(chain([start], deltas))
return takewhile(lambda x: x <= max, numbers)
print(','.join(str(x) for x in numbers(1, [1, 3], 100)))
If the closed form is available you can use a list comprehension. This has the advantage that all the required memory can be allocated right at the beginning:
seq = [(i + 1)**2 for i in range(1, n+1)]
Repeatedly appending to a list causes internal resizing of the underlying memory and thus involves unnecessary memory allocations and copies.
Without a closed form you can still use a generator:
def gen_seq(n):
a = 0
for i in range(1, n+1):
a += 2*i - 1
yield a
Performance comparison
In [1]: def f1(n):
...: return [(i + 1)**2 for i in range(1, n+1)]
...:
In [2]: def gen_seq(n):
...: a = 0
...: for i in range(1, n+1):
...: a += 2*i - 1
...: yield a
...:
In [3]: def f2(n):
...: return list(gen_seq(n))
...:
In [4]: %timeit f1(100_000)
29.7 ms ± 271 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [5]: %timeit f2(100_000)
16.1 ms ± 176 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
The generator version is almost 2x faster than the list comprehension. This is because the recursive version benefits from the relatively simple operations that are involved. Multiplying an integer by 2 is simply a 1-lshift and adding or subtracting a number is an O(N) operation where N is the number of digits. Multiplying two integers however is O(N*log(N)) and hence takes more time to compute. The recursive version benefits from the already-computed part a_{n-1} which it can reuse at each step.
Specifically in this case, you can just use list(range(1, n)) which is much faster
import time
t = time.time()
print(list(range(1, 1_000_000)))
print(time.time() - t)
Takes less than 0.5 seconds.
[str(i) for i in range(3000, 3100+1)]
This is faster than using map().
Use the range function, then combine with a map(str,)
# list of int
values = list(range(3000, 3101))
print(values) # [3000, 3001, 3002, 3003, 3004 ... 3100]
# list of string representation of int
values = list(map(str, range(3000, 3101)))
print(values) # ['3000', '3001', '3002', '3003',, ... '3100']