Peter
Peter Campbell Smith

Three in the middle
and stock answer

Weekly challenge 135 — 18 October 2021

Week 135 - 18 Oct 2021

Task 2

Task — Validate SEDOL

You are given a 7-character alphanumeric SEDOL. Write a script to validate the given SEDOL. Print 1 if it is a valid SEDOL otherwise 0. For more information about SEDOL, please checkout the Wikipedia page.

Examples


Example 1
Input: $SEDOL = '2936921'
Output: 1

Example 2
Input: $SEDOL = '1234567'
Output: 0

Example 3
Input: $SEDOL = 'B0YBKL9'
Output: 1

Analysis

SEDOL stands for the Stock Exchange Daily Official List, a global database of over 108 securities and financial instruments. Each item in the list is identified by a 7-character identifier, which is referred to informally as a SEDOL.

A valid SEDOL:

  1. is 7 characters long
  2. has the first 6 chars alphanumeric but with no vowels
  3. has a check digit 0-9 as the last character
  4. has a weighted sum of all 7 characters which is a multiple of 10

The weights applied to the 7 characters are (1, 3, 1, 7, 3, 9, 1), and the values given to alphabetic characters are B = 11 to Z = 35, ie ord($char) - ord('A') + 10.

Validation therefore consists of checking the 4 conditions listed above.

I have assumed that the task does not include validation that the SEDOL refers to an actual or potential entry in the Stock Exchange Daily Official List.

Try it 

Try running the script with any input:



example: B1VZ0M2

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2021-10-18
# PWC 135 task 2

use v5.20;
use warnings;
use strict;

my (@weights, $sedol, @tests);

@weights = (1, 3, 1, 7, 3, 9, 1);   # weight of each char in the checksum (from Wikipedia)

# check some known valid SEDOLs (from London Stock Exchange listings)
say "\n--- VALID ---";
@tests = qw[0263494 B7S9G98 B1VZ0M2 B12WC93 B6T5S47];
for $sedol (@tests) {
    check_sedol($sedol);
}

# check some known invalid SEDOLs
say "\n--- INVALID ---";
@tests = qw[B12WC9A B1VZ0M27 BDZWC92 1798059];
for $sedol (@tests) {
    check_sedol($sedol);
}

sub check_sedol {
    
    my ($SEDOL, $check_sum, $j, $char, $char_value);

    $SEDOL = $_[0];
    say qq[\nInput:  \$SEDOL = $SEDOL];

    # check length and valid chars
    unless ($SEDOL =~ m|^[B-DF-HJ-NP-TV-Z0-9]{6}\d$|) {
        say qq[Output: 0 (wrong length or invalid chars)];
        return;
    }
    
    # calculate checksum
    @weights = (1, 3, 1, 7, 3, 9, 1);
    $check_sum = 0;
    for $j (0..6) {
        $char = substr($SEDOL, $j, 1);
        $char_value = ord($char) - ($char =~ m|\d| ? ord('0') : ord('A') - 10);
        $check_sum += $weights[$j] * $char_value;
    }

    # is it a multiple of 10?
    if ($check_sum % 10 == 0) {
        say 'Output: 1';
    } else {
        say qq[Output: 0 (checksum is $check_sum - not a multiple of 10)];
    }
}

Output


--- VALID ---

Input:  $SEDOL = 0263494
Output: 1

Input:  $SEDOL = B7S9G98
Output: 1

Input:  $SEDOL = B1VZ0M2
Output: 1

Input:  $SEDOL = B12WC93
Output: 1

Input:  $SEDOL = B6T5S47
Output: 1

--- INVALID ---

Input:  $SEDOL = B12WC9A
Output: 0 (wrong length or invalid chars)

Input:  $SEDOL = B1VZ0M27
Output: 0 (wrong length or invalid chars)

Input:  $SEDOL = BDZWC92
Output: 0 (checksum is 428 - not a multiple of 10)

Input:  $SEDOL = 1798059
Output: 0 (checksum is 141 - not a multiple of 10)