Perl 6 - Curried 函数挂起
Perl 6 - Curried Function Hangs
所以,我希望能够编写一个函数,找出使用不同价值的硬币找零特定金额的所有方法。
所以,我写了一个函数 coin
告诉你对于给定的金额,你可以用多少种方法来改变这个价值,给定一个特定价值的硬币,以及一个函数来计算有多少种方法你可以做出改变,对下一个较小的硬币使用相同类型的参数。
然后我尝试编写一个函数 ladder
我想要 return 一个函数,对于硬币值的@array return 一个函数采用单个形式参数 $amt
计算给定数组中指定的硬币值,您可以更改该金额的方法数。
我尝试使用 &coin
函数和 .assuming
方法来添加硬币的价值并建立适当的阶梯。不幸的是,当我尝试 运行 结果函数时它挂起。
my @values = 2, 5, 10, 20, 50, 100, 200;
#the coin of value 1 is assumed as a base case
my &test = ladder(@values);
say &test(5);
sub ladder(@values) {
my &base = sub () { return @values.shift };
for @values {
&base = &coin.assuming(*,$_,&base);
}
return &base;
}
sub coin($amt,$value,&lesser) {
if $amt >= $value {
return &coin($amt-$value,$value,&lesser) + &lesser($amt);
} else {
return &lesser($amt);
}
}
为了给出一个想法,&ladders 应该在下面的函数系列中产生与 &twopd 等价的东西。
sub twopd($amt) { return &coin($amt,200,&onepd) };
sub onepd($amt) { return &coin($amt,100,&fifp) };
sub fifp($amt) { return &coin($amt,50,&twep) };
sub twep($amt) { return &coin($amt,20,&tenp) };
sub tenp($amt) { return &coin($amt,10,&fivp) };
sub fivp($amt) { return &coin($amt,5,&twop) };
sub twop($amt) { return &coin($amt,2,&onep) };
sub onep($amt) { return 1 };
我想知道是否有人知道我做错了什么。
sub () { return @values.shift }
每次调用时都会从 @values
中删除一个值,这不是您想要的。
&coin.assuming(*,$_,&base)
需要对 &base
做一些事情,以便它获得 &base
中的当前值,而不是它最后剩下的值循环。一种选择是在其前面添加 |
,另一种是使用 <>
对值进行去容器化。
向 coin
添加一些缓存可能是个好主意,因为对于较大的值,它会多次使用相同的参数调用。
sub ladder ( +@ ($initial, *@values) ) {
my &base = -> $ { $initial };
for @values {
&base = &coin.assuming: *, $_, &base<>;
}
return &base;
}
use experimental :cached;
sub coin ( $amt, $value, &lesser ) is cached {
if $amt >= $value {
coin( $amt - $value, $value, &lesser ) + lesser($amt);
} else {
lesser( $amt );
}
}
所以,我希望能够编写一个函数,找出使用不同价值的硬币找零特定金额的所有方法。
所以,我写了一个函数 coin
告诉你对于给定的金额,你可以用多少种方法来改变这个价值,给定一个特定价值的硬币,以及一个函数来计算有多少种方法你可以做出改变,对下一个较小的硬币使用相同类型的参数。
然后我尝试编写一个函数 ladder
我想要 return 一个函数,对于硬币值的@array return 一个函数采用单个形式参数 $amt
计算给定数组中指定的硬币值,您可以更改该金额的方法数。
我尝试使用 &coin
函数和 .assuming
方法来添加硬币的价值并建立适当的阶梯。不幸的是,当我尝试 运行 结果函数时它挂起。
my @values = 2, 5, 10, 20, 50, 100, 200;
#the coin of value 1 is assumed as a base case
my &test = ladder(@values);
say &test(5);
sub ladder(@values) {
my &base = sub () { return @values.shift };
for @values {
&base = &coin.assuming(*,$_,&base);
}
return &base;
}
sub coin($amt,$value,&lesser) {
if $amt >= $value {
return &coin($amt-$value,$value,&lesser) + &lesser($amt);
} else {
return &lesser($amt);
}
}
为了给出一个想法,&ladders 应该在下面的函数系列中产生与 &twopd 等价的东西。
sub twopd($amt) { return &coin($amt,200,&onepd) };
sub onepd($amt) { return &coin($amt,100,&fifp) };
sub fifp($amt) { return &coin($amt,50,&twep) };
sub twep($amt) { return &coin($amt,20,&tenp) };
sub tenp($amt) { return &coin($amt,10,&fivp) };
sub fivp($amt) { return &coin($amt,5,&twop) };
sub twop($amt) { return &coin($amt,2,&onep) };
sub onep($amt) { return 1 };
我想知道是否有人知道我做错了什么。
sub () { return @values.shift }
每次调用时都会从@values
中删除一个值,这不是您想要的。&coin.assuming(*,$_,&base)
需要对&base
做一些事情,以便它获得&base
中的当前值,而不是它最后剩下的值循环。一种选择是在其前面添加|
,另一种是使用<>
对值进行去容器化。
向 coin
添加一些缓存可能是个好主意,因为对于较大的值,它会多次使用相同的参数调用。
sub ladder ( +@ ($initial, *@values) ) {
my &base = -> $ { $initial };
for @values {
&base = &coin.assuming: *, $_, &base<>;
}
return &base;
}
use experimental :cached;
sub coin ( $amt, $value, &lesser ) is cached {
if $amt >= $value {
coin( $amt - $value, $value, &lesser ) + lesser($amt);
} else {
lesser( $amt );
}
}