Skip to content

Instantly share code, notes, and snippets.

@nd3i
Created October 30, 2022 00:40
Show Gist options
  • Save nd3i/2ef29dfc71d0bbbe38ea1e66f8a816a2 to your computer and use it in GitHub Desktop.
Save nd3i/2ef29dfc71d0bbbe38ea1e66f8a816a2 to your computer and use it in GitHub Desktop.
A scratch at PWC 187
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