拆分账单


12

任务

假设ppepole必须拆分钞票;每一个都由一个三元组标识,该三元组(Name, n, k)由以下各项组成:

  • Name名称 ;
  • n他/他必须支付的金额
  • k她/他实际支付的金额

这里的挑战是找出谁欠谁的钱。

假设条件

  • 输入和输出可以采用任何方便的格式。

  • p N,n N+, k N.

  • p >1.

  • 名称是任意长度的唯一字符串,由小写字母字符组成。

解决方案以p人们之间的最小交易量为代表。特别是三元组(from, to, amount)

  • fromname给钱的人;
  • toname收钱者的;
  • amount:交易金额。

注意:所有债务的总和(n)可能与所有已付金额的总和(k)不同。在这种情况下,您必须添加输出('owner', Name, amount)(Name, 'owner', amount)所选的格式。任何名称都不会是owner。字符串'owner'是灵活的。

如果存在多个最小集合,则选择所有交易金额(绝对值)的总和最小的集合;如果是平局,选择其中之一。

测试用例:

inputs(Name,n,k):
[('a',30,40),('b',40,50),('c',30,15)]
[('a',30,30),('b',20,20)]
[('a',30,100),('b',30,2),('c',40,0)]
[('a',344,333),('b',344,200),('c',2,2)]
[('a',450,400),('b',300,300),('c',35,55)]

outputs(from, to, amount):
[('c','a',10),('c','b',5),('owner','b',5)] or [('c','b',10),('c','a',5),('owner','a',5)]
[]
[('owner','a',2),('b','a',28),('c','a',40)] PS: [('owner','a',2),('b','a',68),('c','b',40)] has the same number of transactions, but it is not a valid answer, because the total amount of its transaction is greater than that of the proposed solution.
[('a','owner',11),('b','owner',144)]
[('a','owner',30),('a','c',20)]

这是代码高尔夫:最短的代码胜出


1
我认为您应该更改“您必须输出需要最少事务处理的最简化的方案。” “必须输出需要最少事务处理的方案。如果存在多个这样的方案,请选择总交易概念最少的方案。” 因为我相信这更清楚。
乔纳森·艾伦

1
很好的挑战。但这可能需要更复杂的测试用例,以确保解决方案始终是最佳的。
Arnauld

3
什么是“最小总概念”?
lirtosiast

1
@JonathanAllan仍然对“名义”一词感到困惑。那是哪里来的 根据测试用例3,看起来一个人应该更喜欢同一个人既不给予也不接受的答案?那是对的吗?还为什么将其描述为概念性的?
乔纳

1
@Jonah我使用“总概念”,因为不应考虑交易的方向(只是它们的绝对大小),尽管我现在意识到它有些多余(因为一旦打破平局就不会考虑两个相互抵消的交易) !)。[名义上只是金融中使用的术语。]
乔纳森·艾伦

Answers:


2

的JavaScript(ES6), 252个227 223 222  215字节

将输入作为[[n0, k0, name0], [n1, k1, name1], ...]

解决方案中的交易可能是正面的也可能是负面的。所有者称为undefined

a=>(m=g=(B,t,s)=>B.some(x=>x)?B.map((b,x)=>B.map((c,y)=>b*c<0&b*b<=c*c&&g(C=[...B],[...t,[a[x][2],b,a[y][2]]],s+a.length-1/b/b,C[C[y]+=b,x]=0))):m<s||(r=t,m=s))([...a.map(([x,y])=>t-(t+=y-x),t=0),t],[],a.push(g))&&r

在线尝试!

已评论

a => (                              // a[] = input array
  m =                               // initialize m to a non-numeric value
  g = (B, t, s) =>                  // g = function taking: B = balances, t = transactions,
                                    //     s = score of the current solution
    B.some(x => x) ?                // if at least one balance is not equal to 0:
      B.map((b, x) =>               //   for each balance b at position x:
        B.map((c, y) =>             //     for each balance c at position y:
          b * c < 0 &               //       if b and c are of opposite sign
          b * b <= c * c &&         //       and |b| <= |c|,
          g(                        //       do a recursive call to g:
            C = [...B],             //         - with a copy C of B
            [ ...t,                 //         - append the new transaction to t[]
              [a[x][2], b, a[y][2]] //           in [from_name, amount, to_name] format
            ],                      //
            s + a.length - 1/b/b,   //         - add (a.length - 1/b²) to s
            C[C[y] += b, x] = 0     //         - update C[y] and clear C[x]
          )                         //       end of recursive call
        )                           //     end of inner map()
      )                             //   end of outer map()
    :                               // else:
      m < s ||                      //   if the score of this solution is lower than m,
      (r = t, m = s)                //   update r to t and m to s
)(                                  // initial call to g:
  [                                 //   build the list of balances:
    ...a.map(([x, y]) =>            //     each balance is equal to:
      t - (t += y - x),             //     due_value - paid_value
      t = 0                         //     keep track of the total t ...
    ),                              //
    t                               //   ... which is appended at the end of this array
  ],                                //   (this is the balance of the owner)
  [],                               //   start with t = []
  a.push(g)                         //   append a dummy owner to a[]; start with s = 1
) && r                              // return r
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.