달러 분할 및 완벽한 변화


11

내 주머니에 $ 15가 있습니다. 마찬가지로, 나는 변화를주지 않는 가게에있다. 탐색하는 동안 $ 10 (세금 포함)의 비용이 드는 항목을 발견했습니다. 돈을 잃지 않고 그 품목을 살 수 있습니까?

이 경우 대답은 '예'입니다. $ 15가 어떻게 나뉘어 있든지 (10과 1, 5, 3, 5, 또는 다른 것), 나는 항상 정확한 $ 10를 가질 것입니다.

두 번째 예로, 주머니에 $ 0.16가 있습니다. 정확히 어떤 다른 금액의 돈을 지불해야합니까?

Possible Divisions:
0.01, 0.05, 0.10
0.01, 0.05 x 3
0.01 x 16
Guaranteed Exact Change:
0.01, 0.05, 0.06, 0.10, 0.11, 0.15, 0.16

주머니에 $ 0.27가 있으면 어떻게합니까?

Possible Divisions:
0.01 x 2, 0.25
0.01 x 2, 0.05, 0.10 x 2
0.01 x 2, 0.05 x 3, 0.10
0.01 x 2, 0.05 x 5
0.01 x 27
Guaranteed Exact Change:
0.01, 0.02, 0.25, 0.26, 0.27

위의 경우에, 나는 항상 완벽한 변화를 가질 수있는 돈이 거의 없었습니다.

당신의 작업

A) 정수 금액과 B) 가능한 교파 목록을 입력으로 사용하고 내가 완벽하게 변경해야 할 금액 목록을 출력하는 가장 짧은 프로그램 (또는 명명 된 함수)을 작성하십시오. 입력은 STDIN 또는 프로그램 또는 함수의 인수 일 수 있습니다. 입력 형식을 엄격하게 다루지는 않겠습니다. 언어가 배열을 형식화하는 방식과 일치 할 수 있습니다.

아마도 더 자세한 설명 일 것입니다

나는 주머니에 일정 금액의 돈이 있는데, 이것은 가능한 통화 시연으로 구성됩니다. 8 달러를 가지고 있고 가능한 교파가 2 달러와 3 달러라는 것을 알고 있다면 내 주머니에 넣을 수있는 청구서 조합이 너무 많습니다. 이들은 2+2+2+23+3+2. 정확한 금액의 돈을 생산하려면 주머니에있는 지폐 만 사용하여 그 수량을 생산할 수 있어야합니다. 내가 2를 4 개 가지고 있다면을 생산할 수 있습니다 2, 4, 6, or 8. 3과 2가 2 개인 경우 2, 3, 5, 6, or 8실제로 생산할 수 있습니다. 실제로 이러한 조합 중 어떤 것이 내 주머니에 있는지 알 수 없으므로 최종 답변이로 줄어 듭니다 2, 6, 8. 이 내가 값입니다 알고 난 총 금액과 가능한 교단 주어, 내 주머니에서 생산할 수 있습니다.

수동 계산 예제 I / O

7 [3, 4]
3, 4, 7        //only one possible division into 3 + 4

7 [3, 2]
2, 3, 4, 5, 7  //the only division is 3 + 2 + 2

6 [2, 3, 4]
6     //divisions are 2+2+2, 3+3, 2+4 

16 [1, 5, 10, 25]          //this represents one of the examples above
1, 5, 6, 10, 11, 15, 16

27 [1, 5, 10, 25]          //another example from above
1, 2, 25, 26, 27

1500 [1, 5, 10, 25, 100, 500, 1000, 2000]
500, 1000, 1500

600 [100, 500, 1000, 2000]
100, 500, 600

600 [200, 1, 5, 10, 25, 100, 500, 1000, 2000]
600

이것은 매우 불분명합니다.
motoku

@FryAmTheEggman "아마도 더 자세한 설명"을 추가했습니다. 여전히 혼란 스러운지 알려주세요. (나는 또한 무의미했기 때문에 가장자리 케이스를 제거했습니다.)
PhiNotPi

어떻게 지내고 있는지 모르겠습니다 6 [2, 3, 4]. 2+2+23을 만들 수없고 3+32와 4를 만들 수 없습니까?
xnor

@ xnor 당신은 정확하고 고정되어 있습니다.
PhiNotPi

모든 입력에 대해 적절한 시간에 프로그램을 실행해야합니까? 예를 들어, 가장 짧은 아이디어는 시작 금액이 기하 급수적이며 2 ^ 1500은 많은 것입니다.
randomra

답변:


2

Python 2, 200 197 193 140 바이트

f=lambda n,D,S={0}:sum([f(n-x,D,S|{x+y for y in S})for x in D],[])if n>0else[S]*-~n
g=lambda*a:(f(*a)and reduce(set.__and__,f(*a))or{0})-{0}

(팁은 @Nabb에게 감사합니다)

여기에 일을 시작하기에 제대로 된 골프 솔루션이 있습니다. Call with g(16, [1, 5, 10, 25])— 출력은 관련 명칭으로 설정됩니다.

이 접근 방식은 간단하며 두 단계로 나뉩니다.

  • fn교단 에 도달 하는 모든 방법 D(예 :) 을 살펴보고 [1, 5, 10], 각 교단 에 대해 이러한 교단으로 수행 할 수있는 모든 금액을 계산합니다 (예 :) set([0, 1, 5, 6, 10, 11, 15, 16]).
  • g의 결과의 교집합을 계산 한 f다음 최종 답변에 대해 0을 제거합니다.

이 프로그램은 사례 1-5와 7을 잘 해결하고 6에 스택 오버플로가 발생하며 8에 영원히 걸립니다.

솔루션이없는 경우 (예 :) g(7, [2, 4, 6])프로그램은 빈 세트를 반환합니다. 이러한 경우에 오류가 발생하면 다음이 더 짧습니다 g.

g=lambda*a:reduce(set.__and__,f(*a))-{0}

g=lambda L,c=0:L and g(L[1:],c)|g(L,c+L.pop(0))or{c}조금 짧습니다
Nabb

-{0}g 로 이동 하고 [L]*-~n대신 사용하여 조금 더[L][-n:]
Nabb

1

자바 스크립트 (ES6) 162 203 207

편집 배열 r에서 결과 집합을 교차시키는 방식이 변경되었습니다. 조금 더 빠르지 만 알고리즘은 여전히 ​​악취가납니다.

더 자세한 설명은 다음과 같습니다.
간단히 : c는 가능한 모든 세분을 열거하는 재귀 함수입니다. k는 반복없이 가능한 모든 합계를 열거하는 재귀 함수입니다. k 함수로 찾은 새로운 결과 세트는 이전에 찾은 세트와 비교되며 공통 결과 만 유지됩니다.

왜 그렇게 느려? 1500의 목표와 1의 단일 값을 관리해야하므로 모든 가능한 합계를 열거하는 것은 좋은 생각이 아닙니다.

F=(s,d,r,
  c=(s,i,t=[],v,k=(i,s,v)=>{for(;v=t[i++];)k(i,s+v);o[s]=s})=>
  {for(s||(i=k(o=[],0),r=(r||o).filter(v=>o[v]));v=d[i];++i)s<v||c(s-v,i,[...t,v])}
)=>c(s,0)||r

언 골프

F=(s,d)=>{
  var r
  var c=(s,i,t=[])=>
  {
    var o=[],v
    var k=(i,s)=> // find all sums for the current list t, set a flag in the o array
    {
      var v
      for(;v=t[i++];)k(i,s+v)
      o[s]=s
    }

    if (s==0) {
      k(0,0)
      if (r)
        r = r.filter(v=>o[v]) // after first loop, intersect with current
      else
        r = o.filter(v=>v) // first loop, keep all results
    } 
    else
      for(;v=d[i];++i)
      { 
        if (s >= v) 
          c(s-v, i, t.concat(v))
      }
  }
  c(s,0) // enumerate all possible set of pieces
  return r
}

Firefox / FireBug 콘솔에서 테스트

F(16,[1,5,10,25])

[1, 5, 6, 10, 11, 15, 16]

(시간 84 밀리 초)

F(27, [1, 5, 10, 25]) 

[1, 2, 25, 26, 27]

(시간 147252 msec, 너무 빠르지 않음)


0

Wolfram Methematica, 104 바이트

Rest@*Intersection@@Map[Total]/@Subsets/@Union[Sort/@IntegerPartitions[#,#,PadLeft[{},Length[#2]#,#2]]]&

Ungolfed (끝에서 읽음) :

Rest@* // Removing 0
  Intersection@@   // Intersecting all totals
     Map[Total]/@  // Counting total of each subset
        Subsets/@  // Getting all the subsets of each partition
           Union[  // Removing duplicates 
              Sort/@ // Sorting each partition (to remove duplicates next)
                 IntegerPartitions[#,#,PadLeft[{},Length[#2]#,#2]] // Getting all Integer partitions
                ]&
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.