Understanding factorials and alternate code - python-3.x

Python newbie here. I am trying to understand the following code to calculate Euler's number:
import math
num(i=10):
sum([1 / math.factorial(z) for z in range(0, i)])
I would really like to get a better grasp on how equations are done in code. I have read many tutorials, but I don't understand them well enough to apply a concept to unique situations like in the above code. Can someone just explain to me what is happening in this code step by step? Additionally, I have not been able to figure out how to do factorials, and it would be very helpful to me if someone would explain how input a factorial in a function (the hard way) without imports.

for you to understand the above code, you first must understand the language itself. e=1/0!+1/1!+1/2!+1/3!+1/4!+..., so you need to do:
total=0
for i in range(100):
total +=1/math.factorial(i)
print(total)
2.7182818284590455
in case you understand what a for loop is and how it runs. This is much faster compared to what you wrote above.
Now in python there is something called list comprehension. That is, creating a list from a for-loop without necessarily pre-defining the list. so you can do `[i for i in range(10)] which will create a list of 10 elements. You can therefore manipulate each element as you create the list ie
[i**2 for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
so in your case you are doing [1/math.factorial(i) for i in range(100)]. This creates the list [1.0, 1.0, 0.5, 0.16666666666666666, 0.041666666666666664,...] which you then add the list by calling sum on this list. ie sum([1/math.factorial(i) for i in range(100)])
Defining your own factorial
factorial is a function that multiplies all numbers from 1 to the specified value. with factorial(0) set at 1
factorial(3)= 1*2*3.
thus you can define it as:
def factorial(x):
if x == 0: return 1
val = 1
for i in range(1,x+1):
val *=i
return val
factorial(3)
Out[40]: 6
factorial(4)
Out[41]: 24
You can also use recursiveness to define factorial:
def factorial(x):
if x==0: return 1
else: return x * factorial(x-1)

Related

How to print the Pascal's extended triangle for negative numbers?

(https://i.stack.imgur.com/v9sj1.png)
Hi all, I am currently trying to calculate and print out the pascals extended triangle for negative numbers (-1, -2, ..., -10)
I am aware of the math library but I want to try without the usage of libraries, recursion, lists, string and the other related operations.
the ideal output should be something like this:
(https://i.stack.imgur.com/fnmpL.png)
So I have went ahead and coded up my own factorial function, and a attempt at coding the nCk function:
def factorial(n):
result = 1
for i in range(1, n+1):
result = i
return result
def n_choose_k(n, k):
return factorial(n) / (factorial(k) * factorial(n-k))
when I tried to validate if it works or not, I picked out a value from the sample output from above, where k equals to 6 and n equals to -7
def factorial(n):
result = 1
for i in range(1, n+1):
result = i
return result
def n_choose_k(n, k):
return factorial(n) / (factorial(k) * factorial(n-k))
print(n_choose_k(-7, 6))
^^ what I ran in my program.
the result should be 924 but instead I got 0.166.
Am I calling the functions wrong? Is there an error in my code?
I am a super noob in terms of programming, much feedback is appreciated.
*sidenote im not sure why my images arent showing, also a noob for this website!

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]

Multiplying functions together in Python

I am using Python at the moment and I have a function that I need to multiply against itself for different constants.
e.g. If I have f(x,y)= x^2y+a, where 'a' is some constant (possibly list of constants).
If 'a' is a list (of unknown size as it depends on the input), then if we say a = [1,3,7] the operation I want to do is
(x^2y+1)*(x^2y+3)*(x^2y+7)
but generalised to n elements in 'a'. Is there an easy way to do this in Python as I can't think of a decent way around this problem? If the size in 'a' was fixed then it would seem much easier as I could just define the functions separately and then multiply them together in a new function, but since the size isn't fixed this approach isn't suitable. Does anyone have a way around this?
You can numpy ftw, it's fairly easy to get into.
import numpy as np
a = np.array([1,3,7])
x = 10
y = 0.2
print(x ** (2*y) + a)
print(np.sum(x**(2*y)+a))
Output:
[3.51188643 5.51188643 9.51188643]
18.53565929452874
I haven't really got much for it to be honest, I'm still trying to figure out how to get the functions to not overlap.
a=[1,3,7]
for i in range(0,len(a)-1):
def f(x,y):
return (x**2)*y+a[i]
def g(x,y):
return (x**2)*y+a[i+1]
def h(x,y):
return f(x,y)*g(x,y)
f1= lambda y, x: h(x,y)
integrate.dblquad(f1, 0, 2, lambda x: 1, lambda x: 10)
I should have clarified that the end result can't be in floats as it needs to be integrated afterwards using dblquad.

Is there a solution for the match-mapping-group pattern in python by Functional programming?

For example, I have a list such as [2, 4, 7, 9, 6, 12, 38]. I want to firstly recognize each number by whether it is odd, then add 100 to each odd and 101 to each even,finally get two lists.
There are 3 steps:
1. Number matching that it is odd or even
2. Add a proper decimal to each odd and even
3. Group to two list
In python, might need 3 minimal functions, but still how should we reach the goal by using Functional programming?
The order of the steps seems forced and makes functional programming a lot harder, so with an open order a Python implementation would be the following:
odd = lambda x: x % 2 == 1
even = lambda x: not odd(x)
l = [2, 4, 7 ,9 ,36]
listodd = [i + 100 for i in l if odd(i)]
listeven = [i + 101 for i in l if no odd(i)]
So every list is created with one expression, and list comprehensions are definitely valid functional programming. Another way to express the list comprehension would be with filter and map:
listodd = map(filter(l, odd), lambda x: x + 100)
listeven = map(filter(l, even), lambda x: x + 101)
The code is still highly redundant, but as for now I have no idea how to write this shorter and cleaner.

Typed Lists in Theano

Consider the following machine translation problem. Let s be a source sentence and t be a target sentence. Both sentences are conceptually represented as lists of indices, where the indices correspond to the position of the words in the associated dictionaries. Example:
s = [34, 68, 91, 20]
t = [29, 0, 43]
Note that s and t don't necessarily have the same length. Now let S and T be sets of such instances. In other words, they are a parallel corpus. Example:
S = [[34, 68, 91, 20], [4, 7, 1]]
T = [[29, 0, 43], [190, 37, 25, 60]]
Note that not all s's in S have the same length. That is, sentences have variable numbers of words.
I am implementing a machine translation system in Theano, and the first design decision is what kind of data structures to use for S and T. From one of the answers posted on Matrices with different row lengths in numpy , I learnt that typed lists are a good solution for storing variable length tensors.
However, I realise that they complicate my code a lot. Let me give you one example. Say that we have two typed lists y and p_y_given_x and aim to calculate the negative loss likelihood. If they were regular tensors, a simple statement like this would suffice:
loss = t.mean(t.nnet.categorical_crossentropy(p_y_given_x, y))
But categorical_crossentropy can only be applied to tensors, so in case of typed lists I have to iterate over them and apply the function separately to each element:
_loss, _ = theano.scan(fn=lambda i, p, y: t.nnet.categorical_crossentropy(p[i], y[i]),
non_sequences=[p_y_given_x, y],
sequences=[t.arange(y.__len__(), dtype='int64')])
loss = t.mean(_loss)
On top of making my code more and more messy, these problems propagate. For instance, if I want to calculate the gradient of the loss, the following doesn't work anymore:
grad_params = t.grad(loss, params)
I don't know exactly why it doesn't work. I'm sure it has to do with the type of loss, but I am not interested in investigating any further how I could make it work. The mess is growing exponentially, and what I would like is to know whether I am using typed lists in the wrong way, or if it is time to give up on them because they are not well enough supported yet.
Typed list isn't used by anybody yet. But the idea for having them is that you iterate on them with scan for each sentence. Then you do everything you need in 1 scan. You don't do 1 scan for each operation.
So the scan is only used to do the iteration on each example in the minibatch, and the inside of scan is all what is done on one example.
We haven't tested typed list with grad yet. It is possible that it is missing some implementations.

Resources