PWC 168 › Perrin Primes

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

Task #1 this week asks us to find the first 13 Perrin primes. “What’s a Perrin prime,” I can’t hear you asking? To answer that, we first have to look at the Perrin sequence, as described in OEIS A001608. It’s easy to generate:

Starting with [3, 0, 2], each new term is determined by adding the 2nd and 3rd last terms. So, the 4th number is 3 + 0 = 3, giving us [3, 0, 2, 3]. The 5th number is 0 + 2 = 2, and so on.

Perrin primes are simply the elements of the Perrin sequence that also happen to be prime.

Normally (and per the example output in the task) we are to find the unique Perrin primes, in order. So, we’ll just seed the first prime in our @r results, and then rely on the fact that the sequence is strictly increasing after the first five terms.

Building the sequence is very simple from there:

Continue reading “PWC 168 › Perrin Primes”

PWC 168 › Home Prime

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

Task #2 this week asks us to calculate a so called Home prime. Home primes are found by factoring a number and concatenating the prime factors (including powers, so 20 = 5×2×2), and repeating this until the result is a prime number.

The given example, HP(10) can be found via the following steps: HP(10) = HP(25) = HP(55) = HP(511) = HP(773), and we stop, since 773 is a prime number.

This is a natural problem for recursion:

sub home_prime_recursive {
    my @fac = factor($_[0]);

    @fac == 1 ? $_[0] : home_prime(join '', @fac);
}

I like this solution for its expressiveness, but it’s about 20% slower than the following iterative version:

Continue reading “PWC 168 › Home Prime”

PWC 167 › Circular Primes

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

Task #1 this week has us finding circular primes, 3 digits or more. Circular primes are numbers that remain prime through all of their rotations. For example, since all the rotations of 113 (113, 131, and 311) are all primes, 113 is a circular prime. (131 and 311 are circular primes as well, but based on the example given with this task, we are only to give the lowest circular prime in each group.) This would correspond with OEIS A016114.

I just wrote yet another Sieve of Eratosthenes in week 164, so this time I’ll just use Math::Prime::Util. The basic algorithm I came up with is rather naïve, but effective:

for each digit d in [3..∞)
    for each prime n with d digits
        for each unique rotation r
            next digit if circular[r] or ¬prime[r]
        circular[r] ← true
        say "r is circular"
Continue reading “PWC 167 › Circular Primes”

PWC 167 › Lanczos Gamma Approximation

Gamma function

Let’s flex our mathematical legs a bit by implementing an approximation to the gamma function Γ(z). In this article, I’ll introduce what the gamma function is, what it’s for, and how to actually calculate it, using a well known approximation method.

This topic leans more heavily into mathematics than usual for this blog. Some of the concepts may be new to you, and I regret I cannot give them a proper treatment in a single article. I’ll do my best to give you the flavor of how everything works, and I have provided some resources at the end should you wish to learn more.

What’s the gamma function? What’s it for?

You’re probably familiar with integer factorials already. Here’s a simple definition:

\(n! = 1 \times 2 \times 3 \times \cdots \times (n-2) \times (n-1) \times n\)

For example, \(5! = 1 \times 2 \times 3 \times 4 \times 5 = 120 \). However, that only works for positive integers. The gamma function lets us work with most positive and negative real numbers, and even complex numbers. For positive integers, the gamma function is very closely related to ordinary factorials:

\(\Gamma(z) = (z – 1)!\)

Why is it (z – 1)! instead of just z! ? As H. M. Edwards puts it—in a footnote, no less:

Continue reading “PWC 167 › Lanczos Gamma Approximation”

PWC 166 › K-Directory Diff

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

Task #2 this week is another one of mine. The idea is to take any number of pathnames on the command line (and we must support at least three), and output a side-by-side diff of the files that are different. This is a skin-deep analysis, so there is no recursion, and no comparison of file sizes, modification times, or contents, although those would be worthy additions if someone wants to take it further.

I will be implementing a fairly basic version, although I have a more complex version I’ve been using for years that I might be persuaded to release if there is interest.

Data Design

I am going to have one main data structure, %dirs, that will be built up as we traverse the directories. It will hold all directory and file information, as well as a maxlen value for each directory, for ease of formatting columns later. Here’s what %dirs might look like, given a very simple set of input directories:

%dirs = (
  dir_a =>  {
      files  => {
                "Arial.ttf"       => 1,
                "Comic_Sans.ttf"  => 1,
              },
      maxlen => 14,
  },
  dir_b => {
      files  => {
                "Arial.ttf"       => 1,
                "Comic_Sans.ttf"  => 1,
                "Courier_New.ttf" => 1,
              },
      maxlen => 15,
  },
)
Continue reading “PWC 166 › K-Directory Diff”

PWC 166 › Hexadecimal Words

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

This is another one of my suggested tasks, and another time you’re going to read about a personal story that connects me to a task. For many years, right back to very first days I started hacking filesystems and writing kernel code, I’ve often needed to come up with 16- or 32-bit identifiers for things, usually represented in hexadecimal. And to this day, my repertoire of clever identifiers is more or less limited to 0xdeadbeef and 0xc0dedbad, and a few others. Let’s change that!

The simple version

A very simple solution simply reads the lines, filters out anything that isn’t the right length, or contains characters that can’t be substituted, and prints out the whole works:

use File::Slurper qw< read_lines >;

my $dict = $ARGV[0] // '../../../data/dictionary.txt';

say for map {     y/olist/01157/r    }
       grep { /^[0-9a-folist]{2,8}$/ } read_lines($dict);

That already gives me some great results, like 0xd15abled (“disabled”), and is nice and short. However, we didn’t come here for half measures. This version only returns single words, and doesn’t care how many substitutions it has done, so words like 0x57111e57 (“stillest”‽) are fair game.

Continue reading “PWC 166 › Hexadecimal Words”

PWC 165 › Simple SVG generator

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

The tasks this week are ones I devised. Allow me a moment to explain the motivation behind them.

I often have a need to quickly visualize some random bits of data, and while I’ve gotten great mileage out of terminal output, and things like gnuplot or spreadsheet imports, sometimes better and more convenient results are possible by generating the image myself.

There is ImageMagick (see perlmagick for a Perl interface), but its dependencies are heavy, and getting it to run at all on some systems (particularly the embedded systems I work on), can be challenging. And of course, it only works with raster images, which do not scale well.

Fortunately, it’s very easy to generate vector images with pure Perl (or most any language, for that matter). You can even do it easily without any CPAN modules, but remember, even you can use CPAN!

Enter Scalable Vector Graphics (SVG).

Raster images are comprised of a grid of pixels. Vector images use shapes like circles, lines, and curves. Because these are defined mathematically, vector images can be resized, squished, or rotated with no loss in quality.

Quick Introduction to SVG

For this task, I will be using the SVG module by Morgane Oger and recently maintained by our very own Mohammad Anwar. However, SVG files are simply XML documents, so it would not be much harder to generate the XML yourself. Here’s what SVG source looks like:

Continue reading “PWC 165 › Simple SVG generator”

PWC 164 › Palindromic Primes

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

The first task this week is to list all palindromic primes below 1000. Palindromes are very well known to Weekly Challenge enthusiasts as numbers (or words) that are the same forwards and backwards. Prime numbers should need no introduction.

Prime Sieve

I’m going to jump straight to it. Since the task is simple, I’m not going to use an external library such as Math::Prime::Util, even though that would be quite a bit faster. Instead, I’m going to generate the primes myself, using a Sieve of Eratosthenes. There are faster methods, but you can’t beat Eratosthenes for elegance!

Continue reading “PWC 164 › Palindromic Primes”

PWC 164 › Happy Numbers

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

Task #2 this week comes to us from Robert DiCicco, and Robert demands happiness! Or at least numbers that are happy. Either way, I could use some right about now.

We are to find the first 8 Happy Numbers in base 10. To test whether a number is Happy:

replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1.

Those numbers for which this process end in 1 are happy numbers, while those numbers that do not end in 1 are unhappy numbers.

Weekly Challenge #164

If You’re Happy and You Know It return 1

Using the algorithm exactly as described above, the Perl code is straightforward:

Continue reading “PWC 164 › Happy Numbers”

PWC 163 › A tail of two sums

This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

This week’s challenges are very quick, so I’m putting them in one blog post. The title is a bit of a play on words, given the tail recursion in part 2.

Full solutions are available at GitHub.

Task 1 › Bitwise Sum

For the first task, we’re asked to first bitwise AND (&) each unique pair of numbers, and then compute the sum of those operations. So, given an input of (a, b, c), we would compute:

a & b + a & c + b & c

To formalize this a bit, in preparation for writing the code, consider a pair (ni, nj) where i and j are the indices in the input array. Unique pairs could be interpreted to mean ji. However, the provided example clearly implies that self pairs are to be avoided, so we’ll include pairs where j > i. So for an array of length k (n1 … nk), this looks like:

\({ \displaystyle \sum \limits_{i=1}^{k} } \sum_{j=i+1}^{k} n_i\ \&\ n_j
\)

Continue reading “PWC 163 › A tail of two sums”