From 28bc08ce64bb8698b18aa7c78c4262da6ad08e80 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 09:27:51 -0400 Subject: copied from challenge 169 --- challenge-172/walt-mankowski/perl/primes.pm | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 challenge-172/walt-mankowski/perl/primes.pm diff --git a/challenge-172/walt-mankowski/perl/primes.pm b/challenge-172/walt-mankowski/perl/primes.pm new file mode 100644 index 0000000000..878c523b0b --- /dev/null +++ b/challenge-172/walt-mankowski/perl/primes.pm @@ -0,0 +1,42 @@ +package primes; +use Exporter 'import'; +our @EXPORT_OK = qw(primes_to prime_factors); + +use v5.36; +use builtin 'indexed'; +no warnings 'experimental::for_list'; +no warnings 'experimental::builtin'; + +# find the primes up to $n using the sieve of Eratosthenes and return +# them as an arrayref +sub primes_to($n) { + my @is_prime = map {1} 0..int($n); + $is_prime[0] = $is_prime[1] = 0; + for my $i (2..int(sqrt($n))) { + if ($is_prime[$i]) { + for (my $j = $i+$i; $j <= $n; $j += $i) { + $is_prime[$j] = 0; + } + } + } + + my @primes; + for my ($i, $v) (indexed @is_prime) { + push @primes, $i if $v; + } + return \@primes; +} + +# return the prime factors of $n as a sorted list +sub prime_factors($n, $primes) { + my @factors; + for my $p ($primes->@*) { + return @factors if $p > $n; + while ($n % $p == 0) { + push @factors, $p; + $n /= $p; + } + } +} + +1; -- cgit From 9e40d3e4d6e9565f6fb0d910dce7617b342296be Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 09:39:48 -0400 Subject: Perl solution to challenge 1 --- challenge-172/walt-mankowski/perl/ch-1.pl | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 challenge-172/walt-mankowski/perl/ch-1.pl diff --git a/challenge-172/walt-mankowski/perl/ch-1.pl b/challenge-172/walt-mankowski/perl/ch-1.pl new file mode 100644 index 0000000000..7715ba9f71 --- /dev/null +++ b/challenge-172/walt-mankowski/perl/ch-1.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use v5.36; +use lib "."; +use Algorithm::Combinatorics qw(combinations); +use primes qw(primes_to); +use List::Util qw(sum); + +# You are given two positive integers, $m and $n. +# +# Write a script to find out the Prime Partition of the given +# number. No duplicates allowed. +# +# For example, +# +# Input: $m = 18, $n = 2 +# Output: 5, 13 or 7, 11 +# +# Input: $m = 19, $n = 3 +# Output: 3, 5, 11 + +$, = " "; +my ($m, $n) = @ARGV; +my $primes = primes_to($m); +my $iter = combinations($primes, $n); +while (my $p = $iter->next) { + say $p->@* if sum($p->@*) == $m; +} -- cgit From 2631b5d7d44c939ab78ade0c02eb26b3a10318d7 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 12:25:59 -0400 Subject: Perl solution to challenge 2 --- challenge-172/walt-mankowski/perl/ch-2.pl | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 challenge-172/walt-mankowski/perl/ch-2.pl diff --git a/challenge-172/walt-mankowski/perl/ch-2.pl b/challenge-172/walt-mankowski/perl/ch-2.pl new file mode 100644 index 0000000000..a34f128498 --- /dev/null +++ b/challenge-172/walt-mankowski/perl/ch-2.pl @@ -0,0 +1,43 @@ +#!/usr/bin/env perl +use v5.36; +use builtin qw(floor ceil); +no warnings 'experimental::builtin'; + +# Task 2: Five-number Summary +# Submitted by: Mohammad S Anwar +# +# You are given an array of integers. +# +# Write a script to compute the five-number summary of the given set +# of integers. + +# returns the median of a sorted list +sub median_sorted(@a) { + say "@a"; + my $len = @a; + return $len % 2 == 1 ? + $a[$len/2] : + ($a[$len/2-1] + $a[$len/2]) / 2; +} + +# returns the 5 number summary of a list: minimum, lower quartile, +# median, upper quartile, maximum +sub fivenum(@a) { + my @sorted = sort {$a <=> $b} @a; + my $min = $sorted[0]; + my $max = $sorted[-1]; + my $median = median_sorted(@sorted); + my ($lower, $upper); + my $len = @sorted; + if ($len % 2 == 1) { # odd number of elements + $lower = median_sorted(@sorted[0..floor($len)]); + $upper = median_sorted(@sorted[ceil($len)..$#sorted]); + } else { + $lower = median_sorted(@sorted[0..($len/2-1)]); + $upper = median_sorted(@sorted[($len/2)..$#sorted]); + } + return ($min, $lower, $median, $upper, $max); +} + +$, = " "; +say fivenum(@ARGV); -- cgit From 3933a0194a58623b8bc446ab57a5d03adca65860 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 12:39:39 -0400 Subject: python code for challenge 1 --- challenge-172/walt-mankowski/python/ch-1.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 challenge-172/walt-mankowski/python/ch-1.py diff --git a/challenge-172/walt-mankowski/python/ch-1.py b/challenge-172/walt-mankowski/python/ch-1.py new file mode 100644 index 0000000000..b8032fe1cb --- /dev/null +++ b/challenge-172/walt-mankowski/python/ch-1.py @@ -0,0 +1,11 @@ +import sys +from itertools import combinations +from primes import primes_to + +m, n = [int(x) for x in sys.argv[1:]] +primes = primes_to(m) + +for comb in combinations(primes, n): + if sum(comb) == m: + print(comb) + -- cgit From d75934a5e11be1b9a56286bd169e9a1970d26b42 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 18:47:39 -0400 Subject: python code for challenge 2 --- challenge-172/walt-mankowski/python/ch-2.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 challenge-172/walt-mankowski/python/ch-2.py diff --git a/challenge-172/walt-mankowski/python/ch-2.py b/challenge-172/walt-mankowski/python/ch-2.py new file mode 100644 index 0000000000..c1b356d5f3 --- /dev/null +++ b/challenge-172/walt-mankowski/python/ch-2.py @@ -0,0 +1,26 @@ +import sys + +# returns the median of a sorted list +def median_sorted(a): + len2 = len(a) // 2 + return a[len2] if len(a) % 2 == 1 else (a[len2-1] + a[len2]) / 2 + +# returns the 5 number summary of a list: minimum, lower quartile, +# median, upper quartile, maximum +def fivenum(a): + _sorted = sorted(a) + _min = _sorted[0] + _max = _sorted[-1] + _median = median_sorted(_sorted) + + len2 = len(a) // 2 + _lower = median_sorted(_sorted[0:len2]) + if len(a) % 2 == 1: # odd number of elements + _upper = median_sorted(_sorted[len2+1:]) + else: + _upper = median_sorted(_sorted[len2:]) + + return _min, _lower, _median, _upper, _max + +a = [int(x) for x in sys.argv[1:]] +print(fivenum(a)) -- cgit From c5a37622868919d3af2d4d3011df7bfe6eebc689 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 18:50:27 -0400 Subject: python code to find primes --- challenge-172/walt-mankowski/python/primes.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 challenge-172/walt-mankowski/python/primes.py diff --git a/challenge-172/walt-mankowski/python/primes.py b/challenge-172/walt-mankowski/python/primes.py new file mode 100644 index 0000000000..686143de0f --- /dev/null +++ b/challenge-172/walt-mankowski/python/primes.py @@ -0,0 +1,15 @@ +from math import sqrt + +# find the primes up to n using the sieve of Eratosthenes and return +# them as list +def primes_to(n): + is_prime = [True] * (n+1) + is_prime[0] = is_prime[1] = False + for i in range(2, int(sqrt(n))+1): + if is_prime[i]: + for j in range(i+i, n+1, i): + is_prime[j] = False + + return [i for i,val in enumerate(is_prime) if val] + + -- cgit From 475468224477fb298554f43f30e24c52b26ba99b Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 18:53:21 -0400 Subject: simplified the code --- challenge-172/walt-mankowski/perl/ch-2.pl | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/challenge-172/walt-mankowski/perl/ch-2.pl b/challenge-172/walt-mankowski/perl/ch-2.pl index a34f128498..707455d812 100644 --- a/challenge-172/walt-mankowski/perl/ch-2.pl +++ b/challenge-172/walt-mankowski/perl/ch-2.pl @@ -1,7 +1,5 @@ #!/usr/bin/env perl use v5.36; -use builtin qw(floor ceil); -no warnings 'experimental::builtin'; # Task 2: Five-number Summary # Submitted by: Mohammad S Anwar @@ -13,11 +11,8 @@ no warnings 'experimental::builtin'; # returns the median of a sorted list sub median_sorted(@a) { - say "@a"; - my $len = @a; - return $len % 2 == 1 ? - $a[$len/2] : - ($a[$len/2-1] + $a[$len/2]) / 2; + my $len2 = int(@a / 2); + return @a % 2 == 1 ? $a[$len2] : ($a[$len2-1] + $a[$len2]) / 2; } # returns the 5 number summary of a list: minimum, lower quartile, @@ -27,14 +22,14 @@ sub fivenum(@a) { my $min = $sorted[0]; my $max = $sorted[-1]; my $median = median_sorted(@sorted); - my ($lower, $upper); - my $len = @sorted; - if ($len % 2 == 1) { # odd number of elements - $lower = median_sorted(@sorted[0..floor($len)]); - $upper = median_sorted(@sorted[ceil($len)..$#sorted]); + + my $len2 = int(@sorted / 2); + my $lower = median_sorted(@sorted[0..$len2-1]); + my $upper; + if (@sorted % 2 == 1) { # odd number of elements + $upper = median_sorted(@sorted[$len2+1..$#sorted]); } else { - $lower = median_sorted(@sorted[0..($len/2-1)]); - $upper = median_sorted(@sorted[($len/2)..$#sorted]); + $upper = median_sorted(@sorted[$len2..$#sorted]); } return ($min, $lower, $median, $upper, $max); } -- cgit From aa68bad2533c910ff6b5dadd573b7d7e93af62ea Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 19:52:08 -0400 Subject: Readme file for challenge 172 --- challenge-172/walt-mankowski/README.md | 113 +++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/challenge-172/walt-mankowski/README.md b/challenge-172/walt-mankowski/README.md index 7e4eff8dc2..ff4444732e 100644 --- a/challenge-172/walt-mankowski/README.md +++ b/challenge-172/walt-mankowski/README.md @@ -1,61 +1,106 @@ Solutions by Walt Mankowski. -# Task #1: Abundant Odd Numbers +# Task #1: Prime Partition -For this task we need to find the first 20 odd **Abundant Numbers**. An [Abundant number](https://en.wikipedia.org/wiki/Abundant_number) is a number which is less than the sum of its proper divisors. +For this task we're given 2 positive integers _m_ and _n_, and we need to find _n_ unique prime numbers that add up to _m_. -I don't have much to say about this because it was quite simple to solve this by brute force. My only insight is to note that odd numbers can only have odd divisors, so we only have to check half the possible values. +To solve this I made use of the `primes_to()` function I wrote for Challenge 169. I also used `Algorithm::Combinatorics` to find combinations of primes taking _n_ at time, and `sum()` from `List::Utils` to find the sum. Using those 3 functions this challenge was easy to solve: ```perl -sub odd_divisors($n) { - my @od = (1); - my $max = $n / 2; - for (my $i = 3; $i <= $max; $i += 2) { - push @od, $i if $n % $i == 0; - } - return @od; +$, = " "; +my ($m, $n) = @ARGV; +my $primes = primes_to($m); +my $iter = combinations($primes, $n); +while (my $p = $iter->next) { + say $p->@* if sum($p->@*) == $m; } ``` -I also did a version in Python. In Python we can write `odd_divisors()` basically as a one-liner since `range()` lets us avoid a for loop: +I also wrote a version in Python. First I needed to port `primes_to()` to Python: ```python -def odd_divisors(n): - od = [i for i in range(1,n//2+1,2) if n % i == 0] - return od +# find the primes up to n using the sieve of Eratosthenes and return +# them as a list +def primes_to(n): + is_prime = [True] * (n+1) + is_prime[0] = is_prime[1] = False + for i in range(2, int(sqrt(n))+1): + if is_prime[i]: + for j in range(i+i, n+1, i): + is_prime[j] = False + + return [i for i,val in enumerate(is_prime) if val] ``` -# Task 2: First-class Function +Then the actual code to solve the challenge ended up looking very similar to the Perl version: -For this task we needed to create a function `compose(f,g)` that takes in two parameters `f` and `g` as subroutine references, and returns the subroutine `f(g(x))`. +```python +import sys +from itertools import combinations +from primes import primes_to -I just wrote this as a very simple function in Perl: +m, n = [int(x) for x in sys.argv[1:]] +primes = primes_to(m) -```perl -sub compose($f, $g) { - return sub { $f->($g->(@_)) }; -} +for comb in combinations(primes, n): + if sum(comb) == m: + print(comb) ``` -Then I tested it by composing 2 functions, one which sums its arguments and another which doubles each of its arguments: +# Task 2: Five-number Summary + +For this task we're given a list of numbers and need to compute their (Five-number Summary)[https://en.wikipedia.org/wiki/Five-number_summary], which consists of + +1. The minimum value +2. The lower quartile +3. The median +4. The upper quartile +5. The maximum value + +To solve this I first sorted the list. The minimum and maximum values are just the first and last element of the sorted list. Then I wrote a function to compute the median of a sorted list. ```perl -sub sum { - my $sum = 0; - $sum += $_ for @_; - return $sum; +sub median_sorted(@a) { + my $len2 = int(@a / 2); + return @a % 2 == 1 ? $a[$len2] : ($a[$len2-1] + $a[$len2]) / 2; } +``` +Once we have that, then the lower quartile is the median of the values before the median in the sorted list, and the upper quartile is the median of the values after the median. -sub double { - return map { $_ * 2 } @_; +```perl +sub fivenum(@a) { + my @sorted = sort {$a <=> $b} @a; + my $min = $sorted[0]; + my $max = $sorted[-1]; + my $median = median_sorted(@sorted); + + my $len2 = int(@sorted / 2); + my $lower = median_sorted(@sorted[0..$len2-1]); + my $upper; + if (@sorted % 2 == 1) { # odd number of elements + $upper = median_sorted(@sorted[$len2+1..$#sorted]); + } else { + $upper = median_sorted(@sorted[$len2..$#sorted]); + } + return ($min, $lower, $median, $upper, $max); } ``` -Here's an example of using it. The output is `20`. +`fivenum()` was a little tricky to port to Python. First, `sorted`, `min`, and `max` are all reserved words to Python, so I had to come up with different names for them. I decided to just prefix all the variable names with an underscore. I also had to be careful because the upper range of slices is inclusive in Perl but exclusive in Python. Here's my version: -```perl -my $c = compose(\&sum, \&double); -say $c->(1,2,3,4); +```python +def fivenum(a): + _sorted = sorted(a) + _min = _sorted[0] + _max = _sorted[-1] + _median = median_sorted(_sorted) + + len2 = len(a) // 2 + _lower = median_sorted(_sorted[0:len2]) + if len(a) % 2 == 1: # odd number of elements + _upper = median_sorted(_sorted[len2+1:]) + else: + _upper = median_sorted(_sorted[len2:]) + + return _min, _lower, _median, _upper, _max ``` - -I never got a version of this working in Python. -- cgit From 79c806168990c237d27048fce85af6116ac63127 Mon Sep 17 00:00:00 2001 From: Walt Mankowski Date: Mon, 4 Jul 2022 19:53:03 -0400 Subject: fixed typo in comment --- challenge-172/walt-mankowski/python/primes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-172/walt-mankowski/python/primes.py b/challenge-172/walt-mankowski/python/primes.py index 686143de0f..5de8c87a61 100644 --- a/challenge-172/walt-mankowski/python/primes.py +++ b/challenge-172/walt-mankowski/python/primes.py @@ -1,7 +1,7 @@ from math import sqrt # find the primes up to n using the sieve of Eratosthenes and return -# them as list +# them as a list def primes_to(n): is_prime = [True] * (n+1) is_prime[0] = is_prime[1] = False -- cgit