The Bear's Den

Enter at your own risk

Justified Order

Task 1: Text Justifier

Submitted by: Mohammad Sajid Anwar


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.

Example 1

Input: $str = "Hi", $width = 5
Output: "*Hi**"

Text length = 2, Width = 5
Need 3 padding characters total
Left padding: 1 star, Right padding: 2 stars

Example 2

Input: $str = "Code", $width = 10
Output: "***Code***"

Text length = 4, Width = 10
Need 6 padding characters total
Left padding: 3 stars, Right padding: 3 stars

Example 3

Input: $str = "Hello", $width = 9
Output: "**Hello**"

Text length = 5, Width = 9
Need 4 padding characters total
Left padding: 2 stars, Right padding: 2 stars

Example 4

Input: $str = "Perl", $width = 4
Output: "Perl"

No padding needed

Example 5

Input: $str = "A", $width = 7
Output: "***A***"

Text length = 1, Width = 7
Need 6 padding characters total
Left padding: 3 stars, Right padding: 3 stars

Example 6

Input: $str = "", $width = 5
Output: "*****"

Text length = 0, Width = 5
Entire output is padding

Solution

Instead of calculating the padding prefix and suffix lengths’ and concatenating prefix, string and suffix, I’ll create a buffer in the desired length that is initially filled with the padding character and where the string is placed into its right position.

Perl

Use substr as an lvalue and assign the string.

use strict;
use warnings;
use experimental 'signatures';

sub text_justifier ($str, $width) {
    my $buf = '*' x $width;
    substr($buf, ($width - length($str)) / 2, length($str)) = $str;

    $buf;
}

See the full solution to task 1.

J

J has an adverb } (amend) that acts similar to Perl’s substr. There is a principal difference: it does not operate on position and length, but requires a list of all index positions that are subject to modification.

Using the right argument as the new values (]), calculate the indices ((i.@] + [: <. 2 %~ -) #@]) and use a string made of asterisks as the to-be-modified buffer (#&'*'@[).

TextJustifier =: ]`((i.@] + [: <. 2 %~ -) #@])`(#&'*'@[) }

echo 5 TextJustifier 'Hi'

See the full solution.

Task 2: Word Sorter

Submitted by: Mohammad Sajid Anwar


You are give a sentence.

Write a script to order words in the given sentence alphabetically but keeps the words themselves unchanged.

Example 1

Input: $str = "The quick brown fox"
Output: "brown fox quick The"

Example 2

Input: $str = "Hello    World!   How   are you?"
Output: "are Hello How World! you?"

Example 3

Input: $str = "Hello"
Output: "Hello"

Example 4

Input: $str = "Hello, World! How are you?"
Output: "are Hello, How World! you?"

Example 5

Input: $str = "I have 2 apples and 3 bananas!"
Output: "2 3 and apples bananas! have I"


Solution

Perl

Split the sentence into words, perform a Schwartzian transformation to sort the words by their folded case and re-join them.

use strict;
use warnings;

sub word_sorter {
    join ' ', map $_->[1],
        sort {$a->[0] cmp $b->[0]} map [fc, $_], split /\s+/, shift;
}

See the full solution to task 2.

J

Sorting in J (/:) is different: it operates on two lists, where one list is used to calculate a permutation that would bring this list into order and then applies this permutation to a second list. To simply sort a single list, it has to be used for both arguments. The Schwartzian transformation from Perl is the standard case in J.

Otherwise the solution is the same: split the sentence into words, sort by lower case and re-join.

WordSorter =: (' ' joinstring ] /: tolower&.>)@(' ' cutopen ,&' ')

echo WordSorter 'The quick brown fox'

See the full solution.