From bfbe46021b65c553df3ecc6a4f311d0ab2b23f07 Mon Sep 17 00:00:00 2001 From: dasJake Date: Mon, 29 Nov 2021 21:10:29 +0100 Subject: 141 initial commit for 141/ch-1.pl --- challenge-141/jake/perl/ch-1.pl | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 challenge-141/jake/perl/ch-1.pl diff --git a/challenge-141/jake/perl/ch-1.pl b/challenge-141/jake/perl/ch-1.pl new file mode 100644 index 0000000000..711f5cf4f7 --- /dev/null +++ b/challenge-141/jake/perl/ch-1.pl @@ -0,0 +1,4 @@ +#!/usr/bin/env perl + +use warnings; +use strict; -- cgit From 931699cba0d6373b7f7a9e645ff1a6ef59ad6e5d Mon Sep 17 00:00:00 2001 From: dasJake Date: Mon, 29 Nov 2021 22:33:02 +0100 Subject: 141 create hash for number attributes --- challenge-141/jake/perl/ch-1.pl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) mode change 100644 => 100755 challenge-141/jake/perl/ch-1.pl diff --git a/challenge-141/jake/perl/ch-1.pl b/challenge-141/jake/perl/ch-1.pl old mode 100644 new mode 100755 index 711f5cf4f7..13e4c85102 --- a/challenge-141/jake/perl/ch-1.pl +++ b/challenge-141/jake/perl/ch-1.pl @@ -2,3 +2,27 @@ use warnings; use strict; +use feature 'say'; + +my $number_attributes = { + number => '1', + divisor_counter => '0', + subtractor => '0', +}; +count_divisors( $number_attributes ); +# modulo number n through n, n-1, and so on +# for each modulo 0 increase counter +# when counter hits 8 add number to number array, proceed to next number and increase number counter +# if number counter hits 10 output number array or if array size becomes 10 + +sub count_divisors { + say ( $number_attributes->{divisor_counter}, $number_attributes->{subtractor}, $number_attributes->{number} ); + while ( $number_attributes->{divisor_counter} < 9 ) { + say ( $number_attributes->{divisor_counter}, $number_attributes->{subtractor}, $number_attributes->{number} ); + $number_attributes->{divisor_counter}++ if $number_attributes->{number} % ( $number_attributes->{number} - $number_attributes->{subtractor} ) == 0; + $number_attributes->{subtractor}++; + print "div_c: $number_attributes->{divisor_counter}, subtr: $number_attributes->{subtractor}\n"; + $number_attributes->{number}++; + die if $number_attributes->{number} == 10; + } +} \ No newline at end of file -- cgit From d9e173549d904ceb2da49185c33f071496a779c1 Mon Sep 17 00:00:00 2001 From: dasJake Date: Wed, 1 Dec 2021 00:49:02 +0100 Subject: 141 add brute force ch-1.pl; method is heavy --- challenge-141/jake/perl/ch-1.pl | 62 ++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/challenge-141/jake/perl/ch-1.pl b/challenge-141/jake/perl/ch-1.pl index 13e4c85102..e03638a082 100755 --- a/challenge-141/jake/perl/ch-1.pl +++ b/challenge-141/jake/perl/ch-1.pl @@ -4,25 +4,53 @@ use warnings; use strict; use feature 'say'; -my $number_attributes = { - number => '1', - divisor_counter => '0', - subtractor => '0', +# number attributes +# num specifies the lowest number to start analysis +# div_required specifies for how many divisors we aiming at +# output specifies how many numbers will be displayed +my $num_atr = { + num => '1', + div_required => '8', + output_required => '10' }; -count_divisors( $number_attributes ); -# modulo number n through n, n-1, and so on -# for each modulo 0 increase counter -# when counter hits 8 add number to number array, proceed to next number and increase number counter -# if number counter hits 10 output number array or if array size becomes 10 + +# output +my $res = collect_numbers(); +say join (' ', @$res); + + + +# aggregate required amount of numbers according to output_required +sub collect_numbers { + my @result = (); + + while ( $#result+1 < $num_atr->{output_required} ) { + push @result, count_divisors( $num_atr, 0, 0 ); + $num_atr->{num}++; + } + return \@result; +} + sub count_divisors { - say ( $number_attributes->{divisor_counter}, $number_attributes->{subtractor}, $number_attributes->{number} ); - while ( $number_attributes->{divisor_counter} < 9 ) { - say ( $number_attributes->{divisor_counter}, $number_attributes->{subtractor}, $number_attributes->{number} ); - $number_attributes->{divisor_counter}++ if $number_attributes->{number} % ( $number_attributes->{number} - $number_attributes->{subtractor} ) == 0; - $number_attributes->{subtractor}++; - print "div_c: $number_attributes->{divisor_counter}, subtr: $number_attributes->{subtractor}\n"; - $number_attributes->{number}++; - die if $number_attributes->{number} == 10; + my ( $spec_num, $div_cntr, $subtractor) = @_; + +# divide num through all numbers <= num and count every time modulo is 0 +# each time modulo is 0 we know it's a divisor + while ( $subtractor != $num_atr->{num} ) { + $div_cntr++ if $num_atr->{num} % ( $num_atr->{num} - $subtractor ) == 0; + $subtractor++; + } + +# only return to sub collect_numbers if we hit the required amount of divisors + if ( $div_cntr == $num_atr->{div_required} ) { + return $num_atr->{num}; + } + +# when ever the current num did not meet the required divisors we need to start over counting them for the next num +# in this case we must not return num to sub collect_numbers + else { + $num_atr->{num}++; + return count_divisors( $num_atr, 0, 0 ); } } \ No newline at end of file -- cgit From c6217ae7427a88fc7d4ecf8daa6e5029b935c32f Mon Sep 17 00:00:00 2001 From: dasJake Date: Wed, 1 Dec 2021 23:28:15 +0100 Subject: 141 add more performant method; still buggy --- challenge-141/jake/perl/ch-1.pl | 71 +++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/challenge-141/jake/perl/ch-1.pl b/challenge-141/jake/perl/ch-1.pl index e03638a082..ce8c9da777 100755 --- a/challenge-141/jake/perl/ch-1.pl +++ b/challenge-141/jake/perl/ch-1.pl @@ -6,11 +6,12 @@ use feature 'say'; # number attributes # num specifies the lowest number to start analysis -# div_required specifies for how many divisors we aiming at +# div_required specifies for how many divisors we're aiming at # output specifies how many numbers will be displayed +# div_required and output_required can be adjusted as desired my $num_atr = { num => '1', - div_required => '8', + div_required => '6', output_required => '10' }; @@ -18,39 +19,67 @@ my $num_atr = { my $res = collect_numbers(); say join (' ', @$res); - - # aggregate required amount of numbers according to output_required sub collect_numbers { my @result = (); while ( $#result+1 < $num_atr->{output_required} ) { - push @result, count_divisors( $num_atr, 0, 0 ); + push @result, count_divisors( $num_atr, 1 ); $num_atr->{num}++; } return \@result; } +# starting at 1 we aggregate all divisors in an array +# we also aggregate all corresponding reciprocal values in another array +# if these arrays are symmetric to each other at the position of half our's div_required, we know they have the required amount of divisors +# p.e. num = 24; div_required = 8; the divisor arrays are cross-symmetric at div_required / 2 +# <==\\==> +# 24 12 8 6\\4 3 2 1 +# 1 2 3 4\\6 8 12 24 +# <==\\==> sub count_divisors { - my ( $spec_num, $div_cntr, $subtractor) = @_; + my ( $spec_num, $divisor) = @_; -# divide num through all numbers <= num and count every time modulo is 0 -# each time modulo is 0 we know it's a divisor - while ( $subtractor != $num_atr->{num} ) { - $div_cntr++ if $num_atr->{num} % ( $num_atr->{num} - $subtractor ) == 0; - $subtractor++; - } + # each iteration needs a fresh set of arrays + my @divisors = (); + my @reciprocal = (); -# only return to sub collect_numbers if we hit the required amount of divisors - if ( $div_cntr == $num_atr->{div_required} ) { - return $num_atr->{num}; - } + # in case our divisor gets as large as our number, we stop aggregating our arrays + # because then we have arrived at the largest and smallest divisors + while ( $num_atr->{num} / $divisor >= 1 ) { + + # finding our divisors + if ( $num_atr->{num} % $divisor == 0 ) { + push @divisors, $divisor; + push @reciprocal, ( $num_atr->{num} / $divisor ); + } -# when ever the current num did not meet the required divisors we need to start over counting them for the next num -# in this case we must not return num to sub collect_numbers - else { - $num_atr->{num}++; - return count_divisors( $num_atr, 0, 0 ); + # if div_required is even + if ( $num_atr->{div_required} % 2 == 0 ) { + return $num_atr->{num} if $divisors[$num_atr->{div_required} / 2] && $divisors[$num_atr->{div_required} / 2] == $reciprocal[$num_atr->{div_required} / 2 - 1]; + } + + # if div_required is odd; CAPUTTED: ref massacre + #if ( $num_atr->{div_required} % 2 == 1 ) { + # return $num_atr->{num} if $divisors[int($num_atr->{div_required} / 2) + 1] + # && $divisors[int($num_atr->{div_required} / 2) + 1] == $reciprocal[int($num_atr->{div_required} / 2) + 1]; + #} + if ( $num_atr->{div_required} % 2 == 1 ) { + return $num_atr->{num} if $divisors[3] + && $divisors[3] == $reciprocal[3]; + } + #say ("line $num_atr->{div_required}"); + #say[int($num_atr->{div_required} / 2) + 1]; + #say $divisors[int($num_atr->{div_required} / 2) + 1]; + #say $reciprocal[int($num_atr->{div_required} / 2) + 1]; + #die if $num_atr->{num}==15; + $divisor++; } + + # when ever the current num did not meet the required divisors we need to start over counting them for the next num + # in this case we must not return num to sub collect_numbers + $num_atr->{num}++; + return count_divisors( $num_atr, 1 ); } \ No newline at end of file -- cgit From b2d41e73b5b7a458aa89ed64e993594fdfce2c1e Mon Sep 17 00:00:00 2001 From: dasJake Date: Thu, 2 Dec 2021 21:23:23 +0100 Subject: 141 fix 2nd variant; make output adjustable --- challenge-141/jake/perl/ch-1.pl | 44 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/challenge-141/jake/perl/ch-1.pl b/challenge-141/jake/perl/ch-1.pl index ce8c9da777..33fb88012c 100755 --- a/challenge-141/jake/perl/ch-1.pl +++ b/challenge-141/jake/perl/ch-1.pl @@ -4,14 +4,22 @@ use warnings; use strict; use feature 'say'; -# number attributes +### +# Write a script to find lowest 10 positive integers having exactly 8 divisors +# +# https://theweeklychallenge.org/blog/perl-weekly-challenge-141/#TASK1 +### + +### number attributes # num specifies the lowest number to start analysis -# div_required specifies for how many divisors we're aiming at +# div_required specifies how many divisors we're aiming at # output specifies how many numbers will be displayed -# div_required and output_required can be adjusted as desired +# all of these values can be adjusted as desired +# corner cases that won't comupte correctly: div_required = 0 and div_required = 1 +# also odd div_required may run easily into deep recursion because seemingly they tend to be larger numbers my $num_atr = { num => '1', - div_required => '6', + div_required => '8', output_required => '10' }; @@ -33,11 +41,19 @@ sub collect_numbers { # starting at 1 we aggregate all divisors in an array # we also aggregate all corresponding reciprocal values in another array # if these arrays are symmetric to each other at the position of half our's div_required, we know they have the required amount of divisors -# p.e. num = 24; div_required = 8; the divisor arrays are cross-symmetric at div_required / 2 +# example for even div_required = 8; num = 24; the divisor arrays are cross-symmetric at div_required / 2 +# the axis is between $divisors[3] and $reciprocal[4] # <==\\==> # 24 12 8 6\\4 3 2 1 # 1 2 3 4\\6 8 12 24 # <==\\==> +# +# example for odd div_required = 9; num = 36; the divisor arrays are cross-symmetric at div_required / 2 +# the axis is on $divisors[4] and $reciprocal[4] +# <==\ \==> +# 36 18 12 09 \06\ 04 03 02 01 +# 01 02 03 04 \06\ 09 12 18 36 +# <==\ \==> sub count_divisors { my ( $spec_num, $divisor) = @_; @@ -56,25 +72,17 @@ sub count_divisors { push @reciprocal, ( $num_atr->{num} / $divisor ); } - # if div_required is even + # if div_required is even we look for the axis between array elements if ( $num_atr->{div_required} % 2 == 0 ) { return $num_atr->{num} if $divisors[$num_atr->{div_required} / 2] && $divisors[$num_atr->{div_required} / 2] == $reciprocal[$num_atr->{div_required} / 2 - 1]; } - # if div_required is odd; CAPUTTED: ref massacre - #if ( $num_atr->{div_required} % 2 == 1 ) { - # return $num_atr->{num} if $divisors[int($num_atr->{div_required} / 2) + 1] - # && $divisors[int($num_atr->{div_required} / 2) + 1] == $reciprocal[int($num_atr->{div_required} / 2) + 1]; - #} + # if div_required is odd we look for the axis on an array element if ( $num_atr->{div_required} % 2 == 1 ) { - return $num_atr->{num} if $divisors[3] - && $divisors[3] == $reciprocal[3]; + return $num_atr->{num} if $divisors[int($num_atr->{div_required} / 2)] + && $divisors[int($num_atr->{div_required} / 2)] == $reciprocal[int($num_atr->{div_required} / 2)]; } - #say ("line $num_atr->{div_required}"); - #say[int($num_atr->{div_required} / 2) + 1]; - #say $divisors[int($num_atr->{div_required} / 2) + 1]; - #say $reciprocal[int($num_atr->{div_required} / 2) + 1]; - #die if $num_atr->{num}==15; + $divisor++; } -- cgit