Welcome to Day 19 of the **Perl 6 One-Liner Advent Calendar**! Today, we will be computing the value of Ο using two different methods. The goal of this blog post is to play with different approaches to generate numeric sequences.

## Pre-party

Of course, in Perl 6 you donβt need to calculate the value of Ο yourself, as the language gives us a few predefined constants in the shape of both `Ο` and `pi`, as well as doubled values `Ο` and `tau`.

But to demonstrate the usage of maps and sequences, letβs implement one of the simplest algorithms to calculate Ο:

Hereβs a draft code to check the answer:

my $pi = 1;

my $sign = 1;

for 1..10000 -> $k {

$sign *= -1;

$pi += $sign / ($k * 2 + 1);

}

say 4 * $pi;

## Part 1

Now, let us employ `map` to make the solution compact. It is better to make the formula more generic, too:

And hereβs our first one-liner:

say 4 * [+] (^1000).map({(-1) ** $_ / (2 * $_ + 1)})

I hope you understand everything here. We covered different parts of this solution in the previous days of this yearβs Advent Calendar, for example, in the post on Day 11.

But still, I want to emphasise that you need parentheses around `-1`. If you type `-1 ** $_`, then you always get β1, as the minus prefix is applied to the result of taking power. So the correct code is `(-1) ** $_`.

## Part 2

It is also interesting to try using a sequence operator `...` to generate the row according to the formula mentioned above. Also, weβll use rational numbers (see Day 12) to create the fractions β
, β
, etc.

say 4 * [+] <1/1>,

{-Rat.new($^n.numerator, $^n.denominator + 2)} ...

*.abs < 1E-5;

This sequence starts with a rational number `<1/1>`, which is handy as we can immediately take its numerator and denominator. The generator block of the sequence uses this number to create a new rational number, whose denominator becomes greater by two on each iteration.

You may ask why I am referring `$^n.numerator`, which is always 1. This is needed, because to alter the sign, we need to know the sign of the current value, and the sign is kept in the numerator part of the rational value.

The placeholder variable `$^n` automatically takes the first (and the only) argument of the generator code block.

The sequence is generated until the absolute value of the current value becomes small enough. It may be tempting to replace the final condition with `* β
0`, but that program will run too long to see the result, as the default tolerance of the approximately-equal operator is 10^{β15}, while the row does not converge that fast.

Also, you cannot use the `< ... / ...>` syntax to create a `Rat` number in the generator:

~~{ <$^n.numerator / $^n.denominator + 2> }~~

In this case, Perl 6 will treat this as a quoting construction such as `<red green blue>`, and instead of the code block you get a list of strings.

And thatβs all for today. See you tomorrow!

A small note on the draft code: if you do `for 1..10000 -> int $k {` (so add an `int`), you will save 2 allocations per iteration: one for an `Int`, and one for a `Scalar` container.

LikeLiked by 1 person

Your sequence-of-Rats solution is both interesting and educational,

however the following sequence-based approach is significantly faster

(and also seems simpler and more readable…to my mind, at least):

say 4 * [+] (1, -1, 1 … *) Β«/Β« (1, 3, 5 … 9999);

Especially if you allowed more than a single physical line,

in which case you could lay it out almost exactly like

the original Leibnitz series:

say 4 * [+] (1, -1, 1 … * )

Β«/Β« (1, 3, 5 … 9999);

LikeLiked by 1 person