Python - can't convert to int - python

My entire code is below (didn't want to miss anything). For some reason I keep getting an error where I can't convert a float to an int?
import math
def getRange(input):
if (1 <= input < 10):
return [1,1,9]
elif (10 <= input < 190):
return [2,10,99]
elif (190 <= input < 2890):
return [3,100,999]
elif (2890 <= input < 38890):
return [4,1000,9999]
elif (38890 <= input < 488890):
return [5,10000,99999]
elif (488890 <= input < 5888889):
return [6,100000,999999]
def getDigit(input):
workingRange=getRange(input)
multi_digit_dec = ((input-workingRange[1])/workingRange[0])+workingRange[1]
multi_digit_float = math.floor((input-workingRange[1])/workingRange[0])+workingRange[1]
print multi_digit_float
multi_digit_int = input(multi_digit_float)
decimal_remainder = multi_digit_int - multi_digit_dec
## digit_id = decimal_remainder * len(str(multi_digit_int))
## actual_digit = str(multi_digit_dec)[digit_id]
## return actual_digit
getDigit(100)
My error is:
Traceback (most recent call last):
File "C:\Users\Samuel\Desktop\Python\concatenate string of variables and product values.py", line 29, in <module>
getDigit(100)
File "C:\Users\Samuel\Desktop\Python\concatenate string of variables and product values.py", line 22, in getDigit
multi_digit_int = int(multi_digit_float)
TypeError: 'int' object is not callable
>>>
Code updated above to reflect change of variable called int to input

The problem is that you're using int as a variable name, and that shadows the built-in function. Rename the variable.
In general, it's worth familiarizing oneself with the names of the built-in functions, to avoid this type of problems.

Don't use int as variable name (function getDigit).

In your stack of elif statements, if you start by testing if the input number is less than 1, then there's no need to check the lower ends of ranges other than the first. This will cut out half of the verbiage in the elif's. Also, it is more compact to use a loop for tests like this. For example, the following code produces the output shown below it.
def getRange(k):
if k < 1: return None
e = 1
for d in [10, 190, 2890, 38890, 488890, 5888889]:
if k<d:
return [e, 10**(e-1), 10**e -1]
e += 1
return None
for i in range(14):
print '{:8} {:20}'.format(i * 3**i, getRange(i * 3**i)),
if i&1: print
Output:
0 None 3 [1, 1, 9]
18 [2, 10, 99] 81 [2, 10, 99]
324 [3, 100, 999] 1215 [3, 100, 999]
4374 [4, 1000, 9999] 15309 [4, 1000, 9999]
52488 [5, 10000, 99999] 177147 [5, 10000, 99999]
590490 [6, 100000, 999999] 1948617 [6, 100000, 999999]
6377292 None 20726199 None

I think you want:
multi_digit_int = math.floor(multi_digit_float)
Also, don't use int as a variable name.

The problem with the line multi_digit_int = input(multi_digit_float) in your updated code is that the argument input in def getDigit(input): is hiding the built-in input() function. Since you calle getDigit with an argument of 100, inside the function input is an int instance so the input(multi_digit_float) part is being interpreted as 100(multi_digit_float), i.e. an int calling something.

Related

Why am I unable to compare an iterated value without assigning it to a variable first?

I already have a solution to this Python code problem, but to try to be a better coder I am trying to better understand why the problem exists in the first place.
This works:
numbersA = [45, 22, 25, 73, 10, 33]
for i in range(len(numbersA)):
numz = numbersA[i]
if numz % 3 == 0:
numbersA[i] = "buzz"
if numz % 5 == 0:
numbersA[i] = "fizz"
print(numbersA)
But this one:
numbersB = [45, 22, 25, 73, 10, 33]
for i in range(len(numbersB)):
if numbersB[i] % 3 == 0:
numbersB[i] = "buzz"
if numbersB[i] % 5 == 0:
numbersB[i] = "fizz"
print(numbersB)
gives an error:
Traceback (most recent call last):
File "...", line 18, in <module>
if numbersB[i] % 5 == 0:
TypeError: not all arguments converted during string formatting
My question is why?
Let's look at the first iteration, i.e. i = 0. The number 45 is divisible by 3. So the first if is executed.
Inside it, you change the list in-place and now numbersB[0] = "buzz".
In the following line, you try to do if numbersB[0] % 5 == 0 which is now equivalent to if "buzz" % 5 == 0 which is a way to do string formatting, and this is why you get the error.
In Python it is rarely necessary to iterate over indices. In your case, enumerate will make your code correct and readable:
numbersB = [45, 22, 25, 73, 10, 33]
for i, num in enumerate(numbersB):
if num % 3 == 0:
numbersB[i] = "buzz"
if num % 5 == 0:
numbersB[i] = "fizz"
print(numbersB)
You have a problem in your code.
If the first "if" is satisfied, the value at that location becomes a string, "buzz". Then, when the second "if" is checked, you're finding the remainder of a string and an integer, an operation that is not defined.
in code 2, you are modifing the existing list and then checking that modified value against % operation.
eg for value 45 list is, [45,1,2,3] say, now for condition 1 ie if value%3 is True
so numberB[i]%3==0 ie 45%3==0 is true, so you are modifing it to 'fizz'.
numverB[0]='buzz' now list become ['fizz', 1,2,3..]
now you are testing next condition ie % by 5, so 'buzz'%5 is giving error as mod operation not work on str.
In simple term, code 1 you are using a tempory data value which hold the index value in list, and testing the condition on that variable and then modifying the list value.
in code2, you directly checking against index value in list, and based on condition meet, modifying the internal list value, so due to, value which divided by 3 and 5, value first modified when it is divided by 3 to 'buzz' then when you testing value at that index (which become 'buzz' now not the int value) due to which you cant divide string by integer . so you are getting the error
numbersB = [45, 22, 25, 73, 10, 33]
for i in range(len(numbersB)):
print('value at index {} is {} before any operation'.format(i,numberB[i]))
if numbersB[i] % 3 == 0:
numbersB[i] = "buzz"
print('value at index {} is {} after dividing by 3 operation'.format(i,numberB[i]))
if numbersB[i] % 5 == 0:
numbersB[i] = "fizz"
print('value at index {} is {} after dividing by 5 operation'.format(i,numberB[i]))
print(numbersB)
run above code, and you can see how the value changes in code2

Rewriting R's density() (not really)

In response to this question, I took upon the challenge to make my understanding on R's density() function.
Since I'm pretty much very new to R, I have no ideas about vectors regarding the c() function, which made me use a list as the closest form.
I would make this function:
def density(x, bw, adjust):
bw2 = None
result = 0
if bw == "nrd0":
bw2 = 31.39367
else:
print("No such bandwidth.")
for i in range[len(x)]:
x[i] = x[i] * bw2
for i in range[len(x)]:
result = result + x[i]
return result * adjust
And I wanted to test it:
x = [1, 3, 5]
kern = density(x, "nrd0", 1)
print(kern)
And I gained 2 errors, the main one being a TypeError.
If you want to look into it further, here's the whole terminal message:
Traceback (most recent call last):
File "density.py", line 15, in <module>
kern = density(x, "nrd0", 1)
File "density.py", line 8, in density
for i in range[len(x)]:
TypeError: 'type' object is not subscriptable
How do I fix the TypeError?
for i in range[len(x)]:
x[i] = x[i] * bw2
You have range with [] while it should be (). Try to change it.
Below is an example:
l = [10, 20, 30, 40]
for i in range(len(l)):
print(l[i], end =" ")
print()

If I take a user supplied value as a function parameter, how do I make it a global variable?

I'm writing a program that can riffle shuffle a given sequence (list l), m times. My function takes in the list l and the number m as inputs but Ive defined the shuffle itself for one shuffle and then used a for loop to do it m times. However, now the for loop does not take the user assigned value of m.
I'm a Python noob so it's likely I'm missing a simple thing. Ive tried using global m, to (re)define m within my function but either I dont know how to do it, or it doesn't seem to work.
def riffle_shuffle(l, global m):
#global m goes here?
r = np.random.binomial(len(l),0.5)
sd1 = l[:r]
d2 = l[r:]
fl = []
c = [sd2,sd1]
l2 = sd2+sd1
for i in range(1,len(l) + 1):
x = [sd2,sd1]
y = [(len(sd2))/(len(l) - i+1),(len(sd1))/(len(l) - i+1)]
a = choices(x,y)
a1 = a[0][0]
fl.append(a1)
#Deck Split is c
#Sub decks are',c
#Probabilities are',y
#Deck chosen is',a
#fl
if a1 in sd1:
sd1.remove(a1)
elif a1 in sd2:
sd2.remove(a1)
return fl,m
for j in range(1,m+1):
fl = riffle_shuffle(fl)
return fl
I've gotten errors that say m is not defined, invalid syntax, the following error message. I don't know what this last one means.
'maximum recursion depth exceeded in comparison'
Any help is much appreciated, thanks!
EDIT: I missed the for loop I'd mentioned in the description. It's up now sorry.
So... You want method that do riffle shuffle m times, right?
There is some problems with your code :
First, return is outside of the function.
Second, you call your function in your function, without breaking condition : So the function will call the function, and that will call the function again, and again, and so on, until error occurs. That is maximum recursion depth exceeded in comparison.
Third, you have use np.random.choice like this : np.random.choice(x, p=y). Otherwise, python don't know y is probabilities, and it will interpret it as second argument : size of the output. So error occurs here.
This might be the code you want to write :
import numpy as np
def riffle_shuffle(l, m):
if m == 0:
return l
else:
fl = []
r = np.random.binomial(len(l), 0.5)
sd1 = l[:r]
sd2 = l[r:]
c = [sd2,sd1]
l2 = sd2+sd1
for i in range(1,len(l) + 1):
x = [sd2,sd1]
y = [(len(sd2))/(len(l) - i+1), (len(sd1))/(len(l) - i+1)]
a = np.random.choice(2, p=y)
a = x[a]
a1 = a[0]
fl.append(a1)
#Deck Split is c
#Sub decks are',c
#Probabilities are',y
#Deck chosen is',a
#fl
if a1 in sd1:
sd1.remove(a1)
elif a1 in sd2:
sd2.remove(a1)
fl = riffle_shuffle(fl, m - 1)
return fl
a = riffle_shuffle([1, 2, 3, 4, 5, 6, 7, 8], 3)
print(a)
#output : [5, 6, 1, 7, 4, 8, 2, 3] (can be changed)
As you did, I called the function 'recursively' - call function in function - with break condition.
In this way, you don't have to use global variable - using global variable is not good idea in most situation.
And, about your question(How can I make user-supplied value to global variable), you can do something like this.
a = 0
def foo(m):
global a
a = m
#and your code here...

What is an unorderable error and why can't I compare the values in my lists?

I'm writing a program that plays War the card game. Each player has a set of cards, and I've gotten it to deal randomly fine. I need it to be able to compare two values in the list and do something depending on their integer values. I've written the code as follows:
from random import *
def main():
cards = [1,2,3,4,5,6,7,8,9,10,11,12]*4
p1 = []
p2 = []
while len(cards) != 0:
m = randint(0,len(cards))
p1.append(cards[m-1])
del cards[m-1]
n = randint(0,len(cards))
p2.append(cards[n-1])
del cards[n-1]
print(p1, p2)
def game():
if p1[0] > p2[0]:
p1.append(p2[0])
del p2[0]
elif p2[0] > p1[0]:
p2.append(p1[0])
del p1[0]
else:
if len(p1) > len(p2):
print(p1, p2)
for i in range(1,len(p2)):
if int(p1[i]) > int(p2[i]):
p1.append(p2[0:i])
del p2[0:i]
if int(p2[i]) > int(p1[i]):
p2.append(p1[0:i])
del p1[0:i]
else:
continue
else:
print(p1, p2)
for i in range(1,len(p2)):
if int(p1[i]) > int(p2[i]):
p1.append(p2[0:i])
del p2[0:i]
if int(p2[i]) > int(p1[i]):
p2.append(p1[0:i])
del p1[0:i]
else:
continue
while len(p1) > 0 and len(p2) > 0:
game()
print("player 1 has", p1, " and player 2 has ", p2)
if len(p1) == 0:
print("Player 2 wins")
elif len(p2) == 0:
print("Player 1 wins")
input("Press enter to exit")
But each time I run it it plays fine until it gets a tie. As soon as it's comparing any values other than the first two it prints this error:
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
main()
File "C:\Users\Jesse\Documents\Jesse\homework\Computer Science\Programs\War.py", line 52, in main
game()
File "C:\Users\Jesse\Documents\Jesse\homework\Computer Science\Programs\War.py", line 32, in game
if p1[i] > p2[i]:
TypeError: unorderable types: int() > list()
What does this mean? And what is the difference between comparing the first two and any other two?
Seems like you are using Python3. Python2 would allow you to compare int and list, but it wasn't very useful and would mask a bug like you have here
I think perhaps you mean to use extend here
p1.append(p2[0:i])
and here
p2.append(p1[0:i])
instead of append
A couple of misc. tips (you've got an answer to your direct question though):
m = randint(0,len(cards))
p1.append(cards[m-1])
del cards[m-1]
You're creating work for yourself here. There's a handy function in the random module called randrange which means you don't have to worry about subtracting one (which incidently could mean if you get 0, then you'll have -1, which is the last element of the list, and leads to problems (ie, you're fixing the deck))... Also, lists have a handy method called pop which removes from the list the element from a certain position, so the above could be:
p1.append(cards.pop(randrange(len(cards))))
However, since you're dealing with cards, there's a very aptly named method (again in random), called shuffle:
from random import shuffle
cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ,12] # * 4
shuffle(cards)
# [3, 4, 11, 9, 6, 2, 12, 5, 8, 1, 10, 7]
Using that, you can do much less "manual work", so let's deal the cards...:
>>> p1hand, p2hand = cards[::2], cards[1::2]
>>> p1hand
[3, 11, 6, 12, 8, 10]
>>> p2hand
[4, 9, 2, 5, 1, 7]
The issue you are having is derived from this line (and its variants):
p1.append(p2[0:i])
What this does is append a slice from the list p2 onto the end of p1. That is, it adds a new list as a member of the existing list. This causes trouble later when you try to do a comparison between an integer in one list and a sub-list in the other.
Instead, you want to use extend which will add the members of the slice onto the end of the other list.
p1.extend(p2[0:i]) # note that the 0 here is not necessary!
This should fix the issue.

What is wrong with my merge sort in python?

I am trying to write merge sort and stuck here.
What is the problem here with my code? I am trying to implement it without referring any resources and unnecessarily writing this line since some dumb rule in Stackoverflow forces to me explain my code.
def merge_sort(A):
if len(A) <= 1:
return A
#split list in 2
mid = len(A)/2
B = A[:mid]
C = A[mid:]
B = merge_sort(B)
C = merge_sort(C)
#merge
result = []
while len(B) > 0 and len(C) > 0:
if B[0] > C[0]:
result.append(C.pop(0))
else:
result.append(B.pop(0))
if len(B) > 0:
result.extend(merge_sort(B))
else:
result.extend(merge_sort(C))
print merge_sort([8, 2, 1, 1, 4, 45, 9, 3])
I get this error:
Traceback (most recent call last):
File "merge_sort.py", line 31, in <module>
print merge_sort([8, 2, 1, 1, 4, 45, 9, 3])
File "merge_sort.py", line 11, in merge_sort
B = merge_sort(B)
File "merge_sort.py", line 16, in merge_sort
while len(B) > 0 and len(C) > 0:
TypeError: object of type 'NoneType' has no len()
You merge_sort() function needs to
return result
at the end but it does not. Functions return None by default and this is why you get the error.
You forgot to write return result at the end of the function. Without that line, the function returns None, which eventually leads to a len(None) and the subsequent TypeError: object of type 'NoneType' has no len().

Categories