Task

For each number list of 6-digit SEDOLs, calculate and append the checksum digit.



That is, given this input:

710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT
B00030

Produce this output:

7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300

Extra credit

Check each input is correctly formed, especially with respect to valid characters allowed in a SEDOL string.



Related tasks

   Luhn test
   ISIN


program Sedol;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
 
const
  SEDOL_CHR_COUNT = 6;
  DIGITS = ['0'..'9'];
  LETTERS = ['A'..'Z'];
  VOWELS = ['A', 'E', 'I', 'O', 'U'];
  ACCEPTABLE_CHRS = DIGITS + LETTERS - VOWELS;
  WEIGHTS : ARRAY [1..SEDOL_CHR_COUNT] of integer = (1, 3, 1, 7, 3, 9);
  LETTER_OFFSET = 9;
 
 
function AddSedolCheckDigit(Sedol : string) : string;
var
  iChr : integer;
  Checksum : integer;
  CheckDigit : char;
begin
  if Sedol <> uppercase(Sedol) then
    raise ERangeError.CreateFmt('%s contains lower case characters',[Sedol]);
  if length(Sedol) <> SEDOL_CHR_COUNT then
    raise ERangeError.CreateFmt('"%s" length is invalid. Should be 6 characters',[Sedol]);
 
  Checksum := 0;
  for iChr := 1 to SEDOL_CHR_COUNT do
  begin
 
    if Sedol[iChr] in Vowels then
      raise ERangeError.CreateFmt('%s contains a vowel (%s) at chr %d',[Sedol, Sedol[iChr], iChr]);
    if not (Sedol[iChr] in ACCEPTABLE_CHRS) then
      raise ERangeError.CreateFmt('%s contains an invalid chr (%s) at position %d',[Sedol, Sedol[iChr], iChr]);
 
    if Sedol[iChr] in DIGITS then
      Checksum := Checksum + (ord(Sedol[iChr]) - ord('0')) * WEIGHTS[iChr]
    else
      Checksum := Checksum + (ord(Sedol[iChr]) - ord('A') + 1 + LETTER_OFFSET) * WEIGHTS[iChr];
 
  end;
 
  Checksum := (Checksum mod 10);
  if Checksum <> 0 then
    Checksum := 10 - Checksum;
  CheckDigit := chr(CheckSum + ord('0'));
 
  Result := Sedol + CheckDigit;
end;
 
 
procedure Test(First6 : string);
begin
  writeln(First6, ' becomes ', AddSedolCheckDigit(First6));
end;
 
 
begin
  try
    Test('710889');
    Test('B0YBKJ');
    Test('406566');
    Test('B0YBLH');
    Test('228276');
    Test('B0YBKL');
    Test('557910');
    Test('B0YBKR');
    Test('585284');
    Test('B0YBKT');
    Test('B00030');
  except
    on E : Exception do
      writeln(E.Message);
  end;
  readln;
end.
 