Nghịch lý phân chia


10

Được:

  • Một số tự nhiên S .
  • Một danh sách N trọng số hợp lý W tổng bằng 1.

Trả về danh sách L gồm N số nguyên không âm, sao cho:

(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal

Nói cách khác, S⋅W_is gần đúng với số nguyên càng sát càng tốt.

Ví dụ:

1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]

Quy tắc:

  • Bạn có thể sử dụng bất kỳ định dạng đầu vào nào, hoặc chỉ cung cấp một hàm chấp nhận đầu vào làm đối số.

Lý lịch:

Vấn đề này xuất hiện khi hiển thị S của các loại mặt hàng khác nhau theo tỷ lệ khác nhau W i liên quan đến các loại.

Một ví dụ khác về vấn đề này là đại diện chính trị tỷ lệ, xem nghịch lý phân chia . Hai trường hợp thử nghiệm cuối cùng được gọi là nghịch lý Alabama.

Là một nhà thống kê, tôi nhận ra vấn đề này tương đương với một vấn đề gặp phải trong việc xác định kích thước mẫu khi tiến hành mẫu phân tầng. Trong tình huống đó, chúng tôi muốn làm cho tỷ lệ của mỗi tầng trong mẫu bằng với tỷ lệ của mỗi tầng trong dân số. - @tomi


Bạn có thể nói bằng lời nhiệm vụ là gì không? Tôi gặp khó khăn khi giải nén các biểu thức thành một cái gì đó trực quan.
xnor 14/2/2015

Cả hai nên được, cố định. Nhiệm vụ là trình bày một số nguyên dưới dạng tổng của các số nguyên dựa trên trọng số. Phần còn lại nên phân phối ủng hộ trọng lượng cao nhất, mặc dù tôi không chắc yêu cầu này được mã hóa chính xác? Điều này rất thú vị bởi vì round(A + B) != round(A) + round(B), một giải pháp ngắn đòi hỏi một cái nhìn sâu sắc về những gì đang diễn ra ở đây.
glebm 14/2/2015

1
Có thể thay đổi quy tắc để giảm thiểu tổng khoảng cách L[i] - S*W[i]bình phương, thay vì quy tắc 2 và quy tắc 3. Điều này sẽ gần đúng S*W[i].
Jakube 14/2/2015

1
Ngoài ra [0 1 2 2] là một giải pháp khả thi khác cho5 [0.1 0.2 0.3 0.4]
Jakube 14/2/2015

1
Có lẽ bạn nên thêm một ví dụ cho 1 [0,4 0,3]
aditsu bỏ vì SE là NGÀY 15/2/2015

Câu trả lời:


6

APL, 21

{{⍵+1=⍋⍋⍵-⍺}⍣⍺/⍺0×⊂⍵}

Đây là bản dịch từ câu trả lời CJam 37 byte của aditsu .

Kiểm tra nó trực tuyến .

Giải trình

 {      ⍵-⍺}            ⍝ Right argument - left argument.
 {  1=⍋⍋⍵-⍺}            ⍝ Make one of the smallest number 1, others 0.
 {⍵+1=⍋⍋⍵-⍺}            ⍝ Add the result and the right argument together.
 {⍵+1=⍋⍋⍵-⍺}⍣⍺          ⍝ Repeat that S times. The result of each iteration is the new right argument.
                  ⊂⍵    ⍝ Return enclosed W, which is taken as one unit in APL.
               ⍺0×⊂⍵    ⍝ Return S*W and 0*W.
{{⍵+1=⍋⍋⍵-⍺}⍣⍺/⍺0×⊂⍵}   ⍝ Make S*W the left argument, 0*W the right argument in the first iteration.

7

Con trăn 2, 95 83 132 125 143

Thuật toán đầu tiên (và thứ hai) (và thứ ba) của tôi có vấn đề nên sau khi viết lại (khác!) Và thử nghiệm nhiều hơn, đây là (tôi thực sự hy vọng) một giải pháp chính xác và nhanh chóng:

def a(b,h):
 g=h;c=[];d=[]
 for w in b:f=int(w*h);d+=[f];c+=[h*w-f];g-=f
 if g:
  for e in sorted(c)[-g:]:i=c.index(e);c[i]=2;d[i]+=1
 return d

Nguồn trước trình khai thác bây giờ trông như sau:

# minified 143 bytes
def golfalloc(weights, num):
    # Tiny seq alloc for golfing
    gap = num;
    errors = [];
    counts = []
    for w in weights :
        count = int(w*num);
        counts += [count];
        errors += [num*w - count];
        gap -= count
    if gap:
        for e in sorted(errors)[-gap:] :
            i = errors.index(e);
            errors[i] = 2;
            counts[i] += 1
    return counts

Các bài kiểm tra trở lại:

Pass                    Shape    N               Result Error                        AbsErrSum
ok            [0.4, 0.3, 0.3]    1            [1, 0, 0] -0.60,+0.30,+0.30                 1.20
ok                  [0, 1, 0]    3            [0, 3, 0] +0.00,+0.00,+0.00                 0.00
ok            [0.3, 0.4, 0.3]    4            [1, 2, 1] +0.20,-0.40,+0.20                 0.80
ok            [0.3, 0.4, 0.3]    5            [2, 2, 1] -0.50,+0.00,+0.50                 1.00
ok            [0.3, 0.2, 0.5]   21           [6, 4, 11] +0.30,+0.20,-0.50                 1.00
ok       [0.1, 0.2, 0.3, 0.4]    5         [1, 1, 1, 2] -0.50,+0.00,+0.50,+0.00           1.00
ok          [0.11, 0.3, 0.59]    4            [1, 1, 2] -0.56,+0.20,+0.36                 1.12
ok         [0.47, 0.47, 0.06]   10            [5, 5, 0] -0.30,-0.30,+0.60                 1.20
ok         [0.43, 0.43, 0.14]   10            [4, 4, 2] +0.30,+0.30,-0.60                 1.20
ok         [0.43, 0.43, 0.14]   11            [5, 5, 1] -0.27,-0.27,+0.54                 1.08

Thuật toán này tương tự như các câu trả lời khác ở đây. Đó là O (1) cho num nên nó có cùng thời gian chạy cho các số nguyên 10 và 1000000. Về mặt lý thuyết là O (nlogn) cho số lượng trọng số (vì sắp xếp). Nếu điều này chịu được tất cả các trường hợp đầu vào khó khăn khác, nó sẽ thay thế thuật toán bên dưới trong hộp công cụ lập trình của tôi.

Vui lòng không sử dụng thuật toán đó với bất cứ thứ gì không phải là golf. Tôi đã thỏa hiệp về tốc độ để giảm thiểu kích thước nguồn. Đoạn mã sau sử dụng cùng logic nhưng nhanh hơn và hữu ích hơn nhiều:

def seqalloc(anyweights, num):
    # Distribute integer num depending on weights.
    # weights may be non-negative integers, longs, or floats.
    totalbias = float(sum(anyweights))
    weights = [bias/totalbias for bias in anyweights]
    counts = [int(w*num) for w in weights]
    gap = num - sum(counts)
    if gap:
        errors = [num*w - q for w,q in zip(weights, counts)]
        ordered = sorted(range(len(errors)), key=errors.__getitem__)
        for i in ordered[-gap:]:
            counts[i] += 1
    return counts

Giá trị của num không ảnh hưởng đáng kể đến tốc độ. Tôi đã thử nghiệm nó với các giá trị từ 1 đến 10 ^ 19. Thời gian thực hiện thay đổi tuyến tính với số lượng trọng lượng. Trên máy tính của tôi, mất 0,15 giây với 10 ^ 5 trọng lượng và 15 giây với 10 ^ 7 trọng lượng. Lưu ý rằng các trọng số không bị giới hạn ở các phân số tổng thành một. Kỹ thuật sắp xếp được sử dụng ở đây cũng nhanh gấp khoảng hai lần so với sorted((v,i) for i,v in enumerate...)phong cách truyền thống .

Thuật toán gốc

Đây là một chức năng trong hộp công cụ của tôi, được sửa đổi một chút cho golf. Nó ban đầu từ một câu trả lời SO . Và nó sai.

def seqalloc(seq, num):
    outseq = []
    totalw = float(sum(seq))
    for weight in seq:
        share = int(round(num * weight / totalw)) if weight else 0
        outseq.append(share)
        totalw -= weight
        num -= share
    return outseq

Nó đưa ra một xấp xỉ, nhưng không phải lúc nào cũng đúng, mặc dù tổng (outseq) == num được duy trì. Nhanh nhưng không nên.

Cảm ơn @alephalpha và @ user23013 vì đã phát hiện ra các lỗi.

EDIT: Đặt Totalw (d) thành 1 vì OP chỉ định tổng trọng số sẽ luôn là 1. Bây giờ là 83 byte.

EDIT2: Đã sửa lỗi tìm thấy cho [0,4, 0,3, 0,3], 1.

EDIT3: Thuật toán bị bỏ sót. Đã thêm một cái tốt hơn.

EDIT4: Điều này đang trở nên lố bịch. Thay thế bằng thuật toán chính xác (tôi thực sự hy vọng như vậy).

EDIT5: Đã thêm mã không chơi gôn cho những người khác có thể muốn sử dụng thuật toán này.


4
a([0.4, 0.3, 0.3], 1)trả về [0, 1, 0], trong khi câu trả lời đúng là [1, 0, 0].
alephalpha

1
Vẫn sai. a([0.11,0.3,0.59],4)trở về [0, 1, 3]. Nên [1, 1, 2].
jimmy23013

1
f([0.47,0.47,0.06],10)trở về [5, 4, 1]. Nên [5, 5, 0].
jimmy23013

2
Tôi nghĩ bây giờ đã đúng.
jimmy23013

2
@CarpetPython Tôi đã trải qua một quá trình tương tự với thuật toán này và đây là cách tôi đưa ra vấn đề này. Nếu họ lấy đi giấy phép của bạn, họ cũng sẽ lấy của tôi :)
glebm

4

Toán học, 67 50 46 45 ký tự

f=(b=⌊1##⌋;b[[#~Ordering~-Tr@#&[b-##]]]++;b)&

Ung dung:

f[s_, w_] := Module[{a = s*w, b, c, d},
  b = Floor[a];
  c = b - a;
  d = Ordering[c, -Total[c]];
  b[[d]] += 1;
  b]

Thí dụ:

f[5,{0.1,0.2,0.3,0.4}]

{1, 1, 1, 2}


Chúa ơi, thật ngắn ngủi, coi đó là Mathicala!
DavidC

3

CJam - 37

q~:W,0a*\:S{[_SWf*]z::-_:e<#_2$=)t}*p

Dùng thử trực tuyến

Giải trình:

q~             read and evaluate the input
               (pushing the number and the array on the stack)
:W,            save the array in variable W and calculate its length (N)
0a*            make an array of N zeros (the initial "L")
\:S            swap it with the number and save the number in S
{…}*           execute the block S times
    [_SWf*]    make a matrix with 2 rows: "L" and S*W
    z          transpose the matrix, obtaining rows of [L_i S*W_i]
    ::-_       convert to array of L_i-S*W_i and duplicate
    :e<        get the smallest element
    #          find its index in the unsorted array,
               i.e. the "i" with the largest S*W_i-L_i
    _2$=)t     increment L_i
p              print the result nicely

Ghi chú:

  • Độ phức tạp là về O (S * N), vì vậy nó trở nên rất chậm đối với S lớn
  • CJam rất thiếu các toán tử số học cho 2 mảng, một cái gì đó tôi dự định thực hiện sau

Ý tưởng khác biệt - 46

q~:Sf*_:m[_:+S\-@[1f%_,,]z{0=W*}$<{1=_2$=)t}/p

Dùng thử trực tuyến

Điều này đơn giản và hiệu quả hơn nhiều, nhưng than ôi, lâu hơn một chút. Ý tưởng ở đây là bắt đầu với L_i = floor (S * W_i), xác định sự khác biệt (giả sử D) giữa S và tổng của chúng, tìm các chỉ số D có phần phân số lớn nhất của S * W_i (bằng cách sắp xếp và lấy D hàng đầu) và tăng L_i cho các chỉ số đó. Độ phức tạp O (N * log (N)).


Bây giờ có O (N) :e<.
jimmy23013

@ user23013 oh yeah, đối với chương trình đầu tiên, cảm ơn
aditsu đã thoát vì SE là EVIL 14/2/2015

Nó thật nhanh! Xin chúc mừng 🌟
glebm 14/2/2015

Đối với những người thắc mắc, thay thế sắp xếp bằng thuật toán chọn thời gian tuyến tính sẽ mang lại O (n) thay vì O (nlogn) thực tế gây ra bởi sắp xếp: Tìm phần tử lớn nhất của D, P, trong O (N), sau đó tăng các phần tử có thời gian ≥PD (O (N) kể từ D <= N).
glebm 17/2/2015

@glebm Điều đó khá tuyệt, nhưng tôi nghĩ có vấn đề nếu nhiều yếu tố có cùng giá trị (P). Có lẽ bạn có thể giải quyết nó trong 2 lần sau đó: tăng đầu tiên và đếm các phần tử> P, sau đó bạn biết cần bao nhiêu phần tử = P. Hoặc nếu bạn có thể lấy thông tin đó từ thuật toán lựa chọn, thậm chí tốt hơn.
aditsu bỏ vì SE là EVIL

3

JavaScript (ES6) 126 130 104 115 156 162 194

Sau tất cả các nhận xét và trường hợp thử nghiệm trong câu trả lời của @ RugPython, hãy quay lại thuật toán đầu tiên của tôi. Than ôi, giải pháp thông minh không hoạt động. Việc thực hiện rút ngắn một chút, nó vẫn cố gắng tất cả các giải pháp có thể, tính khoảng cách bình phương và giữ mức tối thiểu.

Chỉnh sửa Đối với mỗi phần tử đầu ra của trọng số w, 'tất cả' các giá trị có thể chỉ là 2: trunc (w * s) và trunc (w * s) +1, do đó, chỉ có (2 ** elemensts) có thể thử các giải pháp.

Q=(s,w)=>
  (n=>{
    for(i=0;
        r=q=s,(y=i++)<1<<w.length;
        q|r>n||(n=r,o=t))
      t=w.map(w=>(f=w*s,q-=d=0|f+(y&1),y/=2,f-=d,r+=f*f,d));
  })()||o

Kiểm tra trong bảng điều khiển Firefox / FireBug

;[[ 1,  [0.4, 0.3, 0.3]      ]
, [ 3,  [0, 1, 0]            ]
, [ 4,  [0.3, 0.4, 0.3]      ]
, [ 5,  [0.3, 0.4, 0.3]      ]
, [ 21, [0.3, 0.2, 0.5]      ]
, [ 5,  [0.1, 0.2, 0.3, 0.4] ]
, [ 4,  [0.11, 0.3, 0.59]    ]
, [ 10, [0.47, 0.47, 0.06]   ]
, [ 10, [0.43, 0.43, 0.14]   ]
, [ 11, [0.43, 0.43, 0.14]   ]]
.forEach(v=>console.log(v[0],v[1],Q(v[0],v[1])))

Đầu ra

1 [0.4, 0.3, 0.3] [1, 0, 0]
3 [0, 1, 0] [0, 3, 0]
4 [0.3, 0.4, 0.3] [1, 2, 1]
5 [0.3, 0.4, 0.3] [1, 2, 2]
21 [0.3, 0.2, 0.5] [6, 4, 11]
5 [0.1, 0.2, 0.3, 0.4] [0, 1, 2, 2]
4 [0.11, 0.3, 0.59] [1, 1, 2]
10 [0.47, 0.47, 0.06] [5, 5, 0]
10 [0.43, 0.43, 0.14] [4, 4, 2]
11 [0.43, 0.43, 0.14] [5, 5, 1]

Đó là một giải pháp thông minh hơn. Vượt qua duy nhất trên mảng weigth.
Đối với mỗi lần vượt qua tôi tìm giá trị tối đa hiện tại trong w. Tôi thay đổi giá trị này tại chỗ bằng giá trị nguyên có trọng số (làm tròn lên), vì vậy nếu s == 21 và w = 0,4, chúng tôi nhận được 0,5 * 21 -> 10,5 -> 11. Tôi lưu trữ giá trị này bị phủ định, vì vậy không thể được tìm thấy tối đa trong vòng lặp tiếp theo. Sau đó, tôi giảm tổng tổng tương ứng (s = s-11) và cũng giảm tổng số các biến trong biến f.
Vòng lặp kết thúc khi không tìm thấy tối đa trên 0 (tất cả các giá trị! = 0 đã được quản lý).
Cuối cùng, tôi trả lại các giá trị thay đổi thành tích cực. Cảnh báo mã này sửa đổi mảng trọng số tại chỗ, vì vậy nó phải được gọi bằng một bản sao của mảng gốc

F=(s,w)=>
 (f=>{
  for(;j=w.indexOf(z=Math.max(...w)),z>0;f-=z)
    s+=w[j]=-Math.ceil(z*s/f);
 })(1)||w.map(x=>0-x)

Lần thử đầu tiên của tôi

Không phải là một giải pháp thông minh. Đối với mọi kết quả có thể, nó đánh giá sự khác biệt và giữ mức tối thiểu.

F=(s,w,t=w.map(_=>0),n=NaN)=>
  (p=>{
    for(;p<w.length;)
      ++t[p]>s?t[p++]=0
      :t.map(b=>r+=b,r=p=0)&&r-s||
        t.map((b,i)=>r+=(z=s*w[i]-b)*z)&&r>n||(n=r,o=[...t])
  })(0)||o

Ungolfed và giải thích

F=(s, w) =>
{
  var t=w.map(_ => 0), // 0 filled array, same size as w
      n=NaN, // initial minumum NaN, as "NaN > value"  is false for any value
      p, r
  // For loop enumerating from [1,0,0,...0] to [s,s,s...s]
  for(p=0; p<w.length;)
  {
    ++t[p]; // increment current cell
    if (t[p] > s)
    {
      // overflow, restart at 0 and point to next cell
      t[p] = 0;
      ++p;
    }
    else
    {
      // increment ok, current cell is the firts one
      p = 0;
      r = 0;
      t.map(b => r += b) // evaluate the cells sum (must be s)
      if (r==s)
      {
        // if sum of cells is s
        // evaluate the total squared distance (always offset by s, that does not matter)
        t.map((b,i) => r += (z=s*w[i]-b)*z) 
        if (!(r > n))
        {
          // if less than current mininum, keep this result
          n=r
          o=[...t] // copy of t goes in o
        }
      }
    }
  }
  return o
}

2

CJam, 48 byte

Một giải pháp thẳng về phía trước cho vấn đề.

q~:Sf*:L,S),a*{m*{(+}%}*{1bS=},{L]z::-Yf#:+}$0=p

Đầu vào đi như

[0.3 0.4 0.3] 4

Giải trình:

q~:S                                 "Read and parse the input, store sum in S";
    f*:L                             "Do S.W, store the dot product in L";
         S),                         "Get array of 0 to S";
        ,   a*                       "Create an array with N copies of the above array";
              {m*{(+}%}*             "Get all possible N length combinations of 0 to S ints";
                        {1bS=},      "Filter to get only those which sum up to S";
{L]z::-Yf#:+}$                       "Sort them based on (S.W_i - L_i)^2 value";
 L                                   "Put the dot product after the sum combination";
  ]z                                 "Wrap in an array and transpose";
    ::-                              "For each row, get difference, i.e. S.W_i - L_i";
       Yf#                           "Square every element";
          :+                         "Take sum";
              0=p                    "After sorting on sum((S.W_i - L_i)^2), take the";
                                     "first element, i.e. smallest sum and print it";

Dùng thử trực tuyến tại đây


2

Pyth: 40 byte

Mhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUH

Điều này xác định một chức năng gvới 2 tham số. Bạn có thể gọi nó như thế nào Mhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4.

Dùng thử trực tuyến: Trình biên dịch / thực thi Pyth

Giải trình:

mms+*G@Hb}bklHyUH     (G is S, H is the list of weights)
m             yUH    map each subset k of [0, 1, ..., len(H)-1] to:
 m          lH          map each element b of [0, 1, ..., len(H)-1] to: 
    *G@Hb                  G*H[b]
   +     }bk               + b in k
  s                       floor(_)

Điều này tạo ra tất cả các giải pháp có thể L, ở đâu L[i] = floor(S*W[i])hoặc L[i] = floor(S*W[i]+1). Ví dụ, đầu vào 4 [0.3 0.4 0.3tạo ra [[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]].

fqsTG...  
f    ... only use the solutions, where
 qsTG       sum(solution) == G

Chỉ [[2, 1, 1], [1, 2, 1], [1, 1, 2]]còn lại.

Mhosm^-*Ghded2C,HN
  o                  order the solutions by
   s                   the sum of 
    m         C,HN       map each element d of zip(H, solution) to
     ^-*Ghded2           (G*d[0] - d[1])^2
 h                   use the first element (minimum)
M                    define a function g(G,H): return _

2

Toán học 108

s_~f~w_:=Sort[{Tr[(s*w-#)^2],#}&/@ 
Flatten[Permutations/@IntegerPartitions[s,{Length@w},0~Range~s],1]][[1,2]]

f[3, {0, 1, 0}]
f[4, {0.3, 0.4, 0.3}]
f[5, {0.3, 0.4, 0.3}]
f[21, {0.3, 0.2, 0.5}]
f[5, {0.1, 0.2, 0.3, 0.4}]

{0, 3, 0}
{1, 2, 1}
{1, 2, 2}
{6, 4, 11}
{0, 1, 2, 2}


Giải trình

Ung dung

f[s_,w_]:=
Module[{partitions},
partitions=Flatten[Permutations/@IntegerPartitions[s,{Length[w]},Range[0,s]],1];
Sort[{Tr[(s *w-#)^2],#}&/@partitions][[1,2]]]

IntegerPartitions[s,{Length@w},0~Range~s]trả về tất cả các phân vùng số nguyên của s, sử dụng các phần tử được lấy từ tập hợp {0, 1, 2, ...s}với ràng buộc là đầu ra phải chứa cùng số phần tử như trong tập các trọng số , w.

Permutations đưa ra tất cả các sắp xếp theo thứ tự của từng phân vùng số nguyên.

{Tr[(s *w-#)^2],#}trả về một danh sách các cặp theo thứ tự, {error, permutation} cho mỗi hoán vị.

Sort[...] sắp xếp danh sách {{error1, permutation1},{error2, permutation2}...according to the size of the error.

[[1,2]]]hoặc Part[<list>,{1,2}]trả về mục thứ hai của phần tử đầu tiên trong danh sách được sắp xếp của {{error, permutation}...}. Nói cách khác, nó trả về hoán vị với lỗi nhỏ nhất.


2

R, 85 80 76

Sử dụng phương pháp Hare Quota.

Đã xóa một cặp vợ chồng sau khi thấy thông số kỹ thuật rằng W sẽ tổng hợp thành 1

function(a,b){s=floor(d<-b*a);s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s}

Chạy thử nghiệm

> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(3,c(0,1,0))
[1] 0 3 0
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(1,c(0.4,0.3,0.3))
[1] 1 0 0
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(4,c(0.3, 0.4, 0.3))
[1] 1 2 1
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(5,c(0.3, 0.4, 0.3))
[1] 1 2 2
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(21,c(0.3, 0.2, 0.5))
[1]  6  4 11
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(5,c(0.1,0.2,0.3,0.4))
[1] 1 1 1 2
>

2

Python, 139 128 117 byte

def f(S,W):
 L=(S+1,0,[]),
 for n in W:L=[(x-i,y+(S*n-i)**2,z+[i])for x,y,z in L for i in range(x)]
 return min(L)[2]

Giải pháp itertools trước đó, 139 byte

from itertools import*
f=lambda S,W:min((sum(x)!=S,sum((S*a-b)**2for a,b in zip(W,x)),list(x))for x in product(*tee(range(S+1),len(W))))[2]

Tôi đã tự hỏi nếu một giải pháp itertools sẽ có thể. Làm tốt lắm +1. Tôi có đúng khi nghĩ điều này có độ phức tạp thời gian O (n ^ 4) không?
Logic Knight

Giải pháp Itertools O(S^len(W))thực sự là: P. Giải pháp mới nhanh hơn rất nhiều, nhưng vẫn chậm
Sp3000 17/2/2015

2

Tháng Mười, 87 76

Chơi gôn

function r=w(s,w)r=0*w;for(i=1:s)[m,x]=max(s*w-r);r(x)+=1;endfor endfunction

Ung dung:

function r=w(s,w)
  r=0*w;   # will be the output
  for(i=1:s)
    [m,x]=max(s*w-r);
    r(x)+=1;
  endfor
endfunction

(Đã nổ tung "endfor" và "endfactor"! Tôi sẽ không bao giờ thắng nhưng tôi thích chơi golf với ngôn ngữ "thực".)


Thuật toán đẹp. Bạn có thể thay thế zeros(size(w))bằng 0*w.
alephalpha

Đẹp! Tại sao tôi không nghĩ về điều đó?
dcsohl

1

T-SQL, 167 265

Bởi vì tôi cũng muốn thử và thực hiện những thử thách này trong một truy vấn.

Biến nó thành một hàm nội tuyến để phù hợp hơn với thông số kỹ thuật và tạo ra một loại cho dữ liệu bảng. Nó có giá một chút, nhưng điều này sẽ không bao giờ là một ứng cử viên. Mỗi câu lệnh cần được chạy riêng.

CREATE TYPE T AS TABLE(A INT IDENTITY, W NUMERIC(9,8))
CREATE FUNCTION W(@ int,@T T READONLY)RETURNS TABLE RETURN SELECT CASE WHEN i<=@-SUM(g)OVER(ORDER BY(SELECT\))THEN g+1 ELSE g END R,A FROM(SELECT A,ROW_NUMBER()OVER(ORDER BY (W*@)%1 DESC)i,FLOOR(W*@)g FROM @T)a

Đang sử dụng

DECLARE @ INT = 21
DECLARE @T T
INSERT INTO @T(W)VALUES(0.3),(0.2),(0.5)
SELECT R FROM dbo.W(@,@T) ORDER BY A

R
---------------------------------------
6
4
11
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.