diff options
| -rwxr-xr-x | challenge-149/alexander-pankoff/perl/ch-1.pl | 79 | ||||
| -rwxr-xr-x | challenge-149/alexander-pankoff/perl/ch-2.pl | 98 |
2 files changed, 177 insertions, 0 deletions
diff --git a/challenge-149/alexander-pankoff/perl/ch-1.pl b/challenge-149/alexander-pankoff/perl/ch-1.pl new file mode 100755 index 0000000000..1adf2557f1 --- /dev/null +++ b/challenge-149/alexander-pankoff/perl/ch-1.pl @@ -0,0 +1,79 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use feature qw'say state signatures'; +no warnings qw'experimental::signatures'; + +# TASK #1 › Fibonacci Digit Sum +# Submitted by: Roger Bell_West +# +# Given an input $N, generate the first $N numbers for which the sum of their digits is a Fibonacci number. +# Example +# +# f(20)=[0, 1, 2, 3, 5, 8, 10, 11, 12, 14, 17, 20, 21, 23, 26, 30, 32, 35, 41, 44] + +use List::Util qw(sum0 first); + +run() unless caller(); + +sub run() { + my ($N) = @ARGV; + + if ( !$N || $N !~ m/^\d+$/ || $N < 1 ) { + die <<EOF; + Usage: + + $0 N + + Options: + + N - a positive integer +EOF + } + + my @numbers = fibonacci_digit_sum($N); + + say "f($N) = [" . join( ', ', @numbers ) . ']'; + +} + +sub fibonacci_digit_sum($n) { + my @found; + for ( my $i = 0 ; @found < $n ; $i++ ) { + push @found, $i if is_fib( digit_sum($i) ); + } + return @found; + +} + +sub is_fib($x) { + state $fibs = { + 0 => 1, + 1 => 1, + + }; + state $cur = 1; + state $prev = 0; + + while ( $x > $cur ) { + my $next = next_fib( $cur, $prev ); + $prev = $cur; + $cur = $next; + + $fibs->{$next} = 1; + } + + return $fibs->{$x}; +} + +sub digit_sum($x) { + my $sum = sum0 split( '', $x ); + + return $sum; +} + +sub next_fib ( $prev, $cur ) { + my $next = $cur + $prev; + + return $next; +} diff --git a/challenge-149/alexander-pankoff/perl/ch-2.pl b/challenge-149/alexander-pankoff/perl/ch-2.pl new file mode 100755 index 0000000000..d140f7e92a --- /dev/null +++ b/challenge-149/alexander-pankoff/perl/ch-2.pl @@ -0,0 +1,98 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use feature qw'say state signatures'; +use bignum; +no warnings qw'experimental::signatures'; + +# TASK #2 › Largest Square +# Submitted by: Roger Bell_West +# +# Given a number base, derive the largest perfect square with no repeated digits and return it as a string. (For base>10, use ‘A’..‘Z’.) +# Example: +# +# f(2)="1" +# f(4)="3201" +# f(10)="9814072356" +# f(12)="B8750A649321" + +use List::Util qw(uniq); + +run() unless caller(); + +sub run() { + + my ($N) = @ARGV; + + if ( !$N || $N !~ m/^\d+$/ || $N < 2 || $N > 36 ) { + die <<EOF; + Usage: + + $0 N + + Options: + + N - a number base (between 2 and 36) +EOF + } + + say "f($N) = " . largest_perfet_square_without_repeated_digits_in_base($N); + +} + +sub largest_perfet_square_without_repeated_digits_in_base($base) { + my @digits = ( 0 .. 9, 'A' .. 'Z' )[ 0 .. $base - 1 ]; + + for ( + my $i = + int( sqrt( base_to_dec( $base, join( '', reverse @digits ) ) ) ) ; + $i > 0 ; + $i-- + ) + { + my $perfect_square = dec_to_base( $base, $i**2 ); + + my @digits = split( '', $perfect_square ); + + return $perfect_square if scalar uniq(@digits) == scalar @digits; + + } +} + +sub dec_to_base ( $base, $n ) { + my @digits = ( 0 .. 9, 'A' .. 'Z' ); + + return $digits[$n] if $n <= $base - 1; + + my $rem = $n % $base; + my $next = int( $n / $base ); + + dec_to_base( $base, $next ) . $digits[$rem]; +} + +sub base_to_dec ( $base, $n ) { + my $power = 1; + my $num = 0; + + my @digits = split( '', $n ); + + for my $i ( reverse( 0 .. $#digits ) ) { + + $num += value( $digits[$i] ) * $power; + $power = $power * $base; + + } + + return $num; + +} + +sub value($c) { + + if ( $c ge '0' && $c le '9' ) { + return ord($c) - ord('0'); + + } + + return ord($c) - ord('A') + 10; +} |
