aboutsummaryrefslogtreecommitdiff
path: root/challenge-157/colin-crain/perl/ch-2.pl
blob: aa73efcc618eefbe613ff6ce80681cfc08753842 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/Users/colincrain/perl5/perlbrew/perls/perl-5.32.0/bin/perl
#
#       waxing-numeric.pl
#
#       Brazilian Number
#         Submitted by: Mohammad S Anwar
#         You are given a number $n > 3.
# 
#         Write a script to find out if the given number is a Brazilian
#         Number.
# 
#         A positive integer number N has at least one natural number B
#         where 1 < B < N-1 where the representation of N in base B has
#         same digits.
# 
# 
#         Example 1:
#             Input: $n = 7
#             Output: 1
#     
#             Since 7 in base 2 is 111.
# 
#         Example 2:
#             Input: $n = 6
#             Output: 0
#     
#             Since 6 in base 2 is 110,
#                   6 in base 3 is 20 and
#                   6 in base 4 is 12.
# 
#         Example 3:
#             Input: $n = 8
#             Output: 1
#     
#             Since 8 in base 3 is 22.
#
#       © 2022 colin crain
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##



use warnings;
use strict;
use utf8;
use feature ":5.26";
use feature qw(signatures);
no warnings 'experimental::signatures';

use constant { ANALYSE => 0 };
use constant { COUNT   => 2000 };


if (ANALYSE) {
    analyse( COUNT );
}
else {
    my $input = shift @ARGV // 1993;
    say "input:  $input";
    say "output: ", brazilian( $input ) ? 1 : 0;
    
    say digit_test_36( 100, 99);
}


## ## ## the task 

sub brazilian ( $num ) {
## up/down check if number is a Brazilian number
    for ( 2..$num-2 ) {
        return $_ if digit_test( $num, $_ );
    }
    return 0;
}

sub digit_test ( $num, $base ) {
## up/down check for all digits are the same in a given base 
## converts from base-10 to any given base
## does not internally store converted number other than 
## single digit as base-10 sequence index: conditional 
## 1 short-circuits returning 0 if non-repeated digit found, 
## otherwise returns 1
    my $rem; 
    my $digit;
    while ( $num > 0  ) {
        ($num, $rem) = (int( $num/$base ), $num % $base);   
        $digit //= $rem;
        return 0 if $digit != $rem;
    }
    return 1;
}

## ## ## /task


## analysis section
sub analyse ( $count ) {

    my $match;
    my @coef;
    for (2..$count) {
        my $b = brazilian( $_ );
        next if $b == 0;
         push @coef, $b;
   
        my @pdiv = nd_brute( $_ );
    
        for my $div ( 2..42 ) {
            next unless $b == $_/$div - 1;
            $match = "match 1/${div}-1";
            last;
        }
    
        $match ||= (sprintf "\t%.2f     ", $_/$b);
        say sprintf "%3d    %-3d     %-20s %s", $_, $b, $match, "@pdiv";
        $match = undef;
    }

    my @a = grep { brazilian($_) } (2..200);
    say "@a";
    say "@coef";
    
    sub nd_brute ( $num, @div ) {
        $num % $_ or push @div, $_ for 2..$num/2 ;    
        return @div;
    }
}    
## /analysis