I’ve been doing the Weekly
Challenges. The
latest
involved string evaluation with fallback and alphabetic rotation.
(Note that this ends today.)
Task 1: Max Str Value
You are given an array of alphanumeric string, @strings.
Write a script to find the max value of alphanumeric string in the
given array. The numeric representation of the string, if it
comprises of digits only otherwise length of the string.
I did parsing of strings that might or might not be integers
(something that varies quite a lot between languages) back in 340
part 2, so I can borrows that code here. Scala:
Build a string to number parser that will return an exception if it
fails. (I assume this is the inspiration for Rust's Option type too,
or at least that they have common ancestry.)
def toInt(in: String): Option[Int] = {
try {
Some(Integer.parseInt(in.trim))
} catch {
case e: NumberFormatException => None
}
}
Return the string's value, numeric parse if it works, otherwise
length.
def strvalue(a: String): Int = {
var n = a.length
toInt(a) match {
case Some(x) => {
n = x
}
case _ => { }
}
n
}
Find the maximum of these in the list.
def maxstrvalue(a: List[String]): Int = {
return a.map(x => strvalue(x)).max
}
Task 2: Encrypted String
You are given a string $str and an integer $int.
Write a script to encrypt the string using the algorithm - for each character $char in $str, replace $char with the $int th character after $char in the alphabet, wrapping if needed and return the encrypted string.
What I need first is a Euclidean remainder (i.e. a modulo N operation
that constrains its result to the range 0 .. N-1, as opposed to most
languages' % operator which can be positive or negative). Some
languages provide this, such as Rust's rem_euclid() method, others
don't. Raku:
sub posmod($x, $y) {
my $z = $x % $y;
while ($z < 0) {
$z += $y;
}
$z;
}
Now a function to rotate an individual character.
sub rotx($a, $offset) {
Squash down the offset to a useful number.
my $o = posmod($offset, 26);
Get a base character value for upper or lower case.
my $base;
if ($a ge 'a' && $a le 'z') {
$base = ord('a');
} elsif ($a ge 'A' && $a le 'Z') {
$base = ord('A');
} else {
If it wasn't a letter, return the input unmodified.
return $a;
}
Calculate the character code, rotate it, and shift it back to a
character.
my $c = posmod(ord($a) - $base + $o, 26) + $base;
chr($c);
}
Finally, the rotator that does this for a string is just a wrapper
round what does it for a character.
sub encryptedstring($a, $offset) {
$a.comb.map({rotx($_, $offset)}).join('');
}
Full code on
github.