TL;DR

On with TASK #2 from The Weekly Challenge #204. Enjoy!

# The challenge

You are given a matrix (m x n) and two integers (r) and (c).

Write a script to reshape the given matrix in form (r x c) with the original value in the given matrix. If you can’t reshape print 0.

Example 1

Input: [ 1 2 ]
[ 3 4 ]

$matrix = [ [ 1, 2 ], [ 3, 4 ] ]$r = 1
$c = 4 Output: [ 1 2 3 4 ]  Example 2 Input: [ 1 2 3 ] [ 4 5 6 ]$matrix = [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]
$r = 3$c = 2

Output: [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]

[ 1 2 ]
[ 3 4 ]
[ 5 6 ]


Example 3

Input: [ 1 2 ]

$matrix = [ [ 1, 2 ] ]$r = 3
$c = 2 Output: 0  # The questions Is an empty matrix allowed? How is it shaped (e.g. does it even have a row, but empty)? Should we check that the input matrix does indeeded contain all elements by just looking at its rows and the number of columns in the first row? # The solution The basic idea I wanted to implement is to do a few pre-checks, but then turn the input matrix into a stream of elements that I can then take row by row. For me, stream of elements basically means iterator, so here’s my Perl take: #!/usr/bin/env perl use v5.24; use warnings; use experimental 'signatures'; no warnings 'experimental::signatures'; use Data::Dumper; my$reshaped = reshape_matrix([ [ 1 .. 3], [ 4 .. 6] ], 3, 2);
say $reshaped ? Dumper($reshaped) : 0;

sub reshape_matrix ($matrix,$r, $c) { my$needed = $r *$c;
my $available =$matrix->@*;
$available *=$matrix->[0]->@* if $available; return 0 if$needed != $available; my$it = elements_it($matrix); return [ map { [ map {$it->() } 1 .. $c ] } 1 ..$r ];
}

sub elements_it ($aoa) { my ($r, $c) = (0, 0); return sub { while ('necessary') { return if$r > $aoa->$#*;
my $row =$aoa->[$r]; if ($c > $row->$#*) {
++$r;$c = 0;
next;
}
return $row->[$c++];
}
};
}


Turning this idea into Raku leads to something quite interesting and idiomatic:

#!/usr/bin/env raku
use v6;
sub MAIN {
my $reshaped = reshape-matrix([ [ 1 .. 3], [ 4 .. 6] ], 3, 2); put$reshaped ?? $reshaped.gist !! 0; } sub reshape-matrix ($matrix, $r,$c) {
my $needed =$r * $c; my$available = $matrix.elems;$available *= $matrix[0].elems if$available;
return Nil if $needed !=$available;

# https://stackoverflow.com/questions/41648119/how-can-i-completely-flatten-a-list-of-lists-of-lists/41649110#41649110
return [$matrix[*;*].rotor($c)];
}


Instead of building an iterator, here we’re leveraging one of the hints here to flatten the input matrix into a single sequence, then use rotor (for the second time in a single weekly challenge, wow!) to take rows out of it.

I wonder if I’ll remember about the two-dimensional matrix flattening trick \$matrix[*;*] next time!

Cheers and stay safe!
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 1, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.37939339876174927, "perplexity": 5805.011715906381}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2023-14/segments/1679296949506.62/warc/CC-MAIN-20230330225648-20230331015648-00629.warc.gz"}