배당 역설


10

주어진:

  • 자연수 S .
  • 1에 해당하는 N 개의 합리적 가중치 W 의 목록 .

N이 아닌 음수가 아닌 정수 의 목록 L 을 반환 합니다.

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

즉, S⋅W_i가능한 정수에 가까운 s를 근사 합니다.

예 :

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]

규칙 :

  • 입력 형식을 전혀 사용하지 않거나 입력을 인수로 받아들이는 함수 만 제공하면됩니다.

배경:

표시 할 때이 문제는 온다 S 다른 비율 항목의 다른 유형의를 W I 유형과 관련하여.

이 문제의 또 다른 예는 비례 정치 표현 입니다. 배분 역설을 참조하십시오 . 마지막 두 테스트 사례를 앨라배마 역설이라고합니다.

통계 학자로서,이 문제는 층화 된 샘플을 수행 할 때 샘플 크기를 식별 할 때 발생하는 문제와 동등한 것으로 인식했습니다. 이 상황에서 표본의 각 지층의 비율을 모집단의 각 지층의 비율과 동일하게 만들고 싶습니다. — @tomi


과제가 무엇인지 말로 표현해 주시겠습니까? 표현을 직관적으로 압축 해제하는 데 문제가 있습니다.
xnor

둘 다 ≤ 고정이어야합니다. 과제는 가중치를 기준으로 정수의 합계로 정수를 표시하는 것입니다. 이 요구 사항이 올바르게 인코딩되었는지 확실하지 않지만 나머지는 가장 높은 가중치를 선호하는 배포해야합니다. round(A + B) != round(A) + round(B)짧은 솔루션에는 여기서 무슨 일이 일어나고 있는지에 대한 통찰력이 필요 하기 때문에 흥미 롭습니다 .
glebm

1
L[i] - S*W[i]규칙 2와 규칙 3 대신 거리의 제곱 을 최소화하도록 규칙을 변경할 수 있습니다 S*W[i].
Jakube

1
또한 [0 1 2 2] 또 다른 가능한 해결책은5 [0.1 0.2 0.3 0.4]
Jakube

1
어쩌면 당신은 1 0.4 0.3 0.3]의 예를 추가해야합니다
aditsu 종료 SE 악이기 때문에

답변:


6

APL, 21

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

이것은 aditsu의 37 바이트 CJam answer의 번역입니다 .

온라인으로 테스트하십시오 .

설명

 {      ⍵-⍺}            ⍝ 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

파이썬 2 95 83 132 125 143

내 첫 번째 (두 번째) (및 세 번째) 알고리즘에 문제가 있었으므로 (또 다른!) 다시 작성하고 더 많은 테스트를 한 후에 정확하고 빠른 해결책이 있습니다.

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

축소 기 앞의 소스는 다음과 같습니다.

# 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

테스트 결과는 다음과 같습니다.

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

이 알고리즘은 다른 답변과 비슷합니다. num의 경우 O (1)이므로 정수 10과 1000000의 경우 동일한 런타임을 갖습니다. 이론적으로 가중치 수 (정렬 때문에)에 대해서는 O (nlogn)입니다. 이것이 다른 까다로운 입력 사례를 모두 견뎌 내면 프로그래밍 도구 상자에서 아래 알고리즘을 대체합니다.

그 알고리즘을 골퍼가 아닌 것으로 사용하지 마십시오. 소스 크기를 최소화하기 위해 속도가 저하되었습니다. 다음 코드는 동일한 논리를 사용하지만 훨씬 빠르고 유용합니다.

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

num 값은 속도에 큰 영향을 미치지 않습니다. 1에서 10 ^ 19 사이의 값으로 테스트했습니다. 실행 시간은 가중치 수에 따라 선형으로 변합니다. 내 컴퓨터에서는 10 ^ 5 가중치의 경우 0.15 초, 10 ^ 7 가중치의 경우 15 초가 걸립니다. 가중치는 1에 해당하는 분수로 제한되지 않습니다. 여기에 사용 된 정렬 기술은 전통적인 sorted((v,i) for i,v in enumerate...)스타일 보다 두 배 빠릅니다 .

원래 알고리즘

이것은 내 도구 상자의 기능으로 골프를 위해 약간 수정되었습니다. 원래 SO 답변 에서 온 입니다. 그리고 잘못되었습니다.

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

sum (outseq) == num이 유지되지만 근사값을 제공하지만 항상 정확한 것은 아닙니다. 빠르지 만 권장하지 않습니다.

오류를 발견 한 @alephalpha와 @ user23013에게 감사합니다.

편집 : 총 가중치가 항상 1이되도록 OP가 지정하므로 totalw (d)를 1로 설정하십시오. 이제 83 바이트.

EDIT2 : [0.4, 0.3, 0.3], 1에서 발견 된 버그가 수정되었습니다.

EDIT3 : 버려진 결함 알고리즘. 더 나은 것을 추가했습니다.

EDIT4 : 이건 말도 안됩니다. 올바른 알고리즘으로 대체되었습니다.

EDIT5 :이 알고리즘을 사용하고 싶을 수도있는 다른 사람들을 위해 골피 코드를 추가했습니다.


4
a([0.4, 0.3, 0.3], 1)반환 [0, 1, 0]정답 인 반면, [1, 0, 0].
alephalpha

1
여전히 틀렸다. a([0.11,0.3,0.59],4)을 반환했습니다 [0, 1, 3]. 이어야 [1, 1, 2]합니다.
jimmy23013

1
f([0.47,0.47,0.06],10)을 반환했습니다 [5, 4, 1]. 이어야 [5, 5, 0]합니다.
jimmy23013

2
지금은 맞다고 생각합니다.
jimmy23013

2
@CarpetPython이 알고리즘으로 비슷한 과정을 거쳤으며 이것이이 문제를 해결하는 방법입니다. 그들이 당신의 라이센스를 빼앗 으면, 그들은 내 것도 가져 가야한다 :)
glebm

4

Mathematica, 67 50 46 45 자

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

언 골프 드 :

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]

예:

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

{1, 1, 1, 2}


나의 장점은 Mathematica라고 생각하면 짧습니다!
DavidC

3

CJam-37

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

온라인으로 사용해보십시오

설명:

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

노트:

  • 복잡성은 O (S * N)에 관한 것이므로 큰 S에서는 실제로 느려집니다.
  • CJam은 2 개의 배열에 대한 산술 연산자가 부족합니다. 나중에 구현할 계획입니다.

다른 아이디어-46

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

온라인으로 사용해보십시오

이것은 훨씬 더 간단하고 효율적이지만 아쉽습니다. 여기서 아이디어는 L_i = floor (S * W_i)로 시작하고 S와 그 합계의 차이 (예 : D)를 결정하고 S * W_i의 가장 큰 소수 부분을 가진 D 인덱스를 찾습니다 (정렬 D를 취하여) 해당 지수에 대해 L_i를 증가시킵니다. 복잡성 O (N * log (N)).


이제 O (N)이 :e<있습니다.
jimmy23013

@ user23013 아, 네, 첫 번째 프로그램에 감사드립니다
SE는 EVIL이기 때문에 aditsu quit

그것은 빠르다! 축하 🌟
glebm

궁금한 점이 있다면 정렬을 선형 시간 선택 알고리즘으로 바꾸면 정렬로 인한 실제 O (nlogn) 대신 O (n)이 생성됩니다 .O (N)에서 D 번째로 큰 요소 P를 찾은 다음 ≥PD 시간 인 요소 (D <= N 이후 O (N)).
glebm

@glebm 그것은 꽤 멋지지만 여러 요소가 같은 값 (P)을 갖는 경우 문제가 있다고 생각합니다. 어쩌면 2 패스로 해결할 수 있습니다 : 먼저 요소를 증가시키고> P를 세면 필요한 요소 수 = P를 알 수 있습니다. 또는 선택 알고리즘에서 해당 정보를 얻을 수 있다면 더 좋습니다.
SE가 EVIL이기 때문에 aditsu 종료

3

자바 스크립트 (ES6) 126 130 104 115 156 162 194

@CarpetPython의 답변에 대한 모든 의견과 테스트 사례가 끝나면 첫 번째 알고리즘으로 돌아갑니다. 아아, 스마트 솔루션이 작동하지 않습니다. 구현은 약간 단축되었지만 여전히 가능한 모든 솔루션을 시도하고 제곱 거리를 계산하고 최소값을 유지합니다.

편집 가중치 w의 각 출력 요소에 대해 '모두'가능한 값은 단지 2 : trunc (w * s) 및 trunc (w * s) +1이므로 (2 ** elemensts) 가능한 해결책이 있습니다.

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

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

산출

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]

더 똑똑한 솔루션입니다. weigth 어레이의 단일 패스.
각 패스마다 w에서 현재 최대 값을 찾습니다. 가중 정수 값 (반올림) 으로이 값을 변경하므로 s == 21 및 w = 0.4 인 경우 0.5 * 21-> 10.5-> 11을 얻습니다.이 값을 저장하지 않으므로 저장할 수 없습니다. 다음 루프에서 최대 값으로 발견됩니다. 그런 다음 총합을 적절하게 줄이고 (s = s-11) 변수 f에서 무게의 총계를 줄입니다.
루프가 0보다 크지 않으면 루프가 종료됩니다 (모든 값! = 0이 관리 됨).
마지막으로 값을 다시 양수로 변경했습니다. 경고 가 원래 배열의 사본을 호출해야하므로 장소에 무게 배열은,이 코드를 수정

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)

나의 첫 번째 시도

그렇게 똑똑한 솔루션은 아닙니다. 가능한 모든 결과에 대해 차이를 평가하고 최소값을 유지합니다.

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 및 설명

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 바이트

문제에 대한 직접적인 해결책.

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

입력은 다음과 같습니다

[0.3 0.4 0.3] 4

설명:

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";

여기에서 온라인으로 사용해보십시오


2

Pyth : 40 바이트

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

g2 개의 파라미터 로 기능 을 정의합니다 . 당신은 그것을처럼 부를 수 있습니다 Mhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4.

온라인 사용해보기 : Pyth Compiler / Executor

설명:

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(_)

이것은 모든 가능한 솔루션을 생성 L, L[i] = floor(S*W[i])또는 L[i] = floor(S*W[i]+1). 예를 들어, 입력 4 [0.3 0.4 0.3은을 만듭니다 [[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

[[2, 1, 1], [1, 2, 1], [1, 1, 2]]남아있다.

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

매스 매 티카 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}


설명

언 골프

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]출력에서 가중치 집합과 동일한 수의 요소를 포함해야한다는 제약 조건이있는 s집합에서 가져온 요소를 사용하여 의 모든 정수 파티션을 반환합니다 .{0, 1, 2, ...s}w

Permutations 각 정수 파티션의 모든 정렬 된 배열을 제공합니다.

{Tr[(s *w-#)^2],#}{error, permutation} 각 순열에 대해 순서 쌍의 목록을 반환합니다 .

Sort[...] 의 목록을 정렬 {{error1, permutation1},{error2, permutation2}...according to the size of the error.

[[1,2]]]또는 Part[<list>,{1,2}]의 정렬 된 목록에서 첫 번째 요소의 두 번째 항목을 반환합니다 {{error, permutation}...}. 즉, 오류가 가장 작은 순열을 반환합니다.


2

R, 85 80 76

헤어 할당량 방법을 사용합니다.

W의 합이 1 인 사양을 확인한 후 커플을 제거했습니다.

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

시운전

> (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

파이썬, 139 128 117 바이트

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]

이전 itertools 솔루션, 139 바이트

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]

itertools 솔루션이 가능한지 궁금합니다. 좋은 일 +1. 이것이 O (n ^ 4) 시간 복잡성을 가지고 있다고 생각하는 것이 맞습니까?
논리 기사

Itertools 솔루션은 O(S^len(W))실제로 다음과 같습니다 .P. 새로운 솔루션은 훨씬 더 빠르지 만 여전히 느립니다
Sp3000

2

옥타브, 87 76

골프 :

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

언 골프 드 :

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

( "endfor"와 "endfunction"이 폭발했습니다! 절대 이길 수는 없지만 "실제"언어로 골프를 즐깁니다.)


좋은 알고리즘. 당신은 대체 할 수 있습니다 zeros(size(w))0*w.
alephalpha

좋은! 왜 그렇게 생각하지 않았습니까?
dcsohl

1

T-SQL, 167 (265)

쿼리에서 이러한 과제를 시도하고 수행하기를 좋아하기 때문입니다.

스펙에 더 잘 맞도록 인라인 함수로 변환하고 테이블 데이터의 유형을 작성했습니다. 약간의 비용이 들었지만 이것은 결코 경쟁자가 될 수 없었습니다. 각 명령문은 별도로 실행해야합니다.

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

사용

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