如何计算 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 位就可以)。