Weekly Challenge 354
Happy New Years everyone.
Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.
Task 1: Min Abs Diff
Task
You are given an array of distinct integers.
Write a script to find all pairs of elements with the minimum absolute difference.
Rules (a,b):
-
a,bare from the given array. a < b-
b - a= min abs diff any two elements in the given array
My solution
This is relatively straight forward. I start by sorting the array numerically. I create two variables. The result list (array in Perl) will store matching pairs. min_abs_diff will store the numerical difference between the two values in a pair, it starts as None (undef in Perl).
def min_abs_diff(ints: list) -> list:
ints = sorted(ints)
min_abs_diff = None
result = []
I then use a loop that starts with 0 to two less than the length of the input list. For each iteration, I compute the difference between the value at the position and following position, using the variable abs_diff.
If the value is less than the current min_abs_diff value (or min_abs_diff is None), I update the variable and set the result array with this pair. If the value is the same, I append this pair to the result array.
for i in range(len(ints) - 1):
abs_diff = ints[i + 1] - ints[i]
if min_abs_diff is None or abs_diff < min_abs_diff:
min_abs_diff = abs_diff
result = [[ints[i], ints[i + 1]]]
elif abs_diff == min_abs_diff:
result.append([ints[i], ints[i + 1]])
return result
The Perl code follows the same logic.
Examples
$ ./ch-1.py 4 2 1 3
[[1, 2], [2, 3], [3, 4]]
$ ./ch-1.py 10 100 20 30
[[10, 20], [20, 30]]
$ ./ch-1.py -5 -2 0 3
[[-2, 0]]
$ ./ch-1.py 8 1 15 3
[[1, 3]]
$ ./ch-1.py 12 5 9 1 15
[[9, 12], [12, 15]]
Task 2: Shift Grid
Task
You are given m x n matrix and an integer, $k > 0.
Write a script to shift the given matrix $k times.
My solution
For input from the command line, I take a JSON string as the first value (representing the matrix) and the second value as k.
These are the steps I take to complete the task.
- Ensure that the matrix has the same number of columns for each row.
- Flatten the list of lists (array of arrays in Perl) into a single list, stored as the
flattened_listvariable. - If
kis not between 0 and one less than the array, take the modulus of the length offlatten_list. For example iskis7and there are five items in the flattened list, change it to2. This will achieve the same result. - Take the last
kelements from the list, and append them to the front. In the Python solution, this is stored asrotated_list. - Rebuild the matrix from this new list as the variable
new_matrix.
def shift_grid(matrix: list[list[int]], k: int) -> list[list[int]]:
row_length = len(matrix[0])
for row in matrix:
if len(row) != row_length:
raise ValueError("All rows must have the same length")
flattened_list = [num for row in matrix for num in row]
k = k % len(flattened_list)
rotated_list = flattened_list[-k:] + flattened_list[:-k]
new_matrix = []
for i in range(0, len(rotated_list), row_length):
new_matrix.append(rotated_list[i:i + row_length])
return new_matrix
Since Perl allows you to remove and append to the same list in a single operation, I use the splice function to achieve this.
sub main ( $matrix_json, $k ) {
my $matrix = decode_json($matrix_json);
my $row_length = scalar( @{ $matrix->[0] } );
foreach my $row (@$matrix) {
if ( scalar(@$row) != $row_length ) {
die "All rows must have the same length\n";
}
}
my @flattened_list = map { @$_ } @$matrix;
$k = $k % scalar(@flattened_list);
splice( @flattened_list, 0, 0, splice( @flattened_list, -$k ) );
my @new_matrix = ();
for ( my $i = 0 ; $i <= $#flattened_list ; $i += $row_length ) {
push @new_matrix, [ @flattened_list[ $i .. $i + $row_length - 1 ] ];
}
say '('
. join( ",\n ",
map { '[' . join( ', ', @$_ ) . ']' } @new_matrix )
. ',)';
}
Examples
$ ./ch-2.py "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]" 1
([9, 1, 2],
[3, 4, 5],
[6, 7, 8],)
$ ./ch-2.py "[[10, 20], [30, 40]]" 1
([40, 10],
[20, 30],)
$ ./ch-2.py "[[1, 2], [3, 4], [5, 6]]" 1
([6, 1],
[2, 3],
[4, 5],)
$ ./ch-2.py "[[1, 2, 3], [4, 5, 6]]" 5
([2, 3, 4],
[5, 6, 1],)
$ ./ch-2.py "[[1, 2, 3, 4]]" 1
([4, 1, 2, 3],)
Top comments (0)