From 61ec2bc8bbe16e41377099a66aeeaab7e35685ab Mon Sep 17 00:00:00 2001 From: Stephen Lynn Date: Fri, 2 Jun 2023 19:29:52 +0800 Subject: pwc 219 --- challenge-219/steve-g-lynn/blog.txt | 1 + challenge-219/steve-g-lynn/perl/ch-1.pdl | 7 +++ challenge-219/steve-g-lynn/perl/ch-2.pl | 82 ++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 challenge-219/steve-g-lynn/blog.txt create mode 100755 challenge-219/steve-g-lynn/perl/ch-1.pdl create mode 100755 challenge-219/steve-g-lynn/perl/ch-2.pl diff --git a/challenge-219/steve-g-lynn/blog.txt b/challenge-219/steve-g-lynn/blog.txt new file mode 100644 index 0000000000..6df602d517 --- /dev/null +++ b/challenge-219/steve-g-lynn/blog.txt @@ -0,0 +1 @@ +https://thiujiac.blogspot.com/2023/06/pwc-219.html diff --git a/challenge-219/steve-g-lynn/perl/ch-1.pdl b/challenge-219/steve-g-lynn/perl/ch-1.pdl new file mode 100755 index 0000000000..8984fc03fe --- /dev/null +++ b/challenge-219/steve-g-lynn/perl/ch-1.pdl @@ -0,0 +1,7 @@ +#!/usr/bin/pdl + +sub sorted_squares {$list=pdl @_; ($list*$list)->qsort; } + +p &sorted_squares(-2,-1,0,3,4); #-- [0 1 4 9 16] +p &sorted_squares(5,-4,-1,3,6); #-- [1 9 16 25 36] + diff --git a/challenge-219/steve-g-lynn/perl/ch-2.pl b/challenge-219/steve-g-lynn/perl/ch-2.pl new file mode 100755 index 0000000000..b6e80f2598 --- /dev/null +++ b/challenge-219/steve-g-lynn/perl/ch-2.pl @@ -0,0 +1,82 @@ +#!/usr/bin/env -S perl -wl + +use PDL; +use PDL::NiceSlice; +use PDL::AutoLoader; + +sub travel_expenditure { + my ($ra_costs, $ra_days)=@_; + my $costs=pdl $ra_costs; + + #-- input validation check that costs are reasonable + #-- 7 day price is less than 7 * daily price + #-- 7 day price is greater than daily price + + (scalar(@$ra_costs) == 3) || (die "bad costs"); + + ( ($ra_costs->[1] < (7*$ra_costs->[0])) + && ($ra_costs->[1] > $ra_costs->[0]) ) + || (die "bad costs"); + + #-- 30 day price is less than 30/7* 7-day price + #-- 30 day price is greater than 7-day price + + ( ($ra_costs->[2] < (30/7*$ra_costs->[1])) + && ($ra_costs->[2] > $ra_costs->[1]) ) + || (die "bad costs"); + + + #-- input validation check that dates are in 0 .. 31 + (((pdl $ra_days)->flat->byte)->max > 31) && (die "bad date"); + (((pdl $ra_days)->flat->byte)->min < 1) && (die "bad date"); + + + #-- store days as a 31-element boolean + #-- with 1 at index corresponding to a travel day + #-- and 0 at the index for non-travel days + my $days=zeros(31); + $days(pdl($ra_days)-1).=1; + + #-- worth paying for a whole month? + #-- check if # of days is greater than 30-day price / 7-day price * 7 + if ($days->sum > ($ra_costs->[2] / $ra_costs->[1] * 7)) { + if ($days(0) & $days(30)) { + #if both 1st and last day of 31-day month, then .. + return $ra_costs->[2]+$ra_costs->[0]; + #cost is 30 days price + 1 day price + } + else { + return $ra_costs->[2]; + } + + } + my $weekly_card=0; + my $days_paid_weekly=0; + my $weekly_cutoff= int( $ra_costs->[1] / $ra_costs->[0] )+1; + + #-- cycle through $days looking for clusters of more than + #-- 7-day price / 1-day price travel days in a 7-day stretch + #-- (weekly cutoff days in a 7-day stretch) + + my $ctr=0; + + while ($ctr <= (30 - $weekly_cutoff)) { + #-- slow interpreted loop is good enough + #-- because the days vector won't scale beyond 31 days + my $days_forward = (pdl (6, 30-$ctr) )->min; + if ($days($ctr:($ctr+$days_forward))->sum >= $weekly_cutoff) { + $weekly_card++; + $days_paid_weekly += $days($ctr:($ctr+$days_forward))->sum; + $ctr += $days_forward; + } + else { + $ctr += 1; + } + } + return $weekly_card*$costs(1) + +( ($days->sum)-$days_paid_weekly ) * $costs(0); +} + +print &travel_expenditure([2,7,25],[2..26,31]); #-- 25 +print &travel_expenditure([2,7,25],[1,5,6,7,9,15]); #-- 11 +print &travel_expenditure([2,7,25],[1..3,5,7,10..12, 14, 20, 30, 31]); #-- 20 -- cgit From ad4cc0e6599c34423a3aee073741595cbaf8c1eb Mon Sep 17 00:00:00 2001 From: Stephen Lynn Date: Sat, 3 Jun 2023 11:28:47 +0800 Subject: fix ch-2 --- challenge-219/steve-g-lynn/perl/ch-2.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-219/steve-g-lynn/perl/ch-2.pl b/challenge-219/steve-g-lynn/perl/ch-2.pl index b6e80f2598..fd27d87d8d 100755 --- a/challenge-219/steve-g-lynn/perl/ch-2.pl +++ b/challenge-219/steve-g-lynn/perl/ch-2.pl @@ -67,7 +67,7 @@ sub travel_expenditure { if ($days($ctr:($ctr+$days_forward))->sum >= $weekly_cutoff) { $weekly_card++; $days_paid_weekly += $days($ctr:($ctr+$days_forward))->sum; - $ctr += $days_forward; + $ctr += $days_forward+1; } else { $ctr += 1; -- cgit From 96fbd7d14ecb1cb3a3e923fe0ae9007491aad34b Mon Sep 17 00:00:00 2001 From: Stephen Lynn Date: Sat, 3 Jun 2023 14:25:57 +0800 Subject: bug fix ch-2.pl --- challenge-219/steve-g-lynn/perl/ch-2.pl | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/challenge-219/steve-g-lynn/perl/ch-2.pl b/challenge-219/steve-g-lynn/perl/ch-2.pl index fd27d87d8d..e138df34e1 100755 --- a/challenge-219/steve-g-lynn/perl/ch-2.pl +++ b/challenge-219/steve-g-lynn/perl/ch-2.pl @@ -36,13 +36,16 @@ sub travel_expenditure { #-- and 0 at the index for non-travel days my $days=zeros(31); $days(pdl($ra_days)-1).=1; + #-- worth paying for a whole month? #-- check if # of days is greater than 30-day price / 7-day price * 7 + my $candidates=pdl [Inf, Inf]; #-- candidate solutions + if ($days->sum > ($ra_costs->[2] / $ra_costs->[1] * 7)) { if ($days(0) & $days(30)) { #if both 1st and last day of 31-day month, then .. - return $ra_costs->[2]+$ra_costs->[0]; + $candidates(0) .= $ra_costs->[2]+$ra_costs->[0]; #cost is 30 days price + 1 day price } else { @@ -60,9 +63,15 @@ sub travel_expenditure { my $ctr=0; - while ($ctr <= (30 - $weekly_cutoff)) { + MYLOOP: while ($ctr <= (30 - $weekly_cutoff)) { #-- slow interpreted loop is good enough #-- because the days vector won't scale beyond 31 days + + #-- start counting 7 days from a travel day only + if ($days($ctr)==0){ + $ctr++; + next MYLOOP; + } my $days_forward = (pdl (6, 30-$ctr) )->min; if ($days($ctr:($ctr+$days_forward))->sum >= $weekly_cutoff) { $weekly_card++; @@ -73,10 +82,12 @@ sub travel_expenditure { $ctr += 1; } } - return $weekly_card*$costs(1) + $candidates(1) .= $weekly_card*$costs(1) +( ($days->sum)-$days_paid_weekly ) * $costs(0); + return $candidates->flat->min; } +print &travel_expenditure([3.5,7,25],[1..21,25..31]); #-- 28 print &travel_expenditure([2,7,25],[2..26,31]); #-- 25 print &travel_expenditure([2,7,25],[1,5,6,7,9,15]); #-- 11 print &travel_expenditure([2,7,25],[1..3,5,7,10..12, 14, 20, 30, 31]); #-- 20 -- cgit