New to python and need help getting started with this function - python-3.x

I am very new to python and I have done research but all I could find on this problem was on outdated versions of python. I hear this community is able to help me with this problem.
I am attempting on making a function called makeChange with amount as a parameter.
The function is supposed to take user input as a decimal and convert what the user inputted into bills and coins. (for example .05$, .10$, .25$, .50$ 1$ and so on.)
Is it possible that I can get a base to build off of? (Not the entire function maybe a few errors just so I can learn.)
(Thanks for taking the time to read what I have to say!)

Problem
So, in makeChange problem we find try to find the minimum number of coins that add up to a give amount of money.
Code
def makeChange(amount):
# You can add more or remove the coins from this list
coins = [.05, .1, .25, .5, 1]
# LEARN: Find out how sort function works on a list, and what does the reverse parameter means. Why do we need to sort it?
# Sort the coins list (incase it's not sorted)
coins.sort(reverse=True)
change = []
for coin in coins:
# LEARN: Find out why we type cast the result of totalCoin to integer,
# LEARN: Find out what do we get by using integer division and modulo to the amount variable
# Notes: // means integer division, / means float division, % means modulo or remainder
totalCoin = int(float(amount) // coin)
amount = amount % coin
# Round the amount to 2 precision point (0.25, 1.00) since there is no $0.001 right
amount = round(amount, 2)
# Append the coin we use for change
for i in range(totalCoin):
change.append(coin)
if amount == 0:
return change
# If we ever reach here, that means, the given coin in coins list
# is not able to return the change
return 'Not changeable'
print('22.76: ', makeChange(22.76)) # 22.76: Not changeable
print('13.8: ', makeChange(13.8)) # 13.8: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 0.25, 0.05]
print('2.4', makeChange(2.4)) # 2.4 [1, 1, 0.25, 0.1, 0.05]
Conclusion
The code above is working properly, I did not any error to it, BUT I added lots of comment for you to find out yourself, how and why this code works the way it is. Good luck on learning Python!

Here is a start for you:
def makeChange(amount):
pass

You can compute how many bills and coins are needed. You can work on float type. int function converts float to int and truncate decimal part. For example
def makeChange(amount):
amt = float(amount)
n100 = int(amt/100.)
amt = amt - n100*100.
n50 = int(amt/50.)
amt = amt - n50*50.
# and so on... you can add more
n100, n50 # return how many bills

Related

Optimization based on rank and absolute deviation

I have a problem statement where i am trying to optimize the position of the shipment such that 2 specific objectives are met, Deviation time and inherent ranking
Given: some Shipments, the objective is to sequence them in a way such that the deviation between the actual start - planned start is minimized, while also ensuring that the ranking of shipments is optimized.
Example: 3 shipments which need to be executed at [10 am, 12 noon, 1 PM] , assuming each statement takes 1 hour to be executed, what should be the sequence of execution?
Shipments [S1 S2 S3]
Planned ranking [1 2 3]
Planned time [10,12,13]
The solver should give me a solution where the ranking and deviation between the planned and actual time should be less
Example Solution
Optimized ranking can be [2 1 3] execute S2 first, then S1 and finally S3
Optimized time can be anywhere between 1 - 24 depending on other constraints.
hence S2 can begin at either 1 and can take values till 22
S1 should begin after S2 and can take matters from S1 end time till 23
and S3 should begin after S2 and S1 and can take values from the End of S1 till 24.
I was able to write down the ranking part where the objective function is Minimizing the rank(Derived froma pre-determined matrix) and binary choice of shipment and position:
'''
import random
import pandas as pd
from pulp import *
shipments = {'D1':1, 'D2':2, 'D3':3}
positions = {'P1':1, 'P2':2, 'P3':3}
endtime = {'D1':10, 'D2':15, 'D3':20}
rank={('D1', 'P1'): 2,
('D1', 'P2'): 4,
('D1', 'P3'): 7,
('D2', 'P1'): 3,
('D2', 'P3'): 2,
('D2', 'P2'): 1,
('D3', 'P3'): 1,
('D3', 'P2'): 2,
('D3', 'P1'): 3}
shipments_labels = sorted(shipments.keys())
positions_labels = sorted(positions.keys())
BIG_M = 9999.9
# Binary to hold shipment assigned to position
x = LpVariable.dicts("x", (shipments_labels,positions_labels), 0, 1, LpInteger)
y = LpVariable.dicts("y", (shipments_labels,positions_labels), 1, 24, LpInteger) # to hold the time starting for shipment
y_diff = LpVariable.dicts("y_diff", (shipments_labels), cat='Real') # to hold absolute deviations
print(x)
print(y)
print(y_diff)
print(rank[('D1', 'P1')])
prob = LpProblem("ranking", LpMinimize)
prob += (lpSum([(rank[(i,j)]**2 -1) * x[i][j] for i in shipments_labels for j in positions_labels]),
'Total_Cost') # Objective Function
# #every shipment should be assigned a position
for i in shipments_labels:
prob += (lpSum([x[i][j] for j in positions_labels])==1)
# #every position only 1 shipment
for i in positions_labels:
prob += (lpSum([x[j][i] for j in shipments_labels])==1)
prob.solve()
for v in prob.variables():
print(v)
print(v.varValue)
'''
However, I am confused about how to code the deviation logic into the objective. I created the variables yij to hold the interger value of the allocated time and y_diff to hold the absolute deviation. Since deviation can be both positive and negative, it can be penalized differently.
1- Problem Statement
2- Problem Statement
3- Problem Statement

Output showing 0 for random() function

So, I have this battle scenario here:
def band_attack():
global new_ship
print('Bandits attack!')
s.sleep(1)
c = r.random()
if c < 0.5:
print('Bandits missed!')
elif 0.5 < c < 0.7:
c = r.random()
new_ship = new_ship - int(c)
print('Your ship was hit for', c, 'damage!')
print('Your ship now has', int(new_ship), 'health!')
else:
new_ship = new_ship - int(c)
print('Critical strike! You were hit for', c, 'damage!')
print('Your ship now has', int(new_ship), 'health!')
if new_ship <= 0:
print('You\'ve been destroyed!')
else:
Fight.band_fight()
Fight is the class holding all the battle functions, r is the random module, s is the time module, band_attack is a function where you attack.
I want the damage obviously to be whole numbers above 0, hence why I turn the random function output to an integer.
It should be outputting a number greater than 0, or if it is 0, should just be a miss, but I'm clearly missing something. Maybe someone else can figure out what I'm missing?
The call to random.random() will always return a floating-point number in the range [0.0, 1.0) as per the documentation.
When you cast the result to int (by calling the int(c)), you are asking for the integer part of that float which is always equal to zero for floats in that range.
There are two ways to fix this: either multiply the result of random.random() by 10 or use the random.randint(a, b), which returns a random integer N, such that a <= N <= b. You will need to adjust your conditions accordingly.
You mentioned in the comments that you are worried about seeding the random number generator when using random.randint(a, b) but since the seed function affects the module's random number generator itself all functions (randint, choice, randrange) will behave as expected.
The random() function from the random module (which I assume is what you named r) returns a float between 0 and 1. You can't pass a float into int(). The best alternative would be to use either randint(x, y) (where x and y denote the range in which you want your random damage to be), or stick to random() and mulitply it by the upper limit of that intended range.

How to find max and min numbers in list within list

I am stuck at this question where I am required to update all largest and smallest numbers in the list with the average value as a way to remove the extreme values in the given list.
For example:
def remove_extreme( [ [0,4], [1,4], [-1,2] ] ) would return [ [0,1.5], [1,1.5], [1.5,2] ].
The function will need to use the average value to modify the elements in the lists, which, in this case the smallest and largest values are -1 and 4 respectively. Then, all the largest and smallest values present in the list need to be changed to the average(mean) of these two values, which is (4+-1)/2 = 1.5
Here's my code:
def remove_extreme(datalist):
for numlist in datalist:
for index, number in enumerate(numlist):
largest = max(number)
smallest = min(number)
average = (largest - smallest)/2
if number == largest or smallest:
num_list[index] = average
return datalist
May I know what went wrong? I keep getting 'int' object is not iterable.
What you asked about
To answer your immediate question, the built in functions max and min return for you the maximum and minimum number from an iterable.
https://docs.python.org/3/library/functions.html#max
So it throws a TypeError when you pass it an integer. Run it on a list/iterable instead.
But your code has more issues than just that.
Your if statement, though syntactically correct, is probably not what you want. More than likely you wanted to do this:
if number == largest or number == smallest:
Like Tomerikoo pointed out, you want to put your max and min outside the loop. As an aside, you do not need to return the list as lists are mutable and you are modifying it freely inside the function.
def remove_extreme(datalist):
for numlist in datalist:
largest = max(numlist)
smallest = min(numlist)
average = (largest - smallest)/2
for index, number in enumerate(numlist):
if number == largest or number == smallest:
numlist[index] = average
return datalist
What your problem is actually asking you
Looking at your original question I think you're a little off from the correct answer if your lists need to look like your given answer. The first hint is that your given answer shows only one of the values changed, and it's not always the average of the inner list. Take [0, 4] for instance. 1.5 is not the average of 0 and 4, yet that is what you say it should return. It seems that you are really desiring to change the most extreme number for each inner list based off the average of all the lists. Taking the average of the numbers of all the inner lists yields 1.66, so I'm not sure of this precisely, but I think one of your numbers might be off by 1 (I think so because 10/6 yields 1.66 while 9/6 yields 1.5).
If the above assumptions are all correct you will want to calculate the average (which is usually the sum/number of elements) and then find the most extreme element within each list.
Your function should look a bit more like this:
def remove_extreme(datalist):
# sum len of each list to get total number of elements
num_elements = sum([len(numlist) for numlist in datalist])
# sum the sum of each list to get total
sum_elements = sum([sum(numlist) for numlist in datalist])
# calculate average
average = sum_elements/num_elements
# find the most extreme element in each list and perform substitution
for numlist in datalist:
smallest = min(numlist)
largest = max(numlist)
large_diff = abs(largest - average)
small_diff = abs(average - smallest)
num_to_change = largest if large_diff > small_diff else smallest
for index, number in enumerate(numlist):
if number == num_to_change: # Just look at the most extreme number
numlist[index] = average
return datalist # list will be modified, but returning it doesn't hurt either
Running this function after changing your -1 to -2:
my_list = [
[0,4],
[1,4],
[-2,2]
]
print("Before: ", my_list)
remove_extreme(my_list)
print("After: ", my_list)
Output:
$ python remove_extreme.py
Before: [[0, 4], [1, 4], [-2, 2]]
After: [[0, 1.5], [1, 1.5], [1.5, 2]]
After further clarification
After clarifying what the question was really asking you, the answer is even simpler:
def remove_extreme(datalist):
flattened = [i for numlist in datalist for i in numlist] # flatten list for convenience
largest = max(flattened)
smallest = min(flattened)
average = (largest + smallest)/2
# find the most extreme element in each list and perform substitution
for numlist in datalist:
for index, number in enumerate(numlist):
if number == smallest or number == largest:
numlist[index] = average
return datalist # list will be modified, but returning it doesn't hurt either
Personally I feel like this makes less sense, but that seems to be what you're asking for.
Also, when writing a question, it's helpful to include the stack trace or point to the specific line where the issue is occurring. Just a helpful tip!
You are trying to get max and min of the element not of the list
>>> list = ( [ [0,4], [1,4], [-1,2] ] )
>>> max(list)
Output
[1, 4]
>>> min(list)
Output
[-1, 2]

OR-Tools VRP: Constrain locations to be served by same vehicle

I would like to constrain locations to be served by the same vehicle.
I used capacity-constraints for achieving this. Say we have l = [[1,2], [3,4]] which means that location 1, 2 must be served by the same vehicle and 3, 4 as well. So 1, 2 ends up on route_1 and 3, 4 on route_2
My code for achieving this is:
for idx, route_constraint in enumerate(l):
vehicle_capacities = [0] * NUM_VEHICLES
vehicle_capacities[idx] = len(route_constraint)
route_dimension_name = 'Same_Route_' + str(idx)
def callback(from_index):
from_node = manager.IndexToNode(from_index)
return 1 if from_node in route_constraint else 0
same_routes_callback_index = routing.RegisterUnaryTransitCallback(callback)
routing.AddDimensionWithVehicleCapacity(
same_routes_callback_index,
0, # null capacity slack
vehicle_capacities, # vehicle maximum capacities
True, # start cumul to zero
route_dimension_name)
The idea is that 1,2 have a capacity demand of each 1 unit (all others have zero). As only vehicle 1 has a capacity of 2 it is the only one able to serve 1,2.
This seems to work fine if len(l) == 1. If greater the solver is not able to find a solution if though I put into l pairs of locations which were on the same route without the above code (hence without the above capacity constraints.
Is there a more elegant way to model my requirement?
Why does the solver fail to find a solution?
I have also considered the possibility of dropping visits (at a high cost) to give the solver the possibility to start from a solution which drops visits such that it will find his way fro this point to a solution without any drops. I had no luck.
Thanks in advance.
Each stop has a vehicle var whose values determine what vehicle is allowed to visit the stop. If you want to have stops 1 and 2 serviced by vehicle 0 use a member constraint on the vehicle var of each stop and set it to [0]. Since you might have other constraints that make stops optional add the value -1 to the list. It is a special value that indicates that the stop is not serviced by a vehicle.
In Python:
n2x = index_manager.NodeToIndex
cpsolver = routing_model.solver()
for stop in [1,2]:
vehicle_var = routing_model.VehicleVar(n2x(stop))
values = [-1, 0]
cpsolver.Add(cpsolver.MemberCt(vehicle_var, values))

Analyzing the time complexity of Coin changing

We're doing the classic problem of determining the number of ways that we can make change that amounts to Z given a set of coins.
For example, Amount=5 and Coins={1, 2, 3}. One way we can make 5 is {2, 3}.
The naive recursive solution has a time complexity of factorial time.
f(n) = n * f(n-1) = n!
My professor argued that it actually has a time complexity of O(2^n), because we only choose to use a coin or not. That intuitively makes sense. However how come my recurence doesn't work out to be O(2^n)?
EDIT:
My recurrence is as follows:
f(5, {1, 2, 3})
/ \ .....
f(4, {2, 3}) f(3, {1, 3}) .....
Notice how the branching factor decreases by 1 at every step.
Formally.
T(n) = n*F(n-1) = n!
The recurrence doesn't work out to what you expect it to work out to because it doesn't reflect the number of operations made by the algorithm.
If the algorithm decides for each coin whether to output it or not, then you can model its time complexity with the recurrence T(n) = 2*T(n-1) + O(1) with T(1)=O(1); the intuition is that for each coin you have two options---output the coin or not; this obviously solves to T(n)=O(2^n).
I too was trying to analyze the time complexity for the brute force which performs depth first search:
def countCombinations(coins, n, amount, k=0):
if amount == 0:
return 1
res = 0
for i in range(k, n):
if coins[k] <= amount:
remaining_amount = amount - coins[i] # considering this coin, try for remaining sum
# in next round include this coin too
res += countCombinations(coins, n, remaining_amount, i)
return res
but we can see that the coins which are used in one round is used again in the next round, so at least for 1st coin we have n items at each stage which is equivalent to permutation with repetition n^r for n items available to arrange into r positions at each stage.
ex: [1, 1, 1, 1]; sum = 4
This will generate a recursive tree where for first path we literally have solutions at each diverged subpath until we have the sum=0. so the time complexity is O(sum^n) ie for each stage in the path towards sum we have n different subpaths.
Note however there is another algorithm which uses take/not-take approach and at most there is 2 branch at a node in recursion tree. Hence the time complexity for this algorithm is O(2^(n*m))
ex: say coins = [1, 1] sum = 2 there are 11 nodes/points to visit in the recursion tree for 6 paths(leaves) then complexity is at most 2^(2*2) => 2^4 => 16 (Hence 11 nodes visiting for a max of 16 possibility is correct but little loose on upper bound).
def get_count(coins, n, sum):
if(n == 0): # no coins left, to try a combination that matches the sum
return 0
if(sum == 0): # no more sum left to match, means that we have completely co-incided with our trial
return 1 # (return success)
# don't-include the last coin in the sum calc so, leave it and try rest
excluded = get_count(coins, n-1, sum)
included = 0
if(coins[n-1] <= sum):
# include the last coin in the sum calc, so reduce by its quantity in the sum
# we assume here that n is constant ie, it is supplied in unlimited(we can choose same coin again and again),
included = get_count(coins, n, sum-coins[n-1])
return included+excluded

Resources