diff options
| -rw-r--r-- | challenge-172/walt-mankowski/README.md | 113 | ||||
| -rw-r--r-- | challenge-172/walt-mankowski/perl/ch-1.pl | 27 | ||||
| -rw-r--r-- | challenge-172/walt-mankowski/perl/ch-2.pl | 38 | ||||
| -rw-r--r-- | challenge-172/walt-mankowski/perl/primes.pm | 42 | ||||
| -rw-r--r-- | challenge-172/walt-mankowski/python/ch-1.py | 11 | ||||
| -rw-r--r-- | challenge-172/walt-mankowski/python/ch-2.py | 26 | ||||
| -rw-r--r-- | challenge-172/walt-mankowski/python/primes.py | 15 |
7 files changed, 238 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. 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; +} 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..707455d812 --- /dev/null +++ b/challenge-172/walt-mankowski/perl/ch-2.pl @@ -0,0 +1,38 @@ +#!/usr/bin/env perl +use v5.36; + +# 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) { + 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, +# 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 $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); +} + +$, = " "; +say fivenum(@ARGV); 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; 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) + 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)) diff --git a/challenge-172/walt-mankowski/python/primes.py b/challenge-172/walt-mankowski/python/primes.py new file mode 100644 index 0000000000..5de8c87a61 --- /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 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] + + |
