diff options
| author | Simon Green <mail@simon.green> | 2022-07-31 22:40:23 +1000 |
|---|---|---|
| committer | Simon Green <mail@simon.green> | 2022-07-31 22:40:23 +1000 |
| commit | 44bfeffafd05618d6a52df49c8428d7d67859704 (patch) | |
| tree | 3f671704163040ee0f0568bf46274d1c6da959bf | |
| parent | 63320aaa829d9153de8139af619454c8b8c0c166 (diff) | |
| download | perlweeklychallenge-club-44bfeffafd05618d6a52df49c8428d7d67859704.tar.gz perlweeklychallenge-club-44bfeffafd05618d6a52df49c8428d7d67859704.tar.bz2 perlweeklychallenge-club-44bfeffafd05618d6a52df49c8428d7d67859704.zip | |
sgreen solutions to challenge 175
| -rw-r--r-- | challenge-175/sgreen/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-175/sgreen/perl/ch-1.pl | 25 | ||||
| -rwxr-xr-x | challenge-175/sgreen/perl/ch-2.pl | 108 | ||||
| -rwxr-xr-x | challenge-175/sgreen/python/ch-1.py | 25 | ||||
| -rwxr-xr-x | challenge-175/sgreen/python/ch-2.py | 97 |
5 files changed, 256 insertions, 0 deletions
diff --git a/challenge-175/sgreen/blog.txt b/challenge-175/sgreen/blog.txt new file mode 100644 index 0000000000..6c0fe917cc --- /dev/null +++ b/challenge-175/sgreen/blog.txt @@ -0,0 +1 @@ +https://dev.to/simongreennet/totient-numbers-on-a-sunday-5fnc
\ No newline at end of file diff --git a/challenge-175/sgreen/perl/ch-1.pl b/challenge-175/sgreen/perl/ch-1.pl new file mode 100755 index 0000000000..632ae593c4 --- /dev/null +++ b/challenge-175/sgreen/perl/ch-1.pl @@ -0,0 +1,25 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature 'say'; +use experimental 'signatures'; + +use Date::Calc (qw(This_Year Days_in_Month Day_of_Week)); + +# Use the year provided or the current year if it wasn't +sub main ( $year = This_Year() ) { + + foreach my $month ( 1 .. 12 ) { + # Get the number of days in a month + my $last_day = Days_in_Month( $year, $month ); + + # Get the day of week of the last day (Monday is 1, Sunday is 7) + my $dow = Day_of_Week( $year, $month, $last_day ); + + # Take off the number of days to get last Sunday + say sprintf '%d-%02d-%02d', $year, $month, $last_day - $dow % 7; + } +} + +main(@ARGV); diff --git a/challenge-175/sgreen/perl/ch-2.pl b/challenge-175/sgreen/perl/ch-2.pl new file mode 100755 index 0000000000..107eb35f2b --- /dev/null +++ b/challenge-175/sgreen/perl/ch-2.pl @@ -0,0 +1,108 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature (qw(say state)); +use experimental 'signatures'; +use List::Util 'none'; + +our @primes = (); + +sub is_prime ($number) { + # Return true or false if the number is a prime + if ( $number < 2 ) { + return; + } + + foreach my $i (@primes) { + if ( $number % $i == 0 ) { + return; + } + } + + # It's a prime + return 1; +} + +sub get_factors ($num) { + # Get the prime factors that make up the numbers + state %factors = (); + + if ( not exists $factors{$num} ) { + $factors{$num} = []; + + foreach my $p (@primes) { + push @{ $factors{$num} }, $p if $num % $p == 0; + } + } + + return $factors{$num}; +} + +sub get_totients ($num) { + state %totients = (); + # Count the number of values between 1 and num-1 that has the gcd of 1 + + # If we've calculated this before, return the result + if ( not exists $totients{$num} ) { + my $factors = get_factors($num); + my %primes = map { $_, 1 } @$factors; + + my $count = 0; + foreach my $n ( 1 .. $num - 1 ) { + # Count this number if it has no common factors (other than 1) + $factors = get_factors($n); + ++$count if none { $primes{$_} } @$factors; + } + + # Store the result when we need it again + $totients{$num} = $count; + } + + return $totients{$num}; +} + +sub is_ptn ($num) { + # Return whether this number is a perfect totient number + + # Keep a count of the total + my $totals = 0; + + # Loop until we get to one + my $n = $num; + while ( $n > 1 ) { + my $totient = get_totients($n); + $totals += $totient; + + if ( $totals > $num ) { + # Short circuit exit if we know it will be False + return; + } + + $n = $totient; + } + + return $totals == $num ? 1 : 0; +} + +sub main { + my @solutions = (); + my $number = 0; + + # Loop until we have 20 solutions + while ( scalar(@solutions) < 20 ) { + $number++; + + if ( is_prime($number) ) { + push @primes, $number; + } + + if ( is_ptn($number) ) { + push @solutions, $number; + } + } + + say join ', ', @solutions; +} + +main();
\ No newline at end of file diff --git a/challenge-175/sgreen/python/ch-1.py b/challenge-175/sgreen/python/ch-1.py new file mode 100755 index 0000000000..9c99981d3b --- /dev/null +++ b/challenge-175/sgreen/python/ch-1.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import sys +from datetime import date, timedelta +from dateutil.relativedelta import relativedelta + + +def main(arg): + # Use the year provided or the current year if it wasn't + year = int(arg[0]) if len(arg) else date.today().year + + for m in range(12): + # Get the last day of each month + dt = date(year, 1+m, 1) + relativedelta(months=1) - timedelta(days=1) + + # Get the day of week (Monday is 1, Sunday is 7) + dow = dt.isoweekday() + + # Take off the number of days to get last Sunday + last_sunday = dt-timedelta(days=dow % 7) + print(last_sunday.isoformat()) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/challenge-175/sgreen/python/ch-2.py b/challenge-175/sgreen/python/ch-2.py new file mode 100755 index 0000000000..a04379a679 --- /dev/null +++ b/challenge-175/sgreen/python/ch-2.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 + +import math + +primes = [] +factors = {} +totients = {} + + +def is_prime(number): + '''Return true or false if the number is a prime''' + if number < 2: + return False + + for i in primes: + if number % i == 0: + return False + + # It's a prime + return True + + +def get_factors(num): + '''Get the prime factors that make up the numbers''' + global factors + + if num not in factors: + factors[num] = set() + + for p in primes: + if num % p == 0: + factors[num].add(p) + + return factors[num] + + +def get_totients(num): + '''Count the number of values between 1 and num-1 that has the gcd of 1''' + global totients + + # If we've calculated this before, return the result + if num not in totients: + factors = get_factors(num) + + count = 0 + for n in range(1, num): + # Count this number if it has no common factors (other than 1) + if not factors.intersection(get_factors(n)): + count += 1 + + # Store the result when we need it again + totients[num] = count + + return totients[num] + + +def is_ptn(num): + '''Return whether this number is a perfect totient number''' + + # Keep a count of the total + totals = 0 + + # Loop until we get to one + n = num + while n > 1: + totient = get_totients(n) + totals += totient + + if totals > num: + # Short circuit exit if we know it will be False + return False + + n = totient + + return totals == num + + +def main(): + global primes + solutions = [] + number = 0 + + # Loop until we have 20 solutions + while(len(solutions) < 20): + number += 1 + + if is_prime(number): + primes.append(number) + + if is_ptn(number): + solutions.append(number) + + print(*solutions, sep=', ') + + +if __name__ == '__main__': + main() |
