aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-09-23 15:33:19 +0100
committerGitHub <noreply@github.com>2024-09-23 15:33:19 +0100
commitba597cbbcd5d0702cd0304c0bf39ec8fddb75c43 (patch)
tree48484ee6a67fbb3cb44846ae1026d957961b6611
parent5d153977cad3f0d33e3f3512f7e61f249e0ceee8 (diff)
parent44618011786dfdb682af99e11b388fc2369551f5 (diff)
downloadperlweeklychallenge-club-ba597cbbcd5d0702cd0304c0bf39ec8fddb75c43.tar.gz
perlweeklychallenge-club-ba597cbbcd5d0702cd0304c0bf39ec8fddb75c43.tar.bz2
perlweeklychallenge-club-ba597cbbcd5d0702cd0304c0bf39ec8fddb75c43.zip
Merge pull request #10895 from LubosKolouch/master
feat(challenge-288/lubos-kolouch/perl,python/): Challenge 288 LK Perl Python
-rw-r--r--challenge-288/lubos-kolouch/perl/ch-1.pl83
-rw-r--r--challenge-288/lubos-kolouch/perl/ch-2.pl99
-rw-r--r--challenge-288/lubos-kolouch/python/ch-1.py80
-rw-r--r--challenge-288/lubos-kolouch/python/ch-2.py91
4 files changed, 353 insertions, 0 deletions
diff --git a/challenge-288/lubos-kolouch/perl/ch-1.pl b/challenge-288/lubos-kolouch/perl/ch-1.pl
new file mode 100644
index 0000000000..55604105ec
--- /dev/null
+++ b/challenge-288/lubos-kolouch/perl/ch-1.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More tests => 4;
+
+=pod
+
+=head1 DESCRIPTION
+
+This script finds the closest palindrome integer to a given integer string,
+excluding the integer itself. If there are multiple palindromes with the same
+minimal absolute difference, it returns the smallest one.
+
+=head1 FUNCTIONS
+
+=head2 closest_palindrome($str)
+
+Given a string representing an integer, returns the closest palindrome as per
+the problem definition.
+
+=over 4
+
+=item * C<$str> - The input integer as a string.
+
+=back
+
+Returns the closest palindrome integer as a string.
+
+=cut
+
+sub closest_palindrome {
+ my ($n_str) = @_;
+ my $n = int($n_str);
+ my $len = length($n_str);
+ my $is_even = $len % 2 == 0;
+ my $mid = int($len / 2);
+
+ # Obtain the left part of the number
+ my $left_len = $is_even ? $mid : $mid + 1;
+ my $left = substr($n_str, 0, $left_len);
+ my @candidates;
+
+ foreach my $i (-1, 0, 1) {
+ my $new_left = int($left) + $i;
+ next if $new_left < 0;
+ my $new_left_str = "$new_left";
+
+ my $palindrome;
+ if ($is_even) {
+ $palindrome = $new_left_str . reverse($new_left_str);
+ } else {
+ $palindrome = $new_left_str . reverse(substr($new_left_str, 0, -1));
+ }
+ push @candidates, $palindrome;
+ }
+
+ # Edge cases
+ push @candidates, ('9' x ($len - 1)) if $len > 1;
+ push @candidates, '1' . ('0' x ($len - 1)) . '1';
+
+ # Remove the original number from candidates
+ @candidates = grep { $_ ne $n_str } @candidates;
+
+ # Find the closest palindrome
+ my $min_diff = undef;
+ my $closest_palindrome = undef;
+ foreach my $candidate (@candidates) {
+ my $diff = abs(int($candidate) - $n);
+ if (!defined $min_diff || $diff < $min_diff || ($diff == $min_diff && int($candidate) < int($closest_palindrome))) {
+ $min_diff = $diff;
+ $closest_palindrome = $candidate;
+ }
+ }
+ return $closest_palindrome;
+}
+
+# Unit Tests
+is(closest_palindrome("123"), "121", 'Example 1');
+is(closest_palindrome("2"), "1", 'Example 2');
+is(closest_palindrome("1400"), "1441", 'Example 3');
+is(closest_palindrome("1001"), "999", 'Example 4');
+
+done_testing();
diff --git a/challenge-288/lubos-kolouch/perl/ch-2.pl b/challenge-288/lubos-kolouch/perl/ch-2.pl
new file mode 100644
index 0000000000..4bb8e24f16
--- /dev/null
+++ b/challenge-288/lubos-kolouch/perl/ch-2.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+=pod
+
+=head1 DESCRIPTION
+
+This script finds the size of the largest contiguous block in a given rectangular matrix of 'x' and 'o'.
+
+A contiguous block consists of elements containing the same symbol which share an edge (not just a corner) with other elements in the block, and where there is a path between any two of these elements that crosses only those shared edges.
+
+=head1 FUNCTIONS
+
+=head2 largest_contiguous_block(\@matrix)
+
+Given a reference to a 2D array representing the matrix, returns the size of the largest contiguous block.
+
+=over 4
+
+=item * C<\@matrix> - Reference to a 2D array of 'x' and 'o'.
+
+=back
+
+Returns the size of the largest contiguous block as an integer.
+
+=back
+
+=cut
+
+sub largest_contiguous_block {
+ my ($matrix_ref) = @_;
+ my @matrix = @$matrix_ref;
+ my $rows = scalar @matrix;
+ my $cols = scalar @{ $matrix[0] };
+ my @visited = map { [(0) x $cols] } (0 .. $rows - 1);
+ my $max_block_size = 0;
+
+ for my $i (0 .. $rows - 1) {
+ for my $j (0 .. $cols - 1) {
+ if (!$visited[$i][$j]) {
+ my $block_size = dfs($matrix_ref, \@visited, $i, $j, $matrix[$i][$j]);
+ $max_block_size = $block_size if $block_size > $max_block_size;
+ }
+ }
+ }
+
+ return $max_block_size;
+}
+
+sub dfs {
+ my ($matrix_ref, $visited_ref, $i, $j, $symbol) = @_;
+ my @matrix = @$matrix_ref;
+ my $rows = scalar @matrix;
+ my $cols = scalar @{ $matrix[0] };
+
+ return 0 if $i < 0 || $i >= $rows || $j < 0 || $j >= $cols;
+ return 0 if $visited_ref->[$i][$j];
+ return 0 if $matrix[$i][$j] ne $symbol;
+
+ $visited_ref->[$i][$j] = 1;
+ my $size = 1;
+
+ # Explore neighbors (up, down, left, right)
+ $size += dfs($matrix_ref, $visited_ref, $i - 1, $j, $symbol);
+ $size += dfs($matrix_ref, $visited_ref, $i + 1, $j, $symbol);
+ $size += dfs($matrix_ref, $visited_ref, $i, $j - 1, $symbol);
+ $size += dfs($matrix_ref, $visited_ref, $i, $j + 1, $symbol);
+
+ return $size;
+}
+
+# Unit Tests
+my $matrix1 = [
+ ['x', 'x', 'x', 'x', 'o'],
+ ['x', 'o', 'o', 'o', 'o'],
+ ['x', 'o', 'o', 'o', 'o'],
+ ['x', 'x', 'x', 'o', 'o'],
+];
+is(largest_contiguous_block($matrix1), 11, 'Example 1');
+
+my $matrix2 = [
+ ['x', 'x', 'x', 'x', 'x'],
+ ['x', 'o', 'o', 'o', 'o'],
+ ['x', 'x', 'x', 'x', 'o'],
+ ['x', 'o', 'o', 'o', 'o'],
+];
+is(largest_contiguous_block($matrix2), 11, 'Example 2');
+
+my $matrix3 = [
+ ['x', 'x', 'x', 'o', 'o'],
+ ['o', 'o', 'o', 'x', 'x'],
+ ['o', 'x', 'x', 'o', 'o'],
+ ['o', 'o', 'o', 'x', 'x'],
+];
+is(largest_contiguous_block($matrix3), 7, 'Example 3');
+
+done_testing();
diff --git a/challenge-288/lubos-kolouch/python/ch-1.py b/challenge-288/lubos-kolouch/python/ch-1.py
new file mode 100644
index 0000000000..c9331a2058
--- /dev/null
+++ b/challenge-288/lubos-kolouch/python/ch-1.py
@@ -0,0 +1,80 @@
+import unittest
+
+
+def closest_palindrome(n_str: str) -> str:
+ """
+ Finds the closest palindrome to the given integer string, excluding itself.
+ If multiple palindromes have the same minimal absolute difference, returns the smallest one.
+
+ Args:
+ n_str (str): The input integer as a string.
+
+ Returns:
+ str: The closest palindrome integer as a string.
+ """
+ n = int(n_str)
+ length = len(n_str)
+ is_even = length % 2 == 0
+ mid = length // 2
+ left_len = mid if is_even else mid + 1
+ left = n_str[:left_len]
+ candidates = set()
+
+ for diff in (-1, 0, 1):
+ new_left = str(int(left) + diff)
+ if len(new_left) != left_len and diff != 0:
+ continue
+ if is_even:
+ pal = new_left + new_left[::-1]
+ else:
+ pal = new_left + new_left[:-1][::-1]
+ candidates.add(pal)
+
+ # Edge cases
+ candidates.add("9" * (length - 1))
+ candidates.add("1" + ("0" * (length - 1)) + "1")
+
+ candidates.discard(n_str)
+
+ min_diff = None
+ closest_pal = ""
+ for cand in candidates:
+ if cand == "":
+ continue
+ diff = abs(int(cand) - n)
+ if diff == 0:
+ continue
+ if (
+ min_diff is None
+ or diff < min_diff
+ or (diff == min_diff and int(cand) < int(closest_pal))
+ ):
+ min_diff = diff
+ closest_pal = cand
+
+ return closest_pal
+
+
+# Unit Tests
+class TestClosestPalindrome(unittest.TestCase):
+ def test_example1(self):
+ self.assertEqual(closest_palindrome("123"), "121", "Example 1")
+
+ def test_example2(self):
+ self.assertEqual(closest_palindrome("2"), "1", "Example 2")
+
+ def test_example3(self):
+ self.assertEqual(closest_palindrome("1400"), "1441", "Example 3")
+
+ def test_example4(self):
+ self.assertEqual(closest_palindrome("1001"), "999", "Example 4")
+
+ def test_large_number(self):
+ self.assertEqual(closest_palindrome("999"), "1001", "Large Number")
+
+ def test_all_nines(self):
+ self.assertEqual(closest_palindrome("9999"), "10001", "All Nines")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/challenge-288/lubos-kolouch/python/ch-2.py b/challenge-288/lubos-kolouch/python/ch-2.py
new file mode 100644
index 0000000000..6c1a36e609
--- /dev/null
+++ b/challenge-288/lubos-kolouch/python/ch-2.py
@@ -0,0 +1,91 @@
+import unittest
+from typing import List
+
+
+def largest_contiguous_block(matrix: list[list[str]]) -> int:
+ """
+ Finds the size of the largest contiguous block in a given matrix of 'x' and 'o'.
+
+ A contiguous block consists of elements containing the same symbol which share
+ an edge (not just a corner) with other elements in the block, and where there
+ is a path between any two of these elements that crosses only those shared edges.
+
+ Args:
+ matrix (List[List[str]]): The input matrix of 'x' and 'o'.
+
+ Returns:
+ int: The size of the largest contiguous block.
+ """
+ if not matrix or not matrix[0]:
+ return 0
+
+ rows = len(matrix)
+ cols = len(matrix[0])
+ visited = [[False] * cols for _ in range(rows)]
+ max_block_size = 0
+
+ def dfs(i: int, j: int, symbol: str) -> int:
+ if i < 0 or i >= rows or j < 0 or j >= cols:
+ return 0
+ if visited[i][j]:
+ return 0
+ if matrix[i][j] != symbol:
+ return 0
+
+ visited[i][j] = True
+ size = 1
+ # Explore neighbors (up, down, left, right)
+ size += dfs(i - 1, j, symbol)
+ size += dfs(i + 1, j, symbol)
+ size += dfs(i, j - 1, symbol)
+ size += dfs(i, j + 1, symbol)
+ return size
+
+ for i in range(rows):
+ for j in range(cols):
+ if not visited[i][j]:
+ block_size = dfs(i, j, matrix[i][j])
+ max_block_size = max(max_block_size, block_size)
+
+ return max_block_size
+
+
+# Unit Tests
+class TestLargestContiguousBlock(unittest.TestCase):
+ def test_example1(self):
+ matrix = [
+ ["x", "x", "x", "x", "o"],
+ ["x", "o", "o", "o", "o"],
+ ["x", "o", "o", "o", "o"],
+ ["x", "x", "x", "o", "o"],
+ ]
+ self.assertEqual(largest_contiguous_block(matrix), 11, "Example 1")
+
+ def test_example2(self):
+ matrix = [
+ ["x", "x", "x", "x", "x"],
+ ["x", "o", "o", "o", "o"],
+ ["x", "x", "x", "x", "o"],
+ ["x", "o", "o", "o", "o"],
+ ]
+ self.assertEqual(largest_contiguous_block(matrix), 11, "Example 2")
+
+ def test_example3(self):
+ matrix = [
+ ["x", "x", "x", "o", "o"],
+ ["o", "o", "o", "x", "x"],
+ ["o", "x", "x", "o", "o"],
+ ["o", "o", "o", "x", "x"],
+ ]
+ self.assertEqual(largest_contiguous_block(matrix), 7, "Example 3")
+
+ def test_empty_matrix(self):
+ self.assertEqual(largest_contiguous_block([]), 0, "Empty Matrix")
+
+ def test_single_element(self):
+ matrix = [["x"]]
+ self.assertEqual(largest_contiguous_block(matrix), 1, "Single Element")
+
+
+if __name__ == "__main__":
+ unittest.main()