This is just a fun project I thought would be cool to do, but I'm struggling to figure it out.
plates = [100, 45, 35, 25, 10, 5, 2.5]
goal_weight = 425
starting_weight = 45
while goal_weight > starting_weight:
My idea was to iterate through plates with a while loop. I need each number to max out into the goal weight (100 goes into 450 4 times) then moves onto the next number and attempts there, to show the ideal way to load the bar. But I may be on the wrong track here.
Example: 250 = 45lb bar(starting_weight), two 100lb plate, two 2.5lb plate
425 = 45lb bar, two 100lb, four 45lb
Wanting it to print something like: Two 100's, two 45's, two 10's
Here is a little program to find the right combinations of weight plates. Note the function zip that combines the list of number of weight plates with the list of weights. list(zip(nweights, weights)) forming a list of tuples, for example [(4, 100), (0, 45) ... (0, 2), (0, 2.5)]
weights=[100, 45, 35, 25, 10, 5, 2, 2.5]
targetweight = int(input('What is the target weight: '))
nweights = []
remaining = targetweight
for i, weight in enumerate(weights):
nweights.append(int(remaining/ weight))
remaining = remaining - nweights[i]*weights[i]
if remaining == 0:
break
listweights=zip(nweights, weights)
for weight in listweights:
print(f'you need {weight[0]} of weight {weight[1]} pound')
if remaining !=0:
print(f'the correct weight combination cannot be found,'
f'the remaining weight is: {remaining} pound')
This is what I ended up with. Appreciate the help, guys!
weights=[100, 45, 35, 25, 10, 5, 2.5]
target_weight = int(input('How much weight do you need? '))
bar_weight = int(input('Enter bar weight: '))
nweights = []
remaining = target_weight - bar_weight
for i, weight in enumerate(weights):
if int(remaining / weight) % 2 == 0:
nweights.append(int(remaining/ weight))
else:
nweights.append(int(remaining/ weight) - 1)
remaining = remaining - nweights[i]*weights[i]
if remaining == 0:
break
listweights=zip(nweights, weights)
print(f'{bar_weight}lb bar')
for weight in listweights:
if weight[0] >= 2:
print(f"{weight[0]} | {weight[1]}'s")
if remaining !=0:
print(f'the correct weight combination cannot be found,'
f'the remaining weight is: {remaining} pound')
Yes I think your solution works, though perhaps the below snippet is more logical...
(using a bit of numpy array methods)
import numpy as np
weights=np.array([100, 45, 35, 25, 10, 5, 2.5])
weights=weights*2
target_weight = int(input('How much weight do you need? '))
nweights=[]
remaining = target_weight
for i, weight in enumerate(weights):
nweights=np.append(nweights, int(remaining/ weight))
remaining = remaining - nweights[i]*weights[i]
if remaining == 0:
break
nweights = nweights*2
weights=weights*0.5
weightlist=zip(nweights, weights)
barweight=0
for weight in weightlist:
print(f"{weight[0]} | {weight[1]}'s")
barweight=barweight+weight[0]*weight[1]
print(f'total weight: {barweight} pound')
if remaining !=0:
print(f'the correct weight combination cannot be found,'
f'the remaining weight is: {remaining} pound')
Related
Set: Do you have the exact change? You are given an infinite supply of bills of three denominations (say, 10 $, 20 $, and 50 $ bills). Given a price, can you identify if you have exact change summing up to that price? For instance, using these three types of bills, we can pay 10, 20, 30, 40, 50, 60, 70 $, etc., but we cannot pay 55, in that case print “Not Possible”. It is also possible that the same price can be constructed using multiple combinations of bills. For instance, 50 $ can be constructed using three bills of 10 and one bill of 20, or by directly using a single 50 $ bill. We can print all the possible combinations. Consider the following sample inputs and outputs.
Sample input: 50
Output
320
120
005
amt=int(input())
if amt%10!=0:
print('Not possible')
else:
n_10=amt/10
n_20=amt/20
n_50=amt/50
st=set()
if(n_10*10+n_20*20+n_50*50==3*amt):
st1={n_10,n_20,n_50}
print(st1)
Here is something very basic to begin with. Note that it generates duplicates (10+20+50 and also 20+50+10, etc.).
def pay(paid, outstanding, bills):
if outstanding == 0:
print(paid)
elif outstanding > 0:
for b in bills:
pay(paid + [b], outstanding - b, bills)
BILLS = (10, 20, 50)
pay([], 80, BILLS)
step 2: we don't want to print the bills combinations, we want to process the data, let's convert the main function to a generator and hide the paid list as an unimportant implementation detail:
def _pay(paid, outstanding, bills):
if outstanding == 0:
yield paid
elif outstanding > 0:
for b in bills:
yield from _pay(paid + [b], outstanding - b, bills)
def pay(outstanding, bills):
return list(_pay([], outstanding, bills))
BILLS = (10, 20, 50)
print(pay(80, BILLS))
step 3: Not we finally count the bills with Counter and remove duplicates with set. (It can be further improved)
from collections import Counter
def _pay(paid, outstanding, bills):
if outstanding == 0:
yield Counter(paid)
elif outstanding > 0:
for b in bills:
yield from _pay(paid + [b], outstanding - b, bills)
def pay(outstanding, bills):
return set(
tuple(cnt[b] for b in BILLS)
for cnt in _pay([], outstanding, bills)
)
BILLS = (10, 20, 50)
print(pay(80, BILLS))
A cash drawer contains 160 bills, all 10s and 50s. The total value of
the 10s and 50s is $1,760.
How many of each type of bill are in the drawer? You can figure this
out by trial and error (or by doing algebra with pencil and paper),
but try to use loops and conditionals to check a plausible
possibilities and stop when you find the correct one.
Algebraically, on a piece of paper I figured out that it was four $50 bills and one hundred and fifty six $10 bills. This is because
x+y=160
10x+50y=1760
x=160-y
10x=1600-10y
1600-10y+50y=1760
1600-40y=1760
40y=1760
y=4
x=156
how would I make a model that i could code to solve this or any other version of this problem? I only know the very basic syntax of python as i've never ever programmed before this.
Using numpy for the system:
x+y=160
10x+50y=1760
import numpy as np
a = np.array([[1, 1], [10, 50]])
b = np.array([160, 1760])
x = np.linalg.solve(a, b)
print(x)
Outputs:
[156. 4.]
There are a total of two variables, the number of tens and the number of fifties. So you could do nested for-loops. A really blunt way of doing this would be:
for fifties in range(161):
for tens in range(161-fifties):
if (fifties+tens == 160) and (50*fifties + 10*tens == 1760):
break
We can improve that a bit by noting that each time we increase the number of fifties, we decrease the possible number of tens:
for fifties in range(161):
for tens in range(161-fifties):
if (fifties+tens == 160) and (50*fifties + 10*tens == 1760:
break
It can be improved even further by noting that although there are a total of two variables, we have the constraint that they add up to 160. Thus, we can use this constraint to get one given the other:
for fifties in range(161):
tens = 160 - fifties
if 50*fifties + 10*tens == 1760:
break
You can take a dynamic programming approach to this for a general solution:
Set up some edge conditions where there is no answer:
If the length of notes it less than 1
You have one note but the total is not divisible by the denomination there's no answer.
The take a note off and see if it works by recursively calling the function with the remaining notes and adjusted bill-count/total.
def countNotes(notes, total, bills):
if len(notes) < 1:
return
if len(notes) == 1:
return [bills] if bills * notes[0] == total else None
for count in range(bills+1):
amount = notes[0] * count
rest = countNotes(notes[1:], total - amount, bills - count)
if rest:
return [count, *rest]
countNotes([50, 10], 1760, 160)
#[4, 156]
countNotes([100, 20, 5], 173, 2)
# None -- not possible
countNotes([100, 20, 5, 2], 1255, 61)
#[1, 57, 3, 0]
This will return the counts as a list in the same order as the notes passed in. If you're dealing with large lists and totals if could be improved by memoizing it.
d = {'x': 10, 'y': 50} #create dictionary to hold bill values
total_value = 1760
num_bills = 160
y = (total_value - num_bills *d['x']) / (d['y']-d['x']) #isolating y
x = num_bills - y # isolating x with y value known
print("the number of ten dollar bills is: " + str(x))
print("the number of fifty dollar bills is: " + str(y))
I need to calculate the minimum number of ways to reach a value, x, from value n, by adding/subtracting a list of values, l, to n.
For example: Value n = 100, value X = 45
List, l,: 50,6,1
The best way to do this is to say:
100-50-6+1 = 45
I want a programme to work this out for any value of x and n given list, l
I am really struggling to outline how I would write this.
I am confused about how to overcome the following issues:
How to inform the programme if I should attempt an addition or
subtraction and how many times this should be done. For example I
might need to subtract, then add, then subtract again to reach a
solution
How do I include enough for/while loops to ensure I can provide a
solution for all possible input values
Has anyone come across an issue like this before and have any ideas how I could outline the code for such a solution (I am using Python if it helps direct me towards learning about particular functions available that could assist me)
Thanks
This is my attempt so far but I am stuck
inputA = ""
while inputA == "":
inputA = input("""Please enter two numbers, separated by a comma.
The first value should indicate the number of jugs:
The second value should indicate the volume to be measured
""")
itemList = list(inputA.split(","))
valueToMeasure = int(itemList[1])
inputB = ""
while inputB == "":
inputB = input("Plese enter the volumes for the {} jug(s) listed: ".format((itemList[0])))
if len(inputB.split(",")) != int(itemList[0]):
inputB = ""
TargetVolume = itemList[1]
jugSizes = inputB.split(",")
print("Calculating: smallest number of steps to get", TargetVolume, "ml using jugs of sizes:", jugSizes)
jugSizes.sort()
jugSizes.reverse()
largestJug = int(jugSizes[0])
ratioTable = {}
for item in jugSizes:
firstVal = int(jugSizes[0])
itemV = int(item)
valueToAssign = firstVal/itemV
ratioTable[int(item)] = int(valueToAssign)
taskPossible = True
if valueToMeasure > largestJug:
print ("Impossible task")
taskPossible = False
newList = jugSizes
if taskPossible == True:
for item in jugSizes:
if item < TargetVolume: break
newList = newList[1:]
newDict = {}
for itemA in ratioTable:
if int(itemA) < int(item):
newDict[itemA]= ratioTable[itemA]
print ("Do work with these numbers:", newDict)
This is how I would approach the problem if I understand correctly.
X = 45
largest_jug = measured = 100
jug_sizes = [50, 6, 1]
steps = []
jug_to_use = 0
while measured != X:
if jug_to_use < len(jug_sizes) - 1: # we have smaller jugs in reserve
error_with_large_jug = min([abs(measured - jug_sizes[jug_to_use] - X), abs(measured + jug_sizes[jug_to_use] - X)])
error_with_small_jug = min([abs(measured - jug_sizes[jug_to_use + 1] - X), abs(measured + jug_sizes[jug_to_use + 1] - X)])
if error_with_small_jug < error_with_large_jug:
jug_to_use += 1
if measured > X:
measured -= jug_sizes[jug_to_use]
steps.append(('-', jug_sizes[jug_to_use]))
else:
measured += jug_sizes[jug_to_use]
steps.append(('+', jug_sizes[jug_to_use]))
print(steps)
Yielding
[('-', 50), ('-', 6), ('+', 1)]
It basically starts by using the largest jug, until it's in range of the next size and so on. We can test it with randomly sized jugs of [30, 7, 1] and see it again results in an accurate answer of [('-', 30), ('-', 30), ('+', 7), ('-', 1), ('-', 1)].
Important notes:
jug_sizes should be ordered largest to smallest
This solution assumes the X can be reached with the numbers provided in jug_sizes (otherwise it will infinitely loop)
This doesn't take into account that a jug size can make the target unreachable (i.e. [50, 12, 5] where the 12 size should be skipped, otherwise the solution is unreachable
This assumes every jug should be used (related to above point)
I'm sure you could figure out solutions for all these problems based on your specific circumstances though
I have the following table, from which a have to create a recipe with a specific value for protein and carbohydrates.
And using or-tools to solve this problem, so far I have:
The formated data
data = [
['f1', 10, 15, 17, 10],
['f2', 2, 11, 12, 14],
['f3', 6.5, 17, 16, 13],
['f4', 8, 12, 8, 16]
]
The constraines for the nutriends:
nutrients = [
["protein",15.5],
["carbohydrates",12.3]]
The objective function, where the upper bound "datai" is the stock of that particular element.
food = [[]] * len(data)
# Objective: minimize the sum of (price-normalized) foods.
objective = solver.Objective()
for i in range(0, len(data)):
food[i] = solver.NumVar(0.0, data[i][1], data[i][0])
objective.SetCoefficient(food[i], 4)
objective.SetMinimization()
I also have the as constrain the required value of each nutrient:
constraints = [0] * (len(nutrients))
for i in range(0, len(nutrients)):
constraints[i] = solver.Constraint(nutrients[i][1], solver.infinity())
for j in range(0, len(data)):
constraints[i].SetCoefficient(food[j], data[j][i+3])
And finally the solver:
status = solver.Solve()
if status == solver.OPTIMAL:
# Display the amounts (in dollars) to purchase of each food.
price = 0
num_nutrients = len(data[i]) - 3
nutrients = [0] * (len(data[i]) - 3)
for i in range(0, len(data)):
price += food[i].solution_value()
for nutrient in range(0, num_nutrients):
nutrients[nutrient] += data[i][nutrient+3] * food[i].solution_value()
if food[i].solution_value() > 0:
print ("%s = %f" % (data[i][0], food[i].solution_value()))
print ('Optimal price: $%.2f' % (price))
else: # No optimal solution was found.
if status == solver.FEASIBLE:
print ('A potentially suboptimal solution was found.')
else:
print ('The solver could not solve the problem.')
Which up to this part is working fine, the result I get is the following:
f1 = 0.077049
f3 = 0.886885
Optimal price: $0.96
Know I need to add as well the constraints of how many kg I will make, which have to satisfy the previous constraints as well.
My first guess was to add a multiplier to the nutrients requirement
factor = 10
nutrients = [
["protein",15.5*factor],
["carbohydrates",12.3*factor]]
Tjis way I will have 10 times more food, but then I realized that this is not correct, since what I need is a concentración E.G.
I need 10kg with 15.5 protein/kg and 12.3 carbohydrates/kg
the constrain I need is something like this:
(f1*W + f2*X + f3*Y + f4*Z)/(W+X+Y+Z) = 10kg with 15.5 protein/kg and 12.3 carbohydrates/kg
Where W, X, Y and Z are the kg of each food
How can I add this constrain to solver?
(f1*W + f2*X + f3*Y + f4*Z)/(W+X+Y+Z) = 10
is the same as
f1*W + f2*X + f3*Y + f4*Z = 10*(W+X+Y+Z)
This is now linear.
And, in case we missed some math classes, we can write this as a standard LP constraint:
(f1-10)*W + (f2-10)*X + (f3-10)*Y + (f4-10)*Z = 0
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am a beginner so if this question sounds stupid/unclear or very easy , please bear with me.
How can I add a list of numbers together in order to reach a target number or get as close as possible? For example, here is a list of numbers: (2,3,4,7,20,25), goal = 105. The result should be this: (25,25,25,25,3,2). The order of given numbers matters; always start with the biggest number in the list and add them up in order get close to the given value, so it will choose the next digit to test. the result could be also (20, 20, 20, 20, 25), which is not right in this case, because it doesn't follow the order of numbers. The algorithm only jump for the next number if it can feet otherwise can't jump.
Best M
l=(2,3,4,7,20,25)
goal = 105
a=max(l)
b=0
res=[]
while b<=goal-24:
b+=a
t=goal-b
res.append(a)
g=0
for x in l:
g+=x
if g==t:
res.append(x)
res.append(g-x)
break
print (res)
Output:
>>>
[25, 25, 25, 25, 3, 2]
>>>
I found this solution, however, really annoyed me :-)! Tricky part is while b<=goal-24: , other codes are basic Python.
I would take a dynamic-programming approach:
def fewest_items_closest_sum_with_repetition(items, goal):
"""
Given an array of items
where each item is 0 < item <= goal
and each item can be used 0 to many times
Find the highest achievable sum <= goal
Return any shortest (fewest items) sequence
which adds to that sum.
"""
assert goal >= 0, "Invalid goal"
# remove any duplicate or invalid items
items = set(item for item in items if 0 < item <= goal)
# sort descending (work with largest values first)
items = sorted(items, reverse=True)
# start with the no-item sequence
best = {0: []}
active = {0: []}
# while we have further seeds to work from
while active:
nactive = {}
for item in items:
for total, seq in active.items():
# find next achievable sum
ntotal = total + item
# if it is a valid subgoal and has not already been found
if (ntotal <= goal and ntotal not in best):
# save it
best[ntotal] = nactive[ntotal] = [item] + seq
if ntotal == goal:
# best possible solution has been found!
break
active = nactive
# return the best solution found
return best[max(best)]
which then runs like
>>> fewest_items_closest_sum_with_repetition([2,3,4,7,20,25], 105)
[25, 20, 20, 20, 20]
>>> fewest_items_closest_sum_with_repetition((40,79), 80)
[40, 40]
Is this right? I don't have time to test right now.
def solution(numbers, goal):
curr = 0
numbers = sorted(numbers)
while curr < goal:
if not numbers: break
n = numbers.pop()
while n + curr <= goal:
yield n
curr += n
list(solution([2,3,4,7,20,25], 105))
Results:
[25, 25, 25, 25, 4]
If speed is not an issue, here's an ultimately correct response:
import itertools
def change_maker(coins, amount):
for r in range(amount//max(coins), amount//min(coins)+1):
possibilities = (combo for combo in itertools.combinations_with_replacement(coins, r) if sum(combo) == amount)
try:
result = next(possibilities)
except StopIteration:
# no solution with current r
continue
else:
return result
This will always return the optimum result, but in some cases can calculate an ABSURD number of combinations to get there.
DEMO:
>>> coins = (2, 3, 4, 7, 20, 25)
>>> goals = 105
>>> print(change_maker(coins, goal))
[20, 20, 20, 20, 25]