可以使用独特的硬币和/或纸币来实现此值吗?


29

编写一个程序,计算输入的货币值(是否为整数)是否可以由硬币和/或纸币的唯一组合表示,这意味着同一硬币/纸币不能多次使用。

您的程序应将一个值作为输入,并可以通过输入或通过您的语言等效数组来获取硬币/纸币值的列表。硬币/纸币的列表应该可以更改,因此,如果您使用常量,请确保在哪里定义了硬币/纸币。

您的程序应分别输出任何真实/虚假值。

请注意,输出硬币/纸币组成值的列表不是必需的。

使用英镑,(1.00英镑= 100和420.69英镑= 42069)

coins = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]

以下内容将输出为true:

6 (1, 5)
15 (10, 5)
88 (1, 2, 5, 10, 20, 50)
512 (500, 10, 2)
7003 (5000, 2000, 2, 1)

以下将输出false:

4
209
8889
4242424242
[ANYTHING ABOVE 8888]

替代测试数据(美元)

coins = [1, 5, 10, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000]

祝好运!


4
我希望我们有更多像您一样的新来者...
漏水的尼姑


2
您应该使用一组不同的硬币添加一些测试用例
Leaky Nun

2
我建议添加无法用贪婪的启发式解决的测试用例,因为贪婪的启发式方法是使用最大的未使用硬币,即最多就是剩余价值。最好不要对输入进行排序,并且可以用多种方法生成值。通常,对于测试用例来说,避免有人对适用于测试用例的问题做出合理的尝试,而不是一味地解决所有问题,这是很好的。
xnor

2
相关的也有关。前一个问题可以说是重复的,但是这个问题是IMO设计得更好的,如果我们要将一个重复作为一个重复,那么我宁愿关闭较旧的一个。

Answers:


13

Brachylog 2(TIO Nexus),2个字节

⊇+

在线尝试!

通过标准输入或通过将其作为数组文字添加到程序的开头来获取硬币列表(两者都可以使用,因此取决于您是否认为“更合法”;这取决于默认情况) PPCG规则,该问题明确允许使用后者);并将要产生的值作为命令行参数。

说明

该程序利用了TIO Nexus的Brachylog功能包装器的实现细节;具体来说,它允许您提供命令行参数以通过输出提供输入。(这不是Brachylog的原始设计所设想的;但是,语言是由它们在PPCG上的实现定义的,并且如果实现实现了我所需要的功能,则可以利用它。)这意味着程序看起来像这样:

⊇+
⊇   Some subset of {standard input}
 +  sums to {the first command-line argument}

作为完整程序,它返回一个布尔值;true.程序中的所有断言可以同时满足还是false.不能满足。

(提醒您或不认识的人:Brachylog 2使用其自己的字符编码,该字符编码为单个字节长。)


您说的是Brachylog中的⊇是单个字节,为什么不将字节粘贴到此处?我敢打赌,这是有原因的,我只是感兴趣,有点字符编码。
theonlygusti

1
它们在磁盘上的编码为08 2B(您可以在此处查看编码)。我没有列出具体编码的原因是它无关紧要。真正重要的是Brachylog使用的唯一字符不超过256个,因此每个字符都可以用一个字节表示。通常,这是通过打高尔夫球的语言来完成的,以使代码更具可读性。他们可以改用类似代码页437的编码,但是如果您这样做了,那么没人会读取它

10

05AB1E,4个字节

æOså

说明:

æ      Calculate the powerset of the first input
 O     Sum each element
  s    Put the second input at the top of the stack
   å   Check whether the input is in the powerset sum.

在线尝试!


看来您已经正式误导了所有人来压缩列表; p
Leaky Nun

删除压缩列表并将其移至输入后,我将删除答案(因为时间相同)
Leaky Nun

这个社区充满了天才。
Tobi

5

Mathematica,25个字节

!FreeQ[Tr/@Subsets@#,#2]&

将硬币值数组作为第一个参数并将目标整数作为第二个参数的纯函数,然后返回TrueFalse



3

视网膜52 31字节

\d+
$*
^((1+) |1+ )+(?<-2>\2)+$

在线尝试!将输入作为硬币和纸币的空格列表,后跟所需的值。编辑:感谢@Kobi调试了我的代码,节省了18个字节。说明:前两行只是从十进制转换为一元。然后,第三行捕获硬币和纸币的列表。交替允许引擎回溯并选择不捕获特定硬币/纸币。然后,平衡组将值与捕获列表的所有后缀相匹配(不必要,但更高尔夫球)。


第二个选项不起作用,因为引擎不会回溯到0长度的组(烦人的优化)。您可以使用^((1+) )+(\2?(?<-2>)|){99}$(34个字节,并限制硬币数量)或^((1+) |1+ )+(\2?(?<-2>))+$(也可以34个字节)。
科比

1
@Kobi美丽!我从两个答案中都保存了2个字节,因为我忘记了它的(?<-2>\2?)工作原理,从第二个答案中又保存了一个字节,因为?不再需要。
尼尔


2

Java(OpenJDK 8),125字节

boolean f(int[]c,int n){int l=c.length;if(l<1)return n==0;int[]a=java.util.Arrays.copyOf(c,l-1);return f(a,n-c[l-1])|f(a,n);}

在线尝试!


在lambda中执行此操作可以使其更短。
Okx

@Okx这是递归的(因此会更长),再加上即使它们会更短,我也不会做lambda。
Leaky Nun

1
由于不需要复制数组,因此算法的迭代版本要短得多:boolean f(int[]c,int n){for(int l=c.length;l-->0;n-=n<c[l]?0:c[l]);return n<1;}(79个字节)。使用Java 8及其lambda,可以将其进一步减少到62个字节。关于您当前的答案,int l=c.length-1那么使用l代替代替l-1也会更短。
奥利维尔·格雷戈尔(OlivierGrégoire)


2

JavaScript(ES6),81 69 67 64字节

以currying语法获取硬币清单c和目标数量。返回或。a(c)(a)0true

c=>g=(a,m=1)=>c.map((c,i)=>x-=c*(m>>i&1),x=a)&&!x||x-a&&g(a,m+1)

测试用例


您可以拿硬币清单吗?
Leaky Nun

@LeakyNun“ ...并且可以获取硬币/纸币的值列表...”
Martin Ender

1
所以我对列表进行了编码……
Leaky Nun

@LeakyNun似乎是这样
艾迪·哈特

2

Haskell,28个字节

运算符函数(#)接受一个整数和一个整数列表(或更常见的是,任何Traversable数字容器)并返回a Bool

用作6#[1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]

c#l=elem c$sum<$>mapM(:[0])l

在线尝试!

怎么运行的

  • c是所需值和l硬币值列表。
  • mapM(:[0])l映射(:[0])l,将每个值与0配对,然后构造笛卡尔乘积,给出列表,其中每个元素要么是其对应的值l,要么是0。
  • sum<$>对每个组合求和,并elem c$检查是否c在结果列表中。

2

R,88 83字节

-5个字节,感谢@Jarko Dubbeldam

返回一个匿名函数。生成所有的硬币的可能的组合(使用expand.grid上对T,F如果值(S)的存在)而检查。k是硬币,因为它c是R中的保留字。可以一次检查多个值。

function(k,v)v%in%apply(expand.grid(Map(function(x)!0:1,k)),1,function(x)sum(k[x]))

在线尝试!


可以更换c(T,F)!0:1,并且rep(list(!0:1),length(k))通过lapply(k,function(x)!0:1)
JAD

1
实际上,做到这一点Map(function(x)!0:1,k)
JAD

1

Japt,7个字节

à mx èN

在线尝试!输出0为falsy,为true为正整数。

说明

à mx èN
          // Implicit: U = input array, V = input integer, N = array of all inputs
à         // Take all combinations of U.
  mx      // Map each combination to its sum.
     è    // Count the number of items in the result which also exist in
      N   //   the array of inputs.
          // This returns 0 if no combination sums to V, a positive integer otherwise.
          // Implicit: output result of last expression


1

Ruby,39个字节

nil作为伪造的值返回,并且在组成该数字的列表中最小的硬币值作为真值(在Ruby中所有数字都是真值)。

f=->c,n{n!=0?c.find{|i|f[c-[i],n-i]}:1}

但是请注意,该算法的速度非常慢,而且O(C!)时间复杂,C硬币列表的长度。它最终完成了,但是大多数测试用例即使在大多数在线解释器上也会超时f(UK_POUND, 5)

这是一个41字节的版本,它通过添加额外的结束条件来更快地完成,并且实际上很难超时

f=->c,n{n>0?c.find{|i|f[c-[i],n-i]}:n==0}

在线尝试!


1

Bash + GNU实用程序,56 39

printf %$2s|egrep "^ {${1//,/\}? {}}?$"

输入面额列表(未排序)以逗号分隔的列表形式给出。输入列表和值作为命令行参数给出。

输出以shell返回码的形式给出。echo $?运行脚本后检查。 0表示真实1表示虚假。

在线尝试

  • printf %$2s输出一串value空格
  • "^ {${1//,/\}? {}}?$"是Shell扩展,将面额列表扩展为regex等正则表达式^ {1}? {2}? {5}? {10}? ... $。事实证明egrep,不管面额以什么顺序排列,正则表达式引擎都足够聪明,可以正确地与此匹配。
  • egrep 检查空格字符串是否与正则表达式匹配

1

C,66字节

m;v;f(n){for(m=1e5;m/=10;)for(v=5;n-=n<v*m?0:v*m,v/=2;);return!n;}

看到它在这里工作

C,53字节

g(c,w,n)int*c;{for(;n-=n<c[--w]?0:c[w],w;);return!n;}

此变体采用硬币阵列,这无法实现此问题,因为它归结为简单的减法。

第一个参数是硬币数组,第二个参数是硬币计数,第三个参数是值。

C,48个字节

g(c,n)int*c;{for(;n-=n<*c?0:*c,*++c;);return!n;}

替代以前的变体。它假定硬币阵列可以反转并且零终止。



0

CJam18 17字节

q~_,2\m*\f.*::+#)

在线尝试!

说明

q~                  e# Read and eval input.
  _,                e# Duplicate the money list and take its length.
    2\m*            e# Take the (length)th Cartesian power of [0 1].
        \f.*        e# Element-wise multiplication of each set of 0's and 1's with the money
                    e#   list. This is essentially the powerset, but with 0s instead of 
                    e#   missing elements.
            ::+     e# Sum each set.
               #    e# Find the index of the desired amount in the list. (-1 if not found)
                )   e# Increment. -1 => 0 (falsy), anything else => nonzero (truthy)



0

八度,39字节

 @(L,n)any(cellfun(@sum,powerset(L))==n)

匿名函数,它将硬币值数组作为第一个参数,将目标整数作为第二个参数,并返回true或false。

在线尝试!


0

Mathematica,42个字节

ListQ@NumberDecompose[#,Sort[#2,Greater]]&

输入

[15,{10,5}]

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.