I am trying to do something with lists. I would like to learn this.
So let's say I have this
_list = [1,2,3]
I want to check values of elements inside the list while iterating,
for x in range(len(_list)):
if _list[x] == _list[x+1]:
print(_list[x])
But the problem here is it throws an error while checking _list[-1] how do i solve this?
I tried -
if _list[x] != _list[-1]
assert _list[3]
These doesnt seem convenient,
I am thinking of trying try and except block but is any other option is available?
Make your loop go till len(_list) -1:
for x in range(len(_list) - 1):
if _list[x] == _list[x+1]:
print(_list[x])
Related
Current assignment is building a basic text adventure. I'm having trouble with the following code. The current assignment uses only functions, and that is the way the rules of the assignment state it must be done.
def make_selections(response):
repeat = True
while repeat == True:
selection = raw_input('-> ')
for i, v in enumerate(response):
i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
if selection == i:
print v[1]
else:
print "There's an error man, what are you doing?!?!?"
firstResponse = 'You chose option one.'
secondResponse = 'You chose option two.'
thirdResponse = 'You chose option three.'
responses = [(0, firstResponse), (1, secondResponse),( 0, thirdResponse)]
make_selections(responses)
My intention in that code is to make it so if the user selects a 1, it will return firstResponse, if the user selects 2 it will return secondResponse, etc.
I am basically just bug testing the code to make sure it produces the appropriate response, hence the "Error man..." string, but for some reason it just loops through the error message without printing the appropriate response string. Why is this?
I know that this code is enumerating the list of tuples and I can call them properly, as I can change the code to the following and get the expected output:
for i, v in enumerate(response):
i += 1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
print i, v
Also, two quick asides before anyone asks:
I know there is currently no way to get out of this while loop. I'm just making sure each part of my code works before I move on to the next part. Which brings me to the point of the tuples.
When I get the code working, a 0 will produce the response message and loop again, asking the user to make a different selection, whereas a 1 will produce the appropriate response, break out of the loop, and move on to the next 'room' in the story... this way I can have as many 'rooms' for as long of a story as I want, the player does not have to 'die' each time they make an incorrect selection, and each 'room' can have any arbitrary amount of options and possible responses to choose from and I don't need to keep writing separate loops for each room.
There are a few problems here.
First, there's no good reason to iterate through all the numbers just to see if one of them matches selection; you already know that will be true if 1 <= selection <= len(response), and you can then just do response[selection-1] to get the v. (If you know anything about dicts, you might be able to see an even more convenient way to write this whole thing… but if not, don't worry about it.)
But if you really want to do this exhaustive search, you shouldn't print out There is an error man after any mismatch, because then you're always going to print it at least twice. Instead, you want to only print it if all of them failed to match. You can do this by keeping track of a "matched" flag, or by using a break and an else: clause on your for loop, whichever seems simpler, but you have to do something. See break and continue Statements, and else Clauses on Loops in the tutorial for more details.
But the biggest problem is that raw_input returns a string, and there's no way a string is ever going to be equal to a number. For example, try '1' == 1 in your interactive interpreter, and it'll say False. So, what you need to do is convert the user's input into a number so you can compare it. You can do that like this:
try:
selection = int(selection)
except ValueError:
print "That's not a number!"
continue
Seems like this is a job for dictionaries in python. Not sure if your assignment allows this, but here's my code:
def make_selections(response):
selection = raw_input('-> ')
print response.get(selection, err_msg)
resp_dict = {
'1':'You chose option one.',
'2':'You chose option two.',
'3':'You chose option three.'
}
err_msg = 'Sorry, you must pick one of these choices: %s'%sorted(resp_dict.keys())
make_selections(resp_dict)
The problem is that you are comparing a string to an integer. Selection is raw input, so it comes in as a str. Convert it to an int and it will evaluate as you expect.
You can check the type of a variable by using type(var). For example, print type(selection) after you take the input will return type 'str'.
def make_selections(response):
repeat = True
while repeat == True:
selection = raw_input('-> ')
for i, v in enumerate(response):
i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
if int(selection) == i:
print v[1]
else:
print "There's an error man, what are you doing?!?!?"
...
def splitMunipulation(p,threshold=5000):
runs=[];i=0
while i<len(p):
l=[];i+=1
print i,p[i]
while p[i]!=press(0,1,0):
l.append(p[i]);i+=1
else:
runs.append(l)#here i points to another (0,1,0)
return runs
...
record=splitMunipulation(record)
'''
Output:
1 <__main__.press instance at 0x046690A8>
File "H:\mutate.py", line 28, in splitMunipulation
while p[i]!=press(0,1,0):
IndexError: list index out of range
pressis a class
and since print p[i] works well,why p[i] is considered out of range?
Really don't get what's going on
'''
so, a few things..
Firstly, your code is very... unpythonic. This isn't C, so you don't need to use while loops for iteration, and don't use semicolons to separate multiple commands on one line in Python. Ever. Also, the while...else format is confusing and should be avoided.
If you look at the first few 'lines' of your while loop,
while i<len(p):
l=[];i+=1
You keep i below the length of p, but you immediately increase i's value by one. As such, when i=len(p) - 1, you will make i one larger, len(p). So when you try to access p[i], you are trying to access a value that doesn't exist.
Fixing those issues, you would get:
...
def splitMunipulation(p,threshold=5000):
runs=[]
for i in p:
l=[]
print i
if i != press(0,1,0):
runs.append(i)
return runs
...
record=splitMunipulation(record)
while p[i]!=press(0,1,0):
l.append(p[i]);i+=1
The variable i gets incremented in this loop until p[i]!=press(0,1,0). Since nothing is happening to make p longer, or to test that i is not greater than the length of p, it is easy to see how the index could get out of range.
len returns the length, not the last index. If l=[1,2,3], then len(l) returns 3, but l[3] is out of range.
so you should use
while i<len(p)-1
or better yet:
for i in range(len(p)):
I am attempting to find objects on the screen, see if they exist, and if so, select them. Using the Sikuli library to run this little automation.
while True:
if exist("image/one.png", "image/two.png", "image/three.png"):
click ("image/one.png", or "image/two.png", or "image/three.png")
break
I get SyntaxError: mismatched input 'or' expecting RPARENa I've done a quick search but there is nothing I saw relevant to my particular issue.
I've even tried
while True:
if exist("image/one.png", or "image/two.png", or "image/three.png"):
click ("image/one.png", or "image/two.png", or "image/three.png")
break
And that results in the same error.
#Stephan: New code snippet with error.
class gameImages():
imageFiles = ["one.png", "two.png", "three,png"]
for imageFile in imageFiles:
if exists(imageFile):
click(imageFile)
The Error now, :
NameError: name 'imageFiles' is not defined
for imageFile in imageFiles:
if exists(imageFile):
click(imageFile)
Your while loop isn't doing anything, and neither is your break statement. This might do what you want, assuming I understand what you want to do.
After reading a little of the Sikuli docs, I think this might also do what you want.
for impath in ("image/one.png", "image/two.png", "image/three.png"):
match = exists(impath)
if match:
click(match.getTarget())
Even easier, this is a perfect use of filter(ifexist,imageFiles). You then know that all >=0 elements in the return of filter can be used :). And it's more concise and clearly conveys your intent - much nicer to read then a chain of for's and if's
a = range(10)
# [1,2,3,4,5,6,7,8,9]
print filter(lambda x: x > 5, a)
# [6,7,8,9]
Also the or is a logical operator:
e.g.
a = 5
b = 6
c = 5
if( (a==c) or (b==c) ):
print 'c is repeated'
# c is repeated
your use of the or here makes no sense as it doesn't have operands to operate on - these can even be two objects, e.g.
1 or 2 since anything can be cast to a boolean
a concise way to do what you want is:
//imagepaths = your list of imagepaths
map(lambda x: click(x.getTarget()), filter(exists, imagepaths))
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:
def rot_dig(x):
y=''
output=[x]
listing=list(x)
for i in range(1,len(x)):
listing.append(listing[0])
del(listing[0])
for i in listing:
y=y+i
output.append(y)
y=''
return output
import math
def prime_is(x,prime):
for m in prime:
if m<=math.sqrt(x):
if x%m==0:
return False
else:
return True
prime=[2]
for x in range(3,1000000):
if prime_is(x,prime):
prime.append(x)
primestr=[]
for x in prime:
primestr.append(str(x))
sums=0
for x in primestr:
count=0
for y in rot_dig(x):
if y in primestr:
count+=1
if count==len(x):
sums+=1
else:
for y in rot_dig(x):
if y in primestr:
primestr.remove(y)
print sums
When run with the bold code the solutions miss the final rotation. So if it looks at say 1193, it includes 1193, 3119, 9311 but not 1931. I have spent a while trying to work out why but I don't get it.
I have since edited the code to make it much quicker and solved the problem I had by simply removing the block of code, but I can't understand why it happens since surely that block of code will only be executed on non circular primes.
It's probably because your outer loop is for x in primestr: and the marked code removes items from primestr. You don't want to change primestr while looping over it that way. You could use a loop like while i < len(primestr) instead.
Some other improvements would be to compute sqrt outside the loop; to use a list comprehension instead of a loop to create primestr; and especially to use string slicing in rot_dig, it's way more complicated than it needs to be.