Idiomatic Perl solutions to the weekly challenge 324

Task 1:

You are given an array of integers and two integers $r amd $c.

Write a script to create two dimension array having $r rows and $c columns using the given array.

I'm sure there are modules to facilitate this, but I'm not sure any provides more readability than simply:

my @out = map [splice @ints, 0, $c], 1..$r;

splice array, 0, N, () is an easy way to loop over an array in fixed size chunks. Often you will see it in this form:

while (my @chunk = splice @array, 0, 1000) {

though it is important to remember it empties the original array; copy first if needed.

full script

Task 2:

You are given an array of integers.

Write a script to return the sum of total XOR for every subset of given array.

This is essentially a combinations problem. Perl has many modules for combinations (and permutations); here is a short survey of some of them. In production code, I would likely use Algorithm::Combinatorics for this.

But for a quick and dirty solution, I'd use Perl's builtin that does combinations: glob:

say List::Util::sum map eval, glob 0 . join '', map "{^$_,}", @array

(Obviously when using eval, validating the data is as expected is important.)

Here we take an array such as 5,1,6 and form a string to glob that provides all combinations, xor'd: "0{^5,}{^1,}{^6,}". These look like:

$ perl -E'say for glob "0{^5,}{^1,}{^6,}"'
0^5^1^6
0^5^1
0^5^6
0^5
0^1^6
0^1
0^6
0

Then simply eval and sum them. Yes, eval's operand defaults to $_.

When using glob, be very careful in scalar context, where it will take an initial argument and iterate over the results of that argument for each call thereafter until the results are exhausted and it returns undef, with the later arguments not actually used.

full script

See you next week.