Розщеплення законопроекту


12

Завдання

Припустимо, що pпеполу доведеться розділити рахунок; кожен з них ідентифікується трійкою, (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
Я думаю, вам слід змінити "Ви повинні вивести найпростіший сценарій, який вимагає найменшої кількості транзакцій". "Ви повинні вивести сценарій, який вимагає найменшої кількості транзакцій. Якщо існує кілька таких сценаріїв, виберіть один із найменшим загальним рівнем транзакцій." оскільки я вважаю, що це зрозуміліше.
Джонатан Аллан

1
Приємний виклик. Але, ймовірно, знадобляться більш складні тестові випадки, щоб переконатися, що рішення дійсно завжди оптимальні.
Арнольд

3
Що таке "найменше загальне поняття"?
lirtosiast

1
@JonathanAllan все ще плутає слово "розумний". звідки це походить? На основі тестового випадку 3 схоже, що слід віддавати перевагу відповідям, коли одна і та сама людина не дає і не отримує? це правильно? також чому це описується як вигадане?
Йона

1
@Jonah Я використовував "повну умовну", оскільки напрямки транзакцій не слід враховувати (лише їх абсолютний розмір), хоча зараз я усвідомлюю, що це дещо зайве (оскільки два транзакції, які протидіють одна одній, не вважатимуться колись розривом розриву. !). [Умовним є лише термін, що використовується у фінансах.]
Джонатан Аллан

Відповіді:


2

JavaScript (ES6),  252 227 223 222  215 байт

Вводиться як " [[n0, k0, name0], [n1, k1, name1], ...].

Операції з рішенням можуть бути як позитивними, так і негативними. Власник називається невизначеним .

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.