법안 나누기


12

직무

ppepole이 청구서를 분할해야 한다고 가정하십시오 . 각각은 다음 (Name, n, k)과 같이 구성된 트리플 로 식별됩니다 .

  • Name: 이름 ;
  • n: 양 그녀 / 그가 지불해야 ;
  • k: 실제로 지불 한 금액 .

여기서의 과제는 누가 누구를 빚지고 있는지 알아내는 것입니다.

가정

  • 입력 및 출력은 편리한 형식 일 수 있습니다.

  • p N,n N+, k N.

  • p >1.

  • 이름은 임의의 길이의 고유 한 문자열이며 소문자 알파벳 문자로 구성됩니다.

해결책

솔루션은 p사람들 간의 최소 트랜잭션 세트로 표현됩니다 . 특히 그들은 트리플입니다(from, to, amount)

  • from: name돈을주는 사람의;
  • to: name돈을받는 사람의;
  • amount: 거래 금액

참고 : 모든 부채의 합계 ( n)는 이미 지불 된 모든 금액의 합계 ( )와 다를 수 있습니다 k. 이 경우 출력 ('owner', Name, amount)또는 (Name, 'owner', amount)선택한 형식으로 추가해야합니다 . 모든 이름은 결코 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
"최소 횟수의 트랜잭션이 필요한 가장 간단한 시나리오를 출력해야합니다."를 변경해야한다고 생각합니다. "최소 횟수의 트랜잭션이 필요한 시나리오를 출력해야합니다. 이러한 시나리오가 여러 개인 경우 총 트랜잭션 수가 가장 적은 시나리오를 선택하십시오." 나는 그것이 더 명확하다고 믿기 때문에.
Jonathan Allan

1
좋은 도전입니다. 그러나 솔루션이 항상 최적인지 확인하려면보다 복잡한 테스트 사례가 필요할 수 있습니다.
Arnauld

3
"최소 총 명목"이란 무엇입니까?
lirtosiast

1
@JonathanAllan은 여전히“notional”이라는 단어와 혼동됩니다. 그게 어디에서 오는거야? 테스트 사례 3을 기반으로 같은 사람이주고받지 않는 답변을 선호 해야하는 것처럼 보입니까? 그 맞습니까? 또한 왜 이것이 명목으로 묘사됩니까?
요나

1
@Jonah 나는 트랜잭션의 방향을 절대 크기로 간주해서는 안되기 때문에 "총 명목"을 사용했지만 이제는 중복성이 있음을 깨달았습니다. !). [명목은 금융에서 사용되는 용어 일뿐입니다.]
Jonathan Allan

답변:


2

자바 스크립트 (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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.