# Why Q?

• Performance
• Expressiveness
• Fun-ctional

# HKID

Convert English letters to number, using the mapping A->10, B->11, C->12 …. Z->35

• character vectors

q)"ABCDEFGHIJKLMNOPQRSTUVWXYZ"

• .q.k

q).Q.n
"0123456789"
q).Q.A
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
q).Q.nA
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
q).Q.na
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"
q).Q.b6
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

• character to integer

q)-55+"j"$"AZ123456" 10 35 -6 -5 -4 -3 -2 -1  • find q).Q.nA?"AZ123456" 10 35 1 2 3 4 5 6  # The Sum • Calculate the check sum • For HKID with 2 English letters check sum = char[0] * 9 + char[1] * 8 + char[2] * 7 + char[3] * 6 + char[4] * 5 + char[5] * 4 + char[6] * 3 + char[7] * 2 • For HKID with only 1 English letter check sum = 36 * 9 + char[1] * 8 + char[2] * 7 + char[3] * 6 + char[4] * 5 + char[5] * 4 + char[6] * 3 + char[7] * 2 • what is 36? q)-55+"j"$"[Z123456"
36 35 -6 -5 -4 -3 -2 -1

• one past the end

q).Q.nA?" Z123456"
36 35 1 2 3 4 5 6

• reshaping lists

q)-8#"[","AZ123456"
"AZ123456"
q)-8#"[","Z123456"
"[Z123456"


q)-8$"Z123456" " Z123456" q)-8$"AZ123456"
"AZ123456"

• vector arithmetic

q)9 8 7 6 5 4 3 2 * .Q.nA?-8$" Z123456" 324 280 7 12 15 16 15 12 q)sum 9 8 7 6 5 4 3 2 * .Q.nA?-8$" Z123456"
681

• dot product

q)9 8 7 6 5 4 3 2f $"f"$.Q.nA?-8$" Z123456" 681f  # The Checksum • mooderate check sum by 11 and use 11 to minus the value • check digit = 11 - checksum mod 11 • modulus q)11 - mod[;11] sum 9 8 7 6 5 4 3 2*.Q.nA?-8$" Z123456"
1
q).Q.nA 11 - mod[;11] sum 9 8 7 6 5 4 3 2*.Q.nA?-8$" Z123456" "1"  • reorder operations q).Q.nA mod[;11] sum 2 3 4 5 6 7 8 9*.Q.nA?-8$" Z123456"
"1"

• lookup table

q)sum 2 3 4 5 6 7 8 9*.Q.nA?-8$" Z999999" 528 q)(529#.Q.n,"A")sum 2 3 4 5 6 7 8 9*.Q.nA?-8$" Z123456"
"1"


# Solutions

• the shortest (composition)

q)hkidcheck:(529#.Q.n,"A")sum 2 3 4 5 6 7 8 9*.Q.nA?-8$q)\ts:100000 hkidcheck each ids 1487 640  • the fastest (projection) q)hkidcheck:{x sum 2 3 4 5 6 7 8 9*y?-8$z}[529#.Q.n,"A";.Q.nA]
q)\ts:100000 hkidcheck each ids
1335 672

• the longest

hkidcheck:{[id]
$[(count id)=8;[abc1:"i"$id[0];abc1:abc1-55;abc2:"i"$id[1];abc2:abc2-55;adigit1:"i"$id[2];adigit2:"i"$id[3];adigit3:"i"$id[4];adigit4:"i"$id[5];adigit5:"i"$id[6];adigit6:"i"$id[7];p1:(abc1*9)];[abc1:324;p1:abc1;abc2:"i"$id[0];abc2-:55;adigit1:"i"$id[1];adigit2:"i"$id[2];adigit3:"i"$id[3];adigit4:"i"$id[4];adigit5:"i"$id[5];adigit6:"i"$id[6]]];
p2:abc2*8;
s1:p1+p2;
s2:p3+p4;
s3:p5+p6;
s4:p7+p8;
s5:s1+s2;
s6:s3+s4;
sumtotal:s5+s6;
remainder:(sumtotal mod 11);
checksum:(11-remainder);
checksum }

• the winner

q)hkidcheck:eval parse"{\"",((2231#"B"),1000#"0", .Q.nA 10-til 10),"\" sum (9 8 7 6 5 4 3 2i)*6h[7=count x; \"[\",x; x]}"
q)\ts:100000 hkidcheck each ids
1350 512


# SEDOL

The check digit for a SEDOL is chosen to make the total weighted sum of all seven characters a multiple of 10. The check digit is computed using a weighted sum of the first six characters. Letters have the value of 9 plus their alphabet position, such that B = 11 and Z = 35. While vowels are never used in SEDOLs, they are not ignored when computing this weighted sum (e.g. H = 17 and J = 19, even though I is not used), simplifying code to compute this sum. The resulting string of numbers is then multiplied by the weighting factor as follows:

First   1
Second  3
Third   1
Fourth  7
Fifth   3
Sixth   9
Seventh 1 (the check digit)


# Insights

• A HKID is a vector of characters
• The modulus operator is slow (but cyclical)
• Fixed values can be pre-calculate

Tags:

Categories:

Updated: