I’ve been doing the Weekly
Challenges. The
latest
involved . (Note that this ends today.)
Task 1: Second Largest Digit
You are given an alphanumeric string.
Write a script to find the second largest distinct digit in the
given string. Return -1 if none found.
So: find the digits, make a list of distinct ones, return the second
largest. In Perl:
sub secondlargestdigit($a) {
Split the string, find the digits, and put them into a pseudo-set.
my %p = map {$_ => 1} grep /[0-9]/, split '', $a;
Sort the entries of that pseudo-set in descending order.
my @k = reverse sort keys %p;
If we have enough of them, return the second, otherwise -1.
if (scalar @k > 1) {
$k[1];
} else {
-1;
}
}
PostScript is pleasingly straightforward (though it relies on some of
my library functions).
/secondlargestdigit {
Get a list.
s2a
Filter it for digits.
{
dup 48 ge exch 57 le and
} filter
Take just the unique digits.
toset keys
Sort in reverse order.
quicksort reverse
If it's long enough, return the value of the second digit, otherwise
-1.
dup length 1 gt {
1 get 48 sub
} {
pop -1
} ifelse
} bind def
Task 2: Sum of Words
You are given three strings consisting of lower case English letters
"a" to "j" only. The letter value of a = 0, b = 1, c = 3, etc.
Write a script to find if sum of first two strings return the third
string.
The examples of leading "a" (i.e. leading zero) make it clear that
there are multiple allowable representations of any given number.
Therefore I write only one direction of conversion, from this
representation to an integer, and then compare integer values.
In Lua:
function l2n(a)
Establish a reference value for "a".
local a0 = string.byte("a")
Initialise the accumulator.
local t = 0
For each "digit",
for _, c in ipairs(split(a)) do
Multiply the previous accumulator value by 10, and add the new digit's
value.
t = t * 10 + string.byte(c) - a0
end
return t
end
Then the target function becomes trivial:
function sumofwords(a, b, c)
return l2n(a) + l2n(b) == l2n(c)
end
Again I find the PostScript pleasing (and I'm always glad not to have
to use local variables).
/l2n {
Put a zero accumulator on the stack below the input string.
0 exch
For each character of that string,
s2a {
Swap with the accumulator, multiply it by 10, then add character and
subtract "a" (PostScript only works in ASCII as far as I know,
certainly on any system I have access to),
exch
10 mul
add
97 sub
} forall
} bind def
Then it's just a matter of converting all the inputs and checking for
equality.
/sumofwords {
3 1 roll
l2n exch
l2n exch
add
exch
l2n eq
} bind def
Full code on
codeberg.