RabbitFarm

2021-04-18

Memory Addresses and Bell Numbers: The Weekly Challenge 108

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

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

Solution


use strict;
use warnings;
use Devel::Peek;
use Capture::Tiny q/capture_stderr/;
use constant A => "test";
my $a = 1;    
my $address;  
my $stderr = capture_stderr {
    Dump(A)
};
$stderr =~ m/at\s(0x.*\n).*/;
$address = $1;  
chomp($address);
print "Address of constant A: $address\n"; 
$stderr = capture_stderr {
    Dump($a)
};
$stderr =~ m/at\s(0x.*\n).*/;
$address = $1;  
chomp($address);
print "Address of \$a: $address\n";

Sample Run


$ perl perl/ch-1.pl
Address of constant A: 0xfd31ae90
Address of $a: 0xfdb2f770

Notes

This is a somewhat unusual challenge for Perl. Sometimes these challenges allow for a certain amount of interpretation. For example, under the hood, the representation of Perl data in memory involves more complicated data structures. I think it is in the spirit of this challenge to demonstrate access to this, without necessarily implementing complete and fully generalized solution.

Here I use Devel::Peek in order to get a report on the underlying memory usage of the given variables. The Dump function only prints a memory report to STDERR, so in order to obtain the information we seek Capture::Tiny is used to encapsulate the STDERR output and save it to a variable. A regex is then used to pull out the memory address which is then printed.

The memory address printed here is the reference address. For additional details on Perl’s core see the perlguts documentation.

Part 2

Write a script to display the first 10 Bell Numbers.

Solution


use strict;
use warnings;

sub bell_triangle{
    my($n) = @_; 
    my @bell_numbers = ([]);
    $bell_numbers[0]->[0] = 1;
    for (my $i=1; $i<=$n; $i++) {
      $bell_numbers[$i]->[0] = $bell_numbers[$i-1]->[$i-1];
      for (my $j=1; $j<=$i; $j++){  
          $bell_numbers[$i]->[$j] = $bell_numbers[$i-1]->[$j-1] + $bell_numbers[$i]->[$j-1];
       }
   }
   return $bell_numbers[$n]->[0];
}

MINA:{
    for my $b (0 .. 9){  
        print "B_$b: " . bell_triangle($b) . "\n";  
    } 
}

Sample Run


$ perl perl/ch-2.pl
B_0: 1
B_1: 1
B_2: 2
B_3: 5
B_4: 15
B_5: 52
B_6: 203
B_7: 877
B_8: 4140
B_9: 21147

Notes

This is an interesting problem. At first glance one might be tempted to proceed and compute the partitions and then take the total number of them all. Instead, it turns out that there is a simpler closed form solution whereby we can compute the Bell Triangle and then take the values on the leftmost diagonal to be the Bell Numbers as required.

For fun the Prolog solution does indeed compute the partitions instead of simply using the Bell Triangle!

References

Challenge 108

perlguts

Bell Numbers

Bell Triangle

posted at: 15:55 by: Adam Russell | path: /perl | permanent link to this entry