🎄 14/25. 昨天问题的另一个解决方案
— 焉知非鱼欢迎来到 Raku One-Liner Advent Calendar 的第14天!今天,我们正在提出我们昨天解决的问题的另一个答案。任务是计算二十世纪第一个月的所有星期日。
昨天,我们只扫描了整个世纪的所有日子,选择星期日( .day-of-week == 7
)并且是本月的第一天(.day == 1
)。
可以制作更有效的算法。由于我们只对本月的第一天感兴趣,因此无需在100年内扫描所有36525天,而只需要扫描100天,这是1901年到2000年之间每个月的第一天。
因此,我们需要两个嵌套循环:年和月。我们需要两个 for
吗?不必要。我们使用 X 运算符;我们从以前的出版帖子中熟悉它。
这是我们今天的单行:
(gather for 1901..2000 X 1..12 {
take Date.new(|@_, 1)
}).grep(*.day-of-week == 7).elems.say;
for 1901..2000 X 1..12
循环在遍历二十世纪的每个月份。对于每个循环变量,我们通过调用具有三个参数的构造函数来创建 Date
对象。
请注意,在循环内部,您可以同时使用 $_[0]
和 $_[1]
,以及 @_[0]
和 @_[1]
。在第一种情况下,$_
变量包含两个元素的列表,而在第二种情况下,它是一个数组 @_
。如果您只是使用点来调用主题(默认)变量上的方法,则可以实现最短的代码:.[0]
和 .[1]
。
您可以键入 Date.new(.[0], .[1], 1)
代替 Date.new(|@_, 1)
。 |@_
语法用于展开数组,否则 Raku 会认为您将数组作为第一个参数传递。
在 gather-take 对儿的帮助下,将这些月份的所有第一天收集到序列中。
最后一步是昨天的 grep
,但这次我们只需要选择星期日,所以单个 *.day-of-week == 7
条件就足够了。
elems
方法的调用返回列表中元素的数量,即我们正在寻找的星期日数量。因此,请用 say
打印出来。
一个新的想法和一个新的答案应该让你在这个 One-Liner 日历中至少有一天感到高兴,直到明天的帖子!