Why is a line in my if statement running every time? (python) - python

I am working on a project were the user inputs a number and a list, and whatever item in the list is closest to the number, is printed out. I have come across a problem were the line in my if() statement in my while loop is running every time? I have a feeling it has something to do with indenting if() statements in python 3 but I am not certain. Anybody know why this is happening?
import math
MatchingI = math.inf
while i < len(compareList):
if (abs(int(mainNum) - int(compareList[i])) < MatchingI):
MatchingI = int(compareList[i])
i += 1

I think that you need to assign abs(int(mainNum) - int(compareList[i])) to MatchingI, instead of assigning int(compareList[i]) to MatchingI.
import math
MatchingI = math.inf
while i < len(compareList):
if (abs(int(mainNum) - int(compareList[i])) < MatchingI):
MatchingI = abs(int(mainNum) - int(compareList[i]))
answer = compareList[i]
i += 1
print(answer)
Isn't this what you are looking for?

Related

IndexError: list index out of range even though printing individual lists and index doesn't seem to have an error

take = randint(0, len(teacherClass[teacher])-1)
print(take)
print(teacherClass)
print(teacher)
print(teacherClass[teacher])
triesDone = 0
while triesDone < len(teacherClass[teacher]):
cp = teacherClass[teacher][take]
if (cp not in (blocks[teacher][day])) and (blocksS[cp][day][block] == ""):
blocks[teacher][day][block] = cp
blocksS[cp][day][block] = teacherSub[teacher]
take +=1
triesDone += 1
if take == len(teacherClass[teacher])-1:
take = 0
When I run the program after some time, the above part is hit and the program starts working as intended but line 8 raises the error ("IndexError: list index out of range").
Trying to solve that and understand the problem, I tried to print the entire dictionary(teacherClass) and the indices used(teacher and take) but even after that, it seems the line 8 should work.
Output I am getting:
Output with list and index
Please help me understand the problem and a solution. Thanks
There is a possibility that take could be: len(teacherClass[teacher])-1 from the assignment on the first line. Later there is take += 1. This mean that it is larger than the limit, so take = 0 is never executed.
Did you mean:
if take >= len(teacherClass[teacher])-1:
take = 0

Conditionally increase integer count with an if statement in python

I'm trying to increase the count of an integer given that an if statement returns true. However, when this program is ran it always prints 0.I want n to increase to 1 the first time the program is ran. To 2 the second time and so on.
I know functions, classes and modules you can use the global command, to go outside it, but this doesn't work with an if statement.
n = 0
print(n)
if True:
n += 1
Based on the comments of the previous answer, do you want something like this:
n = 0
while True:
if True: #Replace True with any other condition you like.
print(n)
n+=1
EDIT:
Based on the comments by OP on this answer, what he wants is for the data to persist or in more precise words the variable n to persist (Or keep it's new modified value) between multiple runs times.
So the code for that goes as(Assuming Python3.x):
try:
file = open('count.txt','r')
n = int(file.read())
file.close()
except IOError:
file = open('count.txt','w')
file.write('1')
file.close()
n = 1
print(n)
n += 1
with open('count.txt','w') as file:
file.write(str(n))
print("Now the variable n persists and is incremented every time.")
#Do what you want to do further, the value of n will increase every time you run the program
NOTE:
There are many methods of object serialization and the above example is one of the simplest, you can use dedicated object serialization modules like pickle and many others.
If you want it to work with if statement only. I think you need to put in a function and make to call itself which we would call it recursion.
def increment():
n=0
if True:
n+=1
print(n)
increment()
increment()
Note: in this solution, it would run infinitely.
Also you can use while loop or for loop as well.
When you rerun a program, all data stored in memory is reset. You need to save the variable somewhere outside of the program, on disk.
for an example see How to increment variable every time script is run in Python?
ps. Nowadays you can simply do += with a bool:
a = 1
b = True
a += b # a will be 2

make a global condition break

allow me to preface this by saying that i am learning python on my own as part of my own curiosity, and i was recommended a free online computer science course that is publicly available, so i apologize if i am using terms incorrectly.
i have seen questions regarding this particular problem on here before - but i have a separate question from them and did not want to hijack those threads. the question:
"a substring is any consecutive sequence of characters inside another string. The same substring may occur several times inside the same string: for example "assesses" has the substring "sses" 2 times, and "trans-Panamanian banana" has the substring "an" 6 times. Write a program that takes two lines of input, we call the first needle and the second haystack. Print the number of times that needle occurs as a substring of haystack."
my solution (which works) is:
first = str(input())
second = str(input())
count = 0
location = 0
while location < len(second):
if location == 0:
location = str.find(second,first,0)
if location < 0:
break
count = count + 1
location = str.find(second,first,location +1)
if location < 0:
break
count = count + 1
print(count)
if you notice, i have on two separate occasions made the if statement that if location is less than 0, to break. is there some way to make this a 'global' condition so i do not have repetitive code? i imagine efficiency becomes paramount with increasing program sophistication so i am trying to develop good practice now.
how would python gurus optimize this code or am i just being too nitpicky?
I think Matthew and darshan have the best solution. I will just post a variation which is based on your solution:
first = str(input())
second = str(input())
def count_needle(first, second):
location = str.find(second,first)
if location == -1:
return 0 # none whatsoever
else:
count = 1
while location < len(second):
location = str.find(second,first,location +1)
if location < 0:
break
count = count + 1
return count
print(count_needle(first, second))
Idea:
use function to structure the code when appropriate
initialise the variable location before entering the while loop save you from checking location < 0 multiple times
Check out regular expressions, python's re module (http://docs.python.org/library/re.html). For example,
import re
first = str(input())
second = str(input())
regex = first[:-1] + '(?=' + first[-1] + ')'
print(len(re.findall(regex, second)))
As mentioned by Matthew Adams the best way to do it is using python'd re module Python re module.
For your case the solution would look something like this:
import re
def find_needle_in_heystack(needle, heystack):
return len(re.findall(needle, heystack))
Since you are learning python, best way would be to use 'DRY' [Don't Repeat Yourself] mantra. There are lots of python utilities that you can use for many similar situation.
For a quick overview of few very important python modules you can go through this class:
Google Python Class
which should only take you a day.
even your aproach could be imo simplified (which uses the fact, that find returns -1, while you aks it to search from non existent offset):
>>> x = 'xoxoxo'
>>> start = x.find('o')
>>> indexes = []
>>> while start > -1:
... indexes.append(start)
... start = x.find('o',start+1)
>>> indexes
[1, 3, 5]
needle = "ss"
haystack = "ssi lass 2 vecess estan ss."
print 'needle occurs %d times in haystack.' % haystack.count(needle)
Here you go :
first = str(input())
second = str(input())
x=len(first)
counter=0
for i in range(0,len(second)):
if first==second[i:(x+i)]:
counter=counter+1
print(counter)
Answer
needle=input()
haystack=input()
counter=0
for i in range(0,len(haystack)):
if(haystack[i:len(needle)+i]!=needle):
continue
counter=counter+1
print(counter)

Bubble sort error with nested (high scores) list - python

For my software major work I have to create a program. In summary, the high scores list needs to be sorted before it can be written to file. To do this, I am using a bubble sort and I can't use the inbuilt sort function. The text file that the data is being read from is stored in a nested list. The text file looks like this:
NameOne
10
NameTwo
15
NameThree
9
This is the bubble sort code I have but does not work:
b_not_sorted = True
while b_not_sorted:
counter = 0
b_not_sorted = False
for counter in range(len(highest_scores) - 1):
if highest_scores[counter] < highest_scores[counter + 1]:
b_not_sorted = True
highest_scores[counter], highest_scores[counter+1] = highest_scores[counter+1], highest_scores[counter]
counter = counter + 1
I need the scores to be sorted from highest to lowest. Any help would be greatly appreciated and you will be credited appropriately in my program credits :). Thanks.
Here's a hint:
Check how many times your outer while loop is running. It should be running more than once, correct? What will always happen that causes the loop to exit, no matter what?
Try going through the code line by line and seeing what happens at every point.
The statement b_not_sorted = False at the end of the outer loop results in the outer loop exiting after executing only once. You need to move that statement to another part of your code. Try changing the name of b_not_sorted to I_still_need_to_go_through_the_list in your head:
Obviously in the first line:
while I_still_need_to_go_through_the_list:
it should be True, since you haven't gone over the list at all. You don't know if it's in order or not.
and after the line:
if highest_scores[counter] < highest_scores[counter + 1]:
Of course then we still need to make another pass, since we just made a change to the list and need to make sure no further changes are needed.
But what if no changes are made? I_still_need_to_go_through_the_list should be False then. Hmmm. If we put I_still_need_to_go_through_the_list = False right before the for loop, then it will be False unless we make changes to the list, which is exactly what we want.
You're doing b_not_sorted = False right after the first iteration, but it shouldn't be there! The algorithm just stops before it finishes the sorting.
You should instead do b_not_sorted = True only if highest_scores[counter] < highest_scores[counter + 1]
Also, the swapping code can look much nicer in Python. Instead of using temp_var just do this:
highest_scores[counter], highest_scores[counter+1] = highest_scores[counter+1], highest_scores[counter]
Python style guide suggests that you shoudn't write == True or == False in if statements. Do it like this:
while b_not_sorted:

Python list index out of range - finding local maxima

I have a dataset and am trying to work out where there are peaks in the data; a data point with a higher value than the point before and after it.
I have code which works for one dataset but now transferring it to another dataset brings up index out of range error for certain lines.
The code I have is:
for line in file.readlines():
peaks.append(0)
line = line.split(',')
time.append(float(line[0]))
TP.append(float(line[3]))
level.append(float(line[5]))
for i in range(len(level)-1):
i = i + 1
if (level[i] > level[i-1]) and (level[i] > level[i+1]):
peaks[i] = 1
noPeaks = noPeaks +1
print noPeaks
Yet for one line (so far) it says data is out of range - visually inspecting the data doesn't suggest this - the value is higher than the previous value but lower than the next so on a rising limb of the graph.
Any help would be great!
I cannot see your loop but the (level[i] > level[i+1]) suggests that you are forgetting to put
for i in range(1,len(list)-1)
key to note there is that -1 since you're doing that +1 and the range only goes to max-1 anyway.
Starting your loop at 0 would not throw an out of bounds error since list[-1] is perfectly legal in python. however, i dont think you want your first comparison to be list[-1] > list[0]
Due to edit,
You do not need to do the
i = i + 1
line in you're code, you will hit the length of the list because the for loop will also increment, causing an out of bounds error. Remove that line and it should work.
If you're looping over a list l usingi`, then you should take to handle both the first and last points specially:
for i in xrange(1, len(l) - 1):
# your check
When i is referring to the last element of level, level[i+1] will not exist and will raise IndexError.
I've rewritten this taking into account other people's answers:
for line in file:
line = line.split(',')
time.append(float(line[0]))
TP.append(float(line[3]))
level.append(float(line[5]))
peaks = [0]*len(level)
numPeaks = 0
for i in range(1, len(level)-1):
if level[i-1] < level[i] and level[i+1] < level[i]:
peaks[i] = 1
numPeaks += 1
print numPeaks

Categories