Python greater than or less than - python

I have an 'if-elif-else' block and if a value is within that range it is assigned a certain value. However it when I run it just assigns it the value in the else block. This is my code:
if mile < 300:
mileInfo['miles'] = 1
elif mile>=300 and mile <2000:
mileInfo['miles'] = 2
elif mile>=2000 and mile <5000:
mileInfo['miles'] = 3
else:
mileInfo['miles'] = 4
Mile returns a float, but I thought that this didn't matter as much as in Java for example.
Thanks

Maybe mile is a string containing a number? It will not be automatically converted.
>>> "1" < 100
False
>>> "1" == 1
False
You don't need to have the elif re-check that the previous if was false. If the value wasn't < 300, it is guaranteed to be >=300.

The issue was that 'mile' was a string and as pointed out by other members string is not automatically converted. So I changed code to:
mileInt = int(float(mile))
if mileInt < 300:
mileInfo['miles'] = 1
elif mileInt < 2000:
mileInfo['miles'] = 2
elif mileInt < 5000:
mileInfo['miles'] = 3
else:
mileInfo['miles'] = 4
Using print type(mile) helps check what the type is.

Related

Converting integers to Bytes in python

I am trying to change a number of integer parameters into bytes and putting them into a byte array. I have most of the required answer but the first 2 bytes in my byte array are different from the required answer. All the if statements in the code are for errors in integer format and the for loop decides how many bytes to allocate to the parameter depending on how big the integer is.
I have tried this on my mac and also Linux computers and I still get the same answer.
def composepacket (version, hdrlen, tosdscp, totallength, identification, flags, fragmentoffset, timetolive, protocoltype, headerchecksum, sourceaddress, destinationaddress):
if version != 4:
return 1
elif hdrlen < 0 or hdrlen > 15:
return 2
elif tosdscp < 0 or tosdscp > 63:
return 3
elif totallength < 0 or totallength > 65535:
return 4
elif identification < 0 or identification > 65535:
return 5
elif flags < 0 or flags > 7:
return 6
elif fragmentoffset < 0 or fragmentoffset > 8191:
return 7
elif timetolive < 0 or timetolive > 255:
return 8
elif protocoltype < 0 or protocoltype > 255:
return 9
elif headerchecksum < 0 or headerchecksum > 65535:
return 10
elif sourceaddress < 0 or sourceaddress > 4294967295:
return 11
elif destinationaddress < 0 or destinationaddress > 4294967295:
return 12
else:
list1 = [version,hdrlen,tosdscp,totallength,identification,flags,fragmentoffset,timetolive,protocoltype,headerchecksum,sourceaddress,destinationaddress]
final = bytearray()
for element in list1:
if element <= 255:
x = element.to_bytes(1,byteorder='big')
final += x
elif element <= 65535:
x = element.to_bytes(2,byteorder='big')
final += x
elif element <= 16777215:
x = element.to_bytes(3,byteorder='big')
final += x
elif element <= 4294967295:
x = element.to_bytes(4,byteorder='big')
final += x
return final
the test line is
print(composepacket(4,5,0,1500,24200,0,63,22,6,4711, 2190815565, 3232270145))
The expected answer is
bytearray(b'E\x00\x05\xdc^\x88\x00?\x16\x06\x12g\x82\x951M\xc0\xa8\x87A')
and the answer I get is
bytearray(b'\x04\x05\x00\x05\xdc^\x88\x00?\x16\x06\x12g\x82\x951M\xc0\xa8\x87A')
so the difference is the first two bytes where i get b'\x04\x05 where i should get b'E
It looks like you're working on building out a IPv4 packet header (you should've mentioned this in your question, assuming you know this to be the case).
Your logic currently takes the version and appends it to your byte array as a whole byte (8 bits), but it should only occupy the first 4 bits (or 1 nibble).
You're likely expecting the first byte to be "E" because 0b0100_0101 (that is, 4 represented as 4 bits followed by 5 represented as 4 bits, as shown in the diagram below) is 69 in decimal, which is the ASCII character for "E". So, if you were to run strings or hexdump on a TCPv4 packet, you might see "E" as the first character. However, the first byte should actually be 0x45, so you're confusing the representations of the initial byte.
Your code isn't quite right because it's treating the version and hdrlen as two separate bytes when they should be in the same byte as two separate nibbles.
So, you want something like:
first_byte = version << 4 | length
This should give you enough direction. Best of luck.

PYTHON parameter passing with lists

When passing a parameter into my function, it will not recognize the list and output the string.
The game is called pass the pigs, and it is required to output a state that the pig lands on.
I know in places that the code is inefficient, though this is due to the fact that I have been trying different methods that have no succeeded :(
Thanks in advance for any help!
Here is code:
norolls = int(input("Enter the number of rolls: "))
counter = 0
def roll(nothrows,counter):
rollList = []
while counter < nothrows:
rollrand = randint(0,100)
rollList.append(rollrand)
counter = (counter + 1)
return rollList
rollList = roll(norolls,counter)
rollList = list(map(int, rollList))
listlen = len(rollList)
def rollout(List, listpos, ListLen):
listpos = 0
for x in range(ListLen):
if List[listpos] == 1< 35:
print("Pink")
elif List[listpos] == 35 < 65:
print("Dot")
elif List[listpos] == 65< 85:
print("Razorback")
elif List[listpos] == 85 < 95:
print("Trotter")
elif List[listpos] == 95 < 99:
print("Snouter")
else:
List[listpos] == 99 < 100
print("Leaning Jewler")
listpos = (listpos + 1)
rollout(rollList, counter, listlen)
I'm assuming you want if List[listpos] == 1< 35 to mean List[listpos] is between 1 and 35, with 35 not being included.
The way to write that is:
if 1 <= List[listpos] < 35:
But, in your case, you don't really need a 3 level condition, since the only the first true if statement will run. So, you can just simply do:
if List[listpos] < 35:
print("Pink")
elif List[listpos] < 65:
...
and so on.
I have too low reputation to comment, but I'm going to try and clarify the code a little and give my answer.
For starters, one thing you should know is that list is a reserved name, so I don't recommend passing it as an argument to any function. You should be passing rollList to rollout(), since that is the list that you are creating. The way to pass a list as an argument is like this:
list_name = [1,2,3,4,5]
def function_name(myList=[]):
for x in myList:
print x
function_name(list_name)
Note the myList=[] in the function definition.
I would also get rid of counter and listlen as arguments, since you are setting counter to 0 at the beginning of the function, and listlen can be found with the len() function.
Secondly, for your equality statements, type them in like this:
if list_name[listpos] >= 1 and list_name[listpos] < 35
I'm sure there's a shorter way to do it, but this would help you visualize it as a range of values.
Since there are only 100 possible rolls (you do not assign an interpretation to 0) there is an alternative approach: replace the if-elif-else change with a lookup table mapping rolls to names. The code below does this. It also creates a list of rolls with a list comprehension.
from random import randint
rollmap = [None]
for sublist in (35*['Pink'], 30*['Dot'], 20*['Razorback'],
10*['Trotter'], 4*['Snouter'], 1*['Leaning Jewler']):
rollmap.extend(sublist)
n = int(input("Enter the number of rolls: "))
rolls = [randint(1, len(rollmap-1)) for i in range(n)]
for roll in rolls:
print(rollmap[roll])

(Python) List index out of range

So, in a Tic-Tac-Toe game I was developing I decided to make the AI a random number, as a joke. Here are the specifics:
board = []
def createboard():
board.append(['_',' ','_',' ','_'])
board.append(['_',' ','_',' ','_'])
board.append(['_',' ','_',' ','_'])
...
while bot_move_val == False or bot_move_made == False:
bot_move_row = 0
bot_move_col = 0
bot_move_row_rand = randint(0,3)
bot_move_col_rand = randint(0,3)
if bot_move_row_rand == 1:
bot_move_row = 0
bot_move_made = True
elif bot_move_row_rand == 2:
bot_move_row = 2
bot_move_made = True
elif bot_move_row_rand == 3:
bot_move_row = 4
bot_move_made = True
if bot_move_col_rand == 1:
bot_move_col = 0
bot_move_made = True
elif bot_move_col_rand == 2:
bot_move_col = 2
bot_move_made = True
elif bot_move_col_rand == 3:
bot_move_col = 4
bot_move_made = True
if bot_move_row > 4 or bot_move_row < 0 or bot_move_col > 4 or bot_move_col < 0 or board[bot_move_row][bot_move_col] == 'X':
break
else:
bot_move_val = True
The code generates this error:
Traceback (most recent call last):
File "C:\Users\[DATA EXPUNGED]\gamestravaganza.py", line 250, in <module>
if bot_move_row > 4 or bot_move_row < 0 or bot_move_col > 4 or bot_move_col < 0 or board[bot_move_row][bot_move_col] == 'X':
IndexError: list index out of range
As far as I can tell, bot_move_row and bot_move_col are not in the list board, despite being at most as long as the list by definition.
Unlike some other places in Python (like the range method), random.randint(a,b) includes the upper bound. So 3 is a possible outcome, and since the board list is zero-indexed, that would be out of range.
Or as the docs put it :
random.randint(a, b)
Return a random integer N such that a <= N <= b.
So you should use randint(0,2) instead.
You have only 3 rows.
The if condition should be
if bot_move_row > 2 or bot_move_row < 0 or bot_move_col > 4 or bot_move_col < 0 or board[bot_move_row][bot_move_col] == 'X':
break
Assuming at some point you call the function createboard to build your board then there are a few places that are causing difficulty.
The board you create has 3 rows and 5 columns, but you are translating both rows and columns in the same way (ie anticipating equal numbers of rows vs columns). I would keep them both the same at 3.
As stated elsewhere your calls to randint select from a range with 4 numbers (0, 1, 2, 3) as randint includes both endpoints.
Finally your if condition tests that values are within a range that you specify yourself, making it less clear what you are really testing for.
To get the same basic functionality as what you seem to intend above you could rewrite it as:
# Create your board
board = [['_','_','_'], ['_','_','_'], ['_','_','_']]
#Handle one move
def botMove():
while False:
# Attempt to choose a row/column
row = randint(0, 2)
column = randint(0, 2)
if board[row][column] == '_':
# Randomly selected row/column is Empty, mark it as the bots and return
board[row][column] = 'X'
break
This of course does not handle what happens when the board is full (as written above it would loop indefinitely). To flesh out the game you would need something to handle user input (presuming player vs computer) and something to determine winner/draw.

Checking whether variable is between a couple of pairs of numbers? (Python 3.3.3)

I suspect this question will have been asked before, so feel free to link, but I couldn't find it.
I want to write a program that will check if my variable a is between two certain numbers, otherwise check the next pair.
IE in psuedocode:
Check if variable is between 1000 and 2000
If it is, do this.
Else, check if variable is between 2000 and 3000
If it is, do this.
Else check if variable is between 3000 and 4000
If it is, do this.
I suspect it's easy, but I really can't seem to figure it out. Any help would be appreciated.
You can use chained comparisons:
if 1000 <= foo < 2000:
do_bar()
elif 2000 <= foo < 3000:
do_quux()
variable = 1500
if 1000 < variable < 2000:
print ('1')
elif 2000 < variable < 3000:
print ('2')
elif 3000 < variable < 4000:
print ('3')
You don't need the second comparison all the time, since its implicitly satisfied because of the earlier comparisons:
if var < 1000:
doLower1000()
elif var < 2000:
doThis()
elif var < 3000:
doThat()
elif var < 4000:
doSomethingelse()
else:
doSomethingBigger4000()
You may need a list to store the boundaries:
In [29]: rang = range(0, 5001, 1000)
...: foo = 1234
...: for i, v in enumerate(rang):
...: if v <= foo < rang[i+1]:
...: print (v, rang[i+1]), foo
...:
(1000, 2000) 1234

Not sure about python function

I am only starting and getting mad over this function (it gives me the wrong outputs):
def rental_car_cost(days):
x = 40
if days < 2:
return days*x
elif days >= 3:
return days*x-20
elif days>= 7:
return days*x-50
else:
print "Please enter nr of days"
Also, how do I make sure that a number is entered for "days"?
Not sure what you are expecting, however change the order of the elif conditions:
def rental_car_cost(days):
if isinstance(days, int):
x = 40
if days < 2:
return days*x
elif days >= 7:
return days*x-50
elif days>= 3:
return days*x-20
else:
print "Please enter nr of days"
The days>= 7 and else clauses never trigger, because the earlier days >= 3 triggers on the same inputs. if/elif/else clauses are processed in order until one of them is triggered.
What you need are clauses for days < 2, days < 7 and else.
To detect non-numbers, start with
if not isinstance(days, int):
which does a type check for integers.
rental_car_cost(2) should equal 60
But, none of your if statements will match 2. 2 isn't less than 2, nor is it greater than or equal to 3, nor is it greater than or equal to 7. Follow the advise from the other two answers by larsmans and Ankit Jaiswal also, but I'm assuming 2 should match the days*x-20 part. Just change elif days >= 3: to elif days >= 2:.

Categories

Resources