DEV Community

Discussion on: Daily Challenge #11 - Cubic Numbers

Collapse
 
yzhernand profile image
Yozen Hernandez • Edited

Perl:

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw(signatures);
no warnings "experimental::signatures";
use List::Util qw(sum0);

# Primary objective
sub is_cubic ($num) {
    return length($num) <= 3 && sum0( map { $_**3 } split //, $num ) == $num;
}

# Secondary objective
sub find_cubes ($string) {
    my @out;
    while ( $string =~ s/(\d{1,3})// ) {
        push @out, $1 if is_cubic($1);
    }

    return join " ", @out if (@out);
    return "Unlucky";
}

use Test::More tests => 5;
is( is_cubic(153), 1, "153 is cubic" );
isnt( is_cubic(152), 1, "152 is not cubic" );
is( find_cubes("aqdf& 0 1 xyz 153 777.777"), "0 1 153", "Found '0 1 153'" );
is( find_cubes("QK29 45[&erui"),
    "Unlucky", "Found no cubic numbers in 'QK29 45[&erui'" );
is( find_cubes("24172410"), "Unlucky",
    "Found no cubic numbers in '24172410'" );
is( find_cubes("2417241530"), "153 0", "Found '153 0'" );

Primary objective

In the is_cubic function, I first check if the input has at most 3 digits. If that check passes, the rest of the logical statement is executed.

Next, the input is split up into digits by splitting on the empty string. The map function goes over that list of digits and cubes each one. I make use of the sum0 aggregate function from List::Util to calculate the sum of the cubes. The sum is finally compared to the original input value.

Secondary objective

In the find_cubes function, I simply use the substitution function in Perl to find and remove 1 to 3 successive digits in the input string. The while loop will be entered as long as s was able to make a substitution. Each match is captured and saved in the special variable $1, which I use as input to the is_cubic function from the primary objective. If the is_cubic function returns a true value, the number is saved to a list.

If any values at all have been saved to the list, the list items are joined together and a space-separated string is returned. Otherwise, the string "Unlucky" is returned.

I've provided some tests to show that it works at least with the test data provided in the challenge. Regex quantifiers are greedy by default, so the engine will try to match 3 digits as much as it can and to prove this, the last checks to see that I can find two known cubes, one of which is 3 digits, in a longer digit string.