使用N个硬币和每个面额的硬币找零问题枚举


13

硬币找零问题是非常有据可查。由于币值的硬币的无限供给x_1x_m你需要找到这加起来的组合的数量y。例如,给定x = {1,2,3}y = 4我们有四个组合:

  1. {1,1,1,1}
  2. {1,1,2}
  3. {1,3}
  4. {2,2}

介绍

硬币找零问题有几种变体。在此变体中,我们还有两个其他限制:

  1. 每个面额必须至少使用一次。
  2. 总共总共必须使用固定数量的硬币。

例如,给定x = {1,2,3}y = 36n = 15在那里n是必须使用硬币的总数,我们得到四种组合:

  1. {1,2,2,2,2,2,2,2,3,3,3,3,3,3,3} (1个,7个2、7个3)
  2. {1,1,2,2,2,2,2,3,3,3,3,3,3,3,3} (2个,5个二,8个三分)
  3. {1,1,1,2,2,2,3,3,3,3,3,3,3,3,3} (3个,3个二,9个三分)
  4. {1,1,1,1,2,3,3,3,3,3,3,3,3,3,3} (4个,1个二,10个三分)

挑战

面临的挑战是用enumerate您选择的语言编写一个函数,该函数枚举上述所有组合:

  1. 面额列表。例如{1,5,10,25}。您可以使用列表或数组。
  2. 一个非负整数y,表示每个组合的总和。
  3. 一个非负整数n,表示硬币总数。

参数的顺序无关紧要。允许无点功能。

enumerate函数的输出必须是组合列表。每个组合都必须是唯一的,并且必须是n加在一起为的整数列表y。每个面额在每个组合中必须至少出现一次,并且不得丢失任何组合。整数及其组合的顺序无关紧要。您可以使用列表或数组作为输出。

请记住以下情况:

  1. 如果yn均为零,并且面额列表为空,则输出为一个组合的列表,即空组合(即{{}})。
  2. 否则,如果y为零,n为零或面额列表为空,则输出为零组合的列表(即{})。
  3. 更一般而言,如果y小于面额之和或n小于面额数,则输出为零组合的列表。

计分将基于整个程序的大小(以字节为单位)。请注意,这包括enumerate函数,辅助函数,导入语句等。它不包括测试用例。


可以肯定的是,我在某处看到了这一挑战……
Leaky Nun

我希望这个问题不会重复。我在Code Golf上找不到相同的问题。因此,我发布了它。
Aadit M Shah's

@PeterTaylor如果y小于面额之和,则在递归解决方案中的某个点上,您将到达基本面,其中面额列表为空。因此,答案将是{}(即找不到解决方案)。如果n小于面额的数量,那么您最终会达到的基本情况,n = 0但是呢y != 0。因此,答案将再次是{}
Aadit M Shah,2016年

@PeterTaylor确实。我可能对实现细节承担了太多的责任。您知道如何解决该问题吗?
Aadit M Shah,2016年

10
我建议您删除“已接受”标志,直到获得有效答案为止。通常,明智的做法是等几天再接受。
彼得·泰勒

Answers:


2

05AB1E,20字节

g-¹sã€{Ùvy¹«DO³Qiˆ}¯

输入顺序为:list of valuesnr of coinssum to reach

简而言之

  1. 获取长度的硬币列表的所有排列: final length - length of unique coin list
  2. 将唯一硬币的列表添加到这些列表中。
  3. 如果总和等于要求的总和,请保存列表
  4. 输出所有保存的列表

在线尝试

在线编译器无法处理大量硬币。


4

MATL,22字节

Z^!S!Xu!tsi=Z)"1G@m?@!

输入顺序为:面额数组n,所取硬币数量(),所需总和(y)。

每个组合显示在不同的行上。空输出显示为空字符串(因此什么也没有)。

在线尝试!

对于挑战中的示例,代码在联机编译器中用尽了内存,但可在标准的,相当现代的计算机上离线运行:

>> matl
 > Z^!S!Xu!tsi=Z)"1G@m?@!
 > 
> [1 2 3]
> 15
> 36
1 1 1 1 2 3 3 3 3 3 3 3 3 3 3
1 1 1 2 2 2 3 3 3 3 3 3 3 3 3
1 1 2 2 2 2 2 3 3 3 3 3 3 3 3
1 2 2 2 2 2 2 2 3 3 3 3 3 3 3

说明

Z^      % Implicitly input array of denomminations and number of coins n. Compute 
        % Cartesian power. This gives 2D array with each "combination"
        % on a different row
!S!     % Sort each row
Xu      % Deduplicate rows
!       % Transpose: rows become columns. Call this array A
ts      % Push a copy, compute sum of each column
i       % Input y (desired sum)
=       % Logical array that contains true if the "combination" has the desired sum
Z)      % Keep only those columns in array A
"       % For each column
  1G    %   Push array of denominations again
  @     %   Push current column
  m     %   Is each denomination present in the column?
  ?     %   If so
    @!  %     Push current column again. Transpose into a row
        %   End if
        % End for
        % Implicitly display stack contents

3

Python 3中,120个 106字节

from itertools import*
lambda d,t,l:[i+d for i in combinations_with_replacement(d,l-len(d))if sum(i+d)==t]

一个匿名函数,它(x_1, x_2, x_3 ... , x_k)通过参数输入形式的元组,目标值和多个硬币,然后返回形式的元组列表[(solution_1), (solution_2), (solution_3), ... (solution_k)]

怎么运行的

Itertoolscombinations_with_replacement函数用于生成所有l-len(d)面额的组合,并带有替换值。通过d对这些组合中的每一个附加,可以确保每个面额至少出现一次,并且新组合的长度为l。如果组合的元素总计为t,则该组合作为元组添加到返回列表中。

在Ideone上尝试


108字节的另一种方法

from itertools import*
lambda d,t,l:set(tuple(sorted(i+d))for i in product(d,repeat=l-len(d))if sum(i+d)==t)

一个匿名函数,它(x_1, x_2, x_3 ... , x_k)通过参数输入形式的元组,目标值和多个硬币,然后返回形式的元组集{(solution_1), (solution_2), (solution_3), ... (solution_k)}

工作原理(其他版本)

这使用product函数from itertools生成l-len(d)面额的所有排列。通过d对这些组合中的每一个附加,可以确保每个面额至少出现一次,并且新组合的长度为l。如果组合的元素总和为t,则对组合进行排序,将其从列表转换为元组,然后添加到返回元组中。最后,调用set将删除所有重复项。

在Ideone(其他版本)上尝试


0

JavaScript(ES6),135个字节

g=(a,n,y,r)=>n>0?y>0&&a.map((x,i)=>g(a.slice(i),n-1,y-x,[...r,x])):n|y||console.log(r)
(a,n,y)=>g(a,n-a.length,a.reduce((y,x)=>y-x,y),a)
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.