欢迎来到
Raku One-Liner Advent Calendar 的第
13天!今天的单行将很长,最好用两行编写,但它会显示 Raku 的 Date 对象的一个非常好的功能:它可以很容易地在一个范围内使用。
今天,我们正在解决欧拉项目的问题19。从本质上讲,任务是计算在1901年1月1日至2000年12月31日期间的星期日,这是在第一个月。
Raku 中的 Date 对象实现了 succ
和 prec
方法,它们递增和递减日期。也可以使用两个日期作为范围的边界:
1 2 3
|
say ( Date.new(year => 1901) ..^ Date.new(year => 2001) ).grep({.day == 1 && .day-of-week == 7}).elems
|
在这里评论一下。
首先,使用单个命名参数(year
)创建两个 Date 对象。这是可能的,因为构造函数的签名具有月和日的默认值:
1 2 3 4 5 6
|
multi method new( Date: Int:D() :$year!, Int:D() :$month = 1, Int:D() :$day = 1, :&formatter, *%_) { . . . }
|
因此,创建1月1日的日期很容易,但是在一年的最后一天你不能这样做。但是 Raku 有一个很好的范围运算符 ..^
,它排除了右边界并允许我们节省相当多的字符(而我们还没有玩 Raku Golf :-)。
具有日期的所有显式部分的较长版本将如下所示:
1 2 3 4
|
say ( Date.new(year => 1901, month => 1, day => 1) .. Date.new(year => 2000, month => 12, day => 31) ).grep({.day == 1 && .day-of-week == 7}).elems
|
您可以使用组合条件创建范围并 grep
其值。请记住,当您要在默认变量上调用方法时,无需显式键入 $_
。
另一种方法是使用带有星号的两个 grep
s:
1 2 3 4
|
say ( Date.new(year => 1901, month => 1, day => 1) .. Date.new(year => 2000, month => 12, day => 31) ).grep(*.day == 1).grep(*.day-of-week == 7).elems
|
给你留个家庭作业:打印此 Advent 日历结束前剩余的天数。明天见!
近期评论