查找乘以数字列表的数字

时间:2017-03-23 22:27:41

标签: python algorithm

我有一个投票系统,用于人们评价从1到10的东西。我能够得到总票数,但不能得到他们的分配。但是,我可以访问每个分数的总数(但不是它们的分数)。

例如,假设有两个人投了2个投票,然后是3投4,那么我会得到[4,12]。从人的角度来说,可能会弄清楚投票的内容,但是由于存在大量数据,我需要一种能够以编程方式完成的算法。为了解决这个问题,我会知道有5票,而且我知道这是一票四四票,两票二票三票。因为这不是最好的例子,我们无法分辨它会是哪一个,所以在这种情况下,算法应该吐出所有的解决方案。对于真实的数据,很少发生类似的事情。

输入的形式为int,表示投票的总票数,以及所有投票小计的列表。输出应该是一个包含pars(x,y)的数组,其中有y个投票数。如果存在多个解决方案,则算法应将所有解决方案返回到数组中。

修改 这是一些真实数据(17人投票):

Dunkel      - 60 + 18 + 8  + 18 + 10 + 4  + 3 + 1     = 122
Satomi      - 20 + 14 + 24 + 12 + 3  + 4  + 3         = 80
Bottersnike - 16 + 28 + 5  + 8  + 6  + 4  + 4         = 71
Woon        - 40 + 36 + 8  + 21 + 5  + 16             = 126
Limelier    - 10 + 18 + 6  + 15 + 8  + 4  + 6         = 67
RandomGamer - 16 + 6  + 10 + 4  + 6  + 4  + 7         = 53
Pillar      - 10 + 8  + 21 + 6  + 15 + 4  + 9 + 4 + 2 = 79
EdgedPixel  - 8  + 28 + 12 + 4  + 18 + 2  + 2         = 74
Lock        - 20 + 24 + 7  + 18 + 10 + 8  + 6 + 2     = 95
Huri        - 10 + 8  + 7  + 6  + 15 + 20 + 3 + 2 + 3 = 74
Sean        - 18 + 32 + 8  + 5  + 4  + 9  + 2         = 78

答案(抱歉订单不同):

Woon        - 4*10 + 4*9 + 1*8 + 3*7 + 0*6 + 1*5 + 4*4 + 0*3 + 0*2 + 0*1 = 126
Dunkel      - 6*10 + 2*9 + 1*8 + 0*7 + 3*6 + 2*5 + 1*4 + 1*3 + 0*2 + 1*1 = 122
Lock        - 2*10 + 0*9 + 3*8 + 1*7 + 3*6 + 2*5 + 2*4 + 2*3 + 0*2 + 2*1 = 95
Satomi      - 2*10 + 0*9 + 3*8 + 4*7 + 2*6 + 0*5 + 0*4 + 1*3 + 2*2 + 3*1 = 80
Pillar      - 1*10 + 0*9 + 1*8 + 3*7 + 1*6 + 3*5 + 1*4 + 3*3 + 2*2 + 2*1 = 79
Sean        - 0*10 + 0*9 + 4*8 + 0*7 + 3*6 + 1*5 + 2*4 + 3*3 + 2*2 + 2*1 = 78
EdgedPixel  - 0*10 + 0*9 + 1*8 + 4*7 + 2*6 + 0*5 + 1*4 + 6*3 + 1*2 + 2*1 = 74
Huri        - 1*10 + 0*9 + 1*8 + 1*7 + 1*6 + 3*5 + 5*4 + 1*3 + 1*2 + 3*1 = 74
Bottersnike - 0*10 + 0*9 + 2*8 + 4*7 + 0*6 + 1*5 + 2*4 + 2*3 + 2*2 + 4*1 = 71
Limelier    - 1*10 + 2*9 + 0*8 + 0*7 + 1*6 + 3*5 + 2*4 + 0*3 + 2*2 + 6*1 = 67
RandomGamer - 0*10 + 0*9 + 2*8 + 0*7 + 1*6 + 2*5 + 1*4 + 2*3 + 2*2 + 7*1 = 53

2 个答案:

答案 0 :(得分:0)

  

我需要一种能够以编程方式执行的算法

我首先考虑你的总数。

What is the most efficient way of finding all the factors of a number in Python?

def factors(n):    
    return set(reduce(list.__add__, 
                ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
  

这将很快返回数字n的所有因素。

这会让你顺利;显然,列出的总数中没有5个因素并非来自评分为5的组

步骤1)计算总计列表中的每个数字

步骤2)创建包含所有可能评级作为键的字典;即键1-10;每个都有空列表作为值。

步骤3)检查每个因素列表是否具有与每个评级密钥匹配的因子;如果是,则将它所代表的总数附加到相应密钥的可能性值列表

from random import randint
from random import shuffle

VOTES = 200
RATINGS = 10

# Generate Test Data
ratings = {}
for i in range(1,(RATINGS+1)):
    ratings[i] = []
for i in range(VOTES):
    rate = randint(1,RATINGS)
    ratings[rate].append(rate)

subtotals = []
for key, values in ratings.iteritems():
   subtotals.append(sum(values))
subtotals = [i for i in subtotals if i != 0]
subtotals.sort()

hidden_subtotals = {}
for key, values in ratings.iteritems():
   hidden_subtotals[key] = sum(values)

print '==================================='
print 'Generate Hidden Test Data'
print 'unknown actual votes: %s' % ratings
print 'unknown actual subtotals: %s' % hidden_subtotals 
print '==================================='
print 'Present Problem'
print 'known vote total: %s' % VOTES
print 'known subtotals: %s' % subtotals
print 'known total: %s' % sum(subtotals)
print 'number of ratings used: %s of %s' % (len(subtotals), RATINGS)
print '==================================='

def factors(n):    
    f = list(set(reduce(list.__add__, ([i, n//i] for i in range(
        1, int(n**0.5) + 1) if n % i == 0))))
    f.sort()
    return f

# Factor Each
subtotal_factors = {}
for i in subtotals:
    subtotal_factors[i]=(factors(i))
print 'process 1: %s' % subtotal_factors

# Remove Factors greater than highest rating
possible_ratings = {}
for i in subtotal_factors:
   possible_ratings[i] = [
      z for z in subtotal_factors[i] if z<=RATINGS]
print 'process 2: %s' % possible_ratings

# Remove Factors if not enough votes for that possibility; too small relative to subtotal
for i in possible_ratings:
    possible_ratings[i] = [
        z for z in possible_ratings[i] if i/z < VOTES]
print 'process 3: %s' % possible_ratings

步骤4)然后你会遇到一个问题,其中2将适合4,6,8,10,10; 4将适用于8,而3将适用于6和9。您必须应用一些逻辑来清理结果。

答案 1 :(得分:0)

我现在已经解决了我的问题。我使用了litepresence的代码作为基础,然后实现了他们所描述的第四步。对于将来,这是我使用的代码:

from random import randint
from random import shuffle
import itertools

NUM_RATINGS = 10
RATING = [10, 10, 10, 10, 10, 10, 9, 9, 8, 6, 6, 6, 5, 5, 4, 3, 1]
VOTES = len(RATING)


ratings = {}
for i in range(1, (NUM_RATINGS + 1)):
    ratings[i] = []
for i in RATING:
    ratings[i].append(i)


subtotals = []
for key, values in ratings.iteritems():
   subtotals.append(sum(values))
subtotals = [i for i in subtotals if i != 0]
subtotals.sort()

hidden_subtotals = {}
for key, values in ratings.iteritems():
   hidden_subtotals[key] = sum(values)

print '==================================='
print 'Hidden Test Data:'
print 'unknown actual votes: %s' % ratings
print 'unknown actual subtotals: %s' % hidden_subtotals 
print '==================================='
print 'Present Problem:'
print 'known vote total: %s' % VOTES
print 'known subtotals: %s' % subtotals
print 'known total: %s' % sum(subtotals)
print 'number of ratings used: %s of %s' % (len(subtotals), NUM_RATINGS)
print '==================================='

def factors(n):    
    f = list(set(reduce(list.__add__, ([i, n//i] for i in range(
        1, int(n**0.5) + 1) if n % i == 0))))
    f.sort()
    return f

# Factor Each
subtotal_factors = {}
for i in subtotals:
    subtotal_factors[i]=(factors(i))
print 'process 1: %s' % subtotal_factors

# Remove Factors greater than highest rating
possible_ratings = {}
for i in subtotal_factors:
   possible_ratings[i] = [
      z for z in subtotal_factors[i] if z<=NUM_RATINGS]
print 'process 2: %s' % possible_ratings

# Remove Factors if not enough votes for that possibility; too small relative to subtotal
for i in possible_ratings:
    possible_ratings[i] = [
        z for z in possible_ratings[i] if i/z < VOTES]
print 'process 3: %s' % possible_ratings


end_res = {}
other = {}  # (count, [poss])
for i in possible_ratings.items():
    if len(i[1]) == 1:
        end_res[i[0]] = (i[1][0], i[1][0])
    else:
        other[i[0]] = (subtotals.count(i[0]), i[1])

combs = {}
for i in other.items():
    combs[i[0]] = (i[1][0], [])  # (count, [data])
    for a in i[1][1]:
        for b in i[1][1]:
            if (a, b) not in combs[i[0]]:
                if a * b == i[0]:
                    combs[i[0]][1].append((a, b))

lists = []
for i in combs.items():
    for j in range(i[1][0]):
        lists.append([])
        for n in i[1][1]:
            lists[-1].append((n[0], n[1], i[0]))

toprocess = itertools.product(*lists)
working = []

for test in toprocess:
    works = True
    seen = []
    tot = 0
    for i in test:
        if i[1] in seen:
            works = False
            break
        tot += i[0]
        if tot > VOTES:
            works = False
            break
        seen.append(i[1])
    if not works:
        continue
    else:
        working.append(test)

formattedWs = []
for w in working:
    w = list(w)
    notseen = [i + 1 for i in range(NUM_RATINGS)]
    for i in w:
        notseen.remove(i[1])
    for i in notseen:
        w.append((0, i))

    t = ""
    def f(x, y):
        return y[1] - x[1]

    w.sort(cmp=f)

    for i in w:
        t += "%d*%d + " % (i[0], i[1])
    t = t[:-3]
    formattedWs.append(t)

seen = []
for w in list(formattedWs):
    if w in seen:
        formattedWs.remove(w)
    else:
        seen.append(w)

print "==================================="
for n, w in enumerate(formattedWs):
    print "Solution #%d: %s" % (n + 1, w)