Perl Weekly Challenge 256: Merge Strings
These are some answers to the Week 256, Task 2, of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Spoiler Alert: This weekly challenge deadline is due in a few days from now (on February 18, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.
Task 2: Merge Strings
You are given two strings, $str1
and $str2
.
Write a script to merge the given strings by adding in alternative order starting with the first string. If a string is longer than the other then append the remaining at the end.
Example 1
Input: $str1 = "abcd", $str2 = "1234"
Output: "a1b2c3d4"
Example 2
Input: $str1 = "abc", $str2 = "12345"
Output: "a1b2c345"
Example 3
Input: $str1 = "abcde", $str2 = "123"
Output: "a1b2c3de"
Merge Strings in Raku
For such a task, the first thing that comes to mind in Raku is to use the built-in zip routine, which iterates through each of the input lists synchronously, 'Zipping' them together, so that elements are grouped according to their input list index, in the order that the lists are provided. The slight problem, though, is that, if the input lists have an unequal number of elements, then zip
terminates once the shortest input list is exhausted, and trailing elements from longer input lists are discarded. This is not what we want here, since the task says: "If a string is longer than the other, then append the remaining at the end." We could still use zip
and add at the end the left-overs from the longer list, but we can do better.
Raku has another built-in similar routine, roundrobin, which does not terminate once one or more of the input lists become exhausted, but proceeds until all elements from all lists have been processed. This is exactly what we need here, and the work is done with just one code-line.
sub merge-strings ($str1, $str2) {
my $res = join "", roundrobin $str1.comb, $str2.comb, :slip;
return $res;
}
my @tests = <abcd 1234>, <abc 12345>, <abcde 123>;
for @tests -> @test {
printf "%-12s => ", "@test[]";
say merge-strings @test[0], @test[1];
}
This program displays the following output:
$ raku ./merge-strings.raku
abcd 1234 => a1b2c3d4
abc 12345 => a1b2c345
abcde 123 => a1b2c3de
Merge Strings in Perl
Perl doesn't have built-in routines such as zip
or roundrobin
, so we need to build the result manually. We loop over the indexes of the longer list and add the items from both lists (or an empty string if a value is not defined for a given index).
use strict;
use warnings;
use feature 'say';
sub merge_strings {
my ($str1, $str2) = @_;
my @let1 = split //, $str1;
my @let2 = split //, $str2;
my $end = scalar @let1 > scalar @let2 ? $#let1 : $#let2;
my @result = map { ($let1[$_] // "") .
($let2[$_] // "") } 0..$end;
return join "", @result;
}
my @tests = ([<abcd 1234>], [<abc 12345>], [<abcde 123>]);
for my $test (@tests) {
printf "%-12s => ", "@$test";
say merge_strings $test->[0], $test->[1];
}
This program displays the following output:
$ perl ./merge-strings.pl
abcd 1234 => a1b2c3d4
abc 12345 => a1b2c345
abcde 123 => a1b2c3de
Merge Strings in Julia
Yet a slightly different method. We loop over the indexes of the shorter list and add the items from both lists. At the end, we add at the end the trailing items from the longer list.
using Printf
function merge_strings(str1, str2)
result = []
let1 = split(str1, "")
let2 = split(str2, "")
size1 = size(let1, 1)
size2 = size(let2, 1)
last_i = size1 > size2 ? size2 : size1
for i in 1:last_i
push!(result, let1[i], let2[i])
end
if size1 > size2
for i in last_i + 1:size1
push!(result, let1[i])
end
else
for i in last_i + 1:size2
push!(result, let2[i])
end
end
return join(result, "");
end
tests = [["abcd", "1234"], ["abc", "12345"], ["abcde", "123"]]
for test in tests
@printf "%-18s => " "$test"
println(merge_strings(test[1], test[2]))
end
This program displays the following output:
$ julia ./merge-strings.jl
["abcd", "1234"] => a1b2c3d4
["abc", "12345"] => a1b2c345
["abcde", "123"] => a1b2c3de
Wrapping up
The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on February 25, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment