ðŸŽ„ 2/25. Grepping dividable numbers in Perl 6

Welcome to Day 2 of the Perl 6Â One-Liner Advent Calendar! Today, weâ€™ll solve a nice task from Project Euler with number 1. Once again, let me warn you that the rest of the text contains a solution, so you are welcome to make a pause to think of your own solution first. But I am almost sure that if you are reading perl6.online then you most likely solved the problems from Project Euler in the past.

The task is to find the sum of all multiples of 3 and 5 below 1000. The first elements of the row of our interest are 3, 5, 9, 15, 20, 21, etc. You can already see that some of them, such as 15, are multiples of both 3 and 5, so it is not possible to add up multiples of 3 and 5 separately.

The short story is here:

`say sum((1..999).grep: * %% (3 | 5))`

Now let us decipher it.

What we need is to filter the numbers that are multiples of either 3 or 5. If you re-read the previous sentence, a bell should ring for you: in Perl 6 this can be achieved with junctions, informally known as quantum superpositions. To test if a number is dividable by either 3 or 5, write the following:

`\$x %% 3 | 5`

By the way, %%, the divisibility operator, is a very sweet thing that helps avoiding negations in Boolean tests, which you would have written as follows, would you only have a single percent:

`!(\$x % (3 | 5))`

OK, the main condition is ready, let us scan the numbers between 1 and (including) 999:

`(1..999).grep: * %% (3 | 5)`

A few more interesting Perl 6 elements appear here. For example, the WhateverCodeÂ block, which was introduced by a * character (learn more about it in my article All the stars of Perl 6 published in the previous Perl 6 Advent Calendar). Together with the colon-form of method calls, it allows to get rid of a nested pair of braces and parentheses:

`(1..999).grep({\$_ %% (3 | 5)})`

The numbers are filtered (grepped if you prefer), and itâ€™s time to add them up and print the result. We come to the final one-liner shown at the beginning of this post.

Of course, instead of writing say sum(...)Â one could do a method call or two:

`((1..999).grep: * %% (3 | 5)).sum.say`

As a bonus track, hereâ€™s my first solution:

```sub f(\$n) {
(\$n <<*>> (1...1000 / \$n)).grep: * < 1000
}

say (f(3) âˆª f(5)).keys.sum;```

And thatâ€™s the end of todayâ€™s story! Come again tomorrow!