The counters in functions "getWeight" and "getPrice" do not go up as I planned. It always reverts back to the original integer, which applies to whatever value you input in the console. How can I fix this error?
import math
class ShippingCharges:
def __init__(self, userInput=None, packNum= None, packPrice = None):
self.userInput = userInput
self.packNum = packNum
self.packPrice = packPrice
def getPrice (self):
if (self.userInput <= 2):
print("Package", self.packNum," will cost $1.10 per pound\n")
elif(6 >= self.userInput and 2 < self.userInput):
print("Package", self.packNum, " will cost $2.20 per pound\n")
elif(10 >= self.userInput and 6 < self.userInput):
print("Package", self.packNum, "will cost 3.70 per pound\n")
elif(self.userInput > 10):
print("Package ", self.packNum, "will cost $3.80 per pound\n")
def getWeight(self):
return self.userInput + self.userInput
def getPrice(self):
if (self.userInput <= 2):
return self.pacPrice + 1.10
elif(6 >= self.userInput and 2 < self.userInput):
return self.packPrice+ 2.20
elif(10 >= self.userInput and 6 < self.userInput):
return self.packPrice + 3.70
elif(self.userInput > 10):
return self.packPrice + 3.80
def displayInfo(self):
print("The total price is: %.2f" % self.getPrice())
print("The total weight of packages is: %.2f" % self.getWeight())
def main():
x = 0
userResponse = "y"
packNum = 1
packPrice = 0
while(x != 1):
userInput = eval(input("Enter the weight of package in pounds: "))
if(userInput >0):
package = ShippingCharges(userInput, packNum, packPrice)
packNum = packNum + 1
userResponse = input("Would you like to send another package? y/n \n")
if(userResponse == "n"):
break
elif(userInput <= 0):
print("Package must be greater than 0")
package.displayInfo()
main()
If I type "5" 5 times as the userInput, why is the output:
The total charge for all packages is: 2.2
The total weight of all packages is: 10.00
Why is it not?
The total charge for all packages is: 11.00
The total weight of all packages is: 25.00
Related
link to assignment**
This is what I have so far but I cant figure out the rest. I am having a hard time solving the rest of the problem. Like calling sum variables from other functions. If anyone could lend a hand I would appreciate it, thank you.
#hello function
def hello():
print("***************************************")
print("*** WELCOME TO THE MAGIC PROGRAM *****")
print("***************************************")
#get_highest function
def get_highest():
first_num = int(input("\nEnter first number: "))
second_num = int(input("Enter second number: "))
largest_num = 0
if first_num > 0 and second_num > 0 and first_num >= second_num:
print("\nThe largest number is: ", first_num)
first_num = largest_num
elif second_num > 0 and first_num > 0 and second_num >= first_num:
print("\nThe largest number is:", second_num)
second_num = largest_num
else:
print("\nERROR: Both numbers must be greater than 0!")
print("Try again.")
get_highest()
return largest_num
#odd_or_even function
def odd_or_even(largest_num):
largest_num = get_highest()
if (largest_num % 2 == 0):
print(largest_num, " is an EVEN NUMBER!!")
else:
print(largest_num, " is an ODD NUMBER!!")
#print_magic function
def print_magic(largest_num):
largest_num = get_highest()
total = 0
for x in range(1, largest_num):
total = total + x
hello()
get_highest()
odd_or_even()
I'm trying to apply the REINFORCE algorithm (with SoftMax policy, undiscounted Gt with baseline) on David Silver's easy21, and I am having problems with the actual implementation. When compared to a pure MC approach, the produced result does not converge to Q*. Here is the related code:
hit = True
stick = False
actions = [hit, stick]
alpha = 0.1
theta = np.random.randn(420).reshape((420,1))
def psi(state, action):
if state.player < 1 or state.player > 21:
return np.zeros((420, 1))
dealers = [int(state.dealer == x + 1) for x in range(0, 10)]
players = [int(state.player == x + 1) for x in range(0, 21)]
actions = [int(action == hit), int(action == stick)]
psi = [1 if (i == 1 and j == 1 and k == 1) else 0
for i in dealers for j in players for k in actions]
return np.array(psi).reshape((420, 1))
def Q(state, action, weight):
return np.matmul(psi(state, action).T, weight)
def softmax(state, weight):
allQ = [Q(state, a, weight) for a in actions]
probs = np.exp(allQ) / np.sum(np.exp(allQ))
return probs.reshape((2,))
def score_function(state, action, weight):
probs = softmax(state, weight)
expected_score = (probs[0] * psi(state, hit)) + (probs[1] * psi(state, stick))
return psi(state, action) - expected_score
def softmax_policy(state, weight):
probs = softmax(state, weight)
if np.random.random() < probs[1]:
return stick
else:
return hit
if __name__ == "__main__":
Q_star = np.load('Q_star.npy')
for k in range(1, ITERATIONS):
terminal = False
state = game.initialise_state()
action = softmax_policy(state, theta)
history = [state, action]
while not terminal:
state, reward = game.step(state, action)
action = softmax_policy(state, theta)
terminal = state.terminal
if terminal:
state_action_pairs = zip(history[0::3], history[1::3])
history.append(reward)
history.append(state)
Gt = sum(history[2::3])
for s, a in state_action_pairs:
advantage = Gt - Q(s, a, prev_theta)
theta += alpha * score_function(s, a, theta) * advantage
else:
history.append(reward)
history.append(state)
history.append(action)
if k % 10000 == 0:
print("MSE: " + str(round(np.sum((Q_star - generate_Q(theta)) ** 2),2)))
Output:
python reinforce.py
MSE: 288.18
MSE: 248.45
MSE: 227.08
MSE: 215.46
MSE: 207.3
MSE: 202.61
MSE: 197.82
MSE: 195.96
MSE: 194.01
The table below shows the value function created using this algorithm:
Update:
Fixed the code by using a different theta initialisation:
theta = np.zeros((420,1))
Current value function:
But the current value function still does not match Q*
(missing peak at player sum = 11)
The entire code is available at:
https://github.com/Soundpulse/easy21-rl/blob/main/reinforce.py
Hi I am having trouble pulling a variable out of a function and then using it in a mathematical equation.
I can use the function usdExRateRand no problem but when try to use the value usdExRate from the function in a nested if statement it only uses the initial usdExRateRand not the newly defined one from the while loop how do i fix this?
import random
def whiles():
cur1 = "NZD"
cur2 = "USD"
usdExRate = round(random.random() * (0.909 - 0.101) + 0.101, 3)
print ("usdExRate Initial = $", usdExRate)
nzdExRate = round(random.random() * (1.909 - 1.101) + 1.101, 3)
print ("nzdExRate Initital = $", nzdExRate)
amt = 1000
amt2 = 0
amtPrev = 0
amt2Prev = 0
def usdExRateRand():
usdExRate = round(random.random() * (0.909 - 0.750) + 0.750, 3)
print ("USD Ex Rate = $", usdExRate,"\n")
usdExRateRand()
def nzdExRateRand():
nzdExRate = round(random.random() * (1.505 - 1.101) + 1.101, 3)
print ("NZD Ex Rate = $", nzdExRate, "\n")
nzdExRateRand()
while amt > 0:
def trade1():
# usdExRate = round(random.random() * (0.909 - 0.101) + 0.101, 3)
print ("TRADE 1")
usdExRateRand()
if usdExRate > 0:
# def trade1():
# usdExRate = round(random.random() * (0.909 - 0.101) + 0.101, 3)
# print (usdExRate)
if (usdExRate * amt > amt2Prev):
print ("My Amount to trade =", cur1," $", amt)
print ("my ",cur2,"rate = $", usdExRate)
trd1 = amt * usdExRate
print ("trade1", cur1,"$", amt," * ",cur2,"$",usdExRate," = $", trd1, "\n")
amt2 = trd1
amtPrev = amt
else:
print ("error reluts in a loss\n")
trade1()
trade1()
def trade2():
print ("TRADE 2")
nzdExRateRand()
if nzdExRate > 0:
if (nzdExRate * amt2 > amtPrev):
print ("My Amount to trade =", cur2," $",amt2,"\n")
print ("my", cur1, "rate = $", nzdExRate)
trd2 = amt2 * nzdExRate
print ("trade2", cur2,"$", amt2," * ",cur1,"$",nzdExRate," = $", trd2, "\n")
amt1 = trd2
amt2Prev = amt2
else:
print ("error results in a loss\n")
trade2()
# amtPrev = amt
# def usdExRateom2():
# usdExRate2 = round(random.random() * (1.909 - 1.101) + 1.101, 3)
# print ("my nzd rate", usdExRate2)
#
# if (trd1 * usdExRate2 < amtPrev):
#
# usdExRate2 = round(random.random() * (1.909 - 1.101) + 1.101, 3)
#
# else:
# trd2 = trd1 * usdExRate2
# print ("trade2 =", trd2)
# usdExRateom2()
whiles()
hopefully i got my indentation right this time when copying over the code the code works in spyder and i get this output as you can see after "my amount to trade" the usd ex rate is always 0.3 not the value above.
TRADE 1
USD Ex Rate = $ 0.761
My Amount to trade = NZD $ 1000
my USD rate = $ 0.3
trade1 NZD $ 1000 * USD $ 0.3 = $ 300.0
TRADE 2
NZD Ex Rate = $ 1.178
error results in a loss
TRADE 1
USD Ex Rate = $ 0.772
My Amount to trade = NZD $ 1000
my USD rate = $ 0.3
trade1 NZD $ 1000 * USD $ 0.3 = $ 300.0
TRADE 2
NZD Ex Rate = $ 1.296
what i would like to do is.
def trade():
usdExRaterand()
this should give me a new usdExRate variable I can then use in the following if statement
Here's a very vague example that should only demonstrate how you can pass values to your functions and how to return values. I'm not sure what you want to achieve, so please provide more information and I'll update this post.
import random
def usdExRateRand():
return round(random.random() * (0.909 - 0.750) + 0.750, 3)
def nzdExRateRand():
return round(random.random() * (1.505 - 1.101) + 1.101, 3)
def trade1(usdExRate, amtPrev):
if usdExRate * amt > amtPrev:
# Do your calculations.
# Then return the updated amt and previous amt. (If you need them.)
return amt, amtPrev
def trade2(nzdExRate, amtPrev):
if nzdExRate * amt > amtPrev:
# Do your calculations.
# Then return the updated amt and previous amt.
return amt, amtPrev
def main():
amt = 1000
amtPrev = amt
while amt > 0:
usdExRate = usdExRateRand()
nzdExRate = nzdExRateRand()
print("USD Ex Rate = $", usdExRate)
print("NZD Ex Rate = $", nzdExRate)
amt, amtPrev = trade(usdExRate, amtPrev)
amt, amtPrev = trade2(nzdExRate, amtPrev)
main()
I'm getting an error on line 3 "TypeError: 'int' object is not iterable," and its been bothering me. Any advice/fixes appreciated.
Example test: collatz_counts(4) → 3 # 4 -> 2 -> 1 (3 steps)
Code I have:
def collatz_counts(x):
num = 0
for i in (x):
if i == 1:
num += 1
return num
elif i % 2 == 0:
num(i) / 2
num += 1
num.append(i)
else:
num = (i*2) + 3
num += 1
num.append(i)
return num
This can be solved recursively:
def collatz_length(n):
if n == 1:
return 1
return 1 + collatz_length(3*n+1 if n%2 else n//2)
Which lends itself to be memoized if you are going to be calling for a range of numbers, e.g. in Py3
import functools as ft
#ft.lru_cache(maxsize=None)
def collatz_length(n):
if n == 1:
return 1
return 1 + collatz_length(3*n+1 if n%2 else n//2)
Which will run through the first million collatz sequences in about 2.31s vs about 28.6s for the iterative solution.
Use a while loop. Just modify x in place until you get to 1 and keep track of the number of steps each time you run a cycle.
def collatz_counts(x):
steps = 0
while x != 1:
if x % 2:
x = x * 3 + 1
else:
x = x // 2
steps += 1
return steps
I have a dataframe that has contains a column of integers. I want to write a function that takes a series as an argument, iterates through each value of the series, and performs a case statement on each integer within the series, and returns a new series from the results of the case statement. Currently I'm working with the following code and getting errors:
def function(series):
if series['column_of_ints'] >= 0 and series['column_of_ints'] < 100:
return series['column_of_ints']
elif series['column_of_ints'] >= 100 and series['column_of_ints'] < 200:
return series['column_of_ints'] + 1
else:
return series['column_of_ints'] + 2
df['column_of_ints_v2'] = df['column_of_ints'].apply(function, axis=1)
Don't use apply you can achieve the same result much faster using 3 .loc calls:
df.loc[(df['column_of_ints'] >= 0) & (df['column_of_ints'] < 100), 'column_of_ints_v2'] df['column_of_ints']
df.loc[(df['column_of_ints'] >= 100) & (df['column_of_ints'] < 200), 'column_of_ints_v2'] = df['column_of_ints'] + 1
df.loc[(df['column_of_ints'] < 0) & (df['column_of_ints'] >= 200), 'column_of_ints_v2'] = df['column_of_ints'] + 2
Or using where:
df['column_of_ints_v2'] = np.where((df['column_of_ints'] >= 0) & (df['column_of_ints') < 100), df['column_of_ints'] + 1, np.where( (df['column_of_ints'] >= 100) & (df['column_of_ints'] < 200), df['column_of_ints'] + 2, df['column_of_ints'] ))
As to why your code fails:
df['column_of_ints'].apply(function, axis=1)
df['column_of_ints'] is a Series not a DataFrame, there is no axis=1 for apply method for a Series, you can force this to a DataFrame using double square brackets:
df[['column_of_ints']].apply(function, axis=1)
If you're applying row-wise to a single column then you don't need the column accessors in your function:
def function(series):
if series >= 0 and series < 100:
return series
elif series >= 100 and series < 200:
return series + 1
else:
return series + 2
but really you should use a vectorised method like my proposal above