# RabbitFarm

### 2021-10-24

#### Caught in the Middle With SEDOL

*The examples used here are from The Weekly Challenge problem statement and demonstrate
the working solution.*

## Part 1

*You are given an integer. Write a script find out the middle 3-digits of the given
integer, if possible, otherwise show a sensible error message.*

### Solution

```
use strict;
use warnings;
use POSIX;
sub middle_3{
my($i) = @_;
$i = abs($i);
my $length = length($i);
return "even number of digits" if $length % 2 == 0;
return "too short" if $length < 3;
my $middle = ceil($length / 2);
return substr($i, $middle - 2, 3);
}
MAIN:{
print middle_3(1234567) . "\n";
print middle_3(-123) . "\n";
print middle_3(1) . "\n";
print middle_3(10) . "\n";
}
```

### Sample Run

```
$ perl perl/ch-1.pl
345
123
too short
even number of digits
```

### Notes

Maybe on of the more interesting things about this is just what we consider the middle 3. Truly it only makes sense for an integer with an odd number of digits. But could we have stretched the idea to allow for an even number of digits, perhaps with some left padding? Perhaps, but here we don't. So all integers with only 1 or 2 digits are discarded as are those with an even number of digits. Negative numbers are allowed, but we do not consider the minus sign in determining the middle.

## Part 2

*You are given 7-characters alphanumeric SEDOL. Write a script to validate the given
SEDOL. Print 1 if it is a valid SEDOL otherwise 0.*

### Solution

```
use strict;
use warnings;
use boolean;
sub is_sedol{
my($sedol) = @_;
my $base = substr($sedol, 0, 6);
my $check_digit = substr($sedol, 6, 1);
##
# check length
##
return false if length($sedol) != 7;
##
# check for alphanumerics only
##
my $test_base = $base;
$test_base =~ tr/[0-9][B-Z]//d;
return false if $test_base;
##
# confirm the check_digit
##
return false if $check_digit != compute_check_digit($base);
##
# all tests passed!
##
return true;
}
sub compute_check_digit{
my($base) = @_;
my @chars = split(//, $base);
my @weights = (1, 3, 1, 7, 3, 9),
my $sum = 0;
do{
my $c = ord(shift @chars);
if($c >= 66 && $c <= 90){
$sum += (($c - 64 + 9) * shift @weights);
}
if($c >= 48 && $c <= 57){
$sum += (($c - 48) * shift @weights);
}
}while(@chars);
return (10 - ($sum % 10)) % 10
}
MAIN:{
print is_sedol(2936921) . "\n";
print is_sedol(1234567) . "\n";
print is_sedol("B0YBKL9") . "\n";
}
```

### Sample Run

```
1
0
1
```

### Notes

The rules around SEDOLs are a bit more complex than this problem lets on. I won't recount them all here, but suffice to say we are dealing with a quite idealized set of validations here. For example, prior to 2004 only numerals were allowed, but since then letters are allowed. But only a numeral can follow a letter. Again, though, those are only rules that apply for a certain time range.

Here we are just checking on length, whether or not the SEDOl contains all numerals and/or (uppercase) letter, and the checksum validation.

## References

posted at: 15:17 by: Adam Russell | path: /perl | permanent link to this entry