zzoop
zzoop

Reputation: 91

Incrementing a variable to 100 then deincrementing to 0 and back again in a loop

I'm just wondering what the most "pythonic" way to increment a varible x all the way from 0 to 100, then when x reaches 100, deincrement back to 0 then back again to 100 in a loop over and over...

Something like this:

x = 0
while True:
  if x < 100:
    x += 1
  elif x == 100:
    x -= 1

NB: Above code is broken, hence my question. :)

What is the simplest way to do this - not necessarily the shortest code, not looking for a one liner, just a really nice bit of code.

Upvotes: 0

Views: 2493

Answers (6)

snakes_on_a_keyboard
snakes_on_a_keyboard

Reputation: 884

well since no one else is doing it, why not some generator fun!

def lazy_forever_and_ever(hi, lo, start=0, step=1):
    x = start
    vals = {hi: lo, lo: hi}
    target=lo
    while True:
        if x == target:
            target = vals[target]
        if x >= target:
            yield x
            x -= step
        elif x <= target:
            yield x
            x += step

if __name__ == '__main__':
    _4eva = lazy_forever_and_ever(0, 10, 0, 1)
    print([next(_4eva) for _ in range(20)])

# output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Upvotes: 0

Peanut Butter Vibes
Peanut Butter Vibes

Reputation: 185

Well, your current solution won't exactly work - you'll deincrement back to 99, then cycle between 99 and 100.

The simplest might be to add a direction flag, for example:

x = 0
isIncreasing = True
while True:
  if isIncreasing = True:
    x += 1
    if x == 100:
      isIncreasing = False
  else: 
    x -= 1
    if x == 0:
      isIncreasing = True

I'm there's a more "one line" way to do this with itertools (see above posts), but this would be the most "direct" solution in your current case. Of course, what you're really looking for is a generator.

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477210

First of all your code does not work: it will count to 100, and then swap between 99 and 100. So: 1,2,3,..,99,100,99,100,99,...

Actually the most Pythonic way is probably not to increment/decrement at all, but use two ranges:

while True:
    for x in range(101):
        pass
        #do something with x
    for x in range(99,0,-1):
        pass
        #do something with x

Or construct an infinite generator with :

generator = itertools.cycle(itertools.chain(range(101),range(99,0,-1)))

and then you can use it as:

for x in generator:
    pass
    #do something with x

Fr instance (I here use 2 because it makes the answer more compact):

for x in itertools.cycle(itertools.chain(range(3),range(1,0,-1))):
    print(x)

will produce:

0
1
2
1
0
1
2
1
0

the loop will be repeated infinitely.

A way to fix your code however would be to add a direction, but this is probably not very Pythonic:

x = 0
dr = True
while True:
    if dr:
        x += 1
        if x >= 100:
            dr = False
    else:
        x -= 1
        if x <= 0:
            dr = True
    #do something with x

Upvotes: 2

mkorvas
mkorvas

Reputation: 603

I find one-liners simple... so what about this:

Python 2:

from itertools import *
ups_and_downs = cycle(chain(xrange(100), xrange(100, 0, -1)))

Python 3:

from itertools import *
ups_and_downs = cycle(chain(range(100), range(100, 0, -1)))

(edited to remove the one-off error)

Upvotes: 3

Shiping
Shiping

Reputation: 1337

How about trying this?

x = 0
inc = 1
while True:
  # do your job here
  if x == 0:
    inc = 1
  elif x == 100:
    inc = -1
  x += inc

Upvotes: 1

kindall
kindall

Reputation: 184280

There's nothing wrong with using two loops!

while True:
    for x in range(100):
        do_something(x)
    for x in range(98, 0, -1):
        do_something(x)

Or you could use a variable to keep track of which direction you're going:

delta = 1
x = 0
while True:
    do_something(x)
    x += delta
    if x < 1 or x > 99:
        delta = -delta

Upvotes: 1

Related Questions