一分钱的节省就是一分钱


21

...算了!

您将为您的程序传递一个变量,该变量代表以美元和/或美分表示的货币数量以及一系列硬币值。您的挑战是输出给定硬币值数组的可能组合的数量,这些数量加起来将等于传递给代码的数量。如果使用命名的硬币不可能,则程序应返回0

关于美国钱币学术语的注释:

  • 1分硬币:美分
  • 5美分硬币:镍
  • 10分硬币:角钱
  • 25美分的硬币:季度(四分之一美元)

范例1:

程序通过:

12, [1, 5, 10]

(12美分)

输出:

4

有四种可能的方法来组合命名为12美分的硬币:

  1. 12便士
  2. 1镍7便士
  3. 2镍2便士
  4. 1角钱和2便士

范例2:

程序通过:

26, [1, 5, 10, 25]

(26分)

输出:

13

有13种可能的方法来组合命名为26美分的硬币:

  1. 26便士
  2. 21便士和1镍
  3. 16便士和2镍
  4. 11便士和3镍
  5. 6便士和4镍
  6. 1便士和5镍
  7. 16便士和1角钱
  8. 6便士和2角钱
  9. 11便士,1角钱和1镍
  10. 6便士,1角钱和2枚镍币
  11. 1便士,1美分和3枚镍币
  12. 1便士,2角钱和1镍
  13. 1个季度1分钱

范例3:

程序通过:

19, [2, 7, 12]

输出:

2

有两种可能的方式来组合命名为19美分的硬币:

  1. 1个12美分硬币和1个7美分硬币
  2. 1个7美分硬币和6个2美分硬币

范例4:

程序通过:

13, [2, 8, 25]

输出:

0

没有可能的方法来组合命名为13美分的硬币。


这已经通过沙箱进行了。有标准漏洞。这是代码高尔夫球,因此字节最少的答案会获胜。


1
s / counted / earned
mbomb007 '16

4
@ mbomb007四个字节:s/count/earn
wizzwizz4 '16

5
对于我和我来说,对于其他不使用美元付款的人来说,一角钱和一角钱并不明显。弄清楚它并不难,但也许您可以将它写得更具国际性?
克里茨菲茨

2
@Kritzefitz。我已将其添加到问题中。
TRiG

2
@jpaugh:虽然硬币爱好者可以同意,但我不得不不同意。一分钱是标准硬币,价值为一美分。五十四美分是一笔钱。五十四便士是五十四硬币。它也被称为“一美分硬币”,或(正式地)为“一美分硬币”。我想不出任何正式的环境,其中“ penny”一词是不可接受的。这些人专门收集硬币,将其称为“便士”没有问题。
MichaelS

Answers:


12

果冻(叉子),2个字节

æf

这依赖于Jelly的一个分支,在该分支中,我正在实现Frobenius求解原子,因此很遗憾,您无法在线进行尝试。

用法

$ ./jelly eun 'æf' '12' '[1,5,10]'
4
$ ./jelly eun 'æf' '26' '[1,5,10,25]'
13
$ ./jelly eun 'æf' '19' '[2,7,12]'
2
$ ./jelly eun 'æf' '13' '[2,8,25]'
0

说明

æf  Input: total T, denominations D
æf  Frobenius count, determines the number of solutions
    of nonnegative X such that X dot-product D = T

10
...这甚至不公平。
ETHproductions '16

...而且我敢打赌,速度要快得多!
乔纳森·艾伦,

18

Haskell,37 34字节

s#l@(c:d)|s>=c=(s-c)#l+s#d
s#_=0^s

用法示例:26 # [1,5,10,25]-> 13

简单的递归方法:尝试列表中的下一个数字(只要它小于或等于该数量),然后跳过它。如果将数字相减得出零,则采用1else(或如果列表用完元素)采用a 0。将这些1s和0s 相加。

编辑:@Damien:通过指向递归的较短基本情况(也可以在@xnors answer中找到)节省了3个字节。


s#l @(c:d)| s> = c =(sc)#l + s#d; s#_ = 0 ^ s
Damien

以及1209 [1,5,10,33,48]和6000 [1,5,10,33]的结果是什么,所以我可以校准我的代码
RosLuP

@RosLuP:1209 # [1,5,10,33,48]-> 1314050
nimi

@nimi ok对于1314050,我在这里有相同的结果...谢谢...
RosLuP

@RosLuP:... 537分钟后:6000 # [1,5,10,33]-> 22086484
nimi

15

Mathematica,35个 22字节

感谢Miles建议FrobeniusSolve和保存13个字节。

Length@*FrobeniusSolve

计算为一个未命名函数,该函数将硬币列表作为第一个参数,将目标值作为第二个参数。FrobeniusSolve是求解形式的Diophantine方程的简写

a1x1 + a2x2 + ... + anxn = b

对于非负整数,并为我们提供了所有解决方案。xi


@RosLuP您需要访问Mathematica才能运行此程序。这也是一个匿名函数,因此可以调用它,或者将其封装在括号中或将其存储到变量中。例如,(Length@*FrobeniusSolve)[{1, 7, 9}, 18]
英里

以及1209 [1,5,10,33,48]和6000 [1,5,10,33]的结果是什么,所以我可以校准我的代码
RosLuP

@RosLuP 1314050和22086484。
Martin Ender

好,这里的结果是一样的,谢谢...
RosLuP

仅当编写Length @ * FrobeniusSolve的程序员是您时,才有16票赞成
。– RosLuP

12

Pyth,8个字节

/sM{yS*E

原始蛮力,对于实际测试而言占用大量内存。这是O(2 mn),其中n是硬币数,m是目标总和。将输入作为target\n[c,o,i,n,s]

/sM{yS*EQQ      (implicit Q's)
      *EQ       multiply coin list by target
     S          sort
    y           powerset (all subsequences)
   {            remove duplicates
 sM             sum all results
/        Q      count correct sums

9

Haskell,37个字节

s%(h:t)=sum$map(%t)[s,s-h..0]
s%_=0^s

使用第一个硬币的某些倍数h将所需的总和s以递减的顺序减少到非负值[s,s-h..0],然后必须使用剩​​余的硬币进行计算。一旦没有硬币,请按算术检查总和为零0^s


令人惊讶的是,您使用不同的方法达到了与@nimi完全相同的字节数。
克里兹菲茨

9

JavaScript(ES6),51 48字节

f=(n,a,[c,...b]=a)=>n?n>0&&c?f(n-c,a)+f(n,b):0:1

接受任何顺序的硬币。尝试使用和不使用第一个硬币,以任何一种方式递归计算组合数量。n==0表示匹配的组合,n<0表示硬币超过数量,而c==undefined表示没有硬币。请注意,该功能非常慢,如果您拥有一分钱硬币,则以下功能会更快(不要将一分钱硬币传递到硬币阵列中):

f=(n,a,[c,...b]=a)=>c?(c<=n&&f(n-c,a))+f(n,b):1

...该死的。真正的好主意。
ETHproductions's October

以及1209 [1,5,10,33,48]和6000 [1,5,10,33]的结果是什么,所以我可以校准我的代码
RosLuP

@RosLuP给定的代码最终将为您的第一个示例返回1314050。我的解释器无法处理评估第二个示例所需的递归。
尼尔

@RosLuP我修改了该函数,以假定存在额外的一分钱硬币,并且该硬币返回了22086484,金额为6000 [5,10,33]。
尼尔

@Neil ok 22086484 for 6000 [1,5,10,33] ...取而代之的是11239,这里是6000 [5,10,33](您编写的数组)
RosLuP

7

Perl,45个字节

字节计数包括44个字节的代码和-p标志。

s%\S+%(1{$&})*%g,(1x<>)=~/^$_$(?{$\++})^/x}{

在第一行获取硬币值,在第二行获取目标金额:

$ perl -pE 's%\S+%(1{$&})*%g,(1x<>)=~/^$_$(?{$\++})^/x}{' <<< "1 5 10 25
26"
13

简短说明:

-p                        # Set $_ to the value of the input, 
                          # and adds a print at the end of the code.
s%\S+%(1{$&})*%g,         # Converts each number n to (1{$&})* (to prepare the regex)
                          # This pattern does half the job.
(1x<>)                    # Converts the target to unary representation.
  =~                      # Match against.. (regex)
    /^ $_ $               # $_ contains the pattern we prepared with the first line.
     (?{$\++})            # Count the number of successful matches
     ^                    # Forces a fail in the regex since the begining can't be matched here.
    /x                    # Ignore white-spaces in the regex 
                          # (needed since the available coins are space-separated)
 }{                       # End the code block to avoid the input being printed (because of -p flag) 
                          # The print will still be executed, but $_ will be empty, 
                          # and only $\ will be printed (this variable is added after every print)

6

果冻10 9 字节

œċЀS€€Fċ

在线尝试!

怎么样?

œċЀS€€Fċ - Main link: coins, target
  Ѐ      - map over right argument, or for each n in [1,2,...,target]
œċ        - combinations with replacement, possible choices of each of n coins
    S€€   - sum for each for each (values of those selections)
       F  - flatten into one list
        ċ - count occurrences of right argument

2
+1表示在与金钱相关的问题中使用了那么多欧元符号。
steenbergh

6

JavaScript(ES6),59个字节

f=(n,c)=>n?c.reduce((x,y,i)=>y>n?x:x+f(n-y,c.slice(i)),0):1

从最高到最低输入硬币,例如f(26,[100,25,10,5,1])。如果您有一分钱,请删除它,然后使用此更快的版本:

f=(n,c)=>n?c.reduce((x,y,i)=>y>n?x:x+f(n-y,c.slice(i)),1):1

这使用了类似于@nimi的递归公式。我最初是在几天前写这篇文章的,当时挑战仍在沙盒中。它看起来像这样:

f=(n,c=[100,25,10,5])=>n?c.reduce((x,y,i)=>y>n?x:x+f(n-y,c.slice(i)),1):1

是的默认值唯一的区别c(它在原始的询问设定值),并改变0.reduce功能1(这是两个字节短,速度比一bazillion倍c=[100,25,10,5,1])。


这是修改后的版本,它输出所有组合,而不是组合数量:

f=(n,c)=>n?c.reduce((x,y,i)=>y>n?x:[...x,...f(n-y,c.slice(i)).map(c=>[...c,y])],[]):[[]]

以及1209 [1,5,10,33,48]和6000 [1,5,10,33]的结果是什么,所以我可以校准我的代码
RosLuP

@RosLuP我分别得到1314050(5分钟后)和堆栈溢出(一个小时后)。使用我刚刚添加的更快的版本,几秒钟内即可获得1314050和22086484。
ETHproductions 16-10-22

使用我的旧Pentium 2.8Gh计算机6秒可获得第一个结果,第二个5分钟+或
RosLuP 16/10/22

5

PHP,327字节

function c($f,$z=0){global$p,$d;if($z){foreach($p as$m){for($j=0;$j<=$f/$d[$z];){$n=$m;$n[$d[$z]]=$j++;$p[]=$n;}}}else for($p=[],$j=0;$j<=$f/$d[$z];$j++)$p[]=[$d[$z]=>$j];if($d[++$z])c($f,$z);}$d=$_GET[a];c($e=$_GET[b]);foreach($p as$u){$s=0;foreach($u as$k=>$v)$s+=$v*$k;if($s==$e&count($u)==count($d))$t[]=$u;}echo count($t);

试试吧


5

公理,63 62字节

@JonathanAllan保存了1个字节

f(n,l)==coefficient(series(reduce(*,[1/(1-x^i)for i in l])),n)

这种方法使用生成函数。可能这没有帮助减小代码大小。我认为这是我在与Axiom一起玩时第一次尝试定义自己的功能。

第一次调用该函数会发出可怕的警告,但仍会产生正确的结果。之后,只要列表不为空,一切都很好。


1
我不知道Axiom-是否可以删除之前的空格for
乔纳森·艾伦,

1
@JonathanAllan是的,是的!良好的高尔夫本能,谢谢!
Christian Sievers

5

R,81 76 63字节

感谢@rturnbull高尔夫球走了13个字节!

function(u,v)sum(t(t(expand.grid(lapply(u/v,seq,f=0))))%*%v==u)

示例(请注意,这c(...)是将值向量传递给R的方式):

f(12,c(1,5,10))
[1] 4

说明:

u是期望值,v是硬币价值的向量。

expand.grid(lapply(u/v,seq,from=0))

使用0到k个硬币的每种可能组合创建一个数据帧(k取决于面额),其中k是最低的,以便k乘以该硬币的值至少为u(要实现的值)。

通常,我们会使用它as.matrix来将其转换为矩阵,但这是许多字符。取而代之的是我们采用转置(!)的转置,该转置会自动将其强制转换,但是占用的字符更少。

%*% v然后计算每一行的货币价值。最后一步是计算这些值中有多少等于所需值u

请注意,此方法的计算复杂性和内存要求令人震惊,但嘿,这是代码高尔夫。


1
很好用expand.grid!我喜欢这个t(t())把戏。由于函数仅涉及一行代码,因此可以删除花括号,从而节省了2个字节。此外,您还可以切换do.call(expand.grid,lapply(u/v,seq,from=0))为刚expand.grid(lapply(u/v,seq,f=0)),节省11个字节。
rturnbull

谢谢那些!我从未意识到expand.grid会接受清单作为输入。有点可耻的是,":"对于非整数的人来说效果不好,否则lapply(u/v,":",0)会节省更多。
JDL

do.call(x,y)与相同x(y),因此与接受哪种输入无关。如果您真的想使用:,我想您可以使用lapply(u%/%v,`:`,0),但是它是相同的字节数。
rturnbull

1
do.call(x,y)x(y)” 相同--仅在y不是列表的情况下,在这种情况下就是这样。不过,同意第二点。
JDL

3

J,27个字节

1#.[=](+/ .*~]#:,@i.)1+<.@%

用法

   f =: 1#.[=](+/ .*~]#:,@i.)1+<.@%
   12 f 1 5 10
4
   26 f 1 5 10 25
13
   19 f 2 7 12
2
   13 f 2 8 25
0

说明

1#.[=](+/ .*~]#:,@i.)1+<.@%  Input: target T (LHS), denominations D (RHS)
                          %  Divide T by each in D
                       <.@   Floor each
                             These are the maximum number of each denomination
                     1+      Add 1 to each, call these B
                ,@i.         Forms the range 0 the the product of B
             ]               Get B
              #:             Convert each in the range to mixed radix B
     ]                       Get D
       +/ .*~                Dot product between D and each mixed radix number
                             These are all combinations of denominations up to T
   [                         Get T
    =                        Test if each sum is equal to T
1#.                          Convert as base 1 digits to decimal (takes the sum)
                             This is the number of times each sum was true

J太棒了,也太疯狂了
CommaToast '16

2

TSQL,105个字节

这4种硬币类型最多只能处理1美元。非高尔夫版本可以处理大约4美元,但是非常慢-在我的盒子上这需要27秒。结果是10045个组合

打高尔夫球:

DECLARE @ INT = 100
DECLARE @t table(z int)
INSERT @t values(1),(5),(10),(25)
;WITH c as(SELECT 0l,0s UNION ALL SELECT z,s+z FROM c,@t WHERE l<=z and s<@)SELECT SUM(1)FROM c WHERE s=@

取消高尔夫:

-- input variables
DECLARE @ INT = 100
DECLARE @t table(z int)
INSERT @t values(1),(5),(10),(25)

-- query
;WITH c as
(
  SELECT 0l,0s
  UNION ALL
  SELECT z,s+z
  FROM c,@t
  WHERE l<=z and s<@
)
SELECT SUM(1)
FROM c
WHERE s=@
-- to allow more than 100 recursions(amounts higher than 1 dollar in this example)
OPTION(MAXRECURSION 0)

小提琴


2

tinylisp repl,66个字节

(d C(q((Q V)(i Q(i(l Q 0)0(i V(s(C(s Q(h V))V)(s 0(C Q(t V))))0))1

递归解决方案:尝试使用第一个硬币而不使用第一个硬币,然后将每个结果相加。指数时间复杂度并且没有尾递归,但是它可以很好地计算测试用例。

Ungolfed(内置关键字:d=定义,q=引用,i=如果,l=小于,s=减,h=头,t=尾):

(d combos
 (q
  ((amount coin-values)
   (i amount
    (i (l amount 0)
     0
     (i coin-values
      (s
       (combos
        (s amount (h coin-values))
        coin-values)
       (s
        0
        (combos
         amount
         (t coin-values))))
      0))
    1))))

用法示例:

tl> (d C(q((Q V)(i Q(i(l Q 0)0(i V(s(C(s Q(h V))V)(s 0(C Q(t V))))0))1
C
tl> (C 12 (q (1 5 10)))
4
tl> (C 26 (q (1 5 10 25)))
13
tl> (C 19 (q (2 7 12)))
2
tl> (C 13 (q (2 8 25)))
0
tl> (C 400 (q (1 5 10 25)))
Error: recursion depth exceeded. How could you forget to use tail calls?!

1

PHP,130字节

function r($n,$a){if($c=$a[0])for(;0<$n;$n-=$c)$o+=r($n,array_slice($a,1));return$o?:$n==0;}echo r($argv[1],array_slice($argv,2));

99字节的递归函数(和31字节的递归函数)可反复从目标中删除当前硬币的值,并使用新值和其他硬币进行调用。计算目标准确达到0的次数。运行像:

 php -r "function r($n,$a){if($c=$a[0])for(;0<$n;$n-=$c)$o+=r($n,array_slice($a,1));return$o?:$n==0;}echo r($argv[1],array_slice($argv,2));" 12 1 5 10

如果使用超过97种不同类型的硬币进行调用,它将在不返回任何内容的情况下死于递归死亡,但是由于这是不同类型的硬币,因此我们必须支持它的罚款。
user59178

1

球拍275字节

(set! l(flatten(for/list((i l))(for/list((j(floor(/ s i))))i))))(define oll'())(for((i(range 1(add1(floor(/ s(apply min l)))))))
(define ol(combinations l i))(for((j ol))(set! j(sort j >))(when(and(= s(apply + j))(not(ormap(λ(x)(equal? x j))oll)))(set! oll(cons j oll)))))oll

取消高尔夫:

(define(f s l)
  (set! l              ; have list contain all possible coins that can be used
        (flatten
         (for/list ((i l))
           (for/list ((j              
                       (floor
                        (/ s i))))
             i))))
  (define oll '())                    ; final list of all solutions initialized
  (for ((i (range 1  
                  (add1
                   (floor             ; for different sizes of coin-set
                    (/ s
                       (apply min l)))))))
    (define ol (combinations l i))          ; get a list of all combinations
    (for ((j ol))                           ; test each combination
      (set! j (sort j >))
      (when (and
             (= s (apply + j))              ; sum is correct
             (not(ormap                     ; solution is not already in list
                  (lambda(x)
                    (equal? x j))
                  oll)))
        (set! oll (cons j oll))             ; add found solution to final list
        )))
  (reverse oll))

测试:

(f 4 '[1 2])
(println "-------------")
(f 12 '[1 5 10])
(println "-------------")
(f 19 '[2 7 12])
(println "-------------")
(f 8 '(1 2 3))

输出:

'((2 2) (2 1 1) (1 1 1 1))
"-------------"
'((10 1 1) (5 5 1 1) (5 1 1 1 1 1 1 1) (1 1 1 1 1 1 1 1 1 1 1 1))
"-------------"
'((12 7) (7 2 2 2 2 2 2))
"-------------"
'((3 3 2) (2 2 2 2) (3 2 2 1) (3 3 1 1) (2 2 2 1 1) (3 2 1 1 1) (2 2 1 1 1 1) (3 1 1 1 1 1) (2 1 1 1 1 1 1) (1 1 1 1 1 1 1 1))

以下递归解决方案有一些错误:

(define (f s l)                      ; s is sum needed; l is list of coin-types
  (set! l (sort l >))
  (define oll '())                   ; list of all solution lists
  (let loop ((l l)   
             (ol '()))               ; a solution list initialized
    (when (not (null? l))
        (set! ol (cons (first l) ol)))
    (define ols (apply + ol))        ; current sum in solution list
    (cond
      [(null? l) (remove-duplicates oll)]
      [(= ols s) (set! oll (cons ol oll))
                 (loop (rest l) '()) 
                 ]
      [(> ols s) (loop (rest l) (rest ol))
                 (loop (rest l) '())   
                 ]
      [(< ols s) (loop l ol) 
                 (loop (rest l) ol)
                 ])))

不适用于以下情况:

(f 8 '[1 2 3])

输出:

'((1 1 1 2 3) (1 2 2 3) (1 1 1 1 1 1 1 1) (2 3 3) (1 1 1 1 1 1 2) (1 1 1 1 2 2) (1 1 2 2 2) (2 2 2 2))

(1 1 3 3)是可能的,但不在解决方案列表中。


我不熟悉球拍,但是我确实在Clojure中写了一个解决方案,解决了与几年前类似的问题,该方案利用了reduce
miles

尽管可以使用“ fold”,但“ reduce”不是Racket基本语言的一部分。由于先前的解决方案存在一些错误,因此我在上面添加了修改后的解决方案。
rnso

看起来像一群Lisp爱好者聚集在一起……拍了拍

1
一些Lisp狂热者首先制作了一个Schemegroups.csail.mit.edu/mac/projects/scheme),最终导致了功能的全面发展Racketracket-lang.orgstackoverflow.com/ questions/3345397 /… )!
rnso

1

果冻,15字节

s+\Fṁḷ
2*BW;ç/Ṫ

在线尝试!要么验证所有测试用例。

这更像是在不使用内置函数的情况下用Jelly编写高效版本的练习。这是基于用于计算更改方式数量的典型动态编程方法的

说明

s+\Fṁḷ  Helper link. Input: solutions S, coin C
s       Slice the solutions into non-overlapping sublists of length C
 +\     Cumulative sum
   F    Flatten
     ḷ  Left, get S
    ṁ   Mold the sums to the shape of S

2*BW;ç/Ṫ  Main link. Input: target T, denominations D
2*        Compute 2^T
  B       Convert to binary, creates a list with 1 followed by T-1 0's
          These are the number of solutions for each value from 0 to T
          starting with no coins used
   W      Wrap it inside another array
    ;     Concatenate with D
     ç/   Reduce using the helper link
       Ṫ  Tail, return the last value which is the solution

1

实际上,15个字节

欢迎打高尔夫球。在线尝试!

╗;R`╜∙♂S╔♂Σi`Mc

开球

         Implicit input n, then the list of coins a.
╗        Save a to register 0.
;R       Duplicate n and create a range [1..n] from that duplicate.
`...`M   Map the following function over that range. Variable i.
  ╜        Push a from register 0.
  ∙        Push the i-th Cartesian power of a.
  ♂S       Sort each member of car_pow.
  ╔        Uniquify car_pow so we don't count too any duplicate coin arrangements.
  ♂Σ       Take the sum of each coin arrangement.
  i        Flatten the list.
c        Using the result of the map and the remaining n, push map.count(n).
         Implicit return.

0

Python,120个字节

from itertools import*
lambda t,L:[sum(map(lambda x,y:x*y,C,L))-t for C in product(range(t+1),repeat=len(L))].count(0)

暴力破解硬币的所有组合直至达到目标值(即使最小不是1)。

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.