# ðŸŽ„ 13/25. How many days in the century match the condition?

Welcome to Day 13 of the Perl 6 One-Liner Advent Calendar! Todayâ€™s one-liner will be quite long, and it would be better to write it in two lines, but it will show a very nice feature of Perl 6â€™s Date objects: it can be easily used in a range.

Today, we are solving Problem 19 of the Project Euler. In essence, the task is to count Sundays between 1 January 1901 and 31 December 2000, which fall on the first of the months.

The Date object in Perl 6 implements the succ and prec methods, which are incrementing and decrementing the date. It is also possible to use two dates as the boundaries of a range:

say (
Date.new(year => 1901) ..^ Date.new(year => 2001)
).grep({.day == 1 && .day-of-week == 7}).elems

There are a few moments to comment here.

First, the two Date objects are created with a single named parameter, the year. This is possible because the signature of the constructor has default values for both the month and the day:

multi method new(
Date: Int:D() :\$year!,
Int:D() :\$month = 1, Int:D() :\$day = 1,
:&formatter, *%_) {
. . .
}

So itâ€™s easy to create a date for 1 January, but you canâ€™t do that for the last day of the year. But Perl 6 has a nice range operator ..^, which excludes the right boundary and allows us to save quite a few characters (while we are not playing Perl 6 Golf yet :-).

The longer version, with all explicit parts of the dates, would then look like this:

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

You create a range and grep its values using a combined condition. Remember that there is no need to explicitly type \$_ when you want to call a method on the default variable.

An alternative would be to use twoÂ greps with a star:

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

An exercise for you to make at home:Â Print the number of days left until the end of this Advent Calendar. See you tomorrow!

## 5 thoughts on “ðŸŽ„ 13/25. How many days in the century match the condition?”

1. Even shorter (and onelinerier):

say +(Date.new(1901,1,1)..^Date.new(2001,1,1)).grep: {.day == 1 && .day-of-week == 7}

Liked by 1 person

2. mrjones1 says:

Thanks for the introduction to dates and a lot more too. I was going to challenge myself to working out every 2nd Sunday when I had a look at the docs and it was very easy to convert your one liner to second sunday…

{ .day-of-week == 7 && .weekday-of-month == 2}

These are great, and a great jumping off point for more exploration…

Like