美元可分割性与完美变化


11

我的口袋里有15美元。同样,我在一家没有零钱的商店。在浏览时,我发现一个售价10美元(含税)的商品。我可以在不损失任何钱的情况下购买该物品吗?

在这种情况下,答案是肯定的。无论我的15美元如何分配(一个10和一个5,或三个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,我可以产生2, 4, 6, or 8。如果我有两个3和一个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 2015年

我不明白你的情况6 [2, 3, 4]。不能2+2+2没有使3,并3+3没有使2和4?
xnor

@xnor您是正确的,已修复。
PhiNotPi

程序是否应该在所有输入中都在合理的时间内运行?例如,我最短的想法是起始金额是指数级的,而2 ^ 1500就是很多东西。
randomra

Answers:


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的提示)

现在这是一个糟糕的解决方案,可以让您开始工作。呼叫方式g(16, [1, 5, 10, 25])-输出是带有相关面额的集合。

该方法很简单,分为两个步骤:

  • f着眼于n以面额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,2015年

1

的JavaScript(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毫秒,因此不能太快)


0

Wolfram Methematica,104个字节

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

取消高尔夫(末尾阅读):

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
                ]&
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.