简体   繁体   English

均匀分组的最好方法是什么?

[英]What's the best way to evenly split a groups total?

I am trying to evenly distribute the total amount to each person involved. 我正在尝试将总额平均分配给每个相关人员。

For example i will use money. 例如我会用钱。

Example 1 例子1

Person A has $20 人物A有$ 20

Person B has $40 乙人有$ 40

Person C has $60 人物C有$ 60

So to make everything even the solution is Person C giving person A $20. 因此,要使所有事情都解决,便是人C给人A 20美元。

Example 2 例子2

Person A has $36 人物A有$ 36

Person B has $15 人B有$ 15

Person C has $9 人物C有$ 9

To make this situation even... 为了使这种情况甚至...

Person A gives Person B $16 then Person B gives Person C $11, 人A给人B $ 16,然后人B给人C $ 11,

Or Person A gives Person B $5 and Person C $11 或人A给人B $ 5和人C $ 11

Example 3 例子3

Person A has $53 人物A有$ 53

Person B has $95 人B有$ 95

Person C has $24 人物C有$ 24

Person D has $98 人D有$ 98

Person E has $30 人E有$ 30

Each Person needs $60, How could i figure out the way to do this that involves the least amount of moving the money around? 每个人需要60美元,我怎么能找出这种方式以最少的钱花钱呢?

A natural approach is: the person with the most gives to the person with the least; 一个自然的方法是:最多的人给最少的人; then repeat. 然后重复。

Specifically: you can calculate the amount V everyone should have at the end (it's just the average of everyone's starting amounts). 具体来说:您可以计算每个人末期应拥有的V值(这只是每个人的初始金额的平均值)。 Then if the person with the most has M and the person with the least has L, give min(MV,VL) from the person with the most to the person with the least. 然后,如果拥有最多的人拥有M,拥有最少的人拥有L,则将拥有最多的人的min(MV,VL)赋予拥有最少的人。 After that move, at least one of those two people has the correct amount. 此举之后,这两个人中至少有一个拥有正确的数量。 Now repeat until everyone has the desired amount. 现在重复,直到每个人都有所需的数量。

The number of moves will be at most the number of people. 搬家的人数最多为人数。

I suspect this might be optimal, but you should check that yourself. 我怀疑这可能是最佳选择,但您应该自己检查一下。 You might try applying the methods in https://cs.stackexchange.com/q/59964/755 to see if you can find a counterexample or prove it correct. 您可以尝试应用https://cs.stackexchange.com/q/59964/755中的方法,以查看是否可以找到反例或证明其正确。

It seems a shame to leave such a question unanswered because it's not difficult to solve - let's use your last example: 留下这样一个问题没有答案似乎很可耻,因为这并不难解决-让我们使用您的最后一个示例:

  • Person A has $53 人物A有$ 53
  • Person B has $95 人B有$ 95
  • Person C has $24 人物C有$ 24
  • Person D has $98 人D有$ 98
  • Person E has $30 人E有$ 30

I'll use an array for simplicity. 为了简单起见,我将使用数组。

const totals = [53, 95, 24, 98, 30]
let sum, target, moveCounter = 0

if (totals.length) {
  sum = totals.reduce(function(a, b) { return (a + b) })
  target = sum / totals.length
}

The target is simply the average of the totals, $60 in the case of the example. 目标只是总数的平均值,在示例中为60美元。

let needs = totals.map(function(a){ return target - a })
// needs = [7, -35, 36, -38, 30]

Now you know what each of the needs are. 现在您知道了每种needs

[0] needs to get $7, [1] needs to drop $35, [2] needs to get $36, etc. [0]需要获得$ 7,[1]需要降低$ 35,[2]需要获得$ 36,依此类推。

The array is zero sum : (7) + (-35) + (36) + (-38) + (30) = 0 数组为零和:(7)+(-35)+(36)+(-38)+(30)= 0

Your problem is how to get each of the elements to 0 in as few moves as possible. 您的问题是如何在尽可能少的移动中将每个元素都设为0。

You can check if any of the elements cancel each other out, for example [20, -20]. 您可以检查是否有任何元素相互抵消,例如[20,-20]。 An efficient way to check this would be to create a Set. 一种有效的检查方法是创建一个Set。

let unmatched = new Set([])
let matches = []
needs.forEach((need) => {
  if (0 !== need) {
    let value = Math.abs(need)
    if (unmatched.has(value)) {
      matches.concat([need, -need])
      unmatched.delete(value)
    } else {
      unmatched.add(value)
    }
  }
})

if (matches.length) {
  matches.forEach((matchElement) => {
    let index = needs.findIndex((needElement) => {
      return matchElement === needElement
    })
    if (index) {
      needs[index] = needs[index] - matchElement
      moveCounter = moveCounter + 1
  })
}

At this point all of the easy moves are done, you can sort the array and brute force the rest. 至此,所有简单的步骤都已完成,您可以对数组进行排序,然后对其余数组进行蛮力操作。 Sorting makes things a little bit easier. 排序使事情变得容易一些。

var sortedNeeds = needs.sort(function(a, b){ return a < b ? -1 : 1 })
// [-38, -35, 7, 30, 36]

The array is zero sum so you could split it into two parts left and right . 该阵列是零和游戏,所以你可以把它分成两个部分, leftright Think of it as the left and right side of a balanced equation. 将其视为平衡方程的左侧和右侧。

const zeroIndex = sortedNeeds.findIndex((value) => { return 0 === value })
// zeroIndex : -1

const positiveIndex = sortedNeeds.findIndex((value) => { return value > 0 })
// positiveIndex : 2

const leftLimit = (zeroIndex > -1) ? zeroIndex : positiveIndex
// leftLimit : 2

let left = sortedNeeds.slice(0, leftLimit)
// left: [-38, -35]

let right = sortedNeeds.slice(positiveIndex)
// right: [7, 30, 36]

The next piece is magic: 下一块是魔术:

moveCounter = moveCounter + (left.length - 1) + right.length
// 4 = 0 + 1 + 3

It doesn't matter how you work it out because the zero sum relationship is the key. 求和无关紧要,因为零和关系是关键。

  1. D gives B $38 D给B $ 38
  2. B gives A $7 B给A $ 7
  3. B gives C $36 B给C $ 36
  4. B gives E $30 B给E $ 30

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在打字稿中拆分字符串的最佳方法是什么 - What is the best way to split the string in typescript 在Rails应用程序中拆分Javascript或Coffeescript的最佳方法是什么? - What's the best way to split up my Javascript or Coffeescript in a Rails app? 每次遇到元素时将数组拆分为多个数组的最佳方法是什么? - What's the best way to split an array into multiple arrays every time an element is met? 在Javascript中从DynamoDB拆分JSON格式的字符串的最佳方法是什么 - What's the best way to split up a JSON formatted string from DynamoDB in Javascript 重写这个的最好方法是什么? - What's the best way to rewrite this? 从D3中的列表形成年龄组的最佳方法是什么? - What is the best way to form age groups from a list in D3? 在javascript中执行split()并忽略空白条目的最佳方法是什么? - What is the best way to do split() in javascript and ignore blank entries? 分割字符串的最佳方法是什么(可能是复杂的正则表达式)? (JavaScript的/ jquery的) - What is the best way to split a string (possible with complicated regex)? (javascript/jquery) 离子应用程序代码可以拆分的最佳方式是什么? - What is the best way in which ionic application code can be split? 替换 eval 的最佳方法是什么? - What's the best way to replace eval?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM