我有一个投票系统,用于人们评价从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
答案 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)