aboutsummaryrefslogtreecommitdiff
path: root/challenge-023/athanasius/perl6/ch-2.p6
blob: 24048e562604fd575a1fbb6c9f261e02761992e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use v6;

################################################################################
=begin comment

Perl Weekly Challenge 023
=========================

Task #2
-------
Create a script that prints *Prime Decomposition* of a given number. The prime
decomposition of a number is defined as a list of prime numbers which when all
multiplied together, are equal to that number. For example, the Prime decomposi-
tion of 228 is 2,2,3,19 as 228 = 2 * 2 * 3 * 19.

=end comment
################################################################################

#--------------------------------------#
# Copyright © 2019 PerlMonk Athanasius #
#--------------------------------------#

BEGIN say '';

#===============================================================================
sub MAIN(UInt:D $number )                                #= Unsigned integer > 1
#===============================================================================
{
    die $*USAGE if $number <= 1;

    say "The prime decomposition of $number is: ", factor($number).join(', ');

    CATCH
    {
        default 
        {
            $*ERR.say: .message;
        }
    }
}

#-------------------------------------------------------------------------------
sub factor(UInt:D $number)
#-------------------------------------------------------------------------------
{
    my UInt $remainder = $number;
    my      @factors;

    MY-OUTER:
    for 2 .. $number -> UInt $f
    {
        if $f.is-prime
        {
            while $remainder % $f == 0
            {
                @factors.push:  $f;
                $remainder div= $f;

                last MY-OUTER if $remainder == 1;
            }
        }
    }

    die "ERROR: for number $number, remainder is $remainder"
        unless $remainder == 1;

    return @factors;
}

################################################################################

=begin note

The label used in sub factor() was originally "OUTER:". Here is the explanation
of the (cryptic!) error message that resulted:

From https://perl6.eu/colonoscopy.html

"Upper Case letters are normally used for labels, but this will cause an error
if you happen to choose a name that is already in use internally by Perl 6. The
label itself isn't a problem, as the trailing colon tells the compiler that it
is a label. The usage, where it is used as a bareword causes the problem, and
there is no way to fix it.

Some examples:

OUTER, which seems perfectly logical as a label name, will give the run time
error («Cannot resolve caller next(OUTER:U); ...»), as OUTER is a built-in
package name and Perl 6 isn't clever enough to spot that it is used as a label
in this case."

=end note