Perl Weekly Challenge: Week 108

Challenge 1:

Locate Memory

Write a script to declare a variable or constant and print it's location in the memory.

Given a variable $a, in Raku you can print it's location in memory like this:

say $a.WHERE.base(16);

(Full code on Github.)

(I converted the result to hexadecimal because memory locations look better in hexadecimal.)

In Perl, it's not quite that simple. If you take a reference to $a and print it...

say \$a;

(Full code on Github.)

...you get the memory location and data type like this:

SCALAR(0x7ffff6bf7688)

Of course in languages like Perl and Raku that manage memory for you, there is not a lot you can do with this information. Maybe it's useful in debugging?

Challenge 2:

Bell Numbers

Write a script to display top 10 Bell Numbers. Please refer to wikipedia page for more information.

Example

B0: 1 as you can only have one partition of zero element set

B1: 1 as you can only have one partition of one element set {a}.

B2: 2

{a}{b}
{a,b}

B3: 5

{a}{b}{c}
{a,b}{c}
{a}{b,c}
{a,c}{b}
{a,b,c}

B4: 15

{a}{b}{c}{d}
{a,b,c,d}
{a,b}{c,d}
{a,c}{b,d}
{a,d}{b,c}
{a,b}{c}{d}
{a,c}{b}{d}
{a,d}{b}{c}
{b,c}{a}{d}
{b,d}{a}{c}
{c,d}{a}{b}
{a}{b,c,d}
{b}{a,c,d}
{c}{a,b,d}
{d}{a,b,c}

Ugh maths again. Not being able to make head nor tail of the referenced wikipedia page, I googled around and found this page. The code below is a Raku translation of the C++ example provided there.

sub bellNumber(Int $n) {
    my @bell;
    @bell[0][0] = 1;
    for 1 .. $n -> $i {
        @bell[$i][0] = @bell[$i - 1][$i - 1];

        for 1 .. $i -> $j {
            @bell[$i][$j] = @bell[$i - 1][$j - 1] + @bell[$i][$j - 1];
        }
    }
    return @bell[$n][0];
}

(Full code on Github.)

Basically we are creating what's known as a Bell Triangle by starting with a known value (1 for a set with 0 elements) and using dynamic programming to calculate succeeding values. The leftmost value in the $nth row of the triangle is the Bell number for $n.

This is the same thing in Perl:

sub bellNumber {
    my ($n) = @_;
    my @bell;
    $bell[0][0] = 1;
    for my $i (1 .. $n) {
        $bell[$i][0] = $bell[$i - 1][$i - 1];

        for my $j (1 .. $i) {
            $bell[$i][$j] = $bell[$i - 1][$j - 1] + $bell[$i][$j - 1];
        }
    }
    return $bell[$n][0];
}

(Full code on Github.)

The spec asks for the "top ten" Bell numbers by which I assume the first ten is meant. In case you are curious, they are:

1 1 2 5 15 52 203 877 4140 21147