Created
October 30, 2022 00:40
-
-
Save nd3i/2ef29dfc71d0bbbe38ea1e66f8a816a2 to your computer and use it in GitHub Desktop.
A scratch at PWC 187
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
subset Even of Int where * %% 2; | |
sub median (*@n) { | |
given @n.elems { | |
when 0 { return () } | |
when Even { return @n.sort[@n/2-1, @n/2].sum/2 } | |
default { return @n.sort[(@n+1)/2-1] } | |
} | |
} | |
# say median(1, 0); # (0, 1)[0,1].sum/2 => 0.5 | |
# say median(0, 2, 1); # (0, 1, 2)[1].sum/1 => 1 | |
# say median(); # => () | |
# say median(6, 1, 3, 2, 5, 4); # (1, 2, 3, 4, 5, 6)[2,3].sum/2 => 3.5 | |
sub common_interval ($a1, $a2, $b1, $b2) { | |
# no overlap possible | |
return () if $b2 < $a1 or $a2 < $b1; | |
# coterminal: may want to handle this differently | |
return ($a1, $b2) if $a1 == $b2; | |
return ($b1, $a2) if $b1 == $a2; | |
# overlap | |
return ( | |
median($a1, $a2, $b1), | |
median($a1, $a2, $b2) | |
).sort; | |
} | |
# say ' 1 ', common_interval(20, 30, 1, 9); # () | |
# say ' 2 ', common_interval(20, 30, 12, 20); # (20, 20) | |
# say '3.1 ', common_interval(20, 30, 13, 21); # (20, 21) | |
# say '3.2 ', common_interval(20, 30, 20, 28); # (20, 28) | |
# say '3.3 ', common_interval(20, 30, 22, 30); # (22, 30) | |
# say '3.4 ', common_interval(20, 30, 22, 30); # (22, 30) | |
# say '3.5 ', common_interval(20, 30, 23, 31); # (23, 30) | |
# say '4.1 ', common_interval(13, 21, 20, 30); # (20, 21) | |
# say '4.2 ', common_interval(20, 28, 20, 30); # (20, 28) | |
# say '4.3 ', common_interval(22, 30, 20, 30); # (22, 30) | |
# say '4.4 ', common_interval(22, 30, 20, 30); # (22, 30) | |
# say '4.5 ', common_interval(23, 31, 20, 30); # (23, 30) | |
# say ' 5 ', common_interval(20, 30, 30, 38); # (30, 30) | |
# say ' 6 ', common_interval(20, 30, 31, 39); # () | |
# Simpler: just use max(a1, b1), min(a2, b2) | |
# See: http://blogs.perl.org/users/laurent_r/2022/10/perl-weekly-challenge-187-days-together.html | |
for <12-01 20-01 15-01 18-01>, | |
<03-03 12-03 13-03 14-03>, | |
<02-03 12-03 11-03 15-03>, | |
<30-03 05-04 28-03 02-04>, | |
<12-01 13-03 09-01 25-04> | |
-> @input { | |
my $year = Date.today.year; | |
my @dates = @input.map: { Date.new($year, |$_.split('-').reverse) }; | |
my ($s, $e) = common_interval(|@dates); | |
say "Days together for dates @input[]: ", | |
($e && $s) ?? $e - $s + 1 !! 0; | |
} | |
for '1', (20, 30, 1, 9), # () | |
'2', (20, 30, 12, 20), # (20, 20) | |
'3.1', (20, 30, 13, 21), # (20, 21) | |
'3.2', (20, 30, 20, 28), # (20, 28) | |
'3.3', (20, 30, 22, 30), # (22, 30) | |
'3.4', (20, 30, 22, 30), # (22, 30) | |
'3.5', (20, 30, 23, 31), # (23, 30) | |
'4.1', (13, 21, 20, 30), # (20, 21) | |
'4.2', (20, 28, 20, 30), # (20, 28) | |
'4.3', (22, 30, 20, 30), # (22, 30) | |
'4.4', (22, 30, 20, 30), # (22, 30) | |
'4.5', (23, 31, 20, 30), # (23, 30) | |
'5', (20, 30, 30, 38), # (30, 30) | |
'6', (20, 30, 31, 39) | |
-> $label, @days { | |
my $base = Date.new(2022, 1, 1); | |
my @dates = @days.map({$_ + $base - 1}); | |
my ($s, $e) = common_interval(|@dates); | |
say "$label: @days[]: ", ($e && $s) ?? "$s to $e, {$e-$s+1} days" !! "(none)"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment