Perl Weekly Challenge 254: Three Power

These are some answers to the Week 254, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on February 4, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Three Power

You are given a positive integer, $n.

Write a script to return true if the given integer is a power of three otherwise return false.

Example 1

Input: $n = 27
Output: true

27 = 3 ^ 3

Example 2

Input: $n = 0
Output: true

0 = 0 ^ 3

Example 3

Input: $n = 6
Output: false

First, we look for the candidate exponent, by computing the base-3 logarithm of the input integer. Then we check that we've actually a power of 3. Since floating point arithmetic can be tricky, we test with the integer immediately below and the integer immediately above the candidate exponent thus found.

Three Power in Raku

Please refer to the above section if you need explanations. Note that the Raku log routine can take two parameters, the number for which you want the logarithm and the base. The input number must be strictly positive, so we have to handle separately an input equal to 0. The returned value is a Boolean expression and will thus be either True or False.

sub exp-three ($in) {
    return True if $in == 0;
    my $exp = (log $in, 3).Int;
    return (3 ** $exp == $in or 3 ** ($exp + 1) == $in);

say "$_ \t=> ", exp-three $_ for <27 26 0 6>;

This program displays the following output:

$ raku ./power-of-three.raku
27      => True
26      => False
0       => True
6       => False

Three Power in Perl

This is a port to Perl of the Raku program above. Please refer to the above sections if you need additional explanations. Perl's built-in log function computes only natural logarithms (base e), but it is easy to compute base-3 logarithm of n as log n / log 3.

use strict;
use warnings;
use feature 'say';

sub exp_three {
    my $in = shift;
    return "true" if $in == 0;
    my $exp = int (log $in / log 3);
    return (3 ** $exp == $in or 3 ** ($exp + 1) == $in)
        ? "true" : "false";

say "$_ \t=> ", exp_three $_ for qw<27 26 0 6>;

This program displays the following output:

$ perl ./
27      => true
26      => false
0       => true
6       => false

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check and make sure you answer the challenge before 23:59 BST (British summer time) on February 11, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.