如何计算 Perl 6 中整数的交替数字和?
How to calculate alternating sum of digits of an integer in Perl 6?
A number is divisible by 11 if its alternating sum of digits is
divisible by 11.
所以,例如如果数字是1595
,+1 -5 +9 -5 == 0
,那么1595可以被11整除。如何实现这样的和?这是我的解决方案,但它太复杂并且只有在位数为偶数时才有效。
my $number = 1595;
say [+] $number.comb.map({$^a - $^b});
最好的方法是什么?
say [+] 1595.comb Z* (1, -1, 1 ... *)
分解:.comb returns 字符列表,Z* 将该列表按元素与 RHS 上的序列相乘。
这个数列是一个几何数列,...
级数算子可以从三个元素推导出来。由于 zip 运算符 Z
在最短序列处停止,因此我们不必注意在 RHS 上终止序列。
另一种写法是:
say [+] 1595.comb Z* (1, -* ... *)
其中 -*
是对前一个值的显式否定,应用于初始元素以生成下一个。
你也可以写成
say [+] 1595.comb Z* (1, &prefix:<-> ... *)
Moritz 使用的交叉很有趣(也很讨人喜欢),但您也可以从列表中分块。这与您最初尝试的很接近。我想你要去 rotor
:
my $number = 1595;
say [+] $number.comb.rotor(2, :partial).map: { $^a.[0] - ($^a.[1] // 0) }
请注意,您的块有一个参数。这就是清单。这有点难看,因为奇数的情况下 $^a.[1]
Nil
会发出警告。
既然我已经尝试了更多,我就用签名来处理它,这样我就可以给 $b
一个默认值。这样好多了:
my $number = 1595;
say [+] $number
.comb
.rotor(2, :partial)
.map: -> ( $a, $b = 0 ) { $a - $b }
但您甚至不需要 rotor
,因为 map
会根据需要获取尽可能多的位置参数(h/t 到评论中的 timotimo)。这意味着你真的很接近,只是错过了签名:
my $number = 1595;
say [+] $number
.comb
.map: -> ( $a, $b = 0 ) { $a - $b }
您在评论中的解决方案不适用于奇数位数的情况:
say [+] $number.comb.rotor(2, :partial).map({[-] $_});
而且,我知道这个问题并不是关于除数的,但我很高兴 Perl 6 有一个 "divisible by" 运算符,%%
:
$ perl6
> 121 %% 11
True
> 122 %% 11
False
> 1595 %% 11
True
> 1596 %% 11
False
这是我的解决方案。
say [+] 15956.comb.kv.map( (-1) ** * * * ); # 6
还有一个更明确的版本。
say [+] 15956.comb.kv.map({ $^b * (-1) ** $^a }); # 6
UPD:又一个解决方案。
say - [+] 15956.comb(2)>>.comb.map({[R-] $_}); # 6
say [+] 1595.comb >>*>> (1,-1)
与 Z* 版本类似,但在右侧使用超元运算符循环效果(如果左侧少于 2 位就可以)。
A number is divisible by 11 if its alternating sum of digits is divisible by 11.
所以,例如如果数字是1595
,+1 -5 +9 -5 == 0
,那么1595可以被11整除。如何实现这样的和?这是我的解决方案,但它太复杂并且只有在位数为偶数时才有效。
my $number = 1595;
say [+] $number.comb.map({$^a - $^b});
最好的方法是什么?
say [+] 1595.comb Z* (1, -1, 1 ... *)
分解:.comb returns 字符列表,Z* 将该列表按元素与 RHS 上的序列相乘。
这个数列是一个几何数列,...
级数算子可以从三个元素推导出来。由于 zip 运算符 Z
在最短序列处停止,因此我们不必注意在 RHS 上终止序列。
另一种写法是:
say [+] 1595.comb Z* (1, -* ... *)
其中 -*
是对前一个值的显式否定,应用于初始元素以生成下一个。
你也可以写成
say [+] 1595.comb Z* (1, &prefix:<-> ... *)
Moritz 使用的交叉很有趣(也很讨人喜欢),但您也可以从列表中分块。这与您最初尝试的很接近。我想你要去 rotor
:
my $number = 1595;
say [+] $number.comb.rotor(2, :partial).map: { $^a.[0] - ($^a.[1] // 0) }
请注意,您的块有一个参数。这就是清单。这有点难看,因为奇数的情况下 $^a.[1]
Nil
会发出警告。
既然我已经尝试了更多,我就用签名来处理它,这样我就可以给 $b
一个默认值。这样好多了:
my $number = 1595;
say [+] $number
.comb
.rotor(2, :partial)
.map: -> ( $a, $b = 0 ) { $a - $b }
但您甚至不需要 rotor
,因为 map
会根据需要获取尽可能多的位置参数(h/t 到评论中的 timotimo)。这意味着你真的很接近,只是错过了签名:
my $number = 1595;
say [+] $number
.comb
.map: -> ( $a, $b = 0 ) { $a - $b }
您在评论中的解决方案不适用于奇数位数的情况:
say [+] $number.comb.rotor(2, :partial).map({[-] $_});
而且,我知道这个问题并不是关于除数的,但我很高兴 Perl 6 有一个 "divisible by" 运算符,%%
:
$ perl6
> 121 %% 11
True
> 122 %% 11
False
> 1595 %% 11
True
> 1596 %% 11
False
这是我的解决方案。
say [+] 15956.comb.kv.map( (-1) ** * * * ); # 6
还有一个更明确的版本。
say [+] 15956.comb.kv.map({ $^b * (-1) ** $^a }); # 6
UPD:又一个解决方案。
say - [+] 15956.comb(2)>>.comb.map({[R-] $_}); # 6
say [+] 1595.comb >>*>> (1,-1)
与 Z* 版本类似,但在右侧使用超元运算符循环效果(如果左侧少于 2 位就可以)。