Tomasz Przemski
Tomasz Przemski

Reputation: 1127

Generating sequences a recursively defined math string in Python

I have a sequence defined:

enter image description here

and my current code:

a = [1]
i=1
while a[-1] < 50:
    if a[-1] + 5*i < 50:
        a.append(a[-1] + 5*i)
        i+=1
    else:
        break

Output:

[1, 6, 16, 31]

can it be done more elegantly and optimally?

Upvotes: 0

Views: 102

Answers (6)

CSQL
CSQL

Reputation: 106

A really cute one liner:

def seq(n):
     return([(1+sum(i for i in range(0,5*j,5))) for j in range(1,n+1)])

print(seq(5))
[1, 6, 16, 31, 51]

Upvotes: 0

ggorlen
ggorlen

Reputation: 56965

I'd write it with a generator:

import itertools

def gen_sequence(maximum):
    n = 1

    for i in itertools.count(0):
        n = n + 5 * i

        if n > maximum: break

        yield n

if __name__ == "__main__":
    print(list(gen_sequence(50))) # => [1, 6, 16, 31]

Or if you don't want to provide an upper limit, you can generate infinitely and let the caller dynamically decide when to quit. This enables the caller to step forward a few iterations and resume later or use itertools.takewhile to immediately pick up to a limit:

from itertools import count, takewhile

def gen_sequence():
    n = 1

    for i in count(0):
        n = n + 5 * i
        yield n

if __name__ == "__main__":
    print(list(takewhile(lambda x: x < 50, gen_sequence()))) # => [1, 6, 16, 31]

Whichever way you do it, it's a good idea to put the logic in a function with parameters and check the termination condition once. Ideally come up with a better name for the sequence than gen_sequence, which is rather ambiguous.

Upvotes: 3

DarrylG
DarrylG

Reputation: 17156

One liners using accumulate

Solution 1: Creates n Terms

from itertools import accumulate

def seq(n):
  " Creates n terms of sequence"
  return list(accumulate(range(1, n+1), lambda acc, v: acc + 5*(v-1)))

print(seq(5))     # Generate first 5 terms
# Out: [1, 6, 16, 31, 51]

Solution 2--Creates up to Max Value

from itertools import accumulate, takewhile, count

def seq_gen(MAX):
  " terms up to value MAX "
  return list(takewhile(lambda v: v<=MAX, accumulate(count(start=1), lambda acc, v: acc + 5*(v-1))))

print(seq_gen(50))  # Generate to a maximum value of 50
# Out: [1, 6, 16, 31]

Upvotes: 3

Mathemagician
Mathemagician

Reputation: 461

Here's the way that I would write it:

def seq(a, n, lst=[]):
    a = a + 5 * (n - 1)
    n += 1
    if a < 50:
        lst.append(a)
        seq(a, n)
    return lst


print(list(seq(1, 1)))

Upvotes: 1

Tomer Shinar
Tomer Shinar

Reputation: 415

This code is just like yours without useless if and break

a = [1]
i=1
while a[-1] + 5*i < 50:
    a.append(a[-1] + 5*i)
    i+=1

Upvotes: 2

Errgod
Errgod

Reputation: 31

I didn't quite understand what exactly the function you are looking for returns, but here's a general implementation in case you are looking to get the number An

def func(n):
    if n==1:
         return 1
    return (func(n-1) + 5*(n-1))

Upvotes: -1

Related Questions