在APL中计数硬币

时间:2019-05-29 13:30:19

标签: greedy apl coin-change

下面的函数 Count 计算总计达到给定数量的最小硬币数量。

∇ R ← d AppendQuotRem qrs; oldR; q; r
    oldR ← 2 ⊃ (⍴qrs) ⊃ qrs
    q ← ⌊oldR ÷ d
    r ← oldR - d × q
    R ← qrs , ,⊂(q r)
∇

∇ R ← Count amount; ds; qrs; qs
    ds ← 1 5 10 25 50  ⍝ coin denominations in cents
    qrs ← ⊃AppendQuotRem/ ds , ⊂,⊂(0 amount)
    qs ← 1 ⊃¨ qrs
    R ← ds ,[0.5] ⌽1 ↓ qs
∇

我为每种面额计算商和余数。余数用于涉及下一个面额的计算。有没有更短和/或更直接的方法来解决问题?

2 个答案:

答案 0 :(得分:1)

change-making problem实际上是quite hard。完整的APL方法是included in the dfns workspace

您的算法很贪婪,对于某些组的硬币面额,这给出了错误的结果。它恰好可以解决您在示例中使用的集合。让我们修改您的Count函数:

∇ R ← Count134 amount; ds; qrs; qs
    ds ← 1 3 4  ⍝ coin denominations in cents
    qrs ← ⊃AppendQuotRem/ ds , ⊂,⊂(0 amount)
    qs ← 1 ⊃¨ qrs
    R ← ds ,[0.5] ⌽1 ↓ qs
∇
      Count134 6
1 3 4
2 0 1

这使用三个硬币,但是两个3美分的硬币是正确的答案:

1 3 4
0 2 0

话虽如此,一般的造币系统被设计成贪婪算法将产生最佳结果。因此,这是您的代码的简化:

∇ R ← d AppendQuotRem qrs; oldR; q; r
    oldR ← 1 ↑ qrs
    q ← ⌊oldR ÷ d
    r ← d | oldR
    R ← r , q , 1 ↓ qrs
∇

∇ R ← Count amount; ds
    ds ← 1 5 10 25 50  ⍝ coin denominations in cents
    R ← ds ,[0.5] ⊃AppendQuotRem/ 1 ↓ ds , amount
∇

Try it online!

答案 1 :(得分:0)

贪婪算法,其中货币价值为100 50 20 10 5 1个单位。

  ∇r←Greedy w;i;d;k;x;l
  r←⍬⋄i←1⋄d←100 50 20 10 5 1⋄l←≢d
  r←r,k←⌊w÷x←d[i]⋄w-←k×x⋄→2×⍳l≥i+←1
  r←2 l⍴d,r
  ∇
  
  Prova←{+/⍵[1;]×⍵[2;]}
  m←Greedy 125
  m
100 50 20 10 5 1
  1  0  1  0 1 0
  Prova m
125