【问题标题】:Divide a value in excel by a set of preset values to find out how many of each are needed将 excel 中的一个值除以一组预设值,以找出每个值需要多少
【发布时间】:2022-11-22 06:21:10
【问题描述】:

我很好奇是否有办法让我的生活更轻松。在 excel 中,我生成了一个总值,比如 750,并且需要从 50,100,200,250,500 的值中找出我需要多少个管道订单。无论如何让 excel 取一个值,然后返回我需要的这些数字中的每一个,所以对于 750 的情况,1 500 和 1 250?

目前,解决方案刚刚在我脑海中形成

【问题讨论】:

  • 为什么不375+375
  • 它必须来自列表 [50 100 200 250 500] 它们是我们提供的产品
  • 没有剩余/多余的解决方案是否总是可能的?在可能有多种解决方案的情况下,是什么决定了应该首选哪个?
  • 因此,如果它说 823,它将超过值 (500+250+100),并且在可能有多个解决方案的情况下,它将选择最大化最高值,因此 500s 然后 250s 等等....

标签: excel


【解决方案1】:

假设您想尝试以尺寸递减的顺序安装管道,并且您可以访问所需的功能,您可以使用 Reduce 作为演示 here 来遍历尺寸并连续除以每个尺寸,尽管公式有点小辛苦了:

=LET(pipes,{500;250;200;100;50},reqd,750,DROP(REDUCE(0,pipes,
LAMBDA(a,c,VSTACK(a,QUOTIENT(reqd-IF(ROWS(a)>1,SUM(DROP(a,1)*TAKE(pipes,ROWS(a)-1)),0),c)))),1))

正如@Jos Woolley 所指出的,如果总数大约为 749,这可能不会给您想要的答案。它将尽可能多地包含值,并给出 500+200 的结果,总计 700(余数 49)。您可以通过四舍五入到下一个 50 的倍数来修复它。

对于 823 的示例,您将拥有:

=LET(pipes,{500;250;200;100;50},reqd,CEILING(823,MIN(pipes)),DROP(REDUCE(0,pipes,
LAMBDA(a,c,VSTACK(a,QUOTIENT(reqd-IF(ROWS(a)>1,SUM(DROP(a,1)*TAKE(pipes,ROWS(a)-1)),0),c)))),1))

得出 500+250+100=850。


好吧,我现在对此有点着迷,我决心让 lambda 工作以找到最佳答案!我一直在研究前面提到的参考资料中的强力解决方案,并设法使用 Reduce 将其转换为 lambda:

 Mincoins1= LAMBDA(coins, m, v,
    IF(
        v <= 0,
        0,
        REDUCE(
            999,
            coins,
            LAMBDA(a, c,
                IF(v >= c, LET(mc, mincoins1.mincoins1(coins, m, v - c) + 1, IF(mc < a, mc, a)), a)
            )
        )
    )
)

当您想从给定的管道列表中组成值 400 时,这确实给出了正确答案 2。下一步将是修改代码以返回给出总数 (200,200) 的管道列表。

https://www.enjoyalgorithms.com/blog/minimum-coin-change

【讨论】:

  • 如我的回答所示,400 可能会产生问题(给出 250 + 100 + 50 而 200 + 200 包含较少的账单),您的提案如何应对?
  • 你当然是对的,它只是遵循一种算法,首先适合最大尺寸,这相对简单。我为不精确拟合而四舍五入到下一个 50 的倍数的相当粗略的修复并不总是有效。但到目前为止我还没有看到更好的选择......
  • 更深入一点,它相当于用最少数量的硬币找给定数量的钱的问题。这似乎是一个众所周知的问题,您可以在此处找到它的伪代码,例如提供递归解决方案的enjoyalgorithms.com/blog/minimum-coin-change。原则上它可以用 lambda 来实现(这将是一项相当英勇的工作)但在实践中你需要 VBA 我认为所以 @Dominique 说这绝不是一个容易解决的最佳问题。
【解决方案2】:

不确定我是否理解这个问题,但让我们试试。

如果要除以 1 450,请使用一个公式将 1 450 除以最大长度 (750),然后向下取整。

所以公式应该是这样的:= rounddown(1 450 / 750; 0)

然后你会得到你需要长度 750 中的 1 个的答案。

然后保留有关剩余长度的信息。所以像这样的公式: =1 450 - 750 * [上一个公式的答案 = 1]。这将总和为 700。

然后用同样的东西重新开始,但将 700 除以 500(第二大尺寸)。

【讨论】:

    【解决方案3】:

    您的问题非常困难:有人可能会想到这个简单的解决方案,从 value_begin 开始:

    amount_of_500 = value_begin DIV 500; // integer division
    temp = value_begin - 500 * amount_of_500;
    amount_of_250 = temp DIV 250; // again integer division
    temp = temp - 250 * amount_of_250;
    amount_of_200 = temp DIV 200; // again integer division
    temp = temp - 200 * amount_of_200;
    ...
    

    但是,这将不起作用,因为值 200 太接近 250:只需以 value_begin 等于 400 开始(算法解决方案:250 + 100 + 50,而最佳解决方案:200 + 200)。

    你确定你需要 200 和 250 作为除以可能的数字吗?如果是,您可能在实施时遇到严重问题。

    【讨论】:

    • 遗憾的是,是的,因为它是我们销售的产品,如果它太复杂,请不要担心,它很简单,可以手工计算/在你的脑海中计算我只是好奇是否存在简单的解决方案
    • @JamesMetcalfe:我展示的算法确实是一个简单的解决方案,但正如我所提到的:有一个陷阱:你会得到一个正确的结果,但账单总额不会最少,如“400”示例所示.因此,200 张钞票不会经常使用。如果你对此没问题,你实际上可以实现这个算法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    相关资源
    最近更新 更多