🎄 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!

🎄 12/25. What’s behind 0.1+0.2 in Perl 6

Welcome to Day 12/25 of this year’s Perl 6 One-Liner Advent Calendar! Today, we will examine a one-liner that computes a zero.

say 0.1 + 0.2 - 0.3

If you are familiar with programming, you know well that as soon as you start using floating-point arithmetic, you loose precision, and you can face the small errors very quickly.

You might also saw the website, 0.30000000000000004.com that has a long list of different programming languages and how they print a simple expression 0.1 + 0.2. In most cases, you don’t get an exact value of 0.3. And often when you get it, it is actually the result of rounding during the print operation.

In Perl 6, 0.1 + 0.2 is exactly 0.3, and today’s one-liner prints an exact zero.

Let us dive a bit to Perl 6 internals to see how that works. A few days ago, we saw that the Grammar of Perl 6 (implemented in the Rakudo compiler) has the following fragment that detects numbers:

token numish {
    [
    | 'NaN' >>
    | <integer>
    | <dec_number>
    | <rad_number>
    | <rat_number>
    | <complex_number>
    | 'Inf' >>
    | $<uinf>='∞'
    | <unum=:No+:Nl>
    ]
}

Most likely you are familiar enough with Perl 6, and you know that the above behaviour is explained by the fact that Perl 6 uses rational numbers to store floating-point numbers such as 0.1. That’s right, but looking at the grammar, you will see that the journey is a bit longer.

What is called rat_number in the grammar is a number written in angle brackets:

token rat_number { '<' <bare_rat_number> '>' }
token bare_rat_number {
<?before <.[-−+0..9<>:boxd]>+? '/'>
<nu=.signed-integer> '/' <de=integer>
}

So if you change the program to:

say <1/10> + <2/10> - <3/10>

then you will immediately be operating rational numbers. Here is a corresponding action that converts numbers in this format:

method rat_number($/) { make $<bare_rat_number>.ast }

method bare_rat_number($/) {
my $nu := $<nu>.ast.compile_time_value;
my $de := $<de>.ast;
my $ast := $*W.add_constant(
'Rat', 'type_new', $nu, $de, :nocache(1));
$ast.node($/);
make $ast;
}

At some point, the abstract syntax tree gets a node containing a constant of the Rat type with the $nu and $de parts as numerator and denominator.

In our example, with numbers written in the form of 0.1, they first pass the dec_number token:

token dec_number {
:dba('decimal number')
[
| $<coeff> = [ '.' <frac=.decint> ] <escale>?
| $<coeff> = [ <int=.decint> '.' <frac=.decint> ]
<escale>?
| $<coeff> = [ <int=.decint> ] <escale>
]
}

The integer and the fractional parts of the number get into the <int> and <frac> keys of the final Match object. The action method for this grammar token is rather complex. Let me show it to you.

method dec_number($/) {
    if $<escale> { # wants a Num
        make $*W.add_numeric_constant: $/, 'Num', ~$/;
    } else { # wants a Rat
        my $Int := $*W.find_symbol(['Int']);
        my $parti;
        my $partf;

        # we build up the number in parts
        if nqp::chars($<int>) {
            $parti := $<int>.ast;
        } else {
            $parti := nqp::box_i(0, $Int);
        }

        if nqp::chars($<frac>) {
            $partf := nqp::radix_I(
                      10, $<frac>.Str, 0, 4, $Int);

            $parti := nqp::mul_I($parti, $partf[1], $Int);
            $parti := nqp::add_I($parti, $partf[0], $Int);

            $partf := $partf[1];
        } else {
            $partf := nqp::box_i(1, $Int);
        }

        my $ast := $*W.add_constant(
            'Rat', 'type_new', $parti, $partf,
            :nocache(1));
        $ast.node($/);
        make $ast;
    }
}

For each of the numbers 0.1, 0.2, and 0.3, the above code takes their integer and fractional parts, prepares the two integers, $parti and $partf, and passes them to the same constructor of a new constant as we saw in the rat_number action, and after that you get a Rat number.

Now we skip some details, and will take a look at another important part with rational numbers that you have to know about them.

In our example, the integer and the fractional part get the following values:

$parti=1, $partf=10
$parti=2, $partf=10
$parti=3, $partf=10

You can easily see it yourself if you hack on your local copy of Rakudo files.

Alternatively, use the --target=parse option in the command line:

$ perl6 --target=parse -e'say 0.1 + 0.2 - 0.3'

A part of the output will contain the data we want to see:

- 0: 0.1
- value: 0.1
    - number: 0.1
    - numish: 0.1
        - dec_number: 0.1
        - frac: 1
        - int: 0
        - coeff: 0.1
- 1: 0.2
- value: 0.2
    - number: 0.2
    - numish: 0.2
        - dec_number: 0.2
        - coeff: 0.2
        - frac: 2
        - int: 0

Having the numbers presented as fractions, it is quite easy to make exact calculations, and that’s why we see a pure zero in the output.

Returning to our fractions. If you print numerator and denominator (using the nude method, for example), you will see that the fraction is normalised if possible:

> <1/10>.nude.say
(1 10)
> <2/10>.nude.say
(1 5)
> 0.2.nude.say
(1 5)
> 0.3.nude.say
(3 10)

As you see, instead of 2/10 we have 1/5, which represents the same number with the same accuracy. When you use the number, you should not worry about finding the common divider for both fractions, for example:

> (0.1 + 0.2).nude.say
(3 10)

I hope there was not too much nudity behind a trivially-looking one-liner today. See you tomorrow with another portion of something interesting with Perl 6!

🎄 11/25. Solving the Problem 34 in Perl 6

Welcome to Day 11 of the Perl 6 One-Liner Advent Calendar! Today, the calendar post is totally devoted to the solution of problem 34 of Project Euler. Once again, let me warn you to pause reading if you want to find your own solution prior to seeing mine.

So, the task is to find the sum of all numbers, which are equal to the sum of factorials of their digits. Sounds clear? 🙂 You may take a look at the solution one-liner to understand it better.

say [+] (3..50_000).grep({$_ == [+] .comb.map({[*] 2..$_})})

Let us start from … something.

We are looping over a range 3 .. 50_000. The upper boundary is a guess based on some considerations. I would not be explaining it here, but you may try to find the answer if you are curious. Basically, at some point you understand that the number either contains too many digits or is too big itself. Refer to the discussion on Project Euler to get a pure explanation.

The second step is to grep. We are searching for numbers, which are equal ($_ ==) to the sum. It is calculated by the second reduction plus [+], but you may use the sum method instead:

{$_ == .comb.map({[*] 2..$_}).sum}

Notice that .comb is a method called on the default variable $_. The comb method splits the number to separate digits (as characters). The map method converts each digit to a factorial (again, using the reduction operator [*], as we did it yesterday).

Finally, the most outer [+] adds up all the grepped numbers, and passes the result to the say routine.

Although the main idea was to show a one-liner, in real practice it would be wiser to prepare the factorials before using them:

my @f = (0..9).map({[*] 1..$_});
say [+] (3..50_000).grep({$_ == [+] .comb.map({@f[$_]})});

And that’s the end of today’s story. There are more for the rest of this calendar!

🎄 10/25. Reduction operator in Perl 6

Welcome to Day 10 of the Perl 6 One-Liner Advent Calendar! Today, there will be three one-liners instead of a regular one.

Our today’s guest is a reduction construction with a pair of square brackets. When they do not surround an array index, they work in a completely different field.

Example 1

The most classical example, which also got to the Perl 6 Calendar 2019, is using the reduction operator to calculate factorial:

say [*] 1..2019

[ ] in Perl 6 is a reduction meta-operator. The meta part of the name tells us that it can be used as an envelope for another operator (and not only operator, by the way).

In the first example, the operator includes another operator, and the whole line can be re-written by enrolling the range to a list and placing the * between all its elements:

say 1 * 2 * 3 #`(more elements) * 2018 * 2019

Example 2

Now, let us solve problem 5 of Project Euler, where we need to find the smallest number, which is dividable by all numbers from 1 to 20.

Let me show you a direct answer in Perl 6:

say [lcm] 1..20

This code looks very similar to the previous example, but uses another operator, the lcm routine, which is an infix operator in Perl 6. The name stands for least common multiplier, but in the documentation you can also read that it returns the smallest integer that is evenly divisible by both arguments. Almost the same words, which were used to formulate the problem we solve.

say 1 lcm 2 lcm 3 lcm 4 lcm 5 lcm 6 lcm 7 # ... and up to 20

Example 3

Other infix operators that are already built-in in Perl 6, can also be very productive. Here’s an example of rotating a matrix with just a few characters of code:

[Z] <A B C>, <D E F>, <H I J>

Here, we are transforming a two-dimentional matrix with nine elements, A through J. In the output, the rows become columns, and columns become rows:

((A D H) (B E I) (C F J))

The zip infix operator Z has been inserted between the elements of the list, and thus the code is similar to the following one:

<A B C> Z <D E F> Z <H I J>

Notice, that if you want to emphasise the order of operations, you might get not exactly what you wanted:

> (<A B C> Z <D E F>) Z <H I J>
(((A D) H) ((B E) I) ((C F) J))

OK, before we did not go too far towards Lisp, let’s stop for today. See you tomorrow!

🎄 9/25. More on X, .., and … in Perl 6

Welcome to Day 9 of the Perl 6 One-Liner Advent Calendar! On Day 6, we had a construct with a cross-operator, (999...100) X* (999...100). Today, we’ll dive into a similar construction from November:

1..10 X* 1..10

It prints the items of the product table for the numbers from 1 to 10:

(1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100)

There are a few things to learn about such constructions.

You may have noticed two subtle differences between 999...100 and 1..10. In one case, there are three dots, in another—only two. In the first case, the boundaries are decreasing numbers, in the second—increasing.

Two dots in Perl 6 is the range operator. It creates a Range, or, in other words, an object of the Range type.

Three dots in Perl 6 are the sequence operator. In our example, it creates a sequence, or an object of the Seq type.

You can always check the type by calling the WHAT method on the object (a fragment of the REPL session is shown below):

> (1..10).WHAT
(Range)
> (1...10).WHAT
(Seq)

It is also interesting to look into the source codes of Rakudo, and see which attributes the Range and Seq have.

my class Range is Cool does Iterable does Positional {
has $.min;
has $.max;
has int $!excludes-min;
has int $!excludes-max;
has int $!infinite;
has int $!is-int;
. . .
}
my class Seq is Cool does Iterable does Sequence {
has Iterator $!iter;
. . .
}

In the Range object, there are minimum and maximum values, while in Seq we see an iterator.

In some cases, for example, in a simple loop, you can choose between either a range or a sequence:

.say for 1..10;
.say for 1...10;

But if you want to count downwards, ranges will not work:

> .say for 10..1;
Nil

With a sequence, there’s no problem:

> .print for 10...1;
10987654321>

It is wise to play with ranges and sequences before you start feeling them well. Save them in variables, use in operations, print using say or dd.

As a starting point, consider three operations:

(1, 2, 3) X* (4, 5, 6);
(1..3) X* (4..6);
(1...3) X* (4...6);

And that’s what you can be doing until tomorrow’s Advent post!

🎄 8/25. Adding up even Fibonacci numbers in Perl 6

Welcome to Day 8 of this year’s Perl 6 One-Liner Advent Calendar. It is about ¼ of the whole series, and don’t forget that you can type ¼ instead of 0.25 in Perl 6!

Today, we are solving problem 2 from Project Euler. The task is to find the sum of all even Fibonacci numbers below four million.

Here’s the complete solution:

(1, 1, * + * ... * > 4_000_000).grep(* %% 2).sum.say

It is equally interesting to parse the code from either left or right. Let’s start from left.

Inside the first parentheses, we are generating a sequence of Fibonacci numbers, which starts with two 1s, and each following number is a sum of two previous ones. In Perl 6, you can express it using a WhateverCode block: * + * is equivalent to {$^a + $^b}.

A less known feature of Perl 6 sequences is the final condition. In many examples you would see either a bare star or an Inf. In our example, we limit the sequence with an explicit upper boundary.

Notice that you cannot simply write:

1, 1, * + * ... 4_000_000

To visualise it better, try a smaller limit, say 100:

> (1, 1, * + * ... 100)
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

Perl 6 does not stop when the sequence crosses our desired border, and continues generating numbers. It will only stop it if the next calculated element of the sequence equals to the given number exactly, for example:

> (1, 1, * + * ... 144)
(1 1 2 3 5 8 13 21 34 55 89 144)

If you don’t know a Fibonacci number preceding four million, use another WhateverCode block with a Boolean condition: * > 4_000_000. Notice that the condition is opposite to what you would write in a regular loop, as here we are demanding more than four million, not less than. This is the condition that becomes True when you have to stop the sequence. Without the star, you could use the default variable: {$_ > 4_000_000}.

The rest of the code greps even numbers and adds them up. See Day 2 for more detailed explanations of these operations.

Sounds great! Let’s talk more about cool Perl 6 one-liners tomorrow.

🎄 7/25. The joy of Unicode in Perl 6

Welcome to Day 7 of the Perl 6 One-Liner Advent Calendar! Today, we’ll look at the month of March in the Perl 6 Calendar 2019:

The code here is using three characters outside of the ASCII land. We can even add one more:

say π × $𝜌²

In Perl 6, you can freely use Unicode characters in identifiers, such as variable or function names. But on top of that, there are many pre-defined symbols such as π, which have ASCII alternatives. Examine the documentation page Unicode versus ASCII symbols to see the whole set of Unicode characters that can be used in Perl 6.

Using ASCII, the above one-liner can be re-written in the following way:

say pi * $r ** 2

Let’s return to the bonus code from Day 2 and see where Unicode characters could be used:

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

say (f(3) ∪ f(5)).keys.sum;

There are a few opportunities here.

First, a hyper-operator <<*>> can be replaced with proper French quotes: «*», and the multiplication character can be a cross that we used today already: «×». The same can be applied to division: ÷.

Second, the three dots of the sequence operator are replaceable with a single Unicode character:  (if you are programming in Word, you get this character automatically after typing the full stop three times).

Finally, in the last line, a Unicode character is used to find the intersection of two sets. The character here is the same that you use in mathematics (do you?), but you can use its ASCII version instead: f(3) (|) f(5).

So, we’ve got a great Christmas gift, the best Unicode support among programming languages. Use it with care not to make other people crazy about your code! See you tomorrow!