I’ve been doing the Weekly
Challenges. The
latest
involved string padding and word rearrangement. (Note that this ends
today.)
Task 1: Text Justifier
You are given a string and a width.
Write a script to return the string that centers the text within
that width using asterisks * as padding.
I see essentially two possible approaches to this: (1) take the
initial word and prepend/append asterisks to it, or (2) start with a
field of asterisks and insert the word at the right spot. I ended up
doing number 2 because it seemed like more fun. In Lua:
(plus "split" and "join" standard functions which I won't include
here)
function textjustifier(intxt, width)
Build the output array.
local working = {}
for _ = 1, width do
table.insert(working, "*")
end
Work out where to start the string insertion.
local offset = math.floor((width - #intxt) / 2)
Copy it, one character at a time.
for i, c in ipairs(split(intxt)) do
working[i + offset] = c
end
Join the array into a string and return it.
return join(working)
end
The other languages' code looks similar.
Task 2: Word Sorter
You are given a sentence.
Write a script to order words in the given sentence alphabetically
but keeps the words themselves unchanged.
Three steps of course: split on spaces, sort, combine. Split and
combine are generally library functions, and if the language doesn't
have them I've written versions that serve. (Some versions of split
elide zero-length fragments, e.g. the gap between two spaces, while
others don't).
Sorting case-insensitively is a little more interesting, because it
calls for a sort by key: i.e. each value to be sorted is transformed
to a new value (here it's the lower-case version), those are sorted,
and the sequence of reordersings is applied to the original.
Some languages have this already, such as Raku and Rust (and of course
my PostScript library includes it too). For languages that don't, such
as Perl and Javascript, it gets a bit more fiddly and I do an indirect
sort.
Directly, in Raku:
sub wordsorter($a) {
Split the words (deleting zero-length words)
my @w = $a.split(/\s+/).grep({$_ ne ""});;
Sort them by the lower-cased versions.
@w = @w.sort({.lc});
Recombine and return the list.
@w.join(' ');
}
Contrastingly in Perl:
sub wordsorter($a) {
Generate the list of words.
my @w = split ' ', $a;
Generate the list of lower-case words.
my @wl = map {lc($_)} @w;
Take a series of integers, and arrange that using the lower-cased words
as a basis for comparison.
my @i = sort {$wl[$::a] cmp $wl[$::b]} (0 .. $#w);
With that rearranged list of integers, rebuild the list of original
words in the right order.
@w = map {$w[$_]} @i;
Combine and return.
join(' ', @w);
}
This is the last time I'll contribute to the Weekly Challenge on
GitHub, which is after all owned by a company abetting genocide that's
headquartered in a rogue state. I will continue to do the challenges
unofficially, and upload my code to my Codeberg pages in case anyone
wants to look at it.
Full code on
github.