Faturayı Bölme


12

Görev

Diyelim ki ppepol bir faturayı bölmeli; her biri aşağıdakilerden oluşan üçlü ile tanımlanır (Name, n, k):

  • Name: isim ;
  • n: ödemek zorunda olduğu miktar ;
  • k: Gerçekte ödediği tutar .

Buradaki zorluk kimin kime borçlu olduğunu bulmaktır.

Varsayımlar

  • Giriş ve çıkış herhangi bir uygun formatta olabilir.

  • p N-,n N-+, k N-.

  • p >1.

  • İsimler, küçük harfli alfabe karakterlerinden oluşan, rastgele uzunluktaki benzersiz dizelerdir.

Çözüm

Çözüm, pinsanlar arasındaki minimum işlemlerle temsil edilir ; özellikle onlar üçlü(from, to, amount)

  • from: namepara veren kişinin;
  • to: namepara alan kişinin;
  • amount: işlemin para miktarı.

NOT : Tüm borçların ( n) toplamı, halihazırda ödenmiş olan tutarların ( k) toplamından farklı olabilir . Bu durumda, çıktıya ('owner', Name, amount)veya (Name, 'owner', amount)seçtiğiniz biçimde eklemeniz gerekir . 'Ad owner' dizesi esnektir.

Birden fazla minimum küme varsa, tüm işlem tutarlarının (toplam değerler) minimum toplamına sahip olanı seçin; Beraberlik durumunda bunlardan birini seçin.

Test Durumları:

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)]

Bu kod golf: en kısa kod kazanır .


1
Sanırım "En az sayıda işlem gerektiren en basitleştirilmiş senaryoyu çıkarmanız gerekiyor." "En az sayıda işlem gerektiren senaryonun çıktısını almalısınız. Bu tür birden çok senaryo varsa, işlemlerin toplam tutarı en düşük olanı seçin." çünkü daha açık olduğuna inanıyorum.
Jonathan Allan

1
Güzel bir meydan okuma. Ancak, çözümlerin gerçekten her zaman optimal olmasını sağlamak için muhtemelen daha karmaşık test senaryoları gerekecektir.
Arnauld

3
"En az toplam kavramsal" nedir?
lirtosiast

1
@JonathanAllan hala “kavramsal” kelimesi ile karıştı. bu nereden geliyor? Test örneği 3'e dayanarak, aynı kişinin hem vermediği hem de almadığı cevapları tercih etmesi gerekir gibi görünüyor? bu doğru mu? ayrıca bu neden kavramsal olarak tanımlanıyor?
Jonah

1
@Jonah "toplam kavramsal" kullandım, çünkü işlemlerin yönleri dikkate alınmamalıdır (sadece mutlak boyutları), ancak artık biraz gereksiz olduğunu fark ettim (birbirini engelleyen iki işlemin bir kez bağlandığını düşünmeyeceğim gibi) !). [Notional, sadece finansta kullanılan terimdir.]
Jonathan Allan

Yanıtlar:


2

JavaScript (ES6),  252 227 223 222  215 bayt

Girişi alır [[n0, k0, name0], [n1, k1, name1], ...].

Çözeltideki işlemler pozitif veya negatif olabilir. Sahibine undefined adı verilir .

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

Çevrimiçi deneyin!

Yorumlananlar

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.