🎄 15/25. Playing with Fibonacci numbers in Perl 6

Welcome to Day 15 of the Perl 6 One-Liner Advent Calendar! Today, there will be two one-liners, and they both generate Fibonacci numbers.

Yes, most likely, you never used such numbers in real code, and, again, most likely, you solved many educating problems with them. Nevertheless, today, let’s solve the Problem 25 of the Project Euler and try to approach the shortest solution for a Fibonacci problem on the Code-Golf.io site.


How do we form a Fibonacci sequence in Perl 6? With a sequential operator ...:

0, 1, * + * ... *

If you want some exotic flavour in the code, you can replace the last star with either Inf or . In any case, the result will be a lazy sequence of the Seq type. Perl 6 will not compute it immediately (and it can’t, as the right edge is infinite).

Part 1

The first task is to find the index of the first Fibonacci number, which has 1000 digits. Of course, you can loop over the above-created sequence and trace the index yourself. But in Perl 6, there is an option to modify the grep routine family, and ask it to return the index of the matched item instead of the item itself.

Also, instead of grep, we’ll use a more appropriate method, first. It will return the first matching item or its index if we call the method with the k key. It is enough just to mention the key, no value is really needed.

say (0, 1, * + * ... *).first(*.chars >= 1000, :k)

This program prints a single integer number, which is the correct answer to the given problem.

Part 2

Now let’s solve a Golf task and print the first 30 Fibonacci numbers, one on a line. This time, we have to use as few characters in the code as possible.

The first approach is rather wordy (even with ^31 instead of 0..30 it needs 33 characters):

.say for (0, 1, * + * ... *)[^31]

There is some room that allows compression. Of course, the first and the most obvious thing is to remove spaces (remaining 28 characters):

.say for (0,1,*+*...*)[^31]

Another interesting trick is to use the >> meta-operator to call the say method on each element of the sequence. It compresses the code further to 24 characters:


At this moment, we can employ some Unicode, and gain three more characters (21 left):


Looks compact already, but there are still some options to try. Let us get rid of the explicit slicing, and try to stop the sequence at the last element:


The code became longer (23 characters), but we do not need an exact number 514229 here. It is enough to give some number, which is bigger then the 29th and smaller then the 30th element of the sequence. For example, it can be 823543, which is 7 powered 7. Write it down using superscripts (19 characters):


Finally, it is possible to make it one character less by using another Unicode character representing 800000 in a single character. Not every (if any) font can display something visually attractive, but Perl 6 takes the character with no complains:


These 18 characters is one character longer than the top result at Gode-Golf. I have a feeling that you could gain another character by replacing the first two elements of the sequence with ^2, but that does not work in current Rakudo, and you have to return a character to flatten the list: |^2, which makes the solution 18 characters long again.

The desire is to remove the *> part in the condition to stop the sequence and replace it with a fixed number. Unfortunately, there’s no way to express 832040 with powers of the numbers between 1 and 90. Would that be possible, we could use a superscript to calculate the number.

Another idea is to use a regex, but we need at least four characters, which does not help:


And let me stop here for today. Would you happen to create a shorter solution, please leave a comment. See you tomorrow!

🎄 14/25. Another solution of yesterday’s problem

Welcome to Day 14 of the Perl 6 One-Liner Advent Calendar! Today, we are presenting another solution of the problem we were solving yesterday. The task was to count all Sundays that fall on the first of the month in the XX century.

Yesterday, we just scanned through all the days in the whole century, selecting the ones that are Sundays (.day-of-week == 7) and are the first of the month (.day == 1).

It is possible to make a more efficient algorithm. As we are only interested in the first days of the month, there is no need to scan all 36525 days during 100 years, but only 1200 days that are the first day of each month between 1901 and 2000.

So, we need two nested loops: over the years and over the months. Do we need two fors? Not necessarily. Let’s use the X operator; we are familiar with it from the previous advent posts.

And here is our today’s one-liner:

(gather for 1901..2000 X 1..12 {
take Date.new(|@_, 1)
}).grep(*.day-of-week == 7).elems.say;

The for 1901..2000 X 1..12 loop goes over each month in the XX century. For each, we create a Date object by calling a constructor with three arguments.

Update. Based on the very relevant comments from the readers, here’s a better and simpler way of the solution:

say +(1901..2000 X 1..12).map(
{Date.new(|@_, 1)}
).grep(*.day-of-week == 7);

Notice that inside the loop, you can use both $_[0] and $_[1], and @_[0] and @_[1]. In the first case, the $_ variable contains a list of two elements, while in the second it is an array @_. The shortest code is achieved if you are just using a dot to call a method on the topic (default) variable: .[0] and .[1].

Instead of Date.new(|@_, 1), you can type Date.new(.[0], .[1], 1). The |@_ syntax is used to unroll the array, as otherwise Perl 6 will think you are passing an array as a first argument.

All first days of the months are collected to a sequence with the help of the gathertake pair.

The final step is a grep as yesterday, but this time we only need to select Sundays, so a single *.day-of-week == 7 condition is enough.

The call of the elems method returns the number of the elements in the list, which is the number of Sundays that we are looking for. Thus, print it with say.

A new idea and a new solution should make you happy for at least one day until tomorrow’s post in this One-Liner Calendar!

🎄 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));
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> ]
| $<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,
        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
> (1...10).WHAT

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;

With a sequence, there’s no problem:

> .print for 10...1;

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!