Làm thế nào để tôi yêu cầu một giao dịch viên rút tiền tại ngân hàng?


35

Tôi cần đến ngân hàng và rút một số tiền. Tôi cần rút $ 30, $ 22 để trả cho bạn cùng phòng của mình cho internet và $ 8 cho việc giặt ủi. Vì cả hai đều không thể thay đổi, tôi cần $ 30 của mình để được chia thành hai phân vùng có hai kích cỡ. Điều đó có nghĩa là khi người giao dịch hỏi tôi muốn 30 đô la như thế nào, tôi sẽ phải đưa ra yêu cầu. Tôi có thể nói với họ rằng tôi muốn nó trong hai mươi, một kẻ rùng mình và năm người. Nhưng tôi muốn làm cho yêu cầu của tôi đơn giản nhất có thể để tránh phải lặp lại chính mình. Để làm cho yêu cầu của tôi đơn giản hơn, tôi có thể yêu cầu tiền mặt của tôi chứa hai mươi và ít nhất 2 cái vì 8 được ngụ ý trong tổng số, nhưng tốt hơn tôi có thể yêu cầu một trong những hóa đơn tôi nhận được là một hóa đơn một đô la (Nếu bạn không bị thuyết phục về điều này chỉ cố gắng kiếm 29 đô la mà không kiếm được 8).

Vì vậy, tất cả đều ổn và bảnh bao nhưng tôi cần thực hiện phép tính này mỗi khi đến ngân hàng nên tôi nghĩ tôi sẽ viết một chương trình để làm việc này (bạn có viết chương trình để làm việc này cho tôi không).

Chương trình hoặc chức năng của bạn nên có một danh sách các số nguyên đại diện cho tất cả các khoản thanh toán tôi cần thực hiện và một bộ số nguyên biểu thị các mệnh giá của các hóa đơn có sẵn tại ngân hàng và bạn phải xuất ra danh sách các mệnh giá nhỏ nhất để mọi cách tạo ra tổng số bao gồm danh sách mệnh giá đó có thể được phân chia rõ ràng thành danh sách thanh toán.

Quy tắc bổ sung

  • Bạn có thể cho rằng danh sách mệnh giá sẽ luôn chứa một 1hoặc bạn có thể tự thêm nó vào mỗi danh sách.

  • Một số đầu vào sẽ có nhiều giải pháp tối thiểu. Trong những trường hợp này, bạn có thể xuất một trong hai.

Đây là vì vậy câu trả lời sẽ được tính bằng byte với ít byte hơn.

Các trường hợp thử nghiệm

Payments, denominations    -> requests
{22,8}    {1,2,5,10,20,50} -> {1} or {2}
{2,1,2}   {1,5}            -> {1}
{20,10}   {1,2,5,10,20,50} -> {}
{1,1,1,1} {1,2}            -> {1,1,1}
{20,6}    {1,4,5}          -> {1}
{2,6}     {1,2,7}          -> {2}
{22, 11}  {1, 3, 30, 50}   -> {1, 3}
{44, 22}  {1, 3, 30, 50}   -> {1, 3, 3, 30}

22
Lúc đầu, tôi nghĩ đây là thư rác hoặc lạc đề hoặc một cái gì đó ...
Erik the Outgolfer

1
Đoạn văn @EriktheOutgolfer làm tổn thương những thách thức rất nhiều> _ <
Bạch tuộc ma thuật Urn

2
Tôi nghĩ bạn nên bao gồm ít nhất một trường hợp thử nghiệm trong đó yêu cầu phải là một cái gì đó không phải là hóa đơn một đô la, như thế {2,6} {1,2,7} -> {2}.
Arnauld

@Arnauld Tôi đã thêm trường hợp của bạn
Thuật sĩ lúa mì

1
(If you are not convinced of this just try to make 29 dollars without making 9)Ý bạn là không làm 8? Hoặc đã làm tôi hiểu sai
undergroundmonorail

Câu trả lời:


5

JavaScript (ES6), 485 476 byte

Được rồi ... đây là một con quái vật. :-(
Nhưng đó là một con quái vật khá nhanh, giải quyết tất cả các trường hợp thử nghiệm gần như ngay lập tức.

Tôi có thể thử chơi golf nâng cao hơn sau này, nhưng tôi đã dành quá nhiều thời gian cho nó.

f=(b,a,L=[...a])=>L.reduce((a,x)=>[...a,...a.map(y=>[x,...y])],[[]]).sort((a,b)=>a[b.length]||-1).find(L=>(Y=G(U(b)-U(L),L.sort((a,b)=>a-b)),Y[0]&&!Y.some(a=>P(b.map(a=>G(a,[]))).every(b=>b+''!=a))),U=a=>~~eval(a.join`+`),P=(e,C=[],R=[])=>e[0].map(v=>R=(c=v.map((x,i)=>x+(C[i]|0)),e[1])?[...P(e.slice(1),c),...R]:[c,...R])&&R,G=(n,l)=>(S=[],g=(n,l)=>n?a.map(x=>x<l[0]|x>n||g(n-x,[x,...l])):S=[l.map(v=>s[a.indexOf(v)]++,s=[...a].fill(0))&&s,...S])(n,l)&&S)||f(b,a,[...a,...L])

Các trường hợp thử nghiệm

Làm sao?

NB: Điều này không phù hợp với phiên bản hiện tại nữa, nhưng dễ đọc hơn nhiều.

// b = list of payments, a = list of bills,
// L = list from which the requested bills are chosen
f = (b, a, L = [...a]) => (
  // U = helper function that computes the sum of an array
  U = a => ~~eval(a.join`+`),

  // P = function that computes the summed Cartesian products of arrays of integers
  // e.g. P([[[1,2],[3,4]], [[10,20],[30,40]]]) --> [[33,44], [13,24], [31,42], [11,22]]
  P = (e, C = [], R = []) => e[0].map(v => R =
    (c = v.map((x, i) => x + (C[i] | 0)), e[1]) ? [...P(e.slice(1), c), ...R] : [c, ...R]
  ) && R,

  // G = function that takes a target amount and a list of requested bills and returns
  // all combinations that contain the requested bills and add up to this amount;
  // each combination is translated into a list of number of bills such as [2,0,0,1,0]
  G = (n, l) => (
    S = [],
    g = (n, l) => n ?
      a.map(x => x < l[0] | x > n || g(n - x, [x, ...l])) :
      S = [l.map(v => s[a.indexOf(v)]++, s = [...a].fill(0)) && s, ...S]
  )(n, l) && S,

  // compute X = list of possible bill combinations to process all payments
  X = P(b.map(a => G(a, []))),

  // compute the powerset of L and sort it from shortest to longest list
  L.reduce((a, x) => [...a, ...a.map(y => [x, ...y])], [[]])
  .sort((a, b) => a[b.length] || -1)

  .find(L => (
    // compute Y = list of possible combinations to reach the total amount,
    // using the requested bills
    Y = G(U(b) - U(L), L.sort((a, b) => a - b)),

    // exit if Y is not empty and all combinations in Y allow to generate all payments
    Y[0] && !Y.some(a => X.every(b => b + '' != a)))
  )

  // if no solution was found, enlarge the set of requested bills and try again
  || f(b, a, [...a, ...L])
)

Tôi không quá quen thuộc với javascript, nhưng bạn có thể giảm &&tới &||đến |?
Taylor Scott

@TaylorScott Điều này chỉ có thể trong một số điều kiện nhất định. Chẳng hạn, a || bsẽ bchỉ đánh giá nếu alà giả, trong khi a | bsẽ vô điều kiện thực hiện một chút HOẶC giữa ab.
Arnauld

4

Python 2 , 456 455 byte

Vô cùng, vô cùng, vô cùng chậm chạp !!!! Nên hoạt động chính xác trên tất cả các ví dụ đầu vào đủ thời gian

Chỉnh sửa: Đã lưu 1 byte nhờ @Jonathan Frech

def F(p,d):v=sum(p);E=enumerate;l=lambda x,y:y[1:]and(x>=y[-1]and[k+[y[-1]]for k in l(x-y[-1],y)]+l(x,y[:-1])or l(x,y[:-1]))or[[1]*x];Q=l(v,d);m=lambda x,y=[0]*len(p):x and max(m(x[1:],[a+x[0]*(i==j)for i,a in E(y)])for j,_ in E(y))or y==p;f=lambda x,h=[]:x and min([S for i,s in E(x)for S in h+[s],f(x[:i]+x[i+1:],h+[s])if all(map(m,filter(lambda k:all(k.count(j)>=S.count(j)for j in S),Q)))],key=len)or[1]*v;print-(all(map(m,Q))-1)*min(map(f,Q),key=len)

Hãy thử trực tuyến!

Giải trình

p,d=input() # Read input
v=sum(p) # Save a byte by keeping track of the total money withdrawn
E=enumerate # We use enumerate a lot
# Generates the possible combinations of denominators that add up to the withdrawn amount 
l=lambda x,y:y[1:]and(x>=y[-1]and[k+[y[-1]]for k in l(x-y[-1],y)]+l(x,y[:-1])or l(x,y[:-1]))or[[1]*x]
# We use the list generated by l quite a few times
Q=l(v,d)
# Checks if we can divide a list of denominators x in such a way that we get the wished division of the money
m=lambda x,y=[0]*len(p):x and max(m(x[1:],[a+x[0]*(i==j)for i,a in E(y)])for j,_ in E(y))or y==p
# For a list of denominators, it tries all possible combinations of the denominators as input to the teller, selecting the one with minimum length
f=lambda x,h=[]:x and min([S for i,s in E(x)for S in h+[s],f(x[:i]+x[i+1:],h+[s])if all(map(m,filter(lambda k:all(k.count(j)>=S.count(j)for j in S),Q)))],key=len)or[1]*v
# Call f with all possible lists of denominators, and check if saying nothing to the teller will work
print-(all(map(m,Q))-1)*min(map(f,Q),key=len)

1
Sử dụng một hàm chứ không phải input()một byte ngắn hơn .
Jonathan Frech
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.