Doing math with numbers in a list - python

i want to be able to add, subtract, divide, multiply etc with integers in a list and in order.
I know you can use sum() to add, but i also want to be able to subtract, etc in order... so i tried making a for loop idk if thats the right thing to do, but it doesn't give me the right output and it really confuses me because it really seems like it should work. I was wondering if anyone knows how to fix this or explain why its not giving me the same output as i expected.
my_list = [100, 15, 3]
for i in my_list:
i -= i
print(i)
# 100 - 15 - 3 = 82
# Wanted output: 82
# Actual output: 0
my_list = [100, 15]
for i in my_list:
i += i
print(i)
# 100 + 15 = 115
# Wanted output: 115
# Actual output: 30

There are two main issues with your code:
i can't be your loop variable and the sum, because it will be overwritten all the time. So make two variables.
Your first task is different from the second. The sum is easy: take all the values of the list and add them, so the order is irrelevant. For your subtraction it's different because you have to take the first value and subtract all others, so it's basically +100-15-3, which means that also the order of the values in the list matter.
There are more elegant ways to solve it, but for the beginning this should be better to understand.
my_list = [100, 15, 3]
my_difference = my_list[0] #initialize with the first value of your list
my_list_sub = my_list[1:] #make a new list with the remaining numbers
for val in my_list_sub:
my_difference=my_difference-val
print(my_difference)
my_list = [100, 15]
my_sum = 0 #initialize your sum with 0
for val in my_list:
my_sum=my_sum+val
print(my_sum)

As others already pointed out: The "running"/temporary variable is overwritten in every loop. You can try this out with a simple test:
for entry in [0, 'a', 13.37]:
print(entry)
It's always a good idea of trying out what happens in simple cases to learn what is going on.
But your idea of solving this with a loop is absolutely fine. If you want to re-use this functionallity later, it is also nice to wrap that in a function.
Assume integer values my_values = [100, 50, 123, 51, 124, 121] in the following examples.
Lets first tacle the sum.
def calculate_sum(values: list) -> int:
result = 0
for entry in values:
result += entry
return result
Check that it does what we want with
print(calculate_sum(my_values))
print(sum(my_values))
Now difference is 'almost' like summing up, but you want to sum up all values but the first one, and then compute the difference to the first one (a-b-c-d = a-(b+c+d)). Great, that we have already a method for summing up stuff, so we could simply do
def calculate_difference(values: list) -> int:
first, *other = values
return first - calculate_sum(other)
Note the *-marker in front of the other variable. When assigning a list two multiple variables, they are "unpacked" by python. Thus a, b, c = [0, 1, 2] would assign 0 to a and so on. However, when we do a, b = [0, 1, 2], then python complains because there are too many variables to unpack in the list (3 > 2). With the asterisk we simply tell python to put all other values, not used so far, into this special variable again. a, b, *rest = [1, 2, 3, 4, 5, 6] is also possible.
Ok, computing the product is as easy as summing up, just replace += by *= in the method. And for the quotient we can do the same as for the difference, since a * 1/b * 1/c * 1/d = a / (b*c*d). However, note that if the divisor is zero, python will raise an Error DivisionByZero, as this is not legal. Also, the result of the method is float and no longer int.

Related

How to return stuff from the dictionary and multiply them all?

So I'm trying to multiply every single number that is assigned to each variable in dictionary output and I created a function totalcalories(inputlst) to find it.
So what I'm trying to do is to define a function totalcalories(inputlst) that will return the total number of calories consumed based on every meal you eat.
The calories will be stored in a dictionary like this...
inputlst = {"Cabbage":"4,2,0", "Carrot":"9,1,5", "Fatty Pork":"431,1,5"}
where the first number will be multiplied by 5, the second will be multiplied by 5 and the third one will be multiplied by 9.
so for instance if Cabbage is called, (its numbers are (4,2,0)), the output should return ((4 * 5)+(2 * 5)+(0 * 9)), which is 30.
I tried to do it like this, which clearly doesn't work...
def totalcalories(inputlist):
output = {inputlist}
g= []
for x in output:
g.append(x)
return g
print(totalcalories(["Cabbage"]))
I'm really new to this, so please try to use dictionaries and simple beginner programming tricks to help me out, Thank you:)
You could use something like this:
sum([x*y for x, y in zip(map(int, inputlst["Cabbage"].split(",")),[5,5,9])])
Essentially, after having parsed the list of inputs into ints, you get their respective multipliers side-by-side and using a list comprehension you multiply them.
The function would be:
def calc(name):
return sum([x*y for x, y in zip(map(int, inputlst[name].split(",")),[5,5,9])])
Your code attempt currently does none of the things you want it to do, so it may be best to start from scratch.
Firstly, you will want a function that will take an inputted food (as a string), and your dictionary inputlst, so we can begin with the below:
def totalcalories(food, inputlst):
#calculate calories
Firstly, you're going to need to be able to acess the values associated with your food key in your dictionary. You can do this as below:
inputlst['Cabbage']
Which returns:
'4,2,0'
Your dictionary values are all strings of numbers, which makes things more complicated. It will be easier to use those numbers if you could have them as lists e.g. [4, 2, 0], but we can change the string to a list and remove ',' like below:
values = list(inputlst[food])
values = [x for x in values if x != ',']
So now you have a list of the values ready to be used, so now its a case of multiplying each value by the values you specified above (5, 5 and 9). It might be useful to add these as variables into your function if they are likely to change, but for now I'm going to write it as below:
output = (values[0] * 5) + (values[1] * 5) + (values[2] * 9)
Then you will need to add return output to the end of your function. Hopefully that's enough information for you to be able to put together your function now.
I'm not sure if you have control over your input list or not. But if you do, try converting it to a list of integers instead of a comma separated string. Why? It requires a extra step to convert it to integers for the multiply action.
So turn it into this:
inputlst = {"Cabbage":[4, 2, 0], "Carrot":[9, 1, 5], "Fatty Pork":[431, 1, 5]}
If you're unable to to this directly, you can easily convert your input into this, using map:
inputlst = {"Cabbage":"4,2,0", "Carrot":"9,1,5", "Fatty Pork":"431,1,5"}
# Loop over all key and value in your dict.
for key, value in inputlst.items():
# Split string into the separate numbers.
new_value = value.split(',')
# Convert them into integers using ma[.
# map returns a map object, convert it into a list.
inputlst[key] = list(map(int, new_value))
print(inputlst) # {'Cabbage': [4, 2, 0], 'Carrot': [9, 1, 5], 'Fatty Pork': [431, 1, 5]}
Then in your code, you don't need to do any conversion of the data. Making it easier for yourself and keeps it simple (KISS approach):
# Define a constant with our multipliers.
MULTIPLIERS = [5, 5, 9]
def totalcalories(list_of_integers):
total = 0
# Loop over the integers and keep track of the index of the loop.
for i, integer_value in enumerate(list_of_integers):
# Fetch the multiplier we want for this index.
multiplier = MULTIPLIERS[i]
# Apply multiply and add it to the total.
total += (integer_value * multiplier)
return total
Which we can then easily call in a for loop:
>>> for key, value in inputlst.items():
>>> print(key, totalcalories(value))
Cabbage 30
Carrot 95
Fatty Pork 2205
Or of course just with the value you want:
>>> totalcalories(inputlst['Cabbage'])
30

Trying to make a "folded list" in python?

I need to make a "folded in half list" where I multiply the first and last term, second and second to last term, third and third to last term, etc.
I know how to make a list and how to print specific values from the list, but don't understand how to do math like this within the list, without simply typing each number and multiplying them.
So far all I have is a list (called a) with six terms, and though I know how to multiply the whole times an integer, I don't know how to make this "folded" thing. Will I need to end up making a loop of some sort? If so, how?
Edit: I should have specified that I need to make it via a function. Someone helped me make one via a method that worked great, but when I realized it needed to be a function I tried it again and it won't work. See the code below.
a = [10, 14, 21, 25 ,52, 55]
print('starting list:', a)
Finding the middle of the list
len(a)//2
Using (what I think is) a function to make a new list of first + last term, etc.
Term i is the term counted from the start of the list, term -(i+1) is the term counted from the bottom of the list
print(sum((a[i]) + (a[-(i + 1) ])) for i in range( len(a) // 2)
A code that works but isn't a function since it has brackets
foldedlist=[ a[i] + a[-(i + 1) ] for i in range( len(a) // 2)]
print('folded list:', foldedlist)
Take your list, here:
l = [1, 2, 3, 4, 5, 6]
Find the mid-way point (where the fold happens - you'll need to think about how this works for an odd-numbered length list)
l_mid = len(l) / 2
Make two sublists up to, and then from the mid-point
l1 = l[:l_mid]
l2 = l[l_mid:]
Create a container for the output and then iterate over both lists, with the latter reversed and append the product to the container.
output = []
for v1, v2 in zip(l1, reversed(l2)):
output.append(v1 * v2)
As we know, indexes in list can be positive or negative. Index -1 refers to last item, index -2 refers to second last item, etc. Hence, we must have:
L[0]*L[-1]+
L[1]*L[-2]+
L[2]*L[-3]+
...+
L[mid]*L[-(mid+1)]
The general formula is: L[i]*L[-(i+1)]. So, we can use the following code:
list = [1, 2, 3, 4, 5, 6]
newList=[ list[i] * list[-(i + 1) ] for i in range( len(list) // 2)]
print(newList)
len(list) // 2 is the index of middle of list.
Output: [6, 10, 12]
Try like this:
myList = [Yourlist]
newList = []
a = myList[:len(myList)//2]
b = myList[len(myList)//2:]
b.reverse()
for x,y in zip(a,b):
newList.append(x*y)

Filling a list inside a for loop in python

I am trying to make a vector out of two different ones as shown in the piece of code below.
However, I get a list out of range exception on the 5th line the first time the code goes in the for loop.
What am I doing wrong?
def get_two_dimensional_vector(speeds, directions):
vector = []
for i in range(10):
if (i % 2 == 0):
vector[i/2][0] = speeds[i/2]
else :
vector[i/2 - 1/2][1] = directions[i/2 - 1/2]
You can't use a Python list this way. It's not like a C array with a
predefined length. If you want to add a new element, you have to use the
append method or something.
Aside from that, you're also using a second index, implying that the
elements of vector are themselves lists or dicts or something, before
they've even been assigned.
It looks like you want to convert speeds and directions to a
two-dimensional list. So, first, here's how to do that with a loop. Note
that I've removed the fixed-size assumption you were using, though the
code still assumes that speeds and directions are the same size.
def get_two_dimensional_vector(speeds, directions):
vector = []
for i in range(len(speeds)):
vector.append([speeds[i], directions[i]])
return vector
speeds = [1, 2, 3]
directions = [4, 5, 6]
v = get_two_dimensional_vector(speeds, directions)
print(v)
Now, the Pythonic way to do it.
print(zip(speeds, directions))

python, loop nesting, functions, if statements

This is a somewhat garbled code excerpt.
The context is that it is trying to iterate through a list, building, which should look like [100, 92, 87, etc]. It wants to iterate through each floor of the building and then move that person (by decrementing the current floor) to the next available staircase.
My issue is nesting list and if statements within functions. It's a triple whammy and I'm having trouble understanding the proper syntax for:
calling on specific parts of lists of lists - i.e. list[i][j]
using if statements in loops
nesting loops
using loop variables in other loops
Here is my code:
def Evacuate(building):
while sum(building) > 0:
for i in building:
if building[i] > 0:
for j in range(STAIRCASE):
if staircasenetwork[j[i-1]] < CAPACITY:
building[i] -= 1
staircase[i-1] += [TRAVELTIME]
EDIT:
I figured out the issue. Building's input is a list. Staircasenetwork is also a list. The lists look like this
building = [100,90,101]
staircasenetwork = [[0,0,0],[0,0,0]]
This represents a 3 story building full of people and two empty staircases.
What I did wrong was I was trying to write something along the lines of:
for i in building:
#I'm skipping or simplifying some specific conditionals for the problem here
for j in staircasenetwork:
building[i] -= 1
staircasenetwork[j][i] += 1
Which was supposed to take (i) in building (which I expected to be [0, 1, 2]) and (j) in staircasenetwork (which I expected to be [0, 1]) and use those two co-ordinates to iterate through the lists I wrote.
What I forgot was that python iterates through a list by directly assigning those values to (i).
So if I have a list:
[100, 90, 101]
And I write:
for i in list:
print i
It will print:
100
90
101
Not:
0
1
2
So the fix to my problem was using range(len(building) instead of building.
This statement takes building and first converts it into an integer equal to the length of the list building using len(). Then it takes that integer and converts it into a list of numbers from 0 to X, using range().
Essentially: [100, 90, 101] >> 3 >> [0, 1, 2]
building = [100, 90, 101]
for i in range(len(building)):
print str(range(len(building))) + " " str(building)
Will print:
0 100
1 90
2 101
So in my first attempt, when i use:
for i in building:
#to call on
building[i]
The first thing it does is it looks at the first value in the building list, which is 100. Then it uses that number to find the 100th number in the building list, which doesn't exist because that list is only 3 values long.
It tries to do this:
building = [100, 90, 101]
for i in building
>>> first val of building = 100
building[100]
>>> IndexError: list index out of range
>>> Is looking for the 100th number in a 3-number long list
There are ways of using statements like:
for i, e in enumerate(building):
To create a list of tuples that may look like:
[(0, 100), (1, 90), (2, 101)]
But I preferred to use the range(len(building)) method. This method may not meet great benchmarks for speed, but it succeeds in teaching me something about how code works and it solves my little problem.
The fixed code will read:
for i in range(len(building)):
for j in range(len(staircasenetwork)):
building[i] -= 1
staircasenetwork[j][i] += 1
Now (i) and (j) will be the co-ordinates of (via range(len())) rather than direct reflections of the variables.
Lego Stormtrooper has also written a great response to other issues with my code.
Calling on specific parts of lists of lists - i.e. list[i][j]
You've got this correct in you question, but not in your code. Consider:
x = [ 1 , [2,3] ]
When we call x[0] we get an object, in this case the integer 1. Not much else to do.
But when we call x[1] we get a list ([2,3]) and then we can operate on that, like so x[1][1] which would give us 3.
In your code, break it down like this:
staircasenetwork[j[i-1]]
Is equivilent to:
x = j[i-1]
staircasenetwork[x]
So unless x is a valid index, it will fail.
Using if statements in loops
Use these like you would anywhere else:
for i in range(10):
if i%2 == 1:
print i
Will only print odd numbers below 10. Not much to it.
Nesting loops
Again, these operate like anywhere else. But you aren't accessing your items correct. In Python for x in some_list iterates through the items in the list, not the indexes.
So you want something like:
for floor in building:
if floor > 0:
Using loop variables in other loops
Variables have scope in their block, so:
for i in range(3):
x = i*2
# i and x in scope
for j in range(x):
# i, j, x and y are all in scope
y = i+j+x
print y
# The next line will fail because ONLY y isn't in scope.
# j is in scope, but is set to the final value of j for the above loop.
print i+j+x+y
Lastly, miscellaneous issue.
sum isn't magic. It won't do what you think there, as sum takes an iterable (list) of integers. You are passing an iterable of iterables.
Some of your variables are unset - specifically STAIRCASE, CAPACITY and TRAVELTIME

Rounding Numbers that fall within variable number of ranges in Python

I have an input list of numbers:
lst = [3.253, -11.348, 6.576, 2.145, -11.559, 7.733, 5.825]
I am trying to think of a way to replace each number in a list with a given number if it falls into a range. I want to create multiple ranges based on min and max of input list and a input number that will control how many ranges there is.
Example, if i said i want 3 ranges equally divided between min and max.
numRanges = 3
lstMin = min(lst)
lstMax = max(lst)
step = (lstMax - lstMin) / numRanges
range1 = range(lstMin, lstMin + step)
range2 = range(range1 + step)
range3 = range(range2 + step)
Right away here, is there a way to make the number of ranges be driven by the numRanges variable?
Later i want to take the input list and for example if:
for i in lst:
if i in range1:
finalLst.append(1) #1 comes from range1 and will be growing if more ranges
elif i in range2:
finalLst.append(2) #2 comes from range2 and will be growing if more ranges
else i in range3:
finalLst.append(3) #3 comes from range2 and will be growing if more ranges
The way i see this now it is all "manual" and I am not sure how to make it a little more flexible where i can just specify how many ranges and a list of numbers and let the code do the rest. Thank you for help in advance.
finalLst = [3, 1, 3, 3, 1, 3, 3]
This is easy to do with basic mathematical operations in a list comprehension:
numRanges = 3
lstMin = min(lst)
lstMax = max(lst) + 1e-12 # small value added to avoid floating point rounding issues
step = (lstMax - lstMin) / numRanges
range_numbers = [int((x-lstMin) / step) for x in lst]
This will give an integer for each value in the original list, with 0 indicating that the value falls in the first range, 1 being the second, and so on. It's almost the same as your code, but the numbers start at 0 rather than 1 (you could stick a + 1 in the calculation if you really want 1-indexing).
The small value I've added to lstMax is there for two reasons. The first is to make sure that floating point rounding issues don't make the largest value in the list yield numRange as its range index rather than numRange-1 (indicating the numRangeth range). The other reason is to avoid a division by zero error if the list only contains a single value (possibly repeated multiple times) such that min(lst) and max(lst) return the same thing.
Python has a very nice tool for doing exactly this kind of work called bisect. Lets say your range list is defined as such:
ranges = [-15, -10, -5, 5, 10, 15]
For your input list, you simply call bisect, like so:
lst = [3.253, -11.348, 6.576, 2.145, -11.559, 7.733, 5.825]
results = [ranges[bisect(ranges, element)] for element in lst]
Which results in
>>>[5, -10, 10, 5, -10, 10, 10]
You can then extend this to any arbitrary list of ranges using ranges = range(start,stop,step) in python 2.7 or ranges = list(range(start,stop,step)) in python 3.X
Update
Reread your question, and this is probably closer to what you're looking for (still using bisect):
from numpy import linspace
from bisect import bisect_left
def find_range(numbers, segments):
mx = max(numbers)
mn = mn(numbers)
ranges = linspace(mn, mx, segments)
return [bisect_left(ranges, element)+1 for element in numbers]
>>> find_range(lst, 3)
[3, 2, 3, 3, 1, 3, 3]

Categories

Resources