aboutsummaryrefslogtreecommitdiff
path: root/challenge-187/izem
diff options
context:
space:
mode:
author冯昶 <fengchang@novel-supertv.com>2022-10-24 17:44:04 +0800
committer冯昶 <fengchang@novel-supertv.com>2022-10-24 17:44:04 +0800
commit7783ecb7dad2ae5ea3d3022a13e3901c196c4154 (patch)
treefa408d0b19c541602d81799c8a13eea61df2cb8f /challenge-187/izem
parenta406c6935f88c7afa04a707a2611ebe4fe4eadae (diff)
parentbb06570f6b1634ca14bfd08927f3bfc6c052c494 (diff)
downloadperlweeklychallenge-club-7783ecb7dad2ae5ea3d3022a13e3901c196c4154.tar.gz
perlweeklychallenge-club-7783ecb7dad2ae5ea3d3022a13e3901c196c4154.tar.bz2
perlweeklychallenge-club-7783ecb7dad2ae5ea3d3022a13e3901c196c4154.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'challenge-187/izem')
-rw-r--r--challenge-187/izem/perl/ch-1.pl88
-rw-r--r--challenge-187/izem/perl/ch-2.pl64
-rw-r--r--challenge-187/izem/python/ch-1.py60
-rw-r--r--challenge-187/izem/python/ch-2.py56
4 files changed, 268 insertions, 0 deletions
diff --git a/challenge-187/izem/perl/ch-1.pl b/challenge-187/izem/perl/ch-1.pl
new file mode 100644
index 0000000000..194df39531
--- /dev/null
+++ b/challenge-187/izem/perl/ch-1.pl
@@ -0,0 +1,88 @@
+
+=head1
+
+Week 187:
+
+ https://theweeklychallenge.org/blog/perl-weekly-challenge-187
+
+Task #1: Days Together
+
+ Two friends, Foo and Bar gone on holidays seperately to the same city.
+ You are given their schedule i.e. 'start date' and 'end date'.
+ To keep the task simple, the date is in the form 'DD-MM' and all dates
+ belong to the same calendar year i.e. between '01-01' and '31-12'. Also
+ the year is 'non-leap year'. Also both dates are inclusive.
+ Write a script to find out for the given schedule, how many days they
+ spent together in the city, if at all.
+
+=cut
+
+use strict;
+use warnings;
+use feature 'say';
+
+use POSIX qw(strftime mktime);
+use List::Util qw(min max);
+use Test::More;
+use Data::Dumper;
+
+my $NONE_LEAP_YEAR = 2022 - 1900;
+$Data::Dumper::Indent = 0;
+
+my @cases = (
+ {
+ 'args' => [
+ { SD => '12-01', ED => '20-01' }, { SD => '15-01', ED => '18-01' }
+ ],
+ 'expected' => 4
+ },
+ {
+ 'args' => [
+ { SD => '02-03', ED => '12-03' }, { SD => '13-03', ED => '14-03' }
+ ],
+ 'expected' => 0
+ },
+ {
+ 'args' => [
+ { SD => '02-03', ED => '12-03' }, { SD => '11-03', ED => '15-03' }
+ ],
+ 'expected' => 2
+ },
+ {
+ 'args' => [
+ { SD => '30-03', ED => '05-04' }, { SD => '28-03', ED => '02-04' }
+ ],
+ 'expected' => 4
+ },
+);
+
+for my $case (@cases) {
+ cmp_ok( daysTogether( @{ $case->{'args'} } ),
+ '==', $case->{'expected'}, Dumper( $case->{'args'} ) );
+}
+
+done_testing( scalar @cases );
+
+sub toDayOfYear {
+ my ($date) = @_;
+ my ( $day, $mon ) = $date =~ /^(\d\d)-(\d\d)$/;
+ ( $day, $mon ) = ( int($day), int($mon) - 1 );
+ return int(
+ strftime(
+ "%j", localtime( mktime( 0, 0, 0, $day, $mon, $NONE_LEAP_YEAR ) )
+ )
+ );
+}
+
+sub daysTogether {
+ my ( $foo, $bar ) = @_;
+ my ( $foo_sd, $foo_ed ) =
+ ( toDayOfYear( $foo->{SD} ), toDayOfYear( $foo->{ED} ) );
+ my ( $bar_sd, $bar_ed ) =
+ ( toDayOfYear( $bar->{SD} ), toDayOfYear( $bar->{ED} ) );
+ if ( $foo_sd > $bar_ed || $foo_ed < $bar_sd ) {
+ return 0;
+ }
+
+ return min( $foo_ed, $bar_ed ) - max( $foo_sd, $bar_sd ) + 1;
+}
diff --git a/challenge-187/izem/perl/ch-2.pl b/challenge-187/izem/perl/ch-2.pl
new file mode 100644
index 0000000000..db3a556611
--- /dev/null
+++ b/challenge-187/izem/perl/ch-2.pl
@@ -0,0 +1,64 @@
+
+=head1
+
+Week 187:
+
+ https://theweeklychallenge.org/blog/perl-weekly-challenge-187/#TASK2
+
+Task #2: Magical Triplets
+
+ You are given a list of positive numbers, @n, having at least 3 numbers.
+ Write a script to find the triplets (a, b, c) from the given list that
+ satisfies the following rules
+ i.e. 'a + b > c', 'b + c > a', 'a + c > b' and 'a + b + c' is maximum.
+ In case, you end up with more than one triplets having the maximum then
+ pick the triplet where 'a >= b >= c'.
+
+=cut
+
+use strict;
+use warnings;
+use feature 'say';
+
+use List::Util qw/sum/;
+use Test::More;
+use Data::Dumper;
+
+$Data::Dumper::Indent = 0;
+
+my @cases = (
+ [ [ 1, 2, 3, 2 ], [ 3, 2, 2 ] ],
+ [ [ 1, 3, 2 ], [] ],
+ [ [ 1, 1, 2, 3 ], [] ],
+ [ [ 2, 4, 3 ], [ 4, 3, 2 ] ],
+);
+for my $case (@cases) {
+ is_deeply( magicalTriplets( @{ $case->[0] } ), $case->[1], Dumper( $case->[0] ) );
+}
+
+done_testing( scalar @cases );
+
+sub magicalTriplets {
+ my @numbers = @_;
+ my @triplet = ();
+ for ( my $i = 0 ; $i <= $#numbers ; $i++ ) {
+ for ( my $j = 0 ; $j <= $#numbers ; $j++ ) {
+ next if $j == $i;
+ for ( my $k = 0 ; $k < $#numbers ; $k++ ) {
+ next if $k == $i || $k == $j;
+ my @cur_triplet = ( $numbers[$i], $numbers[$j], $numbers[$k] );
+ next unless two_nums_bigger(@cur_triplet) && sum(@cur_triplet) >= sum(@triplet);
+ next if sum(@cur_triplet) == sum(@triplet)
+ && ( $numbers[$i] < $numbers[$j] || $numbers[$j] < $numbers[$k] );
+ @triplet = @cur_triplet;
+ }
+ }
+ }
+ return \@triplet;
+}
+
+sub two_nums_bigger {
+ my ( $a, $b, $c ) = @_;
+ return $a + $b > $c && $b + $c > $a && $a + $c > $b ? 1 : 0;
+}
+
diff --git a/challenge-187/izem/python/ch-1.py b/challenge-187/izem/python/ch-1.py
new file mode 100644
index 0000000000..3e5cbdd887
--- /dev/null
+++ b/challenge-187/izem/python/ch-1.py
@@ -0,0 +1,60 @@
+"""Perl weekly challenge 187 - Task 1: Days Together.
+
+Two friends, Foo and Bar gone on holidays seperately to the same city.
+You are given their schedule i.e. 'start date' and 'end date'.
+To keep the task simple, the date is in the form 'DD-MM' and all dates
+belong to the same calendar year i.e. between '01-01' and '31-12'. Also
+the year is 'non-leap year'. Also both dates are inclusive.
+Write a script to find out for the given schedule, how many days they
+spent together in the city, if at all.
+
+https://theweeklychallenge.org/blog/perl-weekly-challenge-187/
+"""
+import datetime
+import unittest
+
+NONE_LEAP_YEAR = 2022
+
+
+def to_day_of_year(day_mon: str, year: int = NONE_LEAP_YEAR) -> int:
+ """Convert a "DD-MM" date string to the day of the year.
+
+ All dates belong to the same calendar year, and it isn't a "leap year".
+
+ :param day_mon: date in "DD-MM" format
+ :param year: year. default is a non-leap year
+ :return: day of the year
+ """
+ date = datetime.date(year, int(day_mon[3:]), int(day_mon[0:2]))
+ return int(f"{date:%j}")
+
+
+def days_together(foo: dict, bar: dict) -> int:
+ """Find how many days are spent together for the given schedules.
+
+ :param foo: schedule of 1st person
+ :param bar:schedule of 2nd person
+ :return: number of pent together days
+ """
+ foo_sd, foo_ed = to_day_of_year(foo['SD']), to_day_of_year(foo['ED'])
+ bar_sd, bar_ed = to_day_of_year(bar['SD']), to_day_of_year(bar['ED'])
+ if foo_sd > bar_ed or foo_ed < bar_sd:
+ return 0
+ return min(foo_ed, bar_ed) - max(foo_sd, bar_sd) + 1
+
+
+class TestDaysTogether(unittest.TestCase):
+
+ def test_days_together(self):
+ cases = (
+ {'args': ({'SD': '12-01', 'ED': '20-01'}, {'SD': '15-01', 'ED': '18-01'}), 'expected': 4},
+ {'args': ({'SD': '02-03', 'ED': '12-03'}, {'SD': '13-03', 'ED': '14-03'}), 'expected': 0},
+ {'args': ({'SD': '02-03', 'ED': '12-03'}, {'SD': '11-03', 'ED': '15-03'}), 'expected': 2},
+ {'args': ({'SD': '30-03', 'ED': '05-04'}, {'SD': '28-03', 'ED': '02-04'}), 'expected': 4},
+ )
+ for case in cases:
+ self.assertEqual(days_together(*case['args']), case['expected'], str(case['args']))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/challenge-187/izem/python/ch-2.py b/challenge-187/izem/python/ch-2.py
new file mode 100644
index 0000000000..2585ae38e0
--- /dev/null
+++ b/challenge-187/izem/python/ch-2.py
@@ -0,0 +1,56 @@
+"""Perl weekly challenge 187 - Task #2: Magical Triplets.
+
+You are given a list of positive numbers, @n, having at least 3 numbers.
+Write a script to find the triplets (a, b, c) from the given list that
+satisfies the following rules
+i.e. 'a + b > c', 'b + c > a', 'a + c > b' and 'a + b + c' is maximum.
+In case, you end up with more than one triplets having the maximum then
+pick the triplet where 'a >= b >= c'.
+
+https://theweeklychallenge.org/blog/perl-weekly-challenge-187/#TASK2
+"""
+import unittest
+from typing import Iterable
+
+
+def magical_triplets(numbers: Iterable[int]) -> Iterable | None:
+ """Return most magical triplet from given numbers.
+
+ :param numbers: numbers to make triplets (at least 3)
+ :return: most magical triplet (or empty)
+ """
+ if len(numbers) < 3:
+ raise ValueError("Input list should be at least 3 numbers.")
+
+ triplet = (0,)
+ for i, a in enumerate(numbers):
+ for j, b in enumerate(numbers):
+ if j == i:
+ continue
+ for k, c in enumerate(numbers):
+ if k == i or k == j:
+ continue
+ if a + b > c and b + c > a and a + c > b \
+ and sum((a, b, c)) >= sum(triplet):
+ if sum((a, b, c)) == sum(triplet) and not a >= b >= c:
+ continue
+ triplet = (a, b, c)
+
+ return triplet if len(triplet) == 3 else None
+
+
+class TestMagicalTriplets(unittest.TestCase):
+
+ def test_magical_triplets(self):
+ cases = (
+ ((1, 2, 3, 2), (3, 2, 2)),
+ ((1, 3, 2), None),
+ ((1, 1, 2, 3), None),
+ ((2, 4, 3), (4, 3, 2)),
+ )
+ for case in cases:
+ self.assertEqual(magical_triplets(case[0]), case[1], f"Input: {case[0]}")
+
+
+if __name__ == '__main__':
+ unittest.main()