SEDOLs: Difference between revisions

76,995 bytes added ,  26 days ago
(added Liberty BASIC)
 
(140 intermediate revisions by 60 users not shown)
Line 1:
{{task|Checksums}}
 
;Task:
For each number list of '''6'''-digit [[wp:SEDOL|SEDOL]]s, calculate and append the checksum digit.
 
 
That is, given this input:<pre>710889
That is, given this input:
<pre>
710889
B0YBKJ
406566
Line 13 ⟶ 17:
585284
B0YBKT
B00030
B00030</pre> Produce this output:
</pre>7108899
Produce this output:
<pre>
7108899
B0YBKJ7
4065663
Line 24 ⟶ 31:
5852842
B0YBKT7
B000300</pre>
</pre>
 
;Extra credit:
For extra credit, check each input is correctly formed, especially with respect to valid characters allowed in a SEDOL string.
Check each input is correctly formed, especially with respect to valid characters allowed in a SEDOL string.
 
 
C.f. [[Luhn test]]
;Related tasks:
* &nbsp; [[Luhn test]]
* &nbsp; [[Calculate International Securities Identification Number|ISIN]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F char2value(c)
assert(c !C ‘AEIOU’, ‘No vowels’)
R Int(c, radix' 36)
 
V sedolweight = [1, 3, 1, 7, 3, 9]
 
F checksum(sedol)
V tmp = sum(zip(sedol, :sedolweight).map((ch, weight) -> char2value(ch) * weight))
R String((10 - (tmp % 10)) % 10)
 
V sedols =
|‘710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT’
 
L(sedol) sedols.split("\n")
print(sedol‘’checksum(sedol))</syntaxhighlight>
 
{{out}}
<pre>
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">INT FUNC SedolChecksum(CHAR ARRAY sedol)
BYTE ARRAY weights=[1 3 1 7 3 9]
INT i,sum
CHAR c
 
IF sedol(0)#6 THEN
RETURN (-1)
FI
 
sum=0
FOR i=1 TO sedol(0)
DO
c=sedol(i)
IF c>='0 AND c<='9 THEN
sum==+(c-'0)*weights(i-1)
ELSE
IF c>='a AND c<='z THEN
c==-'a-'A
FI
IF c='A OR c='E OR c='I OR c='O OR c='U THEN
RETURN (-1)
ELSEIF c>='A AND c<='Z THEN
sum==+(c-'A+10)*weights(i-1)
ELSE
RETURN (-1)
FI
FI
OD
sum=(10-(sum MOD 10)) MOD 10
RETURN (sum)
 
PROC Test(CHAR ARRAY sedol)
INT res
 
res=SedolChecksum(sedol)
Print(sedol) Print(" -> ")
IF res>=0 THEN
Print(sedol) PrintIE(res)
ELSE
PrintE("invalid input")
FI
RETURN
 
PROC Main()
Test("710889")
Test("B0YBKJ")
Test("406566")
Test("B0YBLH")
Test("228276")
Test("B0YBKL")
Test("557910")
Test("B0YBKR")
Test("585284")
Test("B0YBKT")
Test("B00030")
Test("12345A")
Test("12345")
Test("1234567")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/SEDOLs.png Screenshot from Atari 8-bit computer]
<pre>
710889 -> 7108899
B0YBKJ -> B0YBKJ7
406566 -> 4065663
B0YBLH -> B0YBLH2
228276 -> 2282765
B0YBKL -> B0YBKL9
557910 -> 5579107
B0YBKR -> B0YBKR5
585284 -> 5852842
B0YBKT -> B0YBKT7
B00030 -> B000300
12345A -> invalid input
12345 -> invalid input
1234567 -> invalid input
</pre>
 
=={{header|ActionScript}}==
<langsyntaxhighlight ActionScriptlang="actionscript">//Return the code corresponding to a given character.
//ActionScript does not have a character type, so 1-digit strings
//are used instead
Line 80 ⟶ 214:
printWithCheck("585284");
printWithCheck("B0YBKT");
printWithCheck("B00030");</langsyntaxhighlight>
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
 
procedure Test_SEDOL is
Line 122 ⟶ 256:
Put_Line (Test (Index) & Character'Val (Character'Pos ('0') + Check (Test (Index))));
end loop;
end Test_SEDOL;</langsyntaxhighlight>
The function Check raises Constraint_Error upon an invalid input. The calculated sum is trimmed using (-''sum'') mod 10, which is mathematically equivalent to (10 - (''sum'' mod 10)) mod 10.
 
Line 140 ⟶ 274:
{{trans|C}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386 - ''char in string'', ''is alpha'', ''is digit'' and ''to upper'' are not in the standard's prelude}}
<langsyntaxhighlight lang="algol68">[]INT sedol weights = (1, 3, 1, 7, 3, 9);
STRING reject = "AEIOUaeiou";
Line 197 ⟶ 331:
OD;
done: SKIP
)</langsyntaxhighlight>
Output:
<pre>7108899
Line 209 ⟶ 343:
5852842
B0YBKT7</pre>
 
=={{header|ALGOL W}}==
<syntaxhighlight lang="algolw">begin
% returns the check digit for the specified SEDOL %
string(1) procedure sedolCheckDigit ( string(6) value sedol ) ;
begin
integer checkSum, checkDigit;
checkSum := 0;
for cPos := 0 until 5 do begin
string(1) c;
integer digit;
c := sedol( cPos // 1 );
if c >= "0" and c <= "9"
then digit := decode( c ) - decode( "0" )
else digit := 10 + ( decode( c ) - decode( "A" ) );
checkSum := checkSum + ( ( case cPos + 1 of ( 1, 3, 1, 7, 3, 9 ) ) * digit )
end for_cPos ;
checkDigit := ( 10 - ( checkSum rem 10 ) ) rem 10;
if checkDigit < 10
then code( decode( "0" ) + checkDigit )
else code( decode( "A" ) + ( checkDigit - 10 ) )
end sedolCheckDigit ;
 
% task test cases %
 
procedure testCheckDigit ( string(6) value sedol; string(1) value expectedCheckDigit ) ;
begin
string(1) checkDigit;
checkDigit := sedolCheckDigit( sedol );
write( s_w := 0, sedol, checkDigit );
if checkDigit not = expectedCheckDigit then writeon( " ?? expected: ", expectedCheckDigit )
end testCheckDigit ;
 
testCheckDigit( "710889", "9" );
testCheckDigit( "B0YBKJ", "7" );
testCheckDigit( "406566", "3" );
testCheckDigit( "B0YBLH", "2" );
testCheckDigit( "228276", "5" );
testCheckDigit( "B0YBKL", "9" );
testCheckDigit( "557910", "7" );
testCheckDigit( "B0YBKR", "5" );
testCheckDigit( "585284", "2" );
testCheckDigit( "B0YBKT", "7" );
testCheckDigit( "B00030", "0" )
end.</syntaxhighlight>
{{out}}
<pre>
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
</pre>
 
=={{header|AppleScript}}==
 
<syntaxhighlight lang="applescript">on appendCheckDigitToSEDOL(sedol)
if ((count sedol) is not 6) then ¬
return {false, "Error in appendCheckDigitToSEDOL handler: " & sedol & " doesn't have 6 characters."}
set chars to "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set vowels to "AEIOU"
set weights to {1, 3, 1, 7, 3, 9}
set s to 0
considering diacriticals but ignoring case -- In case these are set otherwise when this handler's called.
repeat with i from 1 to 6
set thisCharacter to character i of sedol
set o to (offset of thisCharacter in chars)
if ((o is 0) or (thisCharacter is in vowels)) then ¬
return {false, "Error in appendCheckDigitToSEDOL handler: " & sedol & " contains invalid character(s)."}
set s to s + (o - 1) * (item i of weights)
end repeat
end considering
return {true, sedol & ((10 - (s mod 10)) mod 10)}
end appendCheckDigitToSEDOL
 
-- Test code:
set input to "710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT
B00030"
set output to {}
repeat with thisSEDOL in paragraphs of input
set {valid, theResult} to appendCheckDigitToSEDOL(thisSEDOL)
set end of output to theResult
end repeat
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
set output to output as text
set AppleScript's text item delimiters to astid
return output</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">"7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300"</syntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">ord0: to :integer `0`
ord7: to :integer `7`
c2v: function [c][
ordC: to :integer c
if? c < `A` -> return ordC - ord0
else -> return ordC - ord7
]
 
weight: [1 3 1 7 3 9]
 
checksum: function [sedol][
val: new 0
loop .with:'i sedol 'ch ->
'val + weight\[i] * c2v ch
return to :char ord0 + (10 - val % 10) % 10
]
 
sedols: [
"710889" "B0YBKJ" "406566" "B0YBLH"
"228276" "B0YBKL" "557910" "B0YBKR"
"585284" "B0YBKT" "B00030"
]
 
loop sedols 'sed ->
print [sed "->" sed ++ checksum sed]</syntaxhighlight>
 
{{out}}
 
<pre>710889 -> 7108899
B0YBKJ -> B0YBKJ7
406566 -> 4065663
B0YBLH -> B0YBLH2
228276 -> 2282765
B0YBKL -> B0YBKL9
557910 -> 5579107
B0YBKR -> B0YBKR5
585284 -> 5852842
B0YBKT -> B0YBKT7
B00030 -> B000300</pre>
 
=={{header|AutoHotkey}}==
ahk forum: [http://www.autohotkey.com/forum/post-276683.html#276683 discussion]
 
<lang AutoHotkey>MsgBox % SEDOL("710889") ;7108899
===Full===
<syntaxhighlight lang="autohotkey">codes = 710889,B0YBKJ,406566,B0YBLH,228276,B0YBKL,557910,B0YBKR,585284,B0YBKT,B00030,ABCDEF,BBBBBBB
Loop, Parse, codes, `,
output .= A_LoopField "`t-> " SEDOL(A_LoopField) "`n"
Msgbox %output%
 
SEDOL(code) {
Static weight1:=1, weight2:=3, weight3:=1, weight4:=7, weight5:=3, weight6:=9
If (StrLen(code) != 6)
Return "Invalid length."
StringCaseSense On
Loop, Parse, code
If A_LoopField is Number
check_digit += A_LoopField * weight%A_Index%
Else If A_LoopField in B,C,D,F,G,H,J,K,L,M,N,P,Q,R,S,T,V,W,X,Y,Z
check_digit += (Asc(A_LoopField)-Asc("A") + 10) * weight%A_Index%
Else
Return "Invalid character."
Return code . Mod(10-Mod(check_digit,10),10)
}</syntaxhighlight>
 
===Short===
{{works with|AutoHotkey 1.1}}
<syntaxhighlight lang="autohotkey">MsgBox % SEDOL("710889") ;7108899
MsgBox % SEDOL("B0YBKJ") ;B0YBKJ7
MsgBox % SEDOL("406566") ;4065663
Line 224 ⟶ 542:
 
SEDOL(w) {
Static w1static weights := [1,w2:=3,w3:=1,w4:=7,w5:=3,w6:=9]
Loop Parseloop parse, w
s += ((c := Asc(A_LoopField)) >=Asc("A") 65 ? c -Asc("A") 65 + 10 : c -Asc("0") 48) * w%weights[A_Index%]
Return return w modMod(10 -mod Mod(s, 10), 10)
}</syntaxhighlight>
}</lang>
 
=={{header|AWK}}==
Validate or calculate checksum of SEDOL codes read from standard input (one per line)
<langsyntaxhighlight lang="awk">function ord(a)
{
return amap[a]
Line 280 ⟶ 598:
print sedol sedolcheck
}
}</langsyntaxhighlight>
 
=={{header|BASIC}}==
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<langsyntaxhighlight lang="qbasic">DECLARE FUNCTION getSedolCheckDigit! (str AS STRING)
DO
INPUT a$
Line 314 ⟶ 633:
NEXT i
getSedolCheckDigit = (10 - (total MOD 10)) MOD 10
END FUNCTION</langsyntaxhighlight>
 
=={{header|BBC BASIC}}==
<syntaxhighlight lang="bbcbasic"> PRINT FNsedol("710889")
PRINT FNsedol("B0YBKJ")
PRINT FNsedol("406566")
PRINT FNsedol("B0YBLH")
PRINT FNsedol("228276")
PRINT FNsedol("B0YBKL")
PRINT FNsedol("557910")
PRINT FNsedol("B0YBKR")
PRINT FNsedol("585284")
PRINT FNsedol("B0YBKT")
PRINT FNsedol("B00030")
END
DEF FNsedol(d$)
LOCAL a%, i%, s%, weights%()
DIM weights%(6) : weights%() = 0, 1, 3, 1, 7, 3, 9
FOR i% = 1 TO 6
a% = ASCMID$(d$,i%) - &30
s% += (a% + 7 * (a% > 9)) * weights%(i%)
NEXT
= d$ + CHR$(&30 + (10 - s% MOD 10) MOD 10)</syntaxhighlight>
'''Output:'''
<pre>
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
</pre>
 
=={{header|C}}==
'''Notes''': it reads the codes from standard input, one per line (linefeed terminated); the input encoding must meet the following specifications: single byte encoding, digits (0-9) must have codes that follow the same order of the digits (0, 1, 2, ...) and similar for letters, the encoding must match the one used with the compiled source (likely, ASCII based encodings). This should happen 99% of the time (for ASCII, ISO-8859 family and UTF-8 have the same byte encoding for alphanumeric characters).
 
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <ctype.h>
#include <string.h>
Line 366 ⟶ 722:
}
return 0;
}</langsyntaxhighlight>
 
Fed the input list from the task description, the output is:
Line 380 ⟶ 736:
5852842
B0YBKT7</pre>
 
=={{header|C++}}==
<lang cpp>
#include <numeric>
#include <algorithm>
#include <cctype>
#include <iostream>
#include <stdexcept>
#include <iterator>
#include <vector>
 
using namespace std;
 
const int weights[] = {1,3,1,7,3,9};
const string valid_chars = "BCDFGHJKLMNPQRSTVWXYZ0123456789";
 
int char_value(char c){ return isalpha(c) ? c -'A' + 10 : c - '0'; }
 
int sedol_checksum(string const& sedol)
{
//Check contents
if(sedol.size() != 6)
throw length_error("length of sedol string != 6");
if(sedol.find_first_not_of(valid_chars) != std::string::npos)
throw invalid_argument("sedol string contains disallowed characters");
 
vector<int> char_values;
transform(sedol.begin(), sedol.end(), back_inserter(char_values), char_value);
const int weighted_sum = inner_product(char_values.begin(), char_values.end(), weights, 0);
return (10 - (weighted_sum % 10)) % 10;
}
 
int main()
{
char * inputs[] = {
"710889",
"B0YBKJ",
"406566",
"B0YBLH",
"228276",
"B0YBKL",
"557910",
"B0YBKR",
"585284",
"B0YBKT",
"B00030"
};
const size_t n_inputs = sizeof(inputs) / sizeof(*inputs);
 
for(size_t i = 0; i != n_inputs; ++i)
{
cout << inputs[i] << sedol_checksum(inputs[i]) << "\n";
}
}
</lang>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">static int[] sedol_weights = { 1, 3, 1, 7, 3, 9 };
static int sedolChecksum(string sedol)
{
Line 463 ⟶ 764:
 
return (10 - (sum % 10)) % 10;
}</langsyntaxhighlight>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">
#include <numeric>
#include <cctype>
#include <iostream>
#include <string>
 
template<typename result_sink_t>
auto sedol_checksum(std::string const& sedol, result_sink_t result_sink)
{
if(sedol.size() != 6)
return result_sink(0, "length of sedol string != 6");
const char * valid_chars = "BCDFGHJKLMNPQRSTVWXYZ0123456789";
if(sedol.find_first_not_of(valid_chars) != std::string::npos)
return result_sink(0, "sedol string contains disallowed characters");
const int weights[] = {1,3,1,7,3,9};
auto weighted_sum = std::inner_product(sedol.begin(), sedol.end(), weights, 0
, [](int acc, int prod){ return acc + prod; }
, [](char c, int weight){ return (std::isalpha(c) ? c -'A' + 10 : c - '0') * weight; }
);
return result_sink((10 - (weighted_sum % 10)) % 10, nullptr);
}
 
int main()
{
using namespace std;
string inputs[] = {
"710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL",
"557910", "B0YBKR", "585284", "B0YBKT", "B00030"
};
for(auto const & sedol : inputs)
{
sedol_checksum(sedol, [&](auto sum, char const * errorMessage)
{
if(errorMessage)
cout << "error for sedol: " << sedol << " message: " << errorMessage << "\n";
else
cout << sedol << sum << "\n";
});
}
return 0;
}
</syntaxhighlight>
 
=={{header|Caché ObjectScript}}==
 
<syntaxhighlight lang="cos">Class Utils.Check [ Abstract ]
{
 
ClassMethod SEDOL(x As %String) As %Boolean
{
// https://en.wikipedia.org/wiki/SEDOL
IF x'?1(7N,1U5UN1N) QUIT 0
IF x'=$TRANSLATE(x,"AEIOU") QUIT 0
SET cd=$EXTRACT(x,*), x=$EXTRACT(x,1,*-1)
SET wgt="1317391", t=0
FOR i=1:1:$LENGTH(x) {
SET n=$EXTRACT(x,i)
IF n'=+n SET n=$ASCII(n)-55
SET t=t+(n*$EXTRACT(wgt,i))
}
QUIT cd=((10-(t#10))#10)
}
 
}</syntaxhighlight>
{{out|Examples}}
<pre>USER>For { Read s Quit:s="" Write ": "_##class(Utils.Check).SEDOL(s), ! }
7108899: 1
B0YBKJ7: 1
4065663: 1
B0YBLH2: 1
2282765: 1
B0YBKL9: 1
5579107: 1
B0YBKR5: 1
5852842: 1
B0YBKT7: 1
B000300: 1
 
USER></pre>
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">(defn sedols [xs]
(letfn [(sedol [ys] (let [weights [1 3 1 7 3 9]
convtonum (map #(Character/getNumericValue %) ys)
check (-> (reduce + (map * weights convtonum)) (rem 10) (->> (- 10)) (rem 10))]
(str ys check)))]
(map #(sedol %) xs)))</syntaxhighlight>
 
=={{header|COBOL}}==
{{works with|GNU Cobol|2.0}}
<syntaxhighlight lang="cobol"> >>SOURCE FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. sedol.
 
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT sedol-file ASSIGN "sedol.txt"
ORGANIZATION LINE SEQUENTIAL
FILE STATUS sedol-file-status.
 
DATA DIVISION.
FILE SECTION.
FD sedol-file.
01 sedol PIC X(6).
 
WORKING-STORAGE SECTION.
01 sedol-file-status PIC XX.
88 sedol-file-ok VALUE "00".
 
01 digit-num PIC 9 COMP.
01 digit-weights-area VALUE "1317391".
03 digit-weights PIC 9 OCCURS 7 TIMES.
01 weighted-sum-parts-area.
03 weighted-sum-parts PIC 9(3) COMP OCCURS 6 TIMES.
 
01 weighted-sum PIC 9(3) COMP.
 
01 check-digit PIC 9.
 
PROCEDURE DIVISION.
OPEN INPUT sedol-file
PERFORM UNTIL NOT sedol-file-ok
READ sedol-file
AT END
EXIT PERFORM
END-READ
 
MOVE FUNCTION UPPER-CASE(sedol) TO sedol
PERFORM VARYING digit-num FROM 1 BY 1 UNTIL digit-num > 6
EVALUATE TRUE
WHEN sedol (digit-num:1) IS ALPHABETIC-UPPER
IF sedol (digit-num:1) = "A" OR "E" OR "I" OR "O" OR "U"
DISPLAY "Invalid SEDOL: " sedol
EXIT PERFORM CYCLE
END-IF
COMPUTE weighted-sum-parts (digit-num) =
(FUNCTION ORD(sedol (digit-num:1)) - FUNCTION ORD("A")
+ 10) * digit-weights (digit-num)
WHEN sedol (digit-num:1) IS NUMERIC
MULTIPLY FUNCTION NUMVAL(sedol (digit-num:1))
BY digit-weights (digit-num)
GIVING weighted-sum-parts (digit-num)
WHEN OTHER
DISPLAY "Invalid SEDOL: " sedol
EXIT PERFORM CYCLE
END-EVALUATE
END-PERFORM
 
INITIALIZE weighted-sum
PERFORM VARYING digit-num FROM 1 BY 1 UNTIL digit-num > 6
ADD weighted-sum-parts (digit-num) TO weighted-sum
END-PERFORM
COMPUTE check-digit =
FUNCTION MOD(10 - FUNCTION MOD(weighted-sum, 10), 10)
 
DISPLAY sedol check-digit
END-PERFORM
CLOSE sedol-file
.
END PROGRAM sedol.</syntaxhighlight>
 
=={{header|Common Lisp}}==
Implemented from scratch using the description on Wikipedia as specification.
{{Works with|ClozureCL}}
<langsyntaxhighlight lang="lisp">(defun append-sedol-check-digit (sedol &key (start 0) (end (+ start 6)))
(assert (<= 0 start end (length sedol)))
(assert (= (- end start) 6))
Line 479 ⟶ 954:
(head (subseq sedol start end))
(tail (digit-char posn)))
(return (concatenate 'string head (list tail))))))</langsyntaxhighlight>
 
=={{header|D}}==
===Functional Version===
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string, std.numeric, std.ascii;
 
char checksum(in char[] sedol) pure @safe /*@nogc*/
in {
assert(sedol.length == 6);
foreach (immutable c; sedol)
assert(c.isDigit(c) || (c.isUpper(c) && !canFind("AEIOU", .canFind(c)));
} out (result) {
assert(isDigit(result).isDigit);
} body {
static intimmutable c2v = (in dchar c){ return=> isDigit(c).isDigit ? c - '0' : (c - 'A' + 10); }
immutable int d = sedol.map!c2v().dotProduct([1, 3, 1, 7, 3, 9]);
return '0' + digits[10 - (d % 10)];
}
 
void main() {
foreach (const sedol; "710889 B0YBKJ 406566 B0YBLH 228276
B0YBKL 557910 B0YBKR 585284 B0YBKT".split())
writeln(sedol, checksum(sedol).checksum);
}</langsyntaxhighlight>
{{out}}
<pre>7108899
Line 514 ⟶ 989:
5852842
B0YBKT7</pre>
 
===Imperative Version===
Longer, faster lower-level version, same output.
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string, std.numeric, std.ascii;
 
char sedolChecksum(in char[] sedol) pure nothrow @safe /*pure@nogc*/ nothrow
in {
assert(sedol.length == 6, "SEDOL must be 6 chars long.");
enum uint mask = 0b11_1110_1111_1011_1110_1110_1110;
 
foreach (immutable c; sedol)
assert(isDigit(c).isDigit ||
(c > 'A' && c <= 'Z' && ((1U << (c - 'A')) & mask)),
"SEDOL with wrong char.");
} out(result) {
assert(isDigit(result).isDigit);
static int c2v(in dchar c){ returnpure isDigit(c)nothrow ?@safe c-'0'@nogc : c-'A'+10; }{
return c.isDigit ? c - '0' : c - 'A' + 10;
immutable int d = sedol.map!c2v().dotProduct([1,3,1,7,3,9]);
}
immutable int d = sedol.map!c2v.dotProduct([1, 3, 1, 7, 3, 9]);
assert((d + result - '0') % 10 == 0);
} body {
enumstatic immutable int[] weights = [1, 3, 1, 7, 3, 9];
 
int sum = 0;
foreach (immutable i, immutable c; sedol) {
if (isDigit(c).isDigit)
sum += (c - '0') * weights[i];
else
Line 547 ⟶ 1,025:
 
void main() {
foreach (immutable s; ["710889", "B0YBKJ", "406566", "B0YBLH", "228276",
"B0YBKL", "557910228276", "B0YBKRB0YBKL", "585284557910", "B0YBKTB0YBKR"]),
"585284", "B0YBKT"])
writeln(s, s.sedolChecksum());
writeln(s, s.sedolChecksum);
}</lang>
}</syntaxhighlight>
 
===Short Version===
Same output.
<syntaxhighlight lang="d">void main() {
<lang d>import std.stdio, std.algorithm, std.string, std.numeric;
import std.stdio, std.algorithm, std.string, std.numeric,std.ascii;
 
foreach (const s; "710889 B0YBKJ 406566 B0YBLH 228276
auto checksum(string s) {
B0YBKL 557910 B0YBKR 585284 B0YBKT".split)
auto m = s.map!q{ a>='0' && a<='9' ? a-'0' : a-'A'+10 }();
return writeln(s, '0' + 10 - m.dotProduct([1,3,1,7,3,9]) % 10;s
.map!(c => c.isDigit ? c - '0' : c - 'A' + 10)
}
.dotProduct([1, 3, 1, 7, 3, 9]) % 10);
}</syntaxhighlight>
 
=={{header|Delphi}}==
void main() {
 
foreach (sedol; "710889 B0YBKJ 406566 B0YBLH 228276
<syntaxhighlight lang="delphi">program Sedol;
B0YBKL 557910 B0YBKR 585284 B0YBKT".split())
 
writeln(sedol, sedol.checksum());
{$APPTYPE CONSOLE}
}</lang>
 
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.
</syntaxhighlight>
 
Output:
<pre>710889 becomes 7108899
B0YBKJ becomes B0YBKJ7
406566 becomes 4065663
B0YBLH becomes B0YBLH2
228276 becomes 2282765
B0YBKL becomes B0YBKL9
557910 becomes 5579107
B0YBKR becomes B0YBKR5
585284 becomes 5852842
B0YBKT becomes B0YBKT7
B00030 becomes B000300</pre>
 
=={{header|E}}==
<langsyntaxhighlight lang="e">def weights := [1,3,1,7,3,9]
def Digit := ('0'..'9')
def Letter := ('B'..'D'|'F'..'H'|'J'..'N'|'P'..'T'|'V'..'Z')
Line 603 ⟶ 1,176:
B0YBKT".trim().split("\n") {
println(addChecksum(sedol.trim()))
}</langsyntaxhighlight>
 
=={{header|EasyLang}}==
<syntaxhighlight>
weights[] = [ 1 3 1 7 3 9 ]
func$ chksum sedol6$ .
if len sedol6$ <> 6
return ""
.
for i to 6
c$ = substr sedol6$ 1 1
if strpos "AEIOU" c$ <> 0
return ""
.
h = strcode substr sedol6$ i 1
if h >= 48 and h <= 57
h -= 48
elif h >= 65 and h <= 90
h -= 65 - 10
else
return ""
.
sum += h * weights[i]
.
return strchar ((10 - (sum mod 10)) mod 10 + 48)
.
repeat
s$ = input
until s$ = ""
print s$ & chksum s$
.
input_data
710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT
B00030
</syntaxhighlight>
 
=={{header|Elixir}}==
{{trans|Ruby}}
<syntaxhighlight lang="elixir">defmodule SEDOL do
@sedol_char "0123456789BCDFGHJKLMNPQRSTVWXYZ" |> String.codepoints
@sedolweight [1,3,1,7,3,9]
defp char2value(c) do
unless c in @sedol_char, do: raise ArgumentError, "No vowels"
String.to_integer(c,36)
end
def checksum(sedol) do
if String.length(sedol) != length(@sedolweight), do: raise ArgumentError, "Invalid length"
sum = Enum.zip(String.codepoints(sedol), @sedolweight)
|> Enum.map(fn {ch, weight} -> char2value(ch) * weight end)
|> Enum.sum
to_string(rem(10 - rem(sum, 10), 10))
end
end
 
data = ~w{
710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT
B00030
C0000
1234567
00000A
}
 
Enum.each(data, fn sedol ->
:io.fwrite "~-8s ", [sedol]
try do
IO.puts sedol <> SEDOL.checksum(sedol)
rescue
e in ArgumentError -> IO.inspect e
end
end)</syntaxhighlight>
 
{{out}}
<pre>
710889 7108899
B0YBKJ B0YBKJ7
406566 4065663
B0YBLH B0YBLH2
228276 2282765
B0YBKL B0YBKL9
557910 5579107
B0YBKR B0YBKR5
585284 5852842
B0YBKT B0YBKT7
B00030 B000300
C0000 %ArgumentError{message: "Invalid length"}
1234567 %ArgumentError{message: "Invalid length"}
00000A %ArgumentError{message: "No vowels"}
</pre>
 
=={{header|Excel}}==
===LAMBDA===
 
Defining a reusable Excel function by binding the name SEDOLCHECKSUM to a lambda expression in the Name Manager of the Excel worksheet:
 
(See [https://www.microsoft.com/en-us/research/blog/lambda-the-ultimatae-excel-worksheet-function/ LAMBDA: The ultimate Excel worksheet function])
 
{{Works with|Office 365 Betas 2021}}
 
<syntaxhighlight lang="lisp">SEDOLCHECKSUM
=LAMBDA(s,
IF(6 = LEN(s),
LET(
cs, MID(s, SEQUENCE(1, 6, 1, 1), 1),
isVowel, LAMBDA(c,
ELEM(c)({"A","E","I","O","U"})
),
sedolValue, LAMBDA(c,
LET(
ic, CODE(c),
IF(65 > ic,
ic - 48,
(ic + 10) - 65
)
)
),
IF(OR(isVowel(cs)),
" -> Invalid vowel in SEDOL string",
MOD(
10 - MOD(
SUM(
MUL({1,3,1,7,3,9})(
sedolValue(cs)
)
), 10
), 10
)
)
),
"Expected a 6-character SEDOL"
)
)</syntaxhighlight>
 
and also assuming that the names ELEM and MUL are bound to the following reusable lambdas in Name Manager:
 
<syntaxhighlight lang="lisp">ELEM
=LAMBDA(x,
LAMBDA(xs,
ISNUMBER(MATCH(x, xs, 0))
)
)
 
 
MUL
=LAMBDA(a, LAMBDA(b, a * b))</syntaxhighlight>
{{Out}}
 
The appended value in cell C2 results from the expression '''=A2 & B2'''
 
{| class="wikitable"
|-
|||style="text-align:right; font-family:serif; font-style:italic; font-size:120%;"|fx
! colspan="4" style="text-align:left; vertical-align: bottom; font-family:Arial, Helvetica, sans-serif !important;"|=SEDOLCHECKSUM(A2)
|- style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff;"
|
| A
| B
| C
| D
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 1
| style="text-align:right; font-weight:bold" | Sedols
| style="font-weight:bold" | Checksums
| style="text-align:left; font-weight:bold" | Appended
| style="font-weight:bold" |
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 2
| style="text-align:right; font-weight:bold" | 710889
| style="background-color:#cbcefb;" | 9
| style="text-align:left;" | 7108899
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 3
| style="text-align:right; font-weight:bold" | B0YBKJ
| 7
| style="text-align:left;" | B0YBKJ7
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 4
| style="text-align:right; font-weight:bold" | 406566
| 3
| style="text-align:left;" | 4065663
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 5
| style="text-align:right; font-weight:bold" | B0YBLH
| 2
| style="text-align:left;" | B0YBLH2
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 6
| style="text-align:right; font-weight:bold" | 228276
| 5
| style="text-align:left;" | 2282765
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 7
| style="text-align:right; font-weight:bold" | B0YBKL
| 9
| style="text-align:left;" | B0YBKL9
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 8
| style="text-align:right; font-weight:bold" | 557910
| 7
| style="text-align:left;" | 5579107
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 9
| style="text-align:right; font-weight:bold" | B0YBKR
| 5
| style="text-align:left;" | B0YBKR5
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 10
| style="text-align:right; font-weight:bold" | 585284
| 2
| style="text-align:left;" | 5852842
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 11
| style="text-align:right; font-weight:bold" | B0YBKT
| 7
| style="text-align:left;" | B0YBKT7
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 12
| style="text-align:right; font-weight:bold" | B00030
| 0
| style="text-align:left;" | B000300
|
|- style="text-align:right;"
| style="text-align:center; font-family:Arial, Helvetica, sans-serif !important; background-color:#000000; color:#ffffff" | 13
| style="text-align:right; font-weight:bold" | BOYBKT
| -> Invalid vowel in SEDOL string
| style="text-align:left;" | BOYBKT -> Invalid vowel in SEDOL string
|
|}
 
=={{header|F Sharp|F#}}==
<syntaxhighlight lang="fsharp">open System
let Inputs = ["710889"; "B0YBKJ"; "406566"; "B0YBLH"; "228276"; "B0YBKL"
"557910"; "B0YBKR"; "585284"; "B0YBKT"; "B00030"]
 
let Vowels = set ['A'; 'E'; 'I'; 'O'; 'U']
let Weights = [1; 3; 1; 7; 3; 9; 1]
 
let inline isVowel c = Vowels.Contains (Char.ToUpper c)
 
let char2value c =
if Char.IsDigit c then int c - 0x30
else (['A'..'Z'] |> List.findIndex ((=) (Char.ToUpper c))) + 10
let sedolCheckDigit (input: string) =
if input.Length <> 6 || input |> Seq.exists isVowel then
failwithf "Input must be six characters long and not contain vowels: %s" input
 
let sum = Seq.map2 (fun ch weight -> (char2value ch) * weight) input Weights |> Seq.sum
(10 - sum%10)%10
 
let addCheckDigit inputs =
inputs |> List.map (fun s -> s + (sedolCheckDigit s).ToString())
 
let processDigits() =
try
addCheckDigit Inputs |> List.iter (printfn "%s")
with
ex -> printfn "ERROR: %s" ex.Message</syntaxhighlight>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: combinators combinators.short-circuit formatting io kernel
math math.parser regexp sequences unicode ;
IN: rosetta-code.sedols
 
<PRIVATE
 
CONSTANT: input {
"710889" "B0YBKJ" "406566" "B0YBLH" "228276" "B0YBKL"
"557910" "B0YBKR" "585284" "B0YBKT" "B00030" "AEIOUA"
"123" "" "B_7K90"
}
 
CONSTANT: weights B{ 1 3 1 7 3 9 1 }
 
: sedol-error ( seq -- err-str )
{
{ [ dup empty? ] [ drop "no data" ] }
{ [ dup length 6 = not ] [ drop "invalid length" ] }
[ drop "invalid char(s)" ]
} cond "*error* " prepend ;
 
: sedol-valid? ( seq -- ? )
{ [ length 6 = ] [ R/ [0-9BCDFGHJ-NP-TV-Z]+/ matches? ] } 1&& ;
 
: sedol-value ( m -- n ) dup digit? [ digit> ] [ 55 - ] if ;
 
: sedol-checksum ( seq -- n )
[ sedol-value ] { } map-as weights [ * ] 2map sum ;
 
: (sedol-check-digit) ( seq -- str )
sedol-checksum 10 mod 10 swap - 10 mod number>string ;
 
PRIVATE>
 
: sedol-check-digit ( seq -- str )
dup sedol-valid? [ (sedol-check-digit) ] [ sedol-error ] if ;
 
: sedol-demo ( -- )
"SEDOL Check digit\n====== ===========" print
input [ dup sedol-check-digit "%-6s %s\n" printf ] each ;
 
MAIN: sedol-demo</syntaxhighlight>
{{out}}
<pre>
SEDOL Check digit
====== ===========
710889 9
B0YBKJ 7
406566 3
B0YBLH 2
228276 5
B0YBKL 9
557910 7
B0YBKR 5
585284 2
B0YBKT 7
B00030 0
AEIOUA *error* invalid char(s)
123 *error* invalid length
*error* no data
B_7K90 *error* invalid char(s)
</pre>
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">create weight 1 , 3 , 1 , 7 , 3 , 9 ,
 
: char>num ( '0-9A-Z' -- 0..35 )
Line 633 ⟶ 1,556:
sedol" B0YBKR" B0YBKR5 ok
sedol" 585284" 5852842 ok
sedol" B0YBKT" B0YBKT7 ok</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{Works with|Fortran|90 and later}}
<langsyntaxhighlight lang="fortran">MODULE SEDOL_CHECK
IMPLICIT NONE
CONTAINS
Line 679 ⟶ 1,602:
END DO
END PROGRAM SEDOLTEST</langsyntaxhighlight>
Output
710889 7108899
Line 691 ⟶ 1,614:
585284 5852842
B0YBKT B0YBKT7
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">' version 05-07-2015
' compile with: fbc -s console
 
Function check_sedol(input_nr As String) As Integer
input_nr = Trim(input_nr)
Dim As Integer i, j, x, nr_begin, sum
Dim As String ch, legal = "AEIOU0123456789BCDFGHJKLMNPQRSTVWXYZ"
Dim As Integer weight(0 To ...) = { 1, 3, 1, 7, 3, 9, 1}
 
x = Len(input_nr)
If x < 6 Or x > 7 Then
Return -99 ' to long or to short
End If
 
For i = 0 To 5
ch = Chr(input_nr[i])
j = InStr(legal,ch)
If j < 6 Then
Return -90+j ' not a legal char. or a vowel
End If
j = ch[0] - Asc("0")
If j > 9 Then j = j + (Asc("0") + 10- Asc("A"))
If i = 0 AndAlso j < 10 Then nr_begin = 1
If nr_begin = 1 AndAlso i > 0 Then
If j > 9 Then Return -97 ' first is number then all be numbers
End If
sum = sum + j * weight(i)
Next
sum= ((10 - (sum Mod 10)) Mod 10)
If x = 7 Then
j=input_nr[6] - Asc("0") ' checksum digit is only number
If j = sum Then
Return 100+sum ' correct
Else
Return -98 ' wrong
End If
End If
 
Return sum ' checksum digit
 
End Function
 
Sub sedol(in As String)
 
Dim As Integer checksum = check_sedol(in)
Print(in);
 
Select Case checksum
Case -99
Print " Illegal SEDOL: wrong length"
Case -98
Print " Illegal SEDOL: checksum digits do not match"
Case -97
Print " Illegal SEDOL: starts with number, may only contain numbers"
Case -90
Print " Illegal SEDOL: illegal character"
Case -89 To -85
Print " Illegal SEDOL: No vowels allowed"
Case Is > 99
Print " Valid SEDOL: checksums match"
Case Else
Print " checksum calculated : ";in;Str(checksum)
End Select
 
End Sub
' ------=< MAIN >=------
 
Dim As Integer k,checksum
Dim As String in(1 To ...) = {"710889", "B0YBKJ", "406566", "B0YBLH",_
"228276", "B0YBKL", "557910", "B0YBKR",_
"585284", "B0YBKT", "B00030"}
 
Print "Calculated checksum"
For k = 1 To UBound(in) : sedol(in(k)) : Next
 
Print : Print "Check checksum"
Dim As String in1(1 To ...) = {"7108899", "B0YBKJ7", "4065663", "B0YBLH2",_
"2282765", "B0YBKL9","5579107", "B0YBKR5",_
"5852842", "B0YBKT7", "B000300"}
 
For k = 1 To UBound(in1) : sedol(in1(k)) : Next
 
Print : Print "Error test"
Dim As String errors(1 To ...) = {"12", "1234567890", "1B0000", "123 45",_
"A00000", "B000301"}
 
For k = 1 To UBound(errors) : sedol(errors(k)) : Next
 
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End</syntaxhighlight>
{{out}}
<pre>Calculated checksum
710889 checksum calculated : 7108899
B0YBKJ checksum calculated : B0YBKJ7
406566 checksum calculated : 4065663
B0YBLH checksum calculated : B0YBLH2
228276 checksum calculated : 2282765
B0YBKL checksum calculated : B0YBKL9
557910 checksum calculated : 5579107
B0YBKR checksum calculated : B0YBKR5
585284 checksum calculated : 5852842
B0YBKT checksum calculated : B0YBKT7
B00030 checksum calculated : B000300
 
Check checksum
7108899 Valid SEDOL: checksums match
B0YBKJ7 Valid SEDOL: checksums match
4065663 Valid SEDOL: checksums match
B0YBLH2 Valid SEDOL: checksums match
2282765 Valid SEDOL: checksums match
B0YBKL9 Valid SEDOL: checksums match
5579107 Valid SEDOL: checksums match
B0YBKR5 Valid SEDOL: checksums match
5852842 Valid SEDOL: checksums match
B0YBKT7 Valid SEDOL: checksums match
B000300 Valid SEDOL: checksums match
 
Error test
12 Illegal SEDOL: wrong length
1234567890 Illegal SEDOL: wrong length
1B0000 Illegal SEDOL: starts with number, may only contain numbers
123 45 Illegal SEDOL: illegal character
A00000 Illegal SEDOL: No vowels allowed
B000301 Illegal SEDOL: checksum digits do not match</pre>
 
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=905f91c785f1f15a360726717731862f Click this link to run this code]'''
<syntaxhighlight lang="gambas">Public Sub Main()
Dim byWeight As Byte[] = [1, 3, 1, 7, 3, 9, 1]
Dim byCount, byCompute As Byte
Dim siTotal As Short
Dim sWork As New String[]
Dim sToProcess As String[] = ["710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL",
"557910", "B0YBKR", "585284", "B0YBKT", "B00030"]
 
For byCompute = 0 To sToProcess.Max
For byCount = 1 To 6
If IsLetter(Mid(sToProcess[byCompute], byCount, 1)) Then
sWork.Add(Str(Asc(Mid(sToProcess[byCompute], byCount, 1)) - 55) * byWeight[byCount - 1])
Else
sWork.Add(Val(Mid(sToProcess[byCompute], byCount, 1)) * byWeight[byCount - 1])
End If
Next
 
For byCount = 0 To 5
siTotal += Val(sWork[byCount])
Next
 
siTotal = (10 - (siTotal Mod 10)) Mod 10
 
Print sToProcess[byCompute] & " = " & sToProcess[byCompute] & siTotal
sWork.Clear()
siTotal = 0
Next
 
End</syntaxhighlight>
Output:
<pre>
710889 = 7108899
B0YBKJ = B0YBKJ7
406566 = 4065663
B0YBLH = B0YBLH2
228276 = 2282765
B0YBKL = B0YBKL9
557910 = 5579107
B0YBKR = B0YBKR5
585284 = 5852842
B0YBKT = B0YBKT7
B00030 = B000300
</pre>
 
=={{header|Go}}==
<syntaxhighlight lang="go">
<lang go>
package main
 
Line 755 ⟶ 1,854:
}
}
</syntaxhighlight>
</lang>
Output:
<pre>
Line 783 ⟶ 1,882:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def checksum(text) {
assert text.size() == 6 && !text.toUpperCase().find(/[AEIOU]+/) : "Invalid SEDOL text: $text"
 
Line 792 ⟶ 1,891:
text + (10 - (sum % 10)) % 10
}
String.metaClass.sedol = { this.&checksum(delegate) }</langsyntaxhighlight>
Test Code:
<langsyntaxhighlight lang="groovy">[ '710889': '7108899', 'B0YBKJ': 'B0YBKJ7', '406566': '4065663', 'B0YBLH': 'B0YBLH2',
'228276': '2282765', 'B0YBKL': 'B0YBKL9', '557910': '5579107', 'B0YBKR': 'B0YBKR5',
'585284': '5852842', 'B0YBKT': 'B0YBKT7', 'B00030': 'B000300'].each { text, expected ->
println "Checking $text -> $expected"
assert expected == text.sedol()
}</langsyntaxhighlight>
Output:
<pre>Checking 710889 -> 7108899
Line 814 ⟶ 1,913:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.Char (isAsciiUpper, isDigit, ord)
 
-------------------------- SEDOLS ------------------------
char2value c | c `elem` "AEIOU" = error "No vowels."
| c >= '0' && c <= '9' = ord c - ord '0'
| c >= 'A' && c <= 'Z' = ord c - ord 'A' + 10
 
checkSum :: String -> String
sedolweight = [1,3,1,7,3,9]
checkSum x =
case traverse sedolValue x of
Right xs -> (show . checkSumFromSedolValues) xs
Left annotated -> annotated
 
checkSumFromSedolValues :: [Int] -> Int
checksum sedol = show ((10 - (tmp `mod` 10)) `mod` 10)
checkSumFromSedolValues xs =
where tmp = sum $ zipWith (*) sedolweight $ map char2value sedol
rem
( 10
- rem
( sum $
zipWith
(*)
[1, 3, 1, 7, 3, 9]
xs
)
10
)
10
 
sedolValue :: Char -> Either String Int
main = mapM_ (\sedol -> putStrLn $ sedol ++ checksum sedol)
sedolValue c
[ "710889",
| c `elem` "AEIOU" = Left " ← Unexpected vowel."
"B0YBKJ",
| isDigit c = Right (ord c - "406566",ord '0')
| isAsciiUpper c = Right (ord c - "B0YBLH",ord 'A' + 10)
 
"228276",
--------------------------- TEST -------------------------
"B0YBKL",
main :: IO ()
"557910",
main =
"B0YBKR",
mapM_
"585284",
(putStrLn . ((<>) <*> checkSum))
"B0YBKT" ]</lang>
[ "710889",
"B0YBKJ",
"406566",
"B0YBLH",
"228276",
"B0YBKL",
"557910",
"B0YBKR",
"585284",
"B0YBKT",
"BOYBKT", -- Ill formed test case - illegal vowel.
"B00030"
]</syntaxhighlight>
{{Out}}
<pre>7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
BOYBKT ← Unexpected vowel.
B000300</pre>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main()
every write(sedol("710889"|"B0YBKJ"|"406566"|"B0YBLH"|"228276"|
"B0YBKL"|"557910"|"B0YBKR"|"585284"|"B0YBKT"|"B00030"))
Line 856 ⟶ 1,995:
return x || (10 - (t%10)) % 10 # complete
}
end</langsyntaxhighlight>
 
=={{header|J}}==
There are several ways to perform this in J. This most closely follows the algorithmic description at Wikipedia:
<langsyntaxhighlight lang="j">sn =. '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ac0 =: (, 10 | 1 3 1 7 3 9 +/@:* -)&.(sn i. |:)</langsyntaxhighlight>
However, because J is so concise, having written the above, it becomes clear that the negation (<tt>-</tt>) is unneccsaryunnecessary.
 
The fundamental operation is the linear combination (<tt>+/@:*</tt>) and neither argument is "special". In particular, the coefficients are just another array participating in the calculation, and there's no reason we can't modify them as easily as the input array. Having this insight, it is obvious that manipulating the coefficients, rather than the input array, will be more efficient (because the coefficients are fixed at small size, while the input array can be arbitrarily large).
 
Which leads us to this more efficient formulation:
<langsyntaxhighlight lang="j">ac1 =: (, 10 | (10 - 1 3 1 7 3 9) +/@:* ])&.(sn i. |:)</langsyntaxhighlight>
which reduces to:
<langsyntaxhighlight lang="j">ac1ac2 =: (, 10 | 9 7 9 3 7 1 +/@:* ])&.(sn i. |:)</langsyntaxhighlight>
Which is just as concise as <tt>ac0</tt>, but faster.
 
Following this train of thought, our array thinking leads us to realize that even the modulousmodulus isn't neccesarynecessary. The number of SEDOL numbers is finite, as is the number of coefficients; therefore the number of possible linear combinations of these is finite. In fact, there are only 841 possible outcomes. This is a small number, and can be efficiently stored as a lookup table (even better, since the outcomes will be mod 10, they are restricted to the digits 0-9, and they repeat).
 
Which leads us to:
<langsyntaxhighlight lang="j">ac2ac3 =.: (,"1 0 (841 $ '0987654321') {~ 1 3 1 7 3 9 +/ .*~ sn i. ])</langsyntaxhighlight>
Which is more than twice as fast as even the optimized formulation (<tt>ac1ac2</tt>), though it is slightly longer.
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.Scanner;
 
public class SEDOL{
Line 909 ⟶ 2,048:
return (str.length() == 6) && !str.toUpperCase().matches(".*?[AEIOU].*?");
}
}</langsyntaxhighlight>
 
=={{header|JavaScript}}==
===Imperative===
<lang javascript>function sedol(input) {
<syntaxhighlight lang="javascript">function sedol(input) {
return input + sedol_check_digit(input);
}
Line 952 ⟶ 2,092:
print("error: " + e);
}
}</langsyntaxhighlight>
output
<pre>7108899
Line 968 ⟶ 2,108:
1234563
error: Invalid SEDOL number '1234567'</pre>
 
===Functional===
<syntaxhighlight lang="javascript">(() => {
'use strict';
 
const main = () => {
 
// checkSumLR :: String -> Either String String
const checkSumLR = s => {
const
tpl = partitionEithers(map(charValueLR, s));
return 0 < tpl[0].length ? (
Left(s + ' -> ' + unwords(tpl[0]))
) : Right(rem(10 - rem(
sum(zipWith(
(a, b) => a * b,
[1, 3, 1, 7, 3, 9],
tpl[1]
)), 10
), 10).toString());
};
 
// charValue :: Char -> Either String Int
const charValueLR = c =>
isAlpha(c) ? (
isUpper(c) ? (
elem(c, 'AEIOU') ? Left(
'Unexpected vowel: ' + c
) : Right(ord(c) - ord('A') + 10)
) : Left('Unexpected lower case character: ' + c)
) : isDigit(c) ? Right(
parseInt(c, 10)
) : Left('Unexpected character: ' + c);
 
// TESTS ------------------------------------------
const [problems, checks] = Array.from(
partitionEithers(map(s => bindLR(
checkSumLR(s),
c => Right(s + c)
),
[
"710889", "B0YBKJ", "406566",
"B0YBLH", "228276", "B0YBKL",
"557910", "B0YBKR", "585284",
"B0YBKT", "B00030"
]
))
);
return unlines(
0 < problems.length ? (
problems
) : checks
);
};
 
// GENERIC FUNCTIONS ----------------------------
 
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
 
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
 
// Tuple (,) :: a -> b -> (a, b)
const Tuple = (a, b) => ({
type: 'Tuple',
'0': a,
'1': b,
length: 2
});
 
// bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
const bindLR = (m, mf) =>
undefined !== m.Left ? (
m
) : mf(m.Right);
 
// elem :: Eq a => a -> [a] -> Bool
const elem = (x, xs) => xs.includes(x);
 
// isAlpha :: Char -> Bool
const isAlpha = c =>
/[A-Za-z\u00C0-\u00FF]/.test(c);
 
// isDigit :: Char -> Bool
const isDigit = c => {
const n = ord(c);
return 48 <= n && 57 >= n;
};
 
// isUpper :: Char -> Bool
const isUpper = c =>
/[A-Z]/.test(c);
 
// Returns Infinity over objects without finite length.
// This enables zip and zipWith to choose the shorter
// argument when one is non-finite, like cycle, repeat etc
 
// length :: [a] -> Int
const length = xs =>
(Array.isArray(xs) || 'string' === typeof xs) ? (
xs.length
) : Infinity;
 
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) =>
(Array.isArray(xs) ? (
xs
) : xs.split('')).map(f);
 
// ord :: Char -> Int
const ord = c => c.codePointAt(0);
 
// partitionEithers :: [Either a b] -> ([a],[b])
const partitionEithers = xs =>
xs.reduce(
(a, x) => undefined !== x.Left ? (
Tuple(a[0].concat(x.Left), a[1])
) : Tuple(a[0], a[1].concat(x.Right)),
Tuple([], [])
);
 
// rem :: Int -> Int -> Int
const rem = (n, m) => n % m;
 
// sum :: [Num] -> Num
const sum = xs => xs.reduce((a, x) => a + x, 0);
 
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = (n, xs) =>
'GeneratorFunction' !== xs.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], Array.from({
length: n
}, () => {
const x = xs.next();
return x.done ? [] : [x.value];
}));
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
 
// unwords :: [String] -> String
const unwords = xs => xs.join(' ');
 
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
const
lng = Math.min(length(xs), length(ys)),
as = take(lng, xs),
bs = take(lng, ys);
return Array.from({
length: lng
}, (_, i) => f(as[i], bs[i], i));
};
 
// MAIN ---
return main();
})();</syntaxhighlight>
{{Out}}
<pre>7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300</pre>
 
=={{header|jq}}==
{{works with|jq|1.4}}
This implementation accepts strings with lowercase letters, but converts them to uppercase.
<syntaxhighlight lang="jq">def ascii_upcase:
explode | map( if 97 <= . and . <= 122 then . - 32 else . end) | implode;
 
def sedol_checksum:
def encode(a): 10 + (a|explode[0]) - ("A"|explode[0]);
. as $sed
| [1,3,1,7,3,9] as $sw
| reduce range(0;6) as $i
(0;
$sed[$i:$i+1] as $c
| if ( "0123456789" | index($c) )
then . + ($c|tonumber) * $sw[$i]
else . + encode($c) * $sw[$i]
end )
| (10 - (. % 10)) % 10 ;
 
# error on error, else pass input to output
def check_valid_sedol:
def has_vowel:
("AEIOU"|explode) as $vowels
| reduce explode[] as $c
(false; if . then . else $vowels|index($c) end);
 
if has_vowel then error( "\(.) is not a valid SEDOL code" )
else .
end
| if length > 7 or length < 6 then
error( "\(.) is too long or too short to be valid SEDOL")
else .
end;
 
def sedolize:
ascii_upcase as $in
| $in
| check_valid_sedol
| .[0:6] as $sedol
| ($sedol | sedol_checksum | tostring) as $sedolcheck
| ($sedol + $sedolcheck) as $ans
| if length == 7 and $ans != $in then
$ans + " (original \($in) has wrong checksum digit"
else $ans
end ;
sedolize</syntaxhighlight>
{{Out}}
# Assuming sedol.txt contains the input in the task description
$ jq -R -r -M -f sedol.jq sedol.txt
... (output is exactly as shown in the task description)
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<syntaxhighlight lang="julia">using Base.Test
 
function appendchecksum(chars::AbstractString)
if !all(isalnum, chars) throw(ArgumentError("invalid SEDOL number '$chars'")) end
weights = [1, 3, 1, 7, 3, 9, 1]
 
s = 0
for (w, c) in zip(weights, chars)
s += w * parse(Int, c, 36)
end
return string(chars, (10 - s % 10) % 10)
end
 
tests = ["710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL", "557910", "B0YBKR", "585284", "B0YBKT", "B00030"]
csums = ["7108899", "B0YBKJ7", "4065663", "B0YBLH2", "2282765", "B0YBKL9", "5579107", "B0YBKR5", "5852842", "B0YBKT7", "B000300"]
 
@testset "Checksums" begin
for (t, c) in zip(tests, csums)
@test appendchecksum(t) == c
end
end</syntaxhighlight>
 
{{out}}
<pre>Test Summary: | Pass Total
Checksums | 11 11</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="kotlin">
val weights = arrayOf(1, 3, 1, 7, 3, 9, 1)
val validChars = (('0'..'9') + ('A'..'Z')).toSet() - "AEIOU".toSet()
 
fun sedol7(sedol6: String): String {
require(sedol6.length == 6) { "Length of argument string must be 6" }
require(sedol6.all { it in validChars }) { "Argument string contains an invalid character" }
 
val sum = sedol6.map { it.digitToInt(36) }.zip(weights, Int::times).sum()
val check = (-sum).mod(10)
return sedol6 + ('0' + check)
}
 
fun main() {
val sedol6s = listOf(
"710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL",
"557910", "B0YBKR", "585284", "B0YBKT", "B00030"
)
for (sedol6 in sedol6s)
println("$sedol6 -> ${sedol7(sedol6)}")
}
</syntaxhighlight>
 
{{out}}
<pre>
710889 -> 7108899
B0YBKJ -> B0YBKJ7
406566 -> 4065663
B0YBLH -> B0YBLH2
228276 -> 2282765
B0YBKL -> B0YBKL9
557910 -> 5579107
B0YBKR -> B0YBKR5
585284 -> 5852842
B0YBKT -> B0YBKT7
B00030 -> B000300
</pre>
 
=={{header|langur}}==
{{trans|Go}}
<syntaxhighlight lang="langur">val .csd = fn(.code) {
switch len(.code) {
case 0:
return "nada, zip, zilch"
case != 6:
return "invalid length"
}
 
if .code -> re/[^B-DF-HJ-NP-TV-Z0-9]/ {
return "invalid character(s)"
}
 
val .weight = [1,3,1,7,3,9]
 
val .nums = s2n .code
val .sum = for[=0] .i of .nums {
_for += .nums[.i] * .weight[.i]
}
 
string 9 - (.sum - 1) rem 10
}
 
val .h = {
# invalid...
"": 0,
"123": 0,
"A00030": 0,
"E00030": 0,
"I00030": 0,
"O00030": 0,
"U00030": 0,
"β00030": 0,
 
# valid...
"710889": 9,
"B0YBKJ": 7,
"406566": 3,
"B0YBLH": 2,
"228276": 5,
"B0YBKL": 9,
"557910": 7,
"B0YBKR": 5,
"585284": 2,
"B0YBKT": 7,
"B00030": 0,
}
 
for .input in sort(keys .h) {
val .d = .csd(.input)
if len(.d) > 1 {
writeln .input, ": ", .d
} else {
val .expect = string .h[.input]
write .input, .d
writeln if .expect == .d {""} else {
" (SEDOL test failed; expected check digit {{.expect}})"}
}
}
</syntaxhighlight>
 
{{out}}
<pre>: nada, zip, zilch
123: invalid length
2282765
4065663
5579107
5852842
7108899
A00030: invalid character(s)
B000300
B0YBKJ7
B0YBKL9
B0YBKR5
B0YBKT7
B0YBLH2
E00030: invalid character(s)
I00030: invalid character(s)
O00030: invalid character(s)
U00030: invalid character(s)
β00030: invalid character(s)
</pre>
 
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
'adapted from BASIC solution
mult(1) = 1: mult(2) = 3: mult(3) = 1
Line 1,002 ⟶ 2,523:
getSedolCheckDigit = (10 - (total MOD 10)) MOD 10
END FUNCTION
</syntaxhighlight>
</lang>
 
=={{header|M4}}==
<langsyntaxhighlight M4lang="m4">divert(-1)
changequote(`[',`]')
define([_bar],include(sedol.inp))
Line 1,021 ⟶ 2,542:
])
divert
eachline(_bar,[checksum])</langsyntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">SEDOL[Code_?(Function[v,StringFreeQ[v,{"A","E","I","O","U"}]])]:=
Code<>ToString[10-Mod[ToExpression[Quiet[Flatten[Characters[Code]
/.x_?LetterQ->(ToCharacterCode[x]-55)]]].{1,3,1,7,3,9},10]]
Scan[Print[SEDOL[#]] &, {"710889","B0YBKJ","406566","B0YBLH","228276","B0YBKL","557910","B0YBKR","585284","B0YBKT","B00030","DUMMY"}]</syntaxhighlight>
 
{{out}}
Scan[Print[SEDOL[#]] &, {"710889","B0YBKJ","406566","B0YBLH","228276","B0YBKL","557910","B0YBKR","585284","B0YBKT","B00030","DUMMY"}]
<pre>
 
->Output:
7108899
B0YBKJ7
Line 1,042 ⟶ 2,562:
B0YBKT7
B0003010
SEDOL[DUMMY] -> rejected</langpre>
 
=={{header|Mercury}}==
<syntaxhighlight lang="text">:- module sedol.
:- interface.
 
Line 1,097 ⟶ 2,617:
is_vowel('I').
is_vowel('O').
is_vowel('OU').</langsyntaxhighlight>
 
=={{header|Modula-3}}==
<langsyntaxhighlight lang="modula3">MODULE SEDOL EXPORTS Main;
 
IMPORT IO, Fmt, Text, Stdio;
Line 1,143 ⟶ 2,663:
| BadSedol(text) => IO.Put(text & "\n", Stdio.stderr);
END;
END SEDOL.</langsyntaxhighlight>
Output:
<pre>7108899
Line 1,157 ⟶ 2,677:
 
=={{header|MUMPS}}==
<langsyntaxhighlight MUMPSlang="mumps">SEDOL
NEW A,B
SEDOL1
Line 1,177 ⟶ 2,697:
NEW UP,LO
SET UP="ABCDEFGHIJKLMNOPQRSTUVWXYZ",LO="abcdefghijklmnopqrstuvwxyz"
QUIT $TRANSLATE(X,LO,UP)</langsyntaxhighlight>
Examples:
<pre>USER>D SEDOL^ROSETTA
Line 1,207 ⟶ 2,727:
Enter the first 6 digits of a SEDOL: B123456
INVALID</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">proc c2v(c: char): int =
assert c notin "AEIOU"
if c < 'A': ord(c) - ord('0') else: ord(c) - ord('7')
const weight = [1, 3, 1, 7, 3, 9]
proc checksum(sedol: string): char =
var val = 0
for i, ch in sedol:
val += c2v(ch) * weight[i]
result = chr((10 - val mod 10) mod 10 + ord('0'))
for sedol in ["710889", "B0YBKJ", "406566", "B0YBLH",
"228276", "B0YBKL", "557910", "B0YBKR",
"585284", "B0YBKT", "B00030"]:
echo sedol, " → ", sedol & checksum(sedol)</syntaxhighlight>
 
{{out}}
<pre>710889 → 7108899
B0YBKJ → B0YBKJ7
406566 → 4065663
B0YBLH → B0YBLH2
228276 → 2282765
B0YBKL → B0YBKL9
557910 → 5579107
B0YBKR → B0YBKR5
585284 → 5852842
B0YBKT → B0YBKT7
B00030 → B000300</pre>
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let char2value c =
assert (not (String.contains "AEIOU" c));
match c with
| '0'..'9' -> int_of_char c - int_of_char '0'
| 'A'..'Z' -> int_of_char c - int_of_char 'A' + 10
| _ -> assert false
 
let sedolweight = [1;3;1;7;3;9]
 
let explode s =
s |> String.to_seq |> List.of_seq
let result = ref [] in
String.iter (fun c -> result := c :: !result) s;
List.rev !result
 
let checksum sedol =
let tmp = List.fold_left2 (fun sum ch weight -> sum + char2value ch * weight)
0 (explode sedol) sedolweight in
string_of_int ((10 - (tmp mod 10)) mod 10) ;;
 
List.iter (fun sedol -> print_endline (sedol ^ checksum sedol))
[ "710889";
Line 1,237 ⟶ 2,787:
"B0YBKR";
"585284";
"B0YBKT" ]</langsyntaxhighlight>
 
=={{header|Oforth}}==
 
<syntaxhighlight lang="oforth">func: sedol(s)
[ 1, 3, 1, 7, 3, 9 ] s
zipWith(#[ dup isDigit ifTrue: [ '0' - ] else: [ 'A' - 10 + ] * ]) sum
10 mod 10 swap - 10 mod
StringBuffer new s << swap '0' + <<c ;</syntaxhighlight>
 
{{out}}
<pre>
[ "710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL", "557910", "B0YBKR", "585284", "B0YBKT", "B00030" ]
apply(#[ sedol println ])
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
</pre>
 
=={{header|Pascal}}==
{{works with|Free_Pascal}}
<langsyntaxhighlight lang="pascal">program Sedols(output);
 
function index(c: char): integer;
Line 1,285 ⟶ 2,860:
writeln(codes[i], ' -> ', seforl);
end;
end.</langsyntaxhighlight>
Output:
<pre>% ./Sedols
Line 1,302 ⟶ 2,877:
=={{header|Perl}}==
This program reads from standard input.
<langsyntaxhighlight lang="perl">use List::Util qw(sum);
use POSIX qw(strtol);
 
sub zip :prototype(&\@\@) {
my $f = shift;
my @a = @{shift()};
Line 1,315 ⟶ 2,890:
 
my @weights = (1, 3, 1, 7, 3, 9);
sub sedolsedan :prototype($) {
my $s = shift;
$s =~ /[AEIOU]/ and die "No vowels";
Line 1,327 ⟶ 2,902:
chomp;
print sedol($_), "\n";
}</langsyntaxhighlight>
 
=={{header|Perl 6Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
{{trans|Perl}}
<span style="color: #008080;">type</span> <span style="color: #000000;">string6</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
Note: Change %base36 and @weights from `my` to `constant` when Rakudo implements them.
<span style="color: #008080;">return</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">6</span>
<lang perl6>sub sedol( Str $s ) {
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
die 'No vowels allowed' if $s ~~ /<[AEIOU]>/;
die 'Invalid format' if $s !~~ /^ <[0..9B..DF..HJ..NP..TV..Z]>**6 $ /;
<span style="color: #008080;">type</span> <span style="color: #000000;">sedolch</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'Z'</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"AEIOU"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">sedol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">string6</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">sedolch</span> <span style="color: #000000;">c</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">?</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">+</span><span style="color: #000000;">10</span><span style="color: #0000FF;">:</span><span style="color: #000000;">c</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)*{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">&</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">),</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)+</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"710889"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"B0YBKJ"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"406566"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"B0YBLH"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"228276"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"B0YBKL"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"557910"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"B0YBKR"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"585284"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"B0YBKT"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"B00030"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">sedol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
"7108899"
"B0YBKJ7"
"4065663"
"B0YBLH2"
"2282765"
"B0YBKL9"
"5579107"
"B0YBKR5"
"5852842"
"B0YBKT7"
"B000300"
</pre>
 
=={{header|Phixmonti}}==
my %base36 = ( 0..9, 'A'..'Z' ) Z ( ^36 );
{{trans|RPL}}
my @weights = 1, 3, 1, 7, 3, 9;
<syntaxhighlight lang="Phixmonti">include ..\Utilitys.pmt
 
def ->7DOL
my @vs = %base36{ $s.comb };
( 1 3 1 my7 $checksum3 =9 [+]) @vsvar Z* @weights;
0 >ps
my $check_digit = (10 - $checksum % 10) % 10;
6 for >ps
return $s ~ $check_digit;
tps get
}
dup 65 >= if 7 - endif 48 -
weights ps> get nip * ps> + >ps
endfor
10 ps> 10 mod - 10 mod tostr chain
enddef
 
( "710889" "B0YBKJ" "406566" "B0YBLH" "228276" "B0YBKL" "557910" "B0YBKR" "585284" "B0YBKT" "B00030" )
say sedol($_) for <
 
710889
getid ->7DOL map
B0YBKJ
 
406566
pstack</syntaxhighlight>
B0YBLH
{{out}}
228276
<pre>
B0YBKL
[["7108899", "B0YBKJ7", "4065663", "B0YBLH2", "2282765", "B0YBKL9", "5579107", "B0YBKR5", "5852842", "B0YBKT7", "B000300"]]
557910
 
B0YBKR
=== Press any key to exit ===</pre>
585284
B0YBKT
B00030
>;</lang>
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php">function char2value($c) {
assert(stripos('AEIOU', $c) === FALSE);
return intval($c, 36);
Line 1,385 ⟶ 3,006:
'585284',
'B0YBKT') as $sedol)
echo $sedol, checksum($sedol), "\n";</langsyntaxhighlight>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de sedol (Str)
(pack Str
(char
Line 1,408 ⟶ 3,029:
 
(for S '("710889" "B0YBKJ" "406566" "B0YBLH" "228276" "B0YBKL" "557910" "B0YBKR" "585284" "B0YBKT" "B00030")
(prinl (sedol S)) )</langsyntaxhighlight>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pli">/* Compute SEDOLs; includes check for invalid characters. */
<lang PL/I>
/* Compute SEDOLs; includes check for invalid characters. */
sedol: procedure options (main); /* 3 March 2012 */
declare alphabet character (36) static initial
Line 1,434 ⟶ 3,054:
put edit (s, v) (x(2), a, f(1)); put edit (' ') (a);
end;
end sedol;</syntaxhighlight>
 
</lang>
{{out}}
Output:
<pre>
710889 7108899
Line 1,450 ⟶ 3,070:
B00030 B000300
</pre>
 
=={{header|Potion}}==
No extra credit.
<syntaxhighlight lang="potion">sedolnum = (c) :
if ("0" ord <= c ord and c ord <= "9" ord): c number integer.
else: 10 + c ord - "A" ord.
.
 
sedol = (str) :
weight = (1, 3, 1, 7, 3, 9)
sum = 0
6 times (i) :
sum = sum + sedolnum(str(i)) * weight(i)
.
(str, (10 - (sum % 10)) % 10) join
.</syntaxhighlight>
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">function Add-SEDOLCheckDigit
{
Param ( # Validate input as six-digit SEDOL number
[ValidatePattern( "^[0123456789bcdfghjklmnpqrstvwxyz]{6}$" )]
[parameter ( Mandatory = $True ) ]
[string]
$SixDigitSEDOL )
# Convert to array of single character strings, using type char as an intermediary
$SEDOL = [string[]][char[]]$SixDigitSEDOL
# Define place weights
$Weight = @( 1, 3, 1, 7, 3, 9 )
# Define character values (implicit in 0-based location within string)
$Characters = "0123456789abcdefghijklmnopqrstuvwxyz"
$CheckSum = 0
# For each digit, multiply the character value by the weight and add to check sum
0..5 | ForEach { $CheckSum += $Characters.IndexOf( $SEDOL[$_].ToLower() ) * $Weight[$_] }
# Derive the check digit from the partial check sum
$CheckDigit = ( 10 - $CheckSum % 10 ) % 10
# Return concatenated result
return ( $SixDigitSEDOL + $CheckDigit )
}
# Test
$List = @(
"710889"
"B0YBKJ"
"406566"
"B0YBLH"
"228276"
"B0YBKL"
"557910"
"B0YBKR"
"585284"
"B0YBKT"
"B00030"
)
ForEach ( $PartialSEDOL in $List )
{
Add-SEDOLCheckDigit -SixDigitSEDOL $PartialSEDOL
}</syntaxhighlight>
{{out}}
<pre>7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300</pre>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Procedure.s SEDOLs(rawstring$)
Protected i, j, sum, c, m
For i=1 To Len(rawstring$)
Line 1,491 ⟶ 3,189:
Data.s "710889","B0YBKJ","406566","B0YBLH","228276"
Data.s "B0YBKL","557910","B0YBKR","585284","B0YBKT","B00030"
EndDataSection</langsyntaxhighlight>
 
[[Image:PB SEDOL.png]]
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">def char2value(c):
assert c not in 'AEIOU', "No vowels"
return int(c, 36)
Line 1,506 ⟶ 3,204:
sedol, sedolweight)
)
return str((10 - (tmp % 10)) % 10)
 
for sedol in '''
Line 1,520 ⟶ 3,218:
B0YBKT
'''.split():
print sedol + checksum(sedol)</langsyntaxhighlight>
 
 
Or, combining ''reduce'' with an option type – handling disallowed characters without assertion errors:
 
{{Works with|Python|3.7}}
<syntaxhighlight lang="python">'''SEDOL checksum digits'''
 
from functools import reduce
 
 
# sedolCheckSumDigitLR :: String -> Either String Char
def sedolCheckSumDigitLR(s):
'''Either an explanatory message, or a
checksum digit character to append
to a given six-character SEDOL string.
'''
def goLR(lr, cn):
c, n = cn
return bindLR(lr)(
lambda a: bindLR(sedolValLR(c))(
lambda x: Right(a + x * n)
)
)
return bindLR(
reduce(
goLR,
zip(s, [1, 3, 1, 7, 3, 9]),
Right(0)
)
)(lambda d: Right(str((-d) % 10)))
 
 
# sedolValLR :: Char -> Either String Char
def sedolValLR(c):
'''Either an explanatory message, or the
SEDOL value of a given character.
'''
return Right(int(c, 36)) if (
c not in 'AEIOU'
) else Left('Unexpected vowel in SEDOL string: ' + c)
 
 
# TEST -------------------------------------------------
def main():
'''Append checksums where valid.'''
 
print(
fTable(__doc__ + ':\n')(str)(
either(str)(str)
)(sedolCheckSumDigitLR)(
'''710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
BOYBKL
557910
B0YBKR
585284
B0YBKT
B00030
'''.split()
)
)
 
 
# GENERIC -------------------------------------------------
 
 
# Left :: a -> Either a b
def Left(x):
'''Constructor for an empty Either (option type) value
with an associated string.'''
return {'type': 'Either', 'Right': None, 'Left': x}
 
 
# Right :: b -> Either a b
def Right(x):
'''Constructor for a populated Either (option type) value'''
return {'type': 'Either', 'Left': None, 'Right': x}
 
 
# bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
def bindLR(m):
'''Either monad injection operator.
Two computations sequentially composed,
with any value produced by the first
passed as an argument to the second.'''
return lambda mf: (
mf(m.get('Right')) if None is m.get('Left') else m
)
 
 
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Right to left function composition.'''
return lambda f: lambda x: g(f(x))
 
 
# either :: (a -> c) -> (b -> c) -> Either a b -> c
def either(fl):
'''The application of fl to e if e is a Left value,
or the application of fr to e if e is a Right value.'''
return lambda fr: lambda e: fl(e['Left']) if (
None is e['Right']
) else fr(e['Right'])
 
 
# fTable :: String -> (a -> String) ->
# (b -> String) ->
# (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function -> fx display function ->
f -> value list -> tabular string.'''
def go(xShow, fxShow, f, xs):
w = max(map(compose(len)(xShow), xs))
return s + '\n' + '\n'.join([
xShow(x).rjust(w, ' ') + ' -> ' + fxShow(f(x)) for x in xs
])
return lambda xShow: lambda fxShow: (
lambda f: lambda xs: go(
xShow, fxShow, f, xs
)
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>SEDOL checksum digits:
 
710889 -> 9
B0YBKJ -> 7
406566 -> 3
B0YBLH -> 2
228276 -> 5
B0YBKL -> 9
BOYBKL -> Unexpected vowel in SEDOL string: O
557910 -> 7
B0YBKR -> 5
585284 -> 2
B0YBKT -> 7
B00030 -> 0</pre>
 
=={{header|Q}}==
<syntaxhighlight lang="q">scd:{
v:{("i"$x) - ?[("0"<=x) & x<="9"; "i"$"0"; -10+"i"$"A"]} each x; / Turn characters of SEDOL into their values
w:sum v*1 3 1 7 3 9; / Weighted sum of values
d:(10 - w mod 10) mod 10; / Check digit value
x,"c"$(("i"$"0")+d) / Append to SEDOL
}
 
scd each ("710889";"B0YBKJ";"406566";"B0YBLH";"228276";"B0YBKL";"557910";"B0YBKR";"585284";"B0YBKT";"B00030")</syntaxhighlight>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ 48 - dup 9 > if [ 7 - ] ] is chvalue ( c --> n )
[ 0 over witheach
[ chvalue
' [ 1 3 1 7 3 9 ]
i^ peek * + ]
10 mod 10 swap - 10 mod
48 + join ] is ->sedol ( $ --> $ )
$ "710889 B0YBKJ 406566 B0YBLH
228276 B0YBKL 557910 B0YBKR
585284 B0YBKT B00030" nest$
 
witheach [ ->sedol echo$ cr ]</syntaxhighlight>
 
{{out}}
 
<pre>7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300</pre>
 
=={{header|R}}==
<langsyntaxhighlight rlang="rsplus"># Read in data from text connection
datalines <- readLines(tc <- textConnection("710889
B0YBKJ
Line 1,559 ⟶ 3,443:
 
#Print in format requested
writeLines(withchkdig)</langsyntaxhighlight>
 
=={{header|REXXRacket}}==
<syntaxhighlight lang="racket">#lang racket
<lang rexx>/*REXX program computes the check (last) digit for 6 or 7 char SEDOLs.*/
;;; Since the Task gives us unchecksummed and checksummed SEDOLs, and
/*if the SEDOL is 6 characters, a */
;;; we'll just take a list of the output SEDOLs and remove their last
/*check digit is added. */
;;; characters for the input
(define output-SEDOLS
(list "7108899" "B0YBKJ7" "4065663"
"B0YBLH2" "2282765" "B0YBKL9"
"5579107" "B0YBKR5" "5852842"
"B0YBKT7" "B000300"))
(define (output->input-SEDOL S) (substring S 0 6))
(define input-SEDOLS (map output->input-SEDOL output-SEDOLS))
 
;;; checksum calculation
/*if the SEDOL is 7 characters, a */
(define (SEDOL-character-value c)
/*check digit is created and it is*/
(if (char-numeric? c)
/*verified that it's equal to the */
(- (char->integer c) (char->integer #\0))
/*check digit already on the SEDOL*/
(+ 10 (- (char->integer c) (char->integer #\A)))))
@.=''
(define (SEDOL-character-sum S)
arg @.1 . /*allow user-specified SEDOL. */
(for/sum ((c S) ; if we run out of c's before the final 1 in weight, we'll have the unchecksummed weighted sum
if @.1=='' then do /*if none, then assume 11 defaults*/
(weight (in-list '(1 3 @.1 =7 7108893 9 1))))
(* weight (SEDOL-character-value c))))
@.2 ='B0YBKJ'
(define (SEDOL-checksum S) (number->string (modulo (- 10 (SEDOL-character-sum S)) 10)))
@.3 = 406566
@.4 ='B0YBLH'
@.5 = 228276
@.6 ='B0YBKL'
@.7 = 557910
@.8 ='B0YBKR'
@.9 = 585284
@.10='B0YBKT'
@.11='B00030'
end
 
;;; build output from input
@abcU='ABCDEFGHIJKLMNOPQRSTUVWXYZ' /*the uppercase Latin alphabet. */
(define (SEDOL-append-checksum S) (string-append S (SEDOL-checksum S)))
alphaDigs='0123456789'@abcU /*legal chars, and then some. */
allowable=space(translate(alphaDigs,,'AEIOU'),0) /*remove the vowels.*/
weights=1317391 /*various weights for SEDOL chars*/
/*an alternative would be to use:*/
/* weights='1 3 1 7 3 9 1' if */
/*any weights were greater than 9*/
 
;;; Extra credit -- according to wikipedia:
do j=1 while @.j\==''; sedol=@.j /*process each specified SEDOL. */
;;; "SEDOLs are seven characters in length"
L=length(sedol)
;;; "vowels are never used"
if L<6 | L>7 then call ser "SEDOL isn't a valid length"
;;; there seems to be no statement as to case, but we'll assert that too!
if left(sedol,1)==9 then call swa 'SEDOL is reserved for end user allocation'
;;;
_=verify(sedol,allowable)
;;; valid-SEDOL? is a predicate... it doesn't report a reason
if _\==0 then call ser 'illegal character in SEDOL:' substr(sedol,_,1)
(define (invalid-SEDOL? S)
sum=0 /*checkDigit sum (so far). */
(define (invalid-SEDOL-character? c)
(if
(and (not (char-upper-case? c)) (not (char-numeric? c)))
(format "contains non upper case/non numeric ~a" c)
(case c [(#\A #\E #\I #\O #\U) (format "contains vowel ~a" c)] [else #f])))
(cond
[(< (string-length S) 7) "too few characters"]
[(> (string-length S) 7) "too many characters"]
[(not (zero? (modulo (SEDOL-character-sum S) 10))) "invalid checksum"]
[(for/first ((c S) #:when (invalid-SEDOL-character? c)) c) => identity]
[else #f])) ; a.k.a. valid!
 
(module+ main
do k=1 for 6 /*process each character in SEDOL*/
(for* ((S input-SEDOLS))
sum=sum+(pos(substr(sedol,k,1),alphaDigs)-1)*substr(weights,k,1)
(displayln (SEDOL-append-checksum S)))
end /*k*/
(newline)
(displayln "Extra Credit!")
(displayln (invalid-SEDOL? "B0YBKT7")) ; expect #f output
(displayln (invalid-SEDOL? "B000301")) ; expect "invalid checksum" output
)
 
(module+ test
chkDig=(10-sum//10) // 10
(require rackunit)
r=right(sedol,1)
(check-= (SEDOL-character-value #\3) 3 0)
if L==7 & chkDig\==r then call ser sedol,'invalid check digit:' r
(check-= (SEDOL-character-value #\B) 11 0)
say 'SEDOL:' left(sedol,9) 'SEDOL + check digit:' left(sedol,6)chkDig
(check-equal? (invalid-SEDOL? "B000301") "invalid checksum")
end /*j*/
(for ((S output-SEDOLS))
(check-false (invalid-SEDOL? S))
(check-equal? (SEDOL-append-checksum (substring S 0 6))
S (format "test SEDOL for ~a" S))))</syntaxhighlight>
 
Output:
exit
<pre>7108899
/*─────────────────────────────────────subroutines──────────────────────*/
B0YBKJ7
sed: say; say 'SEDOL:' sedol; say; return
4065663
ser: say; say '*** error! ***'; say; say arg(1); call sed; exit 13
B0YBLH2
swa: say; say '*** warning! ***' arg(1); say; return</lang>
2282765
'''output''' when using the defaults:
B0YBKL9
<pre style="overflow:scroll">
5579107
SEDOL: 710889 SEDOL + check digit: 7108899
B0YBKR5
SEDOL: B0YBKJ SEDOL + check digit: B0YBKJ7
5852842
SEDOL: 406566 SEDOL + check digit: 4065663
B0YBKT7
SEDOL: B0YBLH SEDOL + check digit: B0YBLH2
B000300
SEDOL: 228276 SEDOL + check digit: 2282765
SEDOL: B0YBKL SEDOL + check digit: B0YBKL9
SEDOL: 557910 SEDOL + check digit: 5579107
SEDOL: B0YBKR SEDOL + check digit: B0YBKR5
SEDOL: 585284 SEDOL + check digit: 5852842
SEDOL: B0YBKT SEDOL + check digit: B0YBKT7
SEDOL: B00030 SEDOL + check digit: B000300
</pre>
 
Extra Credit!
=={{header|Ruby}}==
#f
<lang ruby>def char2value(c)
invalid checksum</pre>
raise "No vowels" if 'AEIOU'.include?(c)
c.to_i(36)
end
 
=={{header|Raku}}==
Sedolweight = [1,3,1,7,3,9]
(formerly Perl 6)
{{trans|Perl}}
{{Works with|rakudo|2015-12-17}}
<syntaxhighlight lang="raku" line>sub sedol( Str $s ) {
die 'No vowels allowed' if $s ~~ /<[AEIOU]>/;
die 'Invalid format' if $s !~~ /^ <[0..9B..DF..HJ..NP..TV..Z]>**6 $ /;
 
my %base36 = (flat 0..9, 'A'..'Z') »=>« ^36;
def checksum(sedol)
my @weights = 1, 3, 1, 7, 3, 9;
tmp = sedol.split('').zip(Sedolweight).map { |ch, weight|
char2value(ch) * weight }.inject(0) { |sum, x|
sum + x }
((10 - (tmp % 10)) % 10).to_s
end
 
my @vs = %base36{ $s.comb };
for sedol in %w{
my $checksum = [+] @vs Z* @weights;
my $check_digit = (10 - $checksum % 10) % 10;
return $s ~ $check_digit;
}
 
say sedol($_) for <
710889
B0YBKJ
Line 1,658 ⟶ 3,555:
585284
B0YBKT
}B00030
>;</syntaxhighlight>
 
=={{header|REXX}}==
<pre>
╔════════════════════════════════════════════════════════════════════╗
║ If the SEDOL is 6 characters, a check digit is added. ║
║ ║
║ If the SEDOL is 7 characters, a check digit is created and it's ║
║ verified that it's equal to the check digit already on the SEDOL. ║
╚════════════════════════════════════════════════════════════════════╝
</pre>
<syntaxhighlight lang="rexx">/*REXX program computes the check digit (last digit) for six or seven character SEDOLs.*/
@abcU = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' /*the uppercase Latin alphabet. */
alphaDigs= '0123456789'@abcU /*legal characters, and then some. */
allowable=space(translate(alphaDigs,,'AEIOU'),0) /*remove the vowels from the alphabet. */
weights = 1317391 /*various weights for SEDOL characters.*/
@.= /* [↓] the ARG statement capitalizes. */
arg @.1 . /*allow a user─specified SEDOL from CL*/
if @.1=='' then do /*if none, then assume eleven defaults.*/
@.1 = 710889 /*if all numeric, we don't need quotes.*/
@.2 = 'B0YBKJ'
@.3 = 406566
@.4 = 'B0YBLH'
@.5 = 228276
@.6 = 'B0YBKL'
@.7 = 557910
@.8 = 'B0YBKR'
@.9 = 585284
@.10 = 'B0YBKT'
@.11 = 'B00030'
end
 
do j=1 while @.j\==''; sedol=@.j /*process each of the specified SEDOLs.*/
L=length(sedol)
if L<6 | L>7 then call ser "SEDOL isn't a valid length"
if left(sedol,1)==9 then call swa 'SEDOL is reserved for end user allocation'
_=verify(sedol, allowable)
if _\==0 then call ser 'illegal character in SEDOL:' substr(sedol, _, 1)
sum=0 /*the checkDigit sum (so far). */
do k=1 for 6 /*process each character in the SEDOL. */
sum=sum + ( pos( substr(sedol, k, 1), alphaDigs) -1) * substr(weights, k, 1)
end /*k*/
 
chkDig= (10-sum//10) // 10
r=right(sedol, 1)
if L==7 & chkDig\==r then call ser sedol, 'invalid check digit:' r
say 'SEDOL:' left(sedol,15) 'SEDOL + check digit ───► ' left(sedol,6)chkDig
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
sed: say; say 'SEDOL:' sedol; say; return
ser: say; say '***error***' arg(1); call sed; exit 13
swa: say; say '***warning***' arg(1); say; return</syntaxhighlight>
'''output''' &nbsp; when using the defaults:
<pre>
SEDOL: 710889 SEDOL + check digit ───► 7108899
SEDOL: B0YBKJ SEDOL + check digit ───► B0YBKJ7
SEDOL: 406566 SEDOL + check digit ───► 4065663
SEDOL: B0YBLH SEDOL + check digit ───► B0YBLH2
SEDOL: 228276 SEDOL + check digit ───► 2282765
SEDOL: B0YBKL SEDOL + check digit ───► B0YBKL9
SEDOL: 557910 SEDOL + check digit ───► 5579107
SEDOL: B0YBKR SEDOL + check digit ───► B0YBKR5
SEDOL: 585284 SEDOL + check digit ───► 5852842
SEDOL: B0YBKT SEDOL + check digit ───► B0YBKT7
SEDOL: B00030 SEDOL + check digit ───► B000300
</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
see sedol("710889") + nl
see sedol("B0YBKJ") + nl
see sedol("406566") + nl
see sedol("B0YBLH") + nl
see sedol("228276") + nl
see sedol("B0YBKL") + nl
see sedol("557910") + nl
see sedol("B0YBKR") + nl
see sedol("585284") + nl
see sedol("B0YBKT") + nl
see sedol("B00030") + nl
func sedol d
d = upper(d)
s = 0
weights = [1, 3, 1, 7, 3, 9]
for i = 1 to 6
a = substr(d,i,1)
if ascii(a) >= 48 and ascii(a) <= 57
s += number(a) * weights[i]
else
s += (ascii(a) - 55) * weights[i] ok
next
return d + (10 - (s % 10)) % 10
</syntaxhighlight>
Output:
<pre>
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
</pre>
 
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
{ 1 3 1 7 3 9 } → weights
≪ 0 1 6 '''FOR''' j
OVER j DUP SUB NUM
'''IF''' DUP 65 ≥ '''THEN''' 7 - '''END''' 48 -
weights j GET * +
'''NEXT'''
10 SWAP OVER MOD - 10 MOD →STR +
≫ ≫ ''''→7DOL'''' STO
|
'''→7DOL''' ''( "SEDOL6" -- "SEDOL7" ) ''
store weights
sum=0 ; for j = 1 to 6
get jth character of SEDOL
convert it to its index
sum += index * weight
check = mod(10-mod(sum,10),10)
.
|}
{{in}}
<pre>
≪ { }
{ "710889" "B0YBKJ" "406566" "B0YBLH" "228276" "B0YBKL" "557910" "B0YBKR" "585284" "B0YBKT" "B00030" }
1 OVER SIZE FOR j DUP j GET →7DOL SWAP + SWAP NEXT DROP
≫ EVAL
</pre>
{{out}}
<pre>
1: { "7108899" "B0YBKJ7" "4065663" "B0YBLH2" "2282765" "B0YBKL9" "5579107" "B0YBKR5" "5852842" "B0YBKT7" "B000300" }
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">Sedol_char = "0123456789BCDFGHJKLMNPQRSTVWXYZ"
Sedolweight = [1,3,1,7,3,9]
 
def char2value(c)
raise ArgumentError, "Invalid char #{c}" unless Sedol_char.include?(c)
c.to_i(36)
end
def checksum(sedol)
raise ArgumentError, "Invalid length" unless sedol.size == Sedolweight.size
sum = sedol.chars.zip(Sedolweight).sum{|ch, weight| char2value(ch) * weight }
((10 - (sum % 10)) % 10).to_s
end
data = %w(710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT
B00030
C0000
1234567
00000A)
data.each do |sedol|
print "%-8s " % sedol
begin
puts sedol + checksum(sedol)
rescue => e
end</lang>
p e
end
end</syntaxhighlight>
{{out}}
<pre>
710889 7108899
B0YBKJ B0YBKJ7
406566 4065663
B0YBLH B0YBLH2
228276 2282765
B0YBKL B0YBKL9
557910 5579107
B0YBKR B0YBKR5
585284 5852842
B0YBKT B0YBKT7
B00030 B000300
C0000 #<ArgumentError: Invalid length>
1234567 #<ArgumentError: Invalid length>
00000A #<ArgumentError: No vowels>
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">
fn sedol(input: &str) -> Option<String> {
let weights = vec![1, 3, 1, 7, 3, 9, 1];
let valid_chars = "0123456789BCDFGHJKLMNPQRSTVWXYZ";
 
if input.len() != 6 {
return None;
}
 
// could be done by regex if needed
for c in input.chars() {
if !valid_chars.contains(c) {
return None;
}
}
 
let mut result: u32 = input
.chars()
.map(|c| {
if c.is_digit(10) {
c as u32 - 48
} else {
c as u32 - 55
}
})
.zip(weights)
.map(|(cnum, w)| w * cnum)
.collect::<Vec<u32>>()
.iter()
.sum();
 
result = (10 - result % 10) % 10;
 
Some(input.to_owned() + &result.to_string())
}
 
fn main() {
let inputs = vec![
"710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL", "557910", "B0YBKR", "585284",
"B0YBKT", "B00030",
];
 
for input in inputs {
println!("{} SEDOL: {:?}", &input, sedol(&input).unwrap());
}
}
 
</syntaxhighlight>
{{out}}
<pre>
710889 SEDOL: "7108899"
B0YBKJ SEDOL: "B0YBKJ7"
406566 SEDOL: "4065663"
B0YBLH SEDOL: "B0YBLH2"
228276 SEDOL: "2282765"
B0YBKL SEDOL: "B0YBKL9"
557910 SEDOL: "5579107"
B0YBKR SEDOL: "B0YBKR5"
585284 SEDOL: "5852842"
B0YBKT SEDOL: "B0YBKT7"
B00030 SEDOL: "B000300"
</pre>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">class SEDOL(s: String) {
require(s.size == 6 || s.size == 7, "SEDOL length must be 6 or 7 characters")
require(s.size == 6 || s(6).asDigit == chksum, "Incorrect SEDOL checksum")
Line 1,669 ⟶ 3,832:
def chksum = 10 - ((s zip List(1, 3, 1, 7, 3, 9) map { case (c, w) => c.asDigit * w } sum) % 10)
override def toString = s.take(6) + chksum
}</langsyntaxhighlight>
 
Test cases:
Line 1,710 ⟶ 3,873:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func char: sedolCheckDigit (in string: sedol) is func
Line 1,744 ⟶ 3,907:
writeln(sedol <& sedolCheckDigit(sedol));
end for;
end func;</langsyntaxhighlight>
 
{{out}}
Output:
<pre>
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
</pre>
 
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">func sedol(s) {
 
die 'No vowels allowed' if (s ~~ /[AEIOU]/);
die 'Invalid format' if (s !~ /^[0-9B-DF-HJ-NP-TV-Z]{6}$/);
 
const base36 = ((@(0..9) + @('A'..'Z')) ~Z @(0..35) -> flatten.to_h);
const weights = [1, 3, 1, 7, 3, 9];
 
var vs = [base36{ s.chars... }];
var checksum = (vs ~Z* weights -> sum);
var check_digit = ((10 - checksum%10) % 10);
return (s + check_digit);
}
 
%w(
710889
B0YBKJ
406566
B0YBLH
228276
B0YBKL
557910
B0YBKR
585284
B0YBKT
B00030
).each { |s|
say sedol(s);
}</syntaxhighlight>
{{out}}
<pre>
7108899
Line 1,763 ⟶ 3,972:
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
<langsyntaxhighlight lang="smalltalk">String extend [
includesAnyOf: aSet [
aSet do: [ :e | (self includes: e) ifTrue: [ ^true ] ].
^false
]
].</langsyntaxhighlight>
 
<langsyntaxhighlight lang="smalltalk">Object subclass: SEDOL [
|weight charList|
 
Line 1,812 ⟶ 4,021:
]
]
].</langsyntaxhighlight>
 
<langsyntaxhighlight lang="smalltalk">|sedol|
sedol := SEDOL new.
{ '710889'.
Line 1,825 ⟶ 4,034:
'B0YBKR'.
'585284'.
'B0YBKT' } do: [ :c | (sedol checked: c) displayNl ]</langsyntaxhighlight>
 
{{works with|Smalltalk/X}}
<syntaxhighlight lang="smalltalk">#(
'710889'
'B0YBKJ'
'406566'
'B0YBLH'
'228276'
'B0YBKL'
'557910'
'B0YBKR'
'585284'
'B0YBKT'
'B00030'
) do:[:in |
|um check|
 
sum := 0.
(in to:6) with:#[1 3 1 7 3 9 ] do:[:ch :weight |
sum := sum + (ch digitValue * weight).
].
check := (10 - (sum%10)) % 10.
Transcript showCR: ( in,(Character digitValue:check))
].</syntaxhighlight>
{{out}}
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
 
=={{header|SQL PL}}==
{{works with|Db2 LUW}} version 9.7 or higher.
With SQL PL:
<syntaxhighlight lang="sql pl">
--#SET TERMINATOR @
 
SET SERVEROUTPUT ON@
 
CREATE OR REPLACE FUNCTION CHECK_SEDOL (
IN TEXT VARCHAR(6)
) RETURNS VARCHAR(7)
BEGIN
DECLARE TYPE SEDOL AS CHAR(1) ARRAY [6];
--declare text varchar(6) default 'B12345';
DECLARE WEIGHT SEDOL;
DECLARE I SMALLINT;
DECLARE SENTENCE VARCHAR(256);
DECLARE CHAR_AT CHAR(1);
DECLARE OUTPUT CHAR(1);
DECLARE SUM SMALLINT;
DECLARE CHECK SMALLINT;
DECLARE INVALID_CHAR CONDITION FOR SQLSTATE '22004' ;
DECLARE STMT STATEMENT;
 
-- Converts all to upper.
SET TEXT = UPPER (TEXT);
-- CALL DBMS_OUTPUT.PUT_LINE(TEXT);
-- Checks the characters.
SET I = 1;
WHILE (I <= 6) DO
SET CHAR_AT = SUBSTR(TEXT, I, 1);
-- CALL DBMS_OUTPUT.PUT_LINE('Char ' || CHAR_AT);
SET SENTENCE = 'SET ? = (SELECT SEDOL FROM (SELECT ''' || CHAR_AT
|| ''' SEDOL FROM SYSIBM.SYSDUMMY1) WHERE SEDOL IN (''B'',''C'',''D'',''F'',''G'',''H'',''J'','
|| '''K'',''L'',''M'',''N'',''P'',''Q'',''R'',''S'',''T'',''V'',''W'',''X'',''Y'',''Z'',''0'','
|| '''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9''))';
PREPARE STMT FROM SENTENCE;
EXECUTE STMT INTO OUTPUT;
IF (OUTPUT IS NULL) THEN
SIGNAL INVALID_CHAR;
END IF;
SET I = I + 1;
END WHILE;
-- Assigns weight
SET WEIGHT[1] = '1';
SET WEIGHT[2] = '3';
SET WEIGHT[3] = '1';
SET WEIGHT[4] = '7';
SET WEIGHT[5] = '3';
SET WEIGHT[6] = '9';
 
-- Process the SEDOL.
SET SUM = 0;
SET I = 1;
WHILE (I <= 6) DO
SET CHAR_AT = SUBSTR(TEXT, I, 1);
IF (ASCII(CHAR_AT) > 65) THEN
SET SUM = SUM + WEIGHT[I] * (ASCII(CHAR_AT) - 64 + 9);
ELSE
SET SUM = SUM + WEIGHT[I] * CHAR_AT;
END IF;
SET I = I + 1;
END WHILE;
SET CHECK = MOD((10 - MOD(SUM, 10)), 10);
CALL DBMS_OUTPUT.PUT_LINE(CHECK);
RETURN TEXT || CHECK;
END @
</syntaxhighlight>
Output:
<pre>
db2 -td@
db2 => SET SERVEROUTPUT ON@
DB20000I The SET SERVEROUTPUT command completed successfully.
db2 => CREATE OR REPLACE FUNCTION CHECK_SEDOL (
...
db2 (cont.) => END @
DB20000I The SQL command completed successfully.
 
db2 -x
db2 => values CHECK_SEDOL('710889')
7108899
9
db2 => values CHECK_SEDOL('B0YBKJ')
B0YBKJ7
7
db2 => values CHECK_SEDOL('406566')
4065663
3
db2 => values CHECK_SEDOL('B0YBLH')
B0YBLH2
2
db2 => values CHECK_SEDOL('228276')
2282765
5
db2 => values CHECK_SEDOL('B0YBKL')
B0YBKL9
9
db2 => values CHECK_SEDOL('557910')
5579107
7
db2 => values CHECK_SEDOL('B0YBKR')
B0YBKR5
5
db2 => values CHECK_SEDOL('585284')
5852842
2
db2 => values CHECK_SEDOL('B0YBKT')
B0YBKT7
7
db2 => values CHECK_SEDOL('B00030')
B000300
0
</pre>
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">fun char2value c =
if List.exists (fn x => x = c) (explode "AEIOU") then raise Fail "no vowels"
else if Char.isDigit c then ord c - ord #"0"
Line 1,853 ⟶ 4,213:
"B0YBKR",
"585284",
"B0YBKT" ];</langsyntaxhighlight>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">namespace eval sedol {
variable chars {0 1 2 3 4 5 6 7 8 9 "" B C D "" F G H "" J K L M N "" P Q R S T "" V W X Y Z}
variable weight {1 3 1 7 3 9 1}
Line 1,893 ⟶ 4,253:
assert {$sedol eq $answer} "assertion failed: $sedol ne $answer"
puts $sedol
}</langsyntaxhighlight>
 
=={{header|TTransact-SQL}}==
SQL Server transact-SQL implementation. Compatible with all versions from 6.5 to 2008.
Returns empty string if invalid.
 
<syntaxhighlight lang="tsql">CREATE FUNCTION [dbo].[fn_CheckSEDOL]
examples:
print dbo.fn_CheckSEDOL('710889')
print dbo.fn_CheckSEDOL('B0YBKJ')
print dbo.fn_CheckSEDOL('406566')
print dbo.fn_CheckSEDOL('B0YBLH')
print dbo.fn_CheckSEDOL('228276')
print dbo.fn_CheckSEDOL('B0YBKL')
print dbo.fn_CheckSEDOL('557910')
print dbo.fn_CheckSEDOL('B0YBKR')
print dbo.fn_CheckSEDOL('585284')
print dbo.fn_CheckSEDOL('B0YBKT')
print dbo.fn_CheckSEDOL('B00030')
 
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
 
<lang tsql>
 
CREATE FUNCTION [dbo].[fn_CheckSEDOL]
( @SEDOL varchar(50) )
RETURNS varchar(7)
Line 1,988 ⟶ 4,321:
-- Return the result of the function
RETURN @SEDOL
END</syntaxhighlight>
END
 
Examples:
</lang>
<pre>print dbo.fn_CheckSEDOL('710889')
print dbo.fn_CheckSEDOL('B0YBKJ')
print dbo.fn_CheckSEDOL('406566')
print dbo.fn_CheckSEDOL('B0YBLH')
print dbo.fn_CheckSEDOL('228276')
print dbo.fn_CheckSEDOL('B0YBKL')
print dbo.fn_CheckSEDOL('557910')
print dbo.fn_CheckSEDOL('B0YBKR')
print dbo.fn_CheckSEDOL('585284')
print dbo.fn_CheckSEDOL('B0YBKT')
print dbo.fn_CheckSEDOL('B00030')
 
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300</pre>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
check="1'3'1'7'3'9"
Line 2,014 ⟶ 4,370:
PRINT input, " checkdigit: ", checksum
ENDLOOP
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,038 ⟶ 4,394:
to the list of character values.
 
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 2,045 ⟶ 4,401:
charval = -:@rlXS num alphabet
iprod = sum:-0+ product*p/weights+ charval*
checksum = difference/10+ remainder\10+ iprod</langsyntaxhighlight>
 
An optimization following the J solution avoids a run-time subtraction
by complementing the coefficients at compile time using these
definitions in place of those above.
<langsyntaxhighlight Ursalalang="ursala">weights = difference/*10 <1,3,1,7,3,9>
checksum = remainder\10+ iprod</langsyntaxhighlight>
 
A further performance improvement subsumes the character value lookup
Line 2,057 ⟶ 4,413:
the version shown below.
 
<langsyntaxhighlight Ursalalang="ursala">lookup = -: (^/~& product^|/~& charval)*lsPrK0/weights alphabet
iprod = sum:-0+ lookup*p/weights</langsyntaxhighlight>
 
To optimize further, we can build a separate smaller multiplication table for
Line 2,065 ⟶ 4,421:
index directly into the input list.
 
<langsyntaxhighlight Ursalalang="ursala">lookups = (-:+ * ^/~&l product^|/charval ~&)* *-* -*weights alphabet
iprod = sum:-0+ gang +^|(~&,~)*lNrXXK9 ^(~&,&h!)* lookups</langsyntaxhighlight>
Here is a test program.
<langsyntaxhighlight Ursalalang="ursala">#show+
 
examples = ^T(~&,~&h+ %nP+ checksum)*t
Line 2,082 ⟶ 4,438:
B0YBKR
585284
B0YBKT]-</langsyntaxhighlight>
output:
<pre>7108899
Line 2,094 ⟶ 4,450:
5852842
B0YBKT7</pre>
 
=={{header|VBA}}==
<syntaxhighlight lang="lb">Function getSedolCheckDigit(Input1)
Dim mult(6) As Integer
mult(1) = 1: mult(2) = 3: mult(3) = 1
mult(4) = 7: mult(5) = 3: mult(6) = 9
If Len(Input1) <> 6 Then
getSedolCheckDigit = "Six chars only please"
Exit Function
End If
Input1 = UCase(Input1)
Total = 0
For i = 1 To 6
s1 = Mid(Input1, i, 1)
If (s1 = "A") Or (s1 = "E") Or (s1 = "I") Or (s1 = "O") Or (s1 = "U") Then
getSedolCheckDigit = "No vowels"
Exit Function
End If
If (Asc(s1) >= 48) And (Asc(s1) <= 57) Then
Total = Total + Val(s1) * mult(i)
Else
Total = Total + (Asc(s1) - 55) * mult(i)
End If
Next i
getSedolCheckDigit = Input1 + CStr((10 - (Total Mod 10)) Mod 10)
End Function</syntaxhighlight>
 
=={{header|VBScript}}==
Derived from the BASIC version.
<syntaxhighlight lang="vbscript">
arr = Array("710889",_
"B0YBKJ",_
"406566",_
"B0YBLH",_
"228276",_
"B0YBKL",_
"557910",_
"B0YBKR",_
"585284",_
"B0YBKT",_
"12345",_
"A12345",_
"B00030")
 
For j = 0 To UBound(arr)
WScript.StdOut.Write arr(j) & getSEDOLCheckDigit(arr(j))
WScript.StdOut.WriteLine
Next
 
Function getSEDOLCheckDigit(str)
If Len(str) <> 6 Then
getSEDOLCheckDigit = " is invalid. Only 6 character strings are allowed."
Exit Function
End If
Set mult = CreateObject("Scripting.Dictionary")
With mult
.Add "1","1" : .Add "2", "3" : .Add "3", "1"
.Add "4","7" : .Add "5", "3" : .Add "6", "9"
End With
total = 0
For i = 1 To 6
s = Mid(str,i,1)
If s = "A" Or s = "E" Or s = "I" Or s = "O" Or s = "U" Then
getSEDOLCheckDigit = " is invalid. Vowels are not allowed."
Exit Function
End If
If Asc(s) >= 48 And Asc(s) <=57 Then
total = total + CInt(s) * CInt(mult.Item(CStr(i)))
Else
total = total + (Asc(s) - 55) * CInt(mult.Item(CStr(i)))
End If
Next
getSEDOLCheckDigit = (10 - total Mod 10) Mod 10
End Function</syntaxhighlight>
 
{{out}}
<pre>7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
12345 is invalid. Only 6 character strings are allowed.
A12345 is invalid. Vowels are not allowed.
B000300</pre>
 
=={{header|Visual FoxPro}}==
<syntaxhighlight lang="vfp">
#DEFINE ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#DEFINE VOWELS "AEIOU"
#DEFINE VALIDCHARS "0123456789" + ALPHABET
LOCAL cMsg As String, cCode As String
LOCAL ARRAY codes[12]
codes[1] = "710889"
codes[2] = "B0YBKJ"
codes[3] = "406566"
codes[4] = "B0YBLH"
codes[5] = "228276"
codes[6] = "B0YBKL"
codes[7] = "557910"
codes[8] = "B0YBKR"
codes[9] = "585284"
codes[10] = "B0YBKT"
codes[11] = "B00030"
codes[12] = "B0030A"
DIMENSION w[6]
w[1] = 1
w[2] = 3
w[3] = 1
w[4] = 7
w[5] = 3
w[6] = 9
CLEAR
FOR EACH cCode IN codes
cMsg = ""
IF IsValidCode(@cCode, @cMsg) && Parameters passed by reference
cCode = cCode + GetCheckDigit(cCode)
? cCode
ELSE
? cCode, cMsg
ENDIF
ENDFOR
 
FUNCTION GetCheckDigit(tcCode As String) As String
LOCAL i As Integer, c As String, s As Integer, k As Integer
s = 0
FOR i = 1 TO 6
c = SUBSTR(tcCode, i, 1)
IF ISDIGIT(c)
k = VAL(c)
ELSE
k = 9 + AT(c, ALPHABET)
ENDIF
s = s + k*w[i]
ENDFOR
RETURN TRANSFORM((10 - s%10)%10)
ENDFUNC
 
FUNCTION IsValidCode(tcCode As String, tcMsg As String) As Boolean
LOCAL n As Integer, c As String, i As Integer
*!* Get rid of any spaces and convert to upper case
tcCode = UPPER(STRTRAN(tcCode, " "))
n = LEN(tcCode)
IF LEN(tcCode) # 6
tcMsg = "Code must be 6 characters."
ELSE
FOR i = 1 TO n
c = SUBSTR(tcCode, i, 1)
IF NOT c $ VALIDCHAR
tcMsg = c + " is not a valid character."
EXIT
ELSE
IF c $ VOWELS
tcMsg = "Vowels are not allowed."
EXIT
ENDIF
ENDIF
ENDFOR
ENDIF
RETURN EMPTY(tcMsg)
ENDFUNC
</syntaxhighlight>
{{out}}
<pre>
Output as in task description.
The last code is printed as BOO30A Vowels are not allowed.
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-str}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./str" for Char
import "./fmt" for Conv
 
var sedol = Fn.new { |s|
if (!(s is String && s.count == 6)) return false
var weights = [1, 3, 1, 7, 3, 9]
var sum = 0
for (i in 0..5) {
var c = s[i]
if (!Char.isUpper(c) && !Char.isDigit(c)) return null
if ("AEIOU".contains(c)) return null
sum = sum + Conv.atoi(c, 36) * weights[i]
}
var cd = (10 - sum%10) % 10
return s + "%(cd)"
}
 
var tests = [
"710889",
"B0YBKJ",
"406566",
"B0YBLH",
"228276",
"B0YBKL",
"557910",
"B0YBKR",
"585284",
"B0YBKT",
"B00030",
"I23456"
]
 
for (test in tests) {
var a
var ans = (a = sedol.call(test)) ? a : "not valid"
System.print("%(test) -> %(ans)")
}</syntaxhighlight>
 
{{out}}
<pre>
B0YBKJ -> B0YBKJ7
406566 -> 4065663
B0YBLH -> B0YBLH2
228276 -> 2282765
B0YBKL -> B0YBKL9
557910 -> 5579107
B0YBKR -> B0YBKR5
585284 -> 5852842
B0YBKT -> B0YBKT7
B00030 -> B000300
I23456 -> not valid
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">string 0; \use zero-terminated strings
 
func CheckDigit(Str); \Return the check digit for a SEDOL
char Str;
int Sum, I, C, V;
[Sum:= 0;
for I:= 0 to 6-1 do
[C:= Str(I);
case of
C>=^0 & C<=^9: V:= C-^0;
C>=^A & C<=^Z: V:= C-^A+10
other V:= -1;
case I of
1, 4: V:= V*3;
3: V:= V*7;
5: V:= V*9
other [];
Sum:= Sum+V;
];
return rem( (10 - rem(Sum/10)) / 10 ) + ^0;
];
 
int Sedol, N;
[Sedol:= ["710889",
"B0YBKJ",
"406566",
"B0YBLH",
"228276",
"B0YBKL",
"557910",
"B0YBKR",
"585284",
"B0YBKT",
"B00030"];
for N:= 0 to 11-1 do
[Text(0, Sedol(N));
ChOut(0, CheckDigit(Sedol(N)));
CrLf(0);
];
]</syntaxhighlight>
 
{{out}}
<pre>
7108899
B0YBKJ7
4065663
B0YBLH2
2282765
B0YBKL9
5579107
B0YBKR5
5852842
B0YBKT7
B000300
</pre>
 
=={{header|Yabasic}}==
<syntaxhighlight lang="yabasic">data "710889", "B0YBKJ", "406566", "B0YBLH", "228276", "B0YBKL", "557910", "B0YBKR", "585284", "B0YBKT", "B00030", "AB", "B00A03", ""
 
do
read d$
if d$ = "" break
print sedol$(d$)
loop
 
sub sedol$(d$)
LOCAL a, i, s, weights$(1)
a = len(d$)
if a < 6 or a > 6 return d$ + ": Error in length"
for i = 1 to 6
if not instr("BCDFGHJKLMNPQRSTVWXYZ0123456789", mid$(d$, i, 1)) return d$ + ": Error in symbol " + mid$(d$, i, 1)
next
a = token("1 3 1 7 3 9", weights$())
FOR i = 1 TO 6
a = ASC(MID$(d$, i, 1)) - 48
s = s + (a + 3 * (a > 9)) * val(weights$(i))
NEXT
return d$ + CHR$(48 + mod(10 - mod(s, 10), 10))
end sub</syntaxhighlight>
 
=={{header|zkl}}==
<syntaxhighlight lang="zkl">fcn checksum(text){
( text.len()!=6 or (text..matches("*[AEIOUaeioua-z]*")) ) and
throw(Exception.ValueError("Invalid SEDOL text: "+text));
 
text + (10 - text.pump(List,'wrap(c){
if("0"<=c<="9") c.toAsc()-0x30;
else c.toAsc()-55;
}).zipWith('*,T(1,3,1,7,3,9)).sum() % 10) % 10;
}</syntaxhighlight>
It sure does look like that trailing %10 is extraneous. It also seems like lower case is implicitly invalid.
<syntaxhighlight lang="zkl">T("710889","B0YBKJ","406566","B0YBLH","228276",
"B0YBKL","557910","B0YBKR","585284","B0YBKT","B00030")
.apply(checksum).println();</syntaxhighlight>
{{out}}
<pre>
L("7108899","B0YBKJ7","4065663","B0YBLH2","2282765","B0YBKL9",
"5579107","B0YBKR5","5852842","B0YBKT7","B000300")
</pre>
 
 
{{omit from|GUISS}}
890

edits