关于2a + 3b + 5c = 43的随机算法

0. 算法起源

    有童鞋在群里说到这个问题,但是这个问题实际上算是挺复杂的(对于初学者来说)。当然我也是初学者,所以自己也尝试写了一下代码。

1. 代码

# -*- coding:utf-8 -*-
import random

def divNums(numLst, n):
    """
    目的:对多项式numLst进行求值,使之等于n
    实例: 2a + 3b + 4c = 9,则numLst = [2, 3, 4], n = 9
    返回值: 返回一个列表,里面存储使之成立的值
    备注:
    1. numLst必须为列表,且所有的数据都是int
    2. 算法的基本思路为:假设numLst = [2, 3, 4], n = 9。[2, 3, 4]的倍数为[2, 4, 6, 8, 10], [3, 6, 9], [4, 8]。
    则从这三个数据中随机抽取一个数,如第一个列表抽取2, 第二个列表抽取3, 第三个列表抽取4,则2 + 3 + 4 = 9,则为答案
    3. 一般的想法是for循环所有的列表(这里循环三个列表),但是循环在以下情况下不成立:numLst的参数非常多的情况下,这样得使用递归函数来完成。
    """
    #判断数据输入的合法性
    assert type(n) == int and type(numLst) == list, "第二个参数必须为int,且第一个参数必须为列表"
    for item in numLst:
        assert type(item) == int, "第一个参数的列表里的数据,必须都为int"
        assert item <= n, "第一个参数的列表里的数据,必须小于等于第二个参数"
        
    #对numLst进行排序
    numLst.sort()
       
    #divLst存储numLst中每个数据的倍数集合 
    divLst = []
    for val in numLst:
        divLst.append([x for x in range(2, n + 1) if x % val == 0])
        
    lenLst = len(divLst)
    valLst = []
    result = []
    #采用随机算法:这里随机算法的重复次数必须进行预计,如果为n * n则答案不全
    for i in range(n * n * n):
        for j in range(lenLst):
            valLst.append(random.choice(divLst[j]))
        else:
            #如果值等于n并且值之前并没有找到
            if n == sum(valLst) and valLst not in result:
                result.append(valLst)
            valLst = []
        
    for i in range(len(result)):
        result[i] = map(lambda x, y : x / y, result[i], numLst)
            
    return result
        
#可举例[2, 3, 5], 43 或者 [2, 3, 5, 7], 123
result = divNums([2, 3, 5], 43)
print result
print len(result)

答案输出:

%run "/home/lcj/divNums.py"
[[16, 2, 1], [1, 12, 1], [12, 3, 2], [5, 6, 3], [7, 8, 1], [3, 4, 5], [4, 5, 4], [2, 3, 6], 
[6, 7, 2], [5, 1, 6], [13, 4, 1], [1, 7, 4], [10, 1, 4], [2, 8, 3], [11, 2, 3], [9, 5, 2],
 [4, 10, 1], [8, 4, 3], [1, 2, 7], [6, 2, 5], [15, 1, 2], [7, 3, 4], [3, 9, 2], [10, 6, 1]]
24

备注:

1. 有注释,故不解释。可能存在错误,请轻拍

2. 如果为[2, 3, 4, 7], 123,则必须增加随机循环的次数

你可能感兴趣的:(关于2a + 3b + 5c = 43的随机算法)