Repeat counter when index ends - python

Simple question - I want a loop that counts up and returns to 0 when it reaches a certain number.
Tried something like:
while i < 7:
i += 1
if i == 7
i -= 1 #(or change i in any other way - you get the idea)
My Python actually crashed when I tried the above.
EDIT: Yes, the if condition is never met - it still crashes when I change it to if i == 6 though.

while i < 7:
i += 1
if i == 7:
i = 0
The problem is the i-=1 line. Your code works as i counts up to 6, but when it reaches 6, it is incremented to 7, and then subtracted down to 6 again. Your current sequence is 0,1,2,3,4,5,6,6,6,6,...

If you want to count up to 7 then count down to 0 here is what you can try:
i = 0
add = True
while True:
if add:
i += 1
else:
i -= 1
if i in [0, 7]:
add = not add

This is your corrected code,
i = 0
while i < 7:
i += 1
if i == 6:
i = 0
It reaches 0 on reaching 6.
Lot's of syntax Error fixed.

Related

How to continue the value of a fruitful function within a while loop?

Amateur python user here;
I am creating a program that takes 500 randomized numbers, and counts how many there are of each number ranging from 0-9, then prints a chart that shows how many times each number occurred. I initially created a working program that accomplished this, however the criteria for this program is that I have to use a fruitful function to get a randomized number and return it, which I am having trouble doing.
This is the main code I am having trouble with:
symbol = 0
while timesRun != 500:
timesRun += 1
genRandom(symbol)
if symbol == 0:
zero += 1
elif symbol == 1:
one += 1
elif symbol == 2:
two += 1
elif symbol == 3:
three += 1
elif symbol == 4:
four += 1
elif symbol == 5:
five += 1
elif symbol == 6:
six += 1
elif symbol == 7:
seven += 1
elif symbol == 8:
eight += 1
elif symbol == 9:
nine += 1
And this is the function for the while loop, minus the entirety of the other elif statements and else statement, just to save your reading time:
def genRandom(letter):
ranNum = randint(0,9)
allNumbers.append(ranNum)
if ranNum == 0:
letter = 0
return letter
When I print genRandom(symbol), it does return a 500 random numbers line by line, however when I check the if statements (if symbol ==1:, etc...), it only uses the global symbol and not the argument I sent. When I print my chart, the output looks like this:
Number | Occurrences
-------------------------------
0 | 0
1 | 0
2 | 0
3 | 0
4 | 0
5 | 0
6 | 0
7 | 0
8 | 0
9 | 0
What is the best fix for this?
Thanks in advance
When you call genRandom(symbol), you are assuming that symbol will be modified with the new value. Python doesn't work that way. The only thing you get back from a function is what it returns: symbol = genRandom().
However, there's a better way to do what you are doing:
counts = [0]*10
for _ in range(500):
num = randint(0,9)
counts[num] += 1
print(counts)
Here's your obligatory one-liner:
import collections
import random
print( collections.Counter(random.randint(0,9) for _ in range(500)) )
I am obviously being smug, but here's a walk-though:
collections.Counter does exactly the thing you're trying to do. It takes an iterable and counts how many times that "thing" occurs.
random.randint is another "batteries included" function that'll give you some random numbers... Don't use it for cryptography.
The other magic in there is that argument I've passed to the Counter's constructor. The (f() for _ in range(N)) is called a List Comprehension ("https://www.geeksforgeeks.org/python-list-comprehension/") and is a one-line for-loop. It means do f() for every _ (pythonic way to say "I'm not going to use this value") in the range of [0..N), and return them as an iterable.

Using conditional statements in while loop

I was under the impression that adding the following if statement in my while loop makes python pick only the odd values of i that are smaller than 7 and sums them. However, this is not the case.
Here's my code:
i = 0
sum = 0
while i < 7:
if (i % 2) == 1:
sum += i
i += 1
I expect sum to be 9 but an infinite loop occurs, causing the sum to be infinite.
I can't seem to understand how. Any help is appreciated. Thanks in advance!
You only increment i inside the if, so if the condition is not meant, i stays the same forever
i = 0
sum = 0
while i < 7:
if (i % 2) == 1:
sum += i
i += 1
print(sum)
Output:
9
As you keep conditioning i % 2, but if it doesn't go through, the i never changes, it will always exit the if statement, to solve it:
i = 0
sum = 0
while i < 7:
if (i % 2) == 1:
sum += i
i += 1
print(sum)
You have to unindent by 4 spaces your i += 1 line.
For similar cases it is better to use for loop than while loop. Especially if you have long loops. link
sum = 0
for i in range(7):
if (i % 2) == 1:
sum += i

code passes all the tests but fails in other tests.. please follow the link

Return the sum of the numbers in the array, ignoring sections of numbers between 6 and 7 (every 6 will be followed by at least one 7). Return 0 for no numbers.
sum67([1, 2, 2]) ā†’ 5
sum67([1, 2, 2, 6, 99, 99, 7]) ā†’ 5
sum67([1, 1, 6, 7, 2]) ā†’ 4
my code:
def sum67(nums):
total = 0
n = 0
while(n < len(nums)):
if nums[n] == 6:
while(nums[n] != 7 and n < len(nums)):
n += 1
n += 1
if n > len(nums)-1:
break
total += nums[n]
n += 1
return total
click here to test
The problem arises if there's a 6 directly after a 7.
Your code detects the first 6 and skips forward past the next 7. But if the next number is another 6, it won't be skipped.
It'll work if you change if nums[n]==6: to while n<len(nums) and nums[n] == 6:.
#Rawing got this debugged properly. Here's another simple fix if you prefer:
def sum67(nums):
total = 0
n = 0
while n < len(nums):
if nums[n] == 6:
# Skip forward until we find a 7 (or the end of the list).
while n < len(nums) and nums[n] != 7:
n += 1
else:
total += nums[n]
# We're either looking at a number we just added to the total,
# or we're looking at the 7 we just found. Either way, we need
# to move forward to the next number.
n += 1
return total
As #Rawing pointed out your code doesn't cover the scenario where 6 follows immediately after 7. Instead of having multiple loops and updating loop counter yourself you could just iterate over the numbers on the list and have extra variable telling if you need to skip them or not:
def sum67(nums):
skip = False
total = 0
for x in nums:
if skip:
if x == 7:
skip = False
elif x == 6:
skip = True
else:
total += x
return total

How do I exit this while loop?

Iā€™m having trouble with exiting the following while loop. This is a simple program that prints hello if random value is greater than 5. The program runs fine once but when I try to run it again it goes into an infinite loop.
from random import *
seed()
a = randint(0,10)
b = randint(0,10)
c = randint(0,10)
count = 0
while True:
if a > 5 :
print ("aHello")
count = count + 1
else :
a = randint(0,10)
if b > 5 :
print ("bHello")
count = count + 1
else :
b = randint(0,10)
if c > 5 :
print ("cHello")
count = count + 1
else :
c = randint(0,10)
if count == 20 :
count = 0
break
count = 0
Your while loop might increment the variable count by 0, 1, 2 or 3. This might result in count going from a value below 20 to a value over 20.
For example, if count's value is 18 and the following happens:
a > 5, count += 1
b > 5, count += 1
c > 5, count += 1
After these operations, count's value would be 18 + 3 = 21, which is not 20. Therefore, the condition value == 20 will never be met.
To fix the error, you can either replace the line
if count == 20
with
if count >= 20
or just change your program logic inside the while loop.
Does the following code help?
while True:
if a > 5 :
print ("aHello")
count = count + 1
if count == 20 :
break
else :
a = randint(0,10)
if b > 5 :
print ("bHello")
count = count + 1
if count == 20 :
break
else :
b = randint(0,10)
if c > 5 :
print ("cHello")
count = count + 1
if count == 20 :
break
else :
c = randint(0,10)
You have to check the value of count after incrementing it every time.
The "break" condition might fail if two or more values of the variables a, b, and c are greater than 5. In that case the count will be incremented more than once and count will end up > 20, and the loop can never terminate. You should change:
if count == 20 :
to
if count >= 20:
At the end of iteration, count might be greater than 20 due to multiple increments. So I would update the last if statement to:
if count >= 20:
to feel safe.
If your goal is to stop counting when count is >= 20, then you should use that condition for your while loop and you won't need to break at all, as you only break at the end of the loop anyways.
The new while statement would look like
while count < 20:
# increment count
and then outside of the while loop you can reset count to 0 if you want to use it again for something else.
since you increment count 2 or 3 times in one iteration, it may skip past your count == 20 check
Here's one way to get exactly 20 lines.
from random import seed, randint
seed()
a = randint(0,10)
b = randint(0,10)
c = randint(0,10)
count = iter(range(20))
while True:
try:
if a > 5:
next(count)
print ("aHello")
else:
a = randint(0,10)
if b > 5:
next(count)
print ("bHello")
else:
b = randint(0,10)
if c > 5:
next(count)
print ("cHello")
else:
c = randint(0,10)
except StopIteration:
break
Note there is still a lot of repetition in this code. Storing your a,b,c variables in a list instead of as separate variables would allow the code to be simplified further

string comparison in a while loop

I've written a small piece of code that should detect if there are any matching characters in the same place in the 2 strings. If there is , the score in incremented by 1, if there is 2 or more consecutive matching characters , the score is incremented by 3, if there is no matching character, the score is decremented by 1.
The problem is though , when i try to run the code, it gives me a error: string index out of range.
What might be wrong ? thank you very much.
def pairwiseScore(seqA, seqB):
count = 0
score = 0
while count < len(seqA):
if seqA[count] == seqB[count]:
score = score + 1
count = count + 1
while seqA[count] == seqB[count]: # This is the line the error occurs
score = score + 3
count = count + 1
elif seqA[count] != seqB[count]:
score = score - 1
count = count + 1
return score
Do both strings have the same lenght? otherwise you should consider using something like:
while count < min(len(seqA), len(seqB)):
Also, the zip function might come in handy here to pair off the letters in each word. It is a python builtin. e.g.
def letter_score(s1, s2):
score = 0
previous_match = False
z = zip(s1, s2)
for pair in z:
if pair[0] == pair[1]:
if previous_match:
score += 3
else:
score += 1
previous_match = True
else:
score -= 1
previous_match = False
return score
Indexes are numberd 0 to n.
len(someString)
will give you n + 1.
Let's say that your string is length 10, and the indexes are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Your while loop checks the condition that count is < 10. So far so good.
Ok now let's say that count is equal to 9. Immediately within the first while loop, you increment count.
So now count = 10.
Now attempting to access someString[count] will give you an IndexError because the indices only go up to 9.
The error message says it: You're trying to access a character beyond the boundaries of your string. Consider this:
>>> s = "hello"
>>> len(s)
5
>>> s[4]
'o'
Now when (at the start of the first while loop) count is 1 below len(seqA), then you're incrementing count and then you're doing seqA[count] which will throw this exception.
Let's assume you're calling pairwisescore("a", "a"):
score = 0
count = 0
while count < len(seqA): # 0 < 1 --> OK
if seqA[count] == seqB[count]: # "a" == "a" --> OK
score = score + 1 # score = 1
count = count + 1 # count = 1
while seqA[count] == seqB[count]: # seqA[1] doesn't exist!
In the second while loop you must test that count is less than len(seqA):
while count < len(seqA) and seqA[count] == seqB[count]:
...
and, also there's possibly other bug: If the length of seqB is less than length of seqA, you'll again see runtime exception. so, you should change every occurence of count < len(seqA) with count < min(len(seqA), len(seqB)).
def pairwiseScore(seqA, seqB):
count = 0
score = 0
isOne = False
isTwoOrMore = False
while count < min(len(seqA), len(seqB)):
if seqA[count] == seqB[count]:
if isTwoOrMore:
score = score + 3
count = count + 1
else:
if isOne:
isTwoOrMore = True
score = score + 1
count = count + 1
isOne = True
elif seqA[count] != seqB[count]:
score = score - 1
count = count + 1
isOne = False
isTwoOrMore = False
return score
a = 'apple'
b = 'aplle'
print(pairwiseScore(a, b))
I think this one solve the problem, I added a "counting" bool variable. And to respond to the question, your program didn't compare the length of the second string.
while count < min(len(seqA), len(seqB)):
The problem is that you do this:
count = count + 1
Both before the inner while loop and at the end of it. But you then continue using seqA[count] before checking it against len(seqA) again - so, once it goes too high, Python will try to read past the end of seqA, and you'll get that error (when, if the condition had been checked again after incrementing, the loop would have ended).
Using a Python for loop will get around bugs like this, since Python will manage count for you:
for a,b in zip(seqA, seqB):
if a == b:
score += 1
You can implement the extra-points bit easily in this by keeping track of whether the previous character is a match, rather than trying to work out how many after this one are. A boolean variable last_matched that you keep updated would help with this.

Categories