python在组合数学中的应用入门

本文介绍了Python编程中的语法基础,包括异常处理、递归函数如阶乘的实现、循环结构、元组和列表的区别,以及如何使用字典和类进行数据存储。还涵盖了组合数学概念,如阶乘的循环和递归版本,以及如何计算子集和贝尔数的示例。
摘要由CSDN通过智能技术生成

语法基础

异常处理

def factorial(x):
    if x < 0:
        raise Exception("Invalid input to factorial")
    if x == 0:
        return 1
    return x * factorial(x-1)

用raise抛出一个exception异常

输出

print(x[1:]) # Take all elements from the first one onwards
print(x[2:4]) # Take elements 2 and 3 (we do not take last member of sequence)

for循环

实际上'range(x)'  相当于 list [0,1,..,x-1].

注意:range(起始,终止,步长)取不到右端点值,所以我们要写range(1,10,2)而非range(1,9,2)

for i in range(1,x+1):
   total = total * i
# Or even a 'step' size as a third argument, so we could get the odd numbers between 1 and 9 by writing
 range(1,10,2)

dict()

类似c++中的map,存储key和对应的value,

# In the next section we will want to use a 'dict' to store value we are caching.
# A dict is a map from keys to values
# Create a dict
name = dict()
name["Chris"] = "Jefferson"
print("Chris" in name)
print("Karen" in name)
print(name["Chris"])

我在name中存储了key为"Chris";value为"jefferson"。结果如下

部分运行用shift+enter,撤回用ctrl+z

元组和列表

元组使用小括号,列表使用中括号

# Values in dicts must be immutable (cannot be changed). Lists are mutable, so we cannot use them as keys
# name[ [1,2,3] ] = 6 <-- This would produce an error.
# In Python, lists which cannot change (are immutable) are called tuples, and they are made with round brackets
name[ (1,2,3) ] = 6 # Works fine

# If we have a list, we can turn it into a tuple using 'tuple'
l = [1,2,3]
print(name[tuple(l)]) # Prints '6'

字典中key的value不可以改变,列表中的元素值可以改变,所以显然我们不可以把列表作为dict()的key值。元组tuple则可以当作key值,它的元素不可以改变。

列表的增删

两个list合并

# You can add lists together using '+'
x = [4,5,6,7,8,9]
y = [6,5]
print(x+y)

用appent()添加

# Or we can add an element to a list using 'append'
x.append(2)
print(x)

编码技巧

循环的简写
in_list = [2,3,4,5,6]
out_list = []
for i in in_list:
    out_list.append(i*i)
print(out_list)

# We can write this as:    
other_out_list = [i*i for i in in_list]
print(other_out_list)

组合数学

阶乘

递归实现
def factorial(x):
    if x == 0:
        return 1
    return x * factorial(x-1)
循环实现
for
def factorial_for(x):
    total = 1
    for i in range(x):
        total = total * (i + 1)
    return total
while
def factorial_while(x):
    total = 1
    while x > 0:
        total = total * x
        x = x - 1
    return total

部分阶乘

递归实现
def falling_factorial(n,k):
    return factorial(n)//factorial(n-k)
循环实现

# Technically, it is a bit of a waste to calculate the two factorials, as lots of terms end up cancelling out, so we can instead only ltiply the terms we need. Notice how the 'range' here is a bit tricky
def falling_factorial_for(n,k):
    total = 1
    for i in range(n-k+1, n+1):
        total = total * i
    return total

# We could implement this another way:
def falling_factorial_for_2(n, k):
    result = 1
    for i in range(k):
        result *= n
        n -= 1
    return result

组合数公式

def choose(n,k):
    return factorial(n)//(factorial(n-k) * factorial(k))

注意:为了答案是整数用整除,否则是x.0的形式

阶乘之间的乘除

用list列表
# Here, the second argument is a list
def multinomial(n, list):
    top = factorial(n)
    bottom = 1
    # We can iterate through lists, performing a calculation at every step
    for k in list:
        bottom *= factorial(k)
    return top//bottom

print(multinomial(8,[3,3,2]))

8的阶乘/(3的阶乘*3的阶乘*2的阶乘)

'squig'数

用squig数的递归定义
# Let us now try defining 'squig'.
# While this produces the right answer, it will be very slow for larger values
def squig(s,t):
    if s == 0:
        return (t == 0)
    if t < 0:
        return 0

    return t*squig(s-1,t) + squig(s-1,t-1)
    
squig(10,2)
用全局变量作为"寄存器"
squig_cache = dict()

def squig(s,t):
    if s == 0:
        return (t == 0)
    if t < 0:
        return 0
    global squig_cache
    if (s,t) in squig_cache:
        return squig_cache[(s,t)]
    
    ret = t*squig(s-1,t) + squig(s-1,t-1)
    squig_cache[(s,t)] = ret
    return ret

相当于c++中的记忆化搜索

用类实现

# This use of a global variable is not very neat. We would be better using a class
class Squig:
    
    def __init__(self):
        self.cache = dict()

    def get(self, s,t):
        if s == 1:
            return (t==1)
        if t < 0:
            return 0
        
        if (s,t) in self.cache:
            return self.cache[(s,t)]
        
        ret = t*self.get(s-1,t) + self.get(s-1,t-1)
        self.cache[(s,t)] = ret
        return ret

s = Squig()
s.get(10,2)

贝尔数的计算

# Calculating the 'bell' number will take a very long time to run (4 seconds on my computer for bell(20)), as 'squig' is too slow
def bell(s):
    return sum([squig(s,k) for k in range(s+1)])
    
print(bell(20))

例题

1.求集合的子集
# How can we find all subsets of a set. We can do this recursively
def all_subsets_of(list):
    # The empty set has only a single subset -- the empty set!
    if list == []:
        return [ [] ]
    else:
        # list[1:] takes the list ignoring the first element
        no_first = all_subsets_of(list[1:])
        others = []
        for l in no_first:
            others.append([list[0]] + l)
        return no_first + others

all_subsets_of([1,2,3])

递归实现将n-1个元素的子集加上添加进第n个元素之后新增的集合

2.如果我们限制输出的子集的大小
def all_subsets_of_size_k(list, k):
    #特殊条件处理
    # If we want sets of size '0', there is just the empty set.
    if k == 0:
        return [ [] ]
    # If the list has less than 'k' members, then we can't make any sets of size k
    if len(list) < k:
        return []
    #其他(与上面一样)  
    part1 = all_subsets_of_size_k(list[1:], k)
    # sets of size k-1 which do not include list[0], which we will then add 'list[0]' to
    part2 = all_subsets_of_size_k(list[1:], k-1)
    part2withk = []
    for l in part2:
        part2withk.append([list[0]] + l)
    return part1 + part2withk

all_subsets_of_size_k([1,2,3,4], 2)

  • 48
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值