I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# CUSIP

CUSIP
You are encouraged to solve this task according to the task description, using any language you may know.
 This page uses content from Wikipedia. The original article was at CUSIP. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)

A   CUSIP   is a nine-character alphanumeric code that identifies a North American financial security for the purposes of facilitating clearing and settlement of trades. The CUSIP was adopted as an American National Standard under Accredited Standards X9.6.

Ensure the last digit   (i.e., the   check digit)   of the CUSIP code (the 1st column) is correct, against the following:

•   037833100       Apple Incorporated
•   17275R102       Cisco Systems
•   594918104       Microsoft Corporation
•   68389X106       Oracle Corporation   (incorrect)
•   68389X105       Oracle Corporation

Example pseudo-code below.
`algorithm Cusip-Check-Digit(cusip) is   Input: an 8-character CUSIP    sum := 0   for 1 ≤ i ≤ 8 do      c := the ith character of cusip      if c is a digit then         v := numeric value of the digit c      else if c is a letter then         p := ordinal position of c in the alphabet (A=1, B=2...)         v := p + 9      else if c = "*" then         v := 36      else if c = "@" then         v := 37      else if' c = "#" then         v := 38      end if      if i is even then         v := v × 2      end if       sum := sum + int ( v div 10 ) + v mod 10   repeat    return (10 - (sum mod 10)) mod 10end function`

## 11l

Translation of: Python
`F cusip_check(=cusip)   I cusip.len != 9      X ValueError(‘CUSIP must be 9 characters’)    cusip = cusip.uppercase()   V total = 0   L(i) 8      V v = 0      V c = cusip[i]      I c.is_digit()         v = Int(c)      E I c.is_alpha()         V p = c.code - ‘A’.code + 1         v = p + 9      E I c == ‘*’         v = 36      E I c == ‘@’         v = 37      E I c == ‘#’         v = 38       I i % 2 != 0         v *= 2       total += v I/ 10 + v % 10   V check = (10 - (total % 10)) % 10   R String(check) == cusip.last V codes = [‘037833100’,           ‘17275R102’,           ‘38259P508’,           ‘594918104’,           ‘68389X106’,           ‘68389X105’]L(code) codes   print(code‘: ’(I cusip_check(code) {‘valid’} E ‘invalid’))`
Output:
```037833100: valid
17275R102: valid
38259P508: valid
594918104: valid
68389X106: invalid
68389X105: valid
```

## 360 Assembly

`*        CUSIP                     07/06/2018CUSIP    CSECT         USING  CUSIP,R13          base register         B      72(R15)            skip savearea         DC     17F'0'             savearea         SAVE   (14,12)            save previous context         ST     R13,4(R15)         link backward         ST     R15,8(R13)         link forward         LR     R13,R15            set addressability         LA     R6,1               i=1       DO WHILE=(C,R6,LE,=F'6')    do i=1 to 6         LR     R1,R6                i         MH     R1,=H'9'             *9         LA     R4,T-9(R1)           @t(i)         MVC    X,0(R4)              x=t(i)         SR     R10,R10              w=0         LA     R7,1                 j=1       DO WHILE=(C,R7,LE,=F'8')      do j=1 to 8         LA     R14,X-1                x         AR     R14,R7                 j         MVC    Y(1),0(R14)            y=substr(x,j,1)         LA     R9,L'XX                z=length(xx)         LA     R8,1                   k=1       DO WHILE=(C,R8,LE,=A(L'XX))     do k=1 to length(xx)         LA     R4,XX-1                  xx         AR     R4,R8                    k         MVC    C(1),0(R4)               c=substr(xx,k,1)       IF CLC,Y(1),EQ,C THEN             if y=c then         LR     R9,R8                      k         BCTR   R9,0                       z=k-1       ENDIF    ,                        endif         LA     R8,1(R8)                 k++       ENDDO    ,                      enddo k         LR     R4,R7                  j         LA     R1,2                   2         SRDA   R4,32                  ~         DR     R4,R1                  j/2=0       IF LTR,R4,Z,R4 THEN             if j//2=0 then         AR     R9,R9                    z=z+z       ENDIF    ,                      endif         LR     R4,R9                  z         LA     R1,10                  10         SRDA   R4,32                  ~         DR     R4,R1                  r4=z//10 ; r5=z/10         AR     R10,R5                 w+z/10         AR     R10,R4                 w=w+z/10+z//10         LA     R7,1(R7)               j++       ENDDO    ,                    enddo j         LR     R4,R10               w         LA     R1,10                10         SRDA   R4,32                ~         DR     R4,R1                w/10         LA     R2,10                10         SR     R2,R4                10-w//10         SRDA   R2,32                ~         DR     R2,R1                /10         STC    R2,U                 u=(10-w//10)//10         OI     U,X'F0'              bin to char       IF CLC,U,EQ,X+8 THEN          if u=substr(x,9,1) then         MVC    OK,=CL3' '             ok=' '       ELSE     ,                    else         MVC    OK,=C'n''t'            ok='n''t'       ENDIF    ,                    endif         MVC    PG+6(9),X            output x         MVC    PG+18(3),OK          output ok         XPRNT  PG,L'PG              print         LA     R6,1(R6)             i++       ENDDO    ,                  enddo i         L      R13,4(0,R13)       restore previous savearea pointer         RETURN (14,12),RC=0       restore registers from calling savXX       DC     CL39'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#'U        DS     CL1Y        DS     CL1C        DS     CL1T        DC     CL9'037833100',CL9'17275R102',CL9'38259P508'         DC     CL9'594918104',CL9'68389X106',CL9'68389X105'X        DS     CL9OK       DS     CL3PG       DC     CL80'CUSIP ......... is... valid'         YREGS         END    CUSIP`
Output:
```CUSIP 037833100 is    valid
CUSIP 17275R102 is    valid
CUSIP 38259P508 is    valid
CUSIP 594918104 is    valid
CUSIP 68389X106 isn't valid
CUSIP 68389X105 is    valid
```

## Action!

`INCLUDE "D2:CHARTEST.ACT" ;from the Action! Tool Kit BYTE FUNC Verify(CHAR ARRAY code)  BYTE i,c,v  CARD sum   IF code(0)#9 THEN    RETURN (0)  ELSEIF IsDigit(code(1))=0 THEN    RETURN (0)  FI   sum=0  FOR i=2 TO code(0)  DO    c=code(i)    IF IsDigit(c) THEN      v=c-'0    ELSEIF IsAlpha(c) THEN      v=ToUpper(c)-'A+10    ELSEIF c='* THEN      v=36    ELSEIF c='@ THEN      v=37    ELSEIF c='# THEN      v=38    ELSE      RETURN (0)    FI     IF (i&1)=0 THEN      v==*2    FI     sum==+v/10+v MOD 10  OD   v=(10-(sum MOD 10)) MOD 10  IF v#code(1)-'0 THEN    RETURN (0)  FIRETURN (1) PROC Test(CHAR ARRAY code)  Print(code)  IF Verify(code) THEN    PrintE(" is valid")  ELSE    PrintE(" is invalid")  FIRETURN PROC Main()  Put(125) PutE() ;clear the screen  Test("037833100")  Test("17275R102")  Test("38259P508")  Test("594918104")  Test("68389X106")  Test("68389X105")RETURN`
Output:
```037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid
```

`with Ada.Text_IO; procedure Cusip_Test is   use Ada.Text_IO;    subtype Cusip is String (1 .. 9);    function Check_Cusip (Code : Cusip) return Boolean is      Sum : Integer := 0;      V   : Integer;    begin      for I in Code'First .. Code'Last - 1 loop         case Code (I) is            when '0' .. '9' =>               V := Character'Pos (Code (I)) - Character'Pos ('0');            when 'A' .. 'Z' =>               V := Character'Pos (Code (I)) - Character'Pos ('A') + 10;            when '*' => V := 36;            when '@' => V := 37;            when '#' => V := 38;            when others => return False;         end case;          if I mod 2 = 0 then            V := V * 2;         end if;          Sum := Sum + V / 10 + (V mod 10);      end loop;       return (10 - (Sum mod 10)) mod 10 =        Character'Pos (Code (Code'Last)) - Character'Pos ('0');   end Check_Cusip;    type Cusip_Array is array (Natural range <>) of Cusip;    Test_Array : Cusip_Array :=     ("037833100",      "17275R102",      "38259P508",      "594918104",      "68389X106",      "68389X105");begin   for I in Test_Array'Range loop      Put (Test_Array (I) & ": ");      if Check_Cusip (Test_Array (I)) then         Put_Line ("valid");      else         Put_Line ("not valid");      end if;   end loop;end Cusip_Test;`
Output:
```037833100: valid
17275R102: valid
38259P508: valid
594918104: valid
68389X106: not valid
68389X105: valid
```

## ALGOL 68

`BEGIN    # returns TRUE if cusip is a valid CUSIP code #    OP ISCUSIP = ( STRING cusip )BOOL:       IF ( UPB cusip - LWB cusip ) /= 8       THEN           # code is wrong length #           FALSE       ELSE           # string is 9 characters long - check it is valid #           STRING cusip digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#"[ AT 0 ];           INT check digit := 0;           IF NOT char in string( cusip[ UPB cusip ], check digit, cusip digits )           THEN               # invalid check digit #               FALSE           ELSE               # OK so far compare the calculated check sum to the supplied one #               INT sum := 0;               INT c pos := LWB cusip - 1;               FOR i TO 8 DO                   INT digit := 0;                   IF NOT char in string( cusip[ i + c pos ], digit, cusip digits )                   THEN                       # invalid digit #                       digit := -999                   FI;                   IF NOT ODD i                   THEN                       # even digit #                       digit *:= 2                   FI;                   sum +:= ( digit OVER 10 ) + ( digit MOD 10 )               OD;               ( 10 - ( sum MOD 10 ) ) MOD 10 = check digit           FI       FI ; # ISCUSIP #     # task test cases #     PROC test cusip = ( STRING cusip )VOID:        print( ( cusip, IF ISCUSIP cusip THEN " valid" ELSE " invalid" FI, newline ) );     test cusip( "037833100" );    test cusip( "17275R102" );    test cusip( "38259P508" );    test cusip( "594918104" );    test cusip( "68389X106" );    test cusip( "68389X105" )END`
Output:
```037833100 valid
17275R102 valid
38259P508 valid
594918104 valid
68389X106 invalid
68389X105 valid
```

## ALGOL W

Based on Algol 68

`begin    % returns true if cusip is a valid CUSIP code %    logical procedure isCusip ( string(9) value cusip ) ;    begin        % returns the base 39 digit corresponding to a character of a CUSIP code %        integer procedure cusipDigit( string(1) value cChar ) ;            if      cChar >= "0" and cChar <= "9" then ( decode( cChar ) - decode( "0" ) )            else if cChar >= "A" and cChar <= "Z" then ( decode( cChar ) - decode( "A" ) ) + 10            else if cChar  = "*"                  then   36            else if cChar  = "@"                  then   37            else if cChar  = "#"                  then   38            else    % invalid digit %                  -999 ;         integer checkDigit, sum;        checkDigit := cusipDigit( cusip( 8 // 1 ) );        for cPos := 1 until 8 do begin            integer   digit;            digit := cusipDigit( cusip( ( cPos - 1 ) // 1 ) );            if not odd( cPos ) then digit := digit * 2;            sum := sum + ( digit div 10 ) + ( digit rem 10 )        end for_cPos ;        ( ( 10 - ( sum rem 10 ) ) rem 10 ) = checkDigit    end isCusip ;     begin % task test cases %        procedure testCusip ( string(9) value cusip ) ;            write( s_w := 0, cusip, if isCusip( cusip ) then " valid" else " invalid" );         testCusip( "037833100" );        testCusip( "17275R102" );        testCusip( "38259P508" );        testCusip( "594918104" );        testCusip( "68389X106" );        testCusip( "68389X105" )    end testCasesend.`
Output:
```037833100 valid
17275R102 valid
38259P508 valid
594918104 valid
68389X106 invalid
68389X105 valid
```

## AppleScript

`use AppleScript version "2.4"use framework "Foundation"use scripting additions  -- isCusip :: String -> Boolon isCusip(s)    set cs to "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*&#"    set ns to mapMaybe(elemIndex(cs), s)     script go        on |λ|(f, x)            set fx to apply(f, x)            (fx div 10) + (fx mod 10)        end |λ|    end script     9 = length of ns and item -1 of ns = (10 - (sum(zipWith(go, ¬        cycle({my identity, my double}), ¬        take(8, ns))) mod 10)) mod 10end isCusip  -------------------------- TEST ---------------------------on run    script test        on |λ|(s)            s & " -> " & isCusip(s)        end |λ|    end script     unlines(map(test, ¬        {"037833100", "17275R102", "38259P508", ¬            "594918104", "68389X106", "68389X105"}))end run -- 037833100 -> true-- 17275R102 -> true-- 38259P508 -> true-- 594918104 -> true-- 68389X106 -> false-- 68389X105 -> true  -------------------- GENERIC FUNCTIONS -------------------- -- Just :: a -> Maybe aon Just(x)    -- Constructor for an inhabited Maybe (option type) value.    -- Wrapper containing the result of a computation.    {type:"Maybe", Nothing:false, Just:x}end Just  -- Nothing :: Maybe aon Nothing()    -- Constructor for an empty Maybe (option type) value.    -- Empty wrapper returned where a computation is not possible.    {type:"Maybe", Nothing:true}end Nothing  -- Tuple (,) :: a -> b -> (a, b)on Tuple(a, b)    -- Constructor for a pair of values, possibly of two different types.    {type:"Tuple", |1|:a, |2|:b, length:2}end Tuple  -- apply (\$) :: (a -> b) -> a -> bon apply(f, x)    -- The value of f(x)    mReturn(f)'s |λ|(x)end apply  -- cycle :: [a] -> Generator [a]on cycle(xs)    script        property lng : 1 + (length of xs)        property i : missing value        on |λ|()            if missing value is i then                set i to 1            else                set nxt to (1 + i) mod lng                if 0 = ((1 + i) mod lng) then                    set i to 1                else                    set i to nxt                end if            end if            return item i of xs        end |λ|    end scriptend cycle  -- double :: Num -> Numon double(x)    2 * xend double  -- elemIndex :: Eq a => [a] -> a -> Maybe Inton elemIndex(xs)    script        on |λ|(x)            set lng to length of xs            repeat with i from 1 to lng                if x = (item i of xs) then return Just(i - 1)            end repeat            return Nothing()        end |λ|    end scriptend elemIndex  -- identity :: a -> aon identity(x)    -- The argument unchanged.    xend identity  -- foldl :: (a -> b -> a) -> a -> [b] -> aon foldl(f, startValue, xs)    tell mReturn(f)        set v to startValue        set lng to length of xs        repeat with i from 1 to lng            set v to |λ|(v, item i of xs, i, xs)        end repeat        return v    end tellend foldl  -- length :: [a] -> Inton |length|(xs)    set c to class of xs    if list is c or string is c then        length of xs    else        (2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)    end ifend |length|  -- map :: (a -> b) -> [a] -> [b]on map(f, xs)    -- The list obtained by applying f    -- to each element of xs.    tell mReturn(f)        set lng to length of xs        set lst to {}        repeat with i from 1 to lng            set end of lst to |λ|(item i of xs, i, xs)        end repeat        return lst    end tellend map  -- The mapMaybe function is a version of map which can throw out-- elements. In particular, the functional argument returns-- something of type Maybe b. If this is Nothing, no element is-- added on to the result list. If it just Just b, then b is-- included in the result list.-- mapMaybe :: (a -> Maybe b) -> [a] -> [b]on mapMaybe(mf, xs)    script        property g : mReturn(mf)        on |λ|(a, x)            set mb to g's |λ|(x)            if Nothing of mb then                a            else                a & (Just of mb)            end if        end |λ|    end script    foldl(result, {}, xs)end mapMaybe  -- min :: Ord a => a -> a -> aon min(x, y)    if y < x then        y    else        x    end ifend min  -- mReturn :: First-class m => (a -> b) -> m (a -> b)on mReturn(f)    -- 2nd class handler function lifted into 1st class script wrapper.     if script is class of f then        f    else        script            property |λ| : f        end script    end ifend mReturn  -- sum :: [Num] -> Numon sum(xs)    script add        on |λ|(a, b)            a + b        end |λ|    end script     foldl(add, 0, xs)end sum  -- take :: Int -> [a] -> [a]-- take :: Int -> String -> Stringon take(n, xs)    set c to class of xs    if list is c then        if 0 < n then            items 1 thru min(n, length of xs) of xs        else            {}        end if    else if string is c then        if 0 < n then            text 1 thru min(n, length of xs) of xs        else            ""        end if    else if script is c then        set ys to {}        repeat with i from 1 to n            set v to |λ|() of xs            if missing value is v then                return ys            else                set end of ys to v            end if        end repeat        return ys    else        missing value    end ifend take  -- unlines :: [String] -> Stringon unlines(xs)    -- A single string formed by the intercalation    -- of a list of strings with the newline character.    set {dlm, my text item delimiters} to ¬        {my text item delimiters, linefeed}    set str to xs as text    set my text item delimiters to dlm    strend unlines  -- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]on zipWith(f, xs, ys)    set lng to min(|length|(xs), |length|(ys))    if 1 > lng then return {}    set xs_ to take(lng, xs) -- Allow for non-finite    set ys_ to take(lng, ys) -- generators like cycle etc    set lst to {}    tell mReturn(f)        repeat with i from 1 to lng            set end of lst to |λ|(item i of xs_, item i of ys_)        end repeat        return lst    end tellend zipWith`
Output:
```037833100 -> true
17275R102 -> true
38259P508 -> true
594918104 -> true
68389X106 -> false
68389X105 -> true```

## Arturo

Translation of: Ruby
`validCUSIP?: function [cusip][    s: 0    alpha: `A`..`Z`     loop.with:'i chop cusip 'c [        v: 0         case ø            when? [numeric? c] -> v: to :integer to :string c            when? [in? c alpha] -> v: (index alpha c) + 1 + 9            when? [c = `*`] -> v: 36            when? [c = `@`] -> v: 37            when? [c = `#`] -> v: 38            else []         if odd? i -> v: 2 * v         s: s + (v / 10) + (v % 10)    ]    check: (10 - (s % 10)) % 10     return check = to :integer to :string last cusip] loop ["037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105"] 'cusip [    print [cusip "=>" (validCUSIP? cusip)? -> "VALID" -> "INVALID"]]`
Output:
```037833100 => VALID
17275R102 => VALID
38259P508 => VALID
594918104 => VALID
68389X106 => INVALID
68389X105 => VALID```

## AutoHotkey

`Cusip_Check_Digit(cusip){    sum := 0, i := 1, x := StrSplit(cusip)    while (i <= 8) {        c := x[i]        if c is digit            v := c        else if c is alpha            v := Asc(c) - 64 + 9        else if (c = "*")            v := 36        else if (c = "@")            v := 37        else if (c = "#")            v := 38        if (i/2 = Floor(i/2))            v *= 2        sum += Floor(v/10) + Mod(v, 10)        i++    }    return (Mod(10 - Mod(sum, 10), 10) = x[9])}`
Examples:
`data =(03783310017275R10238259P50859491810468389X10668389X105) output := "Cusip`t`tValid`n"loop, Parse, data, `n, `r    output .= A_LoopField "`t" Cusip_Check_Digit(A_LoopField) "`n"MsgBox % output`
Output:
```Cusip		Valid
037833100	1
17275R102	1
38259P508	1
594918104	1
68389X106	0
68389X105	1```

## AWK

` # syntax: GAWK -f CUSIP.AWKBEGIN {    n = split("037833100,17275R102,38259P508,594918104,68389X106,68389X105",arr,",")    for (i=1; i<=n; i++) {      printf("%9s %s\n",arr[i],cusip(arr[i]))    }    exit(0)}function cusip(n,  c,i,sum,v,x) {# returns: 1=OK, 0=NG, -1=bad data    if (length(n) != 9) {      return(-1)    }    for (i=1; i<=8; i++) {      c = substr(n,i,1)      if (c ~ /[0-9]/) {        v = c      }      else if (c ~ /[A-Z]/) {        v = index("ABCDEFGHIJKLMNOPQRSTUVWXYZ",c) + 9      }      else if (c == "*") {        v = 36      }      else if (c == "@") {        v = 37      }      else if (c == "#") {        v = 38      }      else {        return(-1)      }      if (i ~ /[02468]/) {        v *= 2      }      sum += int(v / 10) + (v % 10)    }    x = (10 - (sum % 10)) % 10    return(substr(n,9,1) == x ? 1 : 0)} `
Output:
```037833100 1
17275R102 1
38259P508 1
594918104 1
68389X106 0
68389X105 1
```

## BCPL

`get "libhdr" let validcusip(c) = valof\$(  let sum = 0    unless c%0 = 9 resultis false     for i = 1 to 8 do    \$(  let v = ( 2 - (i & 1) ) * valof        \$(  test '0' <= c%i <= '9'                then resultis c%i - '0'            or test 'A' <= c%i <= 'Z'                then resultis 10 + c%i - 'A'            or test c%i = '**'                then resultis 36            or test c%i = '@'                then resultis 37            or test c%i = '#'                then resultis 38            else resultis -1        \$)        sum := sum + v/10 + v rem 10    \$)    resultis (10 - (sum rem 10)) rem 10 = c%9 - '0'\$) let show(c) be    writef("%S: %Svalid*N", c, validcusip(c) -> "", "in") let start() be\$(  show("037833100")    show("17275R102")    show("38259P508")    show("594918104")    show("68389X106")    show("68389X105")\$)`
Output:
```037833100: valid
17275R102: valid
38259P508: valid
594918104: valid
68389X106: invalid
68389X105: valid```

## C

Reads CUSIP strings from a file and prints results to console, usage printed on incorrect invocation.

` #include<stdlib.h>#include<stdio.h> int cusipCheck(char str[10]){	int sum=0,i,v; 	for(i=0;i<8;i++){		if(str[i]>='0'&&str[i]<='9')			v = str[i]-'0';		else if(str[i]>='A'&&str[i]<='Z')			v = (str[i] - 'A' + 10);		else if(str[i]=='*')			v = 36;		else if(str[i]=='@')			v = 37;		else if(str[i]=='#')			v = 38;		if(i%2!=0)			v*=2; 		sum += ((int)(v/10) + v%10);	}	return ((10 - (sum%10))%10);} int main(int argC,char* argV[]){	char cusipStr[10]; 	int i,numLines; 	if(argC==1)		printf("Usage : %s <full path of CUSIP Data file>",argV[0]); 	else{		FILE* fp = fopen(argV[1],"r"); 		fscanf(fp,"%d",&numLines); 		printf("CUSIP       Verdict\n");		printf("-------------------"); 		for(i=0;i<numLines;i++){ 			fscanf(fp,"%s",cusipStr); 			printf("\n%s : %s",cusipStr,(cusipCheck(cusipStr)==(cusipStr[8]-'0'))?"Valid":"Invalid");		} 		fclose(fp);	}	return 0;} `

Input file :

```6
037833100
17275R102
38259P508
594918104
68389X106
68389X105
```

Invocation and output :

```C:\rosettaCode>cusipCheck.exe cusipData.txt
CUSIP       Verdict
-------------------
037833100 : Valid
17275R102 : Valid
38259P508 : Valid
594918104 : Valid
68389X106 : Invalid
68389X105 : Valid
```

## C#

Translation of: Java
`using System;using System.Collections.Generic; namespace CUSIP {    class Program {        static bool IsCusip(string s) {            if (s.Length != 9) return false;            int sum = 0;            for (int i = 0; i <= 7; i++) {                char c = s[i];                 int v;                if (c >= '0' && c <= '9') {                    v = c - 48;                }                else if (c >= 'A' && c <= 'Z') {                    v = c - 55;  // lower case letters apparently invalid                }                else if (c == '*') {                    v = 36;                }                else if (c == '#') {                    v = 38;                }                else {                    return false;                }                if (i % 2 == 1) v *= 2;  // check if odd as using 0-based indexing                sum += v / 10 + v % 10;            }            return s[8] - 48 == (10 - (sum % 10)) % 10;        }         static void Main(string[] args) {            List<string> candidates = new List<string>() {                "037833100",                "17275R102",                "38259P508",                "594918104",                "68389X106",                "68389X105"            };            foreach (var candidate in candidates) {                Console.WriteLine("{0} -> {1}", candidate, IsCusip(candidate) ? "correct" : "incorrect");            }        }    }}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct```

## C++

Translation of: C#
`#include <iostream>#include <vector> bool isCusip(const std::string& s) {    if (s.size() != 9) return false;     int sum = 0;    for (int i = 0; i <= 7; ++i) {        char c = s[i];         int v;        if ('0' <= c && c <= '9') {            v = c - '0';        } else if ('A' <= c && c <= 'Z') {            v = c - '@';        } else if (c = '*') {            v = 36;        } else if (c = '#') {            v = 38;        } else {            return false;        }        if (i % 2 == 1) {            v *= 2;        }        sum += v / 10 + v % 10;    }    return s[8] - '0' == (10 - (sum % 10)) % 10;} int main() {    using namespace std;     vector<string> candidates{        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105"    };     for (auto str : candidates) {        auto res = isCusip(str) ? "correct" : "incorrect";        cout << str.c_str() << " -> " << res << "\n";    }     return 0;}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct```

## Caché ObjectScript

`Class Utils.Check [ Abstract ]{ ClassMethod CUSIP(x As %String) As %Boolean{	SET x=\$TRANSLATE(x," ")	// https://leiq.bus.umich.edu/res_codes_cusip.htm	IF x'?8UNP1N QUIT 0	SET cd=\$EXTRACT(x,*), x=\$EXTRACT(x,1,*-1), t=0	FOR i=1:1:\$LENGTH(x) {		SET n=\$EXTRACT(x,i)		IF n'=+n SET n=\$CASE(n,"*":36,"@":37,"#":38,:\$ASCII(n)-55)		IF i#2=0 SET n=n*2		SET t=t+(n\10)+(n#10)	}	QUIT cd=((10-(t#10))#10)} }`
Examples:
```USER>For  { Read s Quit:s=""  Write ": "_##class(Utils.Check).CUSIP(s), ! }
037833100: 1
17275R102: 1
38259P508: 1
594918104: 1
68389X106: 0
68389X105: 1

USER>```

## Clojure

` (defn- char->value  "convert the given char c to a value used to calculate the cusip check sum"  [c]  (let [int-char (int c)]    (cond      (and (>= int-char (int \0)) (<= int-char (int \9))) (- int-char 48)      (and (>= int-char (int \A)) (<= int-char (int \Z))) (- int-char 55)      (= c \*) 36      (= c \@) 37      (= c \#) 38      :else nil))) (defn- calc-sum  "Calculate cusip sum. nil is returned for an invalid cusip."  [cusip]  (reduce    (fn [sum [i c]]      (if-let [v (char->value c)]        (let [v (if (= (mod i 2) 1) (* v 2) v)]          (+ sum (int (+ (/ v 10) (mod v 10)))))        (reduced nil)))    0    (map-indexed vector (subs cusip 0 8)))) (defn calc-cusip-checksum  "Given a valid 8 or 9 digit cusip, return the 9th checksum digit"  [cusip]  (when (>= (count cusip) 8)    (let [sum (calc-sum cusip)]      (when sum        (mod (- 10 (mod sum 10)) 10))))) (defn is-valid-cusip9?  "predicate validating a 9 digit cusip."  [cusip9]  (when-let [checksum (and (= (count cusip9) 9)                           (calc-cusip-checksum cusip9))]    (= (- (int (nth cusip9 8)) 48)       checksum))) (defn rosetta-output  "show some nice output for the Rosetta Wiki"  []  (doseq [cusip ["037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105" "EXTRACRD8"                 "EXTRACRD9" "BADCUSIP!" "683&9X106" "68389x105" "683\$9X106" "68389}105" "87264ABE4"]]    (println cusip (if (is-valid-cusip9? cusip) "valid" "invalid")))) `
Output:
```(rosetta-output)
037833100 valid
17275R102 valid
38259P508 valid
594918104 valid
68389X106 invalid
68389X105 valid
EXTRACRD8 invalid
EXTRACRD9 valid
683&9X106 invalid
68389x105 invalid
683\$9X106 invalid
68389}105 invalid
87264ABE4 valid
```

## CLU

`valid_cusip = proc (s: string) returns (bool)    own chars: string := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#"    if string\$size(s) ~= 9 then return(false) end    sum: int := 0    for i: int in int\$from_to(1,8) do        v: int := string\$indexc(s[i], chars)-1        if v<0 then return(false) end        if i//2=0 then v := v*2 end        sum := sum + v/10 + v//10    end    check: int := (10 - sum // 10) // 10    return(check = string\$indexc(s[9], chars)-1)end valid_cusip start_up = proc ()    po: stream := stream\$primary_output()    cusips: array[string] := array[string]\$[        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105"    ]     for cusip: string in array[string]\$elements(cusips) do        stream\$puts(po, cusip || ": ")        if valid_cusip(cusip)            then stream\$putl(po, "valid")            else stream\$putl(po, "invalid")        end     endend start_up`
Output:
```037833100: valid
17275R102: valid
38259P508: valid
594918104: valid
68389X106: invalid
68389X105: valid```

## Common Lisp

`(defun char->value (c)  (cond ((digit-char-p c 36))        ((char= c #\*) 36)        ((char= c #\@) 37)        ((char= c #\#) 38)        (t (error "Invalid character: ~A" c)))) (defun cusip-p (cusip)  (and (= 9 (length cusip))       (loop for i from 1 to 8             for c across cusip             for v = (char->value c)             when (evenp i)               do (setf v (* 2 v))             sum (multiple-value-bind (quot rem) (floor v 10)                   (+ quot rem))               into sum             finally (return (eql (digit-char-p (char cusip 8))                                  (mod (- 10 (mod sum 10)) 10)))))) (defun main ()  (dolist (cusip '("037833100" "17275R102" "38259P508" "594918104" "68389X106" "68389X105"))    (format t "~A: ~A~%" cusip (cusip-p cusip))))`
Output:
```037833100: T
17275R102: T
38259P508: T
594918104: T
68389X106: NIL
68389X105: T```

## D

`import std.stdio; void main(string[] args) {    writeln("CUSIP       Verdict");    foreach(arg; args[1..\$]) {        writefln("%9s : %s", arg, isValidCusip(arg) ? "Valid" : "Invalid");    }} class IllegalCharacterException : Exception {    this(string msg) {        super(msg);    }} bool isValidCusip(string cusip) in {    assert(cusip.length == 9, "Incorrect cusip length");} body {    try {        auto check = cusipCheckDigit(cusip);        return cusip[8] == ('0' + check);    } catch (IllegalCharacterException e) {        return false;    }} unittest {    // Oracle Corporation    assertEquals(isValidCusip("68389X105"), true);     // Oracle Corporation (invalid)    assertEquals(isValidCusip("68389X106"), false);} int cusipCheckDigit(string cusip) in {    assert(cusip.length == 9, "Incorrect cusip length");} body {    int sum;    for (int i=0; i<8; ++i) {        char c = cusip[i];        int v;         switch(c) {            case '0': .. case '9':                v = c - '0';                break;            case 'A': .. case 'Z':                v = c - 'A' + 10;                break;            case '*':                v = 36;                break;            case '@':                v = 37;                break;            case '#':                v = 38;                break;            default:                throw new IllegalCharacterException("Saw character: " ~ c);        }        if (i%2 == 1) {            v = 2 * v;        }         sum = sum + (v / 10) + (v % 10);    }    return (10 - (sum % 10)) % 10;} unittest {    // Apple Incorporated    assertEquals(cusipCheckDigit("037833100"), 0);     // Cisco Systems    assertEquals(cusipCheckDigit("17275R102"), 2);     // Google Incorporated    assertEquals(cusipCheckDigit("38259P508"), 8);     // Microsoft Corporation    assertEquals(cusipCheckDigit("594918104"), 4);     // Oracle Corporation    assertEquals(cusipCheckDigit("68389X105"), 5);} version(unittest) {    void assertEquals(T)(T actual, T expected) {        import core.exception;        import std.conv;        if (actual != expected) {            throw new AssertError("Actual [" ~ to!string(actual) ~ "]; Expected [" ~ to!string(expected) ~ "]");        }    }} /// Invoke with `cusip 037833100 17275R102 38259P508 594918104 68389X106 68389X105``
Output:
```CUSIP       Verdict
037833100 : Valid
17275R102 : Valid
38259P508 : Valid
594918104 : Valid
68389X106 : Invalid
68389X105 : Valid```

## Dyalect

Translation of: Go
`func isCusip(s) {    if s.Length() != 9 { return false }    var sum = 0    for i in 0..7 {        var c = s[i]        var v =            match c {                '0'..'9' => c.Order() - 48,                'A'..'Z' => c.Order() - 55,                '*' => 36,                '@' => 37,                '#' => 38,                _ => false            }        if i % 2 == 1 { v *= 2 }        sum += v / 10 + v % 10    }    s[8].Order() - 48 == (10 - (sum % 10)) % 10} var candidates = [    "037833100",    "17275R102",    "38259P508",    "594918104",    "68389X106",    "68389X105"] for candidate in candidates {    var b =        if isCusip(candidate) {            "correct"        } else {            "incorrect"        }    print("\(candidate) -> \(b)")}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct```

## Excel

### LAMBDA

Binding the names ISCUSIP and CUSIPMAP to the following lambda expressions in the Name Manager of the Excel WorkBook:

`=LAMBDA(s,    LET(        ns, VLOOKUP(            CHARS(s), CUSIPMAP, 2, FALSE        ),         AND(            9 = COLUMNS(ns),            LET(                firstEight, INITCOLS(ns),                 ixs, SEQUENCE(1, 8),                 evensDoubled, IF(ISEVEN(ixs),                    2 * INDEX(firstEight, 1, ixs),                    INDEX(firstEight, 1, ixs)                ),                 LASTCOL(ns) = MOD(                    10 - MOD(                        SUM(                            QUOTIENT(evensDoubled, 10),                            MOD(evensDoubled, 10)                        ),                         10                    ),                     10                )            )        )    ))  CUSIPMAP={"0",0;"1",1;"2",2;"3",3;"4",4;"5",5;"6",6;"7",7;"8",8;"9",9;"A",10;"B",11;"C",12;"D",13;"E",14;"F",15;"G",16;"H",17;"I",18;"J",19;"K",20;"L",21;"M",22;"N",23;"O",24;"P",25;"Q",26;"R",27;"S",28;"T",29;"U",30;"V",31;"W",32;"X",33;"Y",34;"Z",35;"*",36;"@",37;"#",38}`

and also assuming the following generic bindings in the Name Manager for the WorkBook:

`CHARS=LAMBDA(s,    MID(        s,        SEQUENCE(1, LEN(s), 1, 1),        1    ))  INITCOLS=LAMBDA(xs,    INDEX(        xs,        SEQUENCE(            1,            COLUMNS(xs) - 1,            1,        )    ))  LASTCOL=LAMBDA(xs,    INDEX(        xs,        SEQUENCE(ROWS(xs), 1, 1, 1),        COLUMNS(xs)    ))`
Output:
 =ISCUSIP(A2) fx A B 1 Strings CUSIP verdicts 2 037833100 TRUE 3 17275R102 TRUE 4 38259P508 TRUE 5 594918104 TRUE 6 68389X106 FALSE 7 68389X105 TRUE

## F#

` // Validate CUSIP: Nigel Galloway. June 2nd., 2021let fN=function n when n>47 && n<58->n-48 |n when n>64 && n<91->n-55 |42->36 |64->37 |_->38let cD(n:string)=(10-(fst((n.[0..7])|>Seq.fold(fun(z,n)g->let g=(fN(int g))*(n+1) in (z+g/10+g%10,(n+1)%2))(0,0)))%10)%10=int(n.[8])-48["037833100";"17275R102";"38259P508";"594918104";"68389X103";"68389X105"]|>List.iter(fun n->printfn "CUSIP %s is %s" n (if cD n then "valid" else "invalid")) `
Output:
```CUSIP 037833100 is valid
CUSIP 17275R102 is valid
CUSIP 38259P508 is valid
CUSIP 594918104 is valid
CUSIP 68389X103 is invalid
CUSIP 68389X105 is valid
Real: 00:00:00.009
```

## Factor

`USING: combinators.short-circuit formatting kernel mathmath.parser qw regexp sequences unicode ;IN: rosetta-code.cusip : cusip-check-digit ( seq -- n )    but-last-slice [        [ dup alpha? [ digit> ] [ "*@#" index 36 + ] if ] dip        odd? [ 2 * ] when 10 /mod +    ] map-index sum 10 mod 10 swap - 10 mod ; : cusip? ( seq -- ? )    {        [ R/ [0-9A-Z*@#]+/ matches? ]        [ [ last digit> ] [ cusip-check-digit ] bi = ]    } 1&& ; qw{ 037833100 17275R102 38259P508 594918104 68389X106 68389X105 }[ dup cusip? "correct" "incorrect" ? "%s -> %s\n" printf ] each`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
```

## Fortran

The key notion here is to employ a single sequence of valid characters, VALID, and for each character C of the code under test, use function INDEX(VALID,C) to find its position within that sequence, which turns out to be the desired v of the example pseudocode. The only slight difficulty is that INDEX starts its counting with one for the first character of VALID, which is zero, so one must be subtracted; similarly, to return a digit character code via indexing into VALID, one must be added. By using a list of valid characters rather than peculiar character arithmetic (such as c <= "9" & c >= "0" or similar) there is no reliance on the ASCII way of things. Recall that EBCDIC encodements have different orderings and notably, non-alphabetic characters between A and Z.

The source does not bother with the MODULE protocol of F90 and later, and so the type of function CUSIPCHECK must be declared in all routines wishing to invoke it. However, the F90 feature of having the END statement of a subroutine or function give its name is to valuable to ignore. The function returns a character code rather than an integer, since the presumption is that it is to be compared to the check character of the code being inspected, which is known as a character not an integer. This means some blather when extracting the eight characters to be presented to CUSIPCHECK and comparing the result to the ninth character, but the test can be done in one expression.

There is no checking that only valid characters are presented, nor that eight-character codes only are offered, though the compiler might complain if the function were to be invoked with a text literal of the wrong size. In the absence of such checks, there need be no added complications to support a scheme for reporting such errors.
`      CHARACTER*1 FUNCTION CUSIPCHECK(TEXT)	!Determines the check sum character.Committee on Uniform Security Identification Purposes, of the American (i.e. USA) Bankers' Association.       CHARACTER*8 TEXT		!Specifically, an eight-symbol code.       CHARACTER*(*) VALID	!These only are valid.       PARAMETER (VALID = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#")       INTEGER I,V,S		!Assistants.        S = 0		!Start the checksum.        DO I = 1,LEN(TEXT)	!Step through the text.          V = INDEX(VALID,TEXT(I:I)) - 1	!Since counting starts with one.          IF (MOD(I,2).EQ.0) V = V*2		!V = V*(2 - MOD(I,2))?          S = S + V/10 + MOD(V,10)		!Specified calculation.        END DO			!On to the next character.        I = MOD(10 - MOD(S,10),10) + 1	!Again, counting starts with one.        CUSIPCHECK = VALID(I:I)	!Thanks to the MOD 10, surely a digit.      END FUNCTION CUSIPCHECK	!No checking for invalid input...       PROGRAM POKE	!Just to try it out.      INTEGER I,N	!Assistants.      PARAMETER (N = 6)		!A whole lot of blather      CHARACTER*9 CUSIP(N)	!Just to have an array of test codes.      DATA CUSIP/		!Here they are, as specified.     1  "037833100",     2  "17275R102",     3  "38259P508",     4  "594918104",     5  "68389X106",     6  "68389X105"/      CHARACTER*1 CUSIPCHECK	!Needed as no use of the MODULE protocol.       DO I = 1,N	!"More than two? Use a DO..."        WRITE (6,*) CUSIP(I),CUSIPCHECK(CUSIP(I)(1:8)).EQ.CUSIP(I)(9:9)      END DO       END`

Output: standard output is to I/O unit 6, and free-format (the *) will suffice for this. Each line output starts with a space (in case it is to go to a lineprinter, with carriage control), which is convenient for layout here.

```037833100 T
17275R102 T
38259P508 T
594918104 T
68389X106 F
68389X105 T
```

This would have worked first time, except that a fymgre frmble caused the omission of the digit 2 from the text of VALID. The benefits of checking checksums reach to unexpected places!

## FreeBASIC

`' version 04-04-2017' compile with: fbc -s console sub cusip(input_str As String)     Print input_str;    If Len(input_str) <> 9 Then        Print " length is incorrect, invalid cusip"        Return    End If     Dim As Long i, v , sum    Dim As UByte x     For i = 1 To 8        x = input_str[i-1]        Select Case x            Case Asc("0") To Asc("9")                v = x - Asc("0")            Case Asc("A") To Asc("Z")                v = x - Asc("A") + 1 + 9            Case Asc("*")                v= 36            Case Asc("@")                v = 37            Case Asc("#")                v = 38            Case Else                Print " found a invalid character, invalid cusip"                return        End Select         If (i And 1) = 0 Then v = v * 2        sum = sum + v \ 10 + v Mod 10    Next     sum = (10 - (sum Mod 10)) Mod 10    If sum = (input_str[8] - Asc("0")) Then        Print " is valid"    Else        Print " is invalid"    End If End Sub ' ------=< MAIN >=------ Data "037833100", "17275R102", "38259P508"Data "594918104", "68389X106", "68389X105" Dim As String input_str PrintFor i As Integer = 1 To 6    Read input_str    cusip(input_str)Next ' empty keyboard bufferWhile InKey <> "" : WendPrint : Print "hit any key to end program"SleepEnd`
Output:
```037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid```

## Go

`package main import "fmt" func isCusip(s string) bool {    if len(s) != 9 { return false }    sum := 0    for i := 0; i < 8; i++ {        c := s[i]        var v int        switch {            case c >= '0' && c <= '9':                v = int(c) - 48            case c >= 'A' && c <= 'Z':                v = int(c) - 55            case c == '*':                v = 36            case c == '@':                v = 37            case c == '#':                v = 38            default:                return false        }        if i % 2 == 1 { v *= 2 }  // check if odd as using 0-based indexing        sum += v/10 + v%10    }    return int(s[8]) - 48 == (10 - (sum%10)) % 10} func main() {    candidates := []string {        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105",    }     for _, candidate := range candidates {        var b string        if isCusip(candidate) {            b = "correct"        } else {            b = "incorrect"        }        fmt.Printf("%s -> %s\n", candidate, b)    }} `
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
```

## Groovy

Translation of: Java
`class Cusip {    private static Boolean isCusip(String s) {        if (s.length() != 9) return false        int sum = 0        for (int i = 0; i <= 7; i++) {            char c = s.charAt(i)             int v            if (c >= ('0' as char) && c <= ('9' as char)) {                v = c - 48            } else if (c >= ('A' as char) && c <= ('Z' as char)) {                v = c - 55  // lower case letters apparently invalid            } else if (c == '*' as char) {                v = 36            } else if (c == '@' as char) {                v = 37            } else if (c == '#' as char) {                v = 38            } else {                return false            }            if (i % 2 == 1) v *= 2  // check if odd as using 0-based indexing            sum += v / 10 + v % 10        }        return s.charAt(8) - 48 == (10 - (sum % 10)) % 10    }     static void main(String[] args) {        List<String> candidates=new ArrayList<>()        candidates.add("037833100")        candidates.add("17275R102")        candidates.add("38259P508")        candidates.add("594918104")        candidates.add("68389X106")        candidates.add("68389X105")        for (String candidate : candidates) {            System.out.printf("%s -> %s%n", candidate, isCusip(candidate) ? "correct" : "incorrect")        }    }}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct```

`import Data.List(elemIndex) data Result = Valid | BadCheck | TooLong | TooShort | InvalidContent deriving Show -- convert a list of Maybe to a Maybe list.-- result is Nothing if any of values from the original list are NothingallMaybe :: [Maybe a] -> Maybe [a]allMaybe = sequence toValue :: Char -> Maybe InttoValue c = elemIndex c \$ ['0'..'9'] ++ ['A'..'Z'] ++ "*@#"  -- check a list of ints to see if they represent a valid CUSIPvalid :: [Int] -> Boolvalid ns0 =     let -- multiply values with even index by 2        ns1 = zipWith (\i n -> (if odd i then n else 2*n)) [1..] \$ take 8 ns0         -- apply div/mod formula from site and sum up results        sm = sum \$ fmap (\s -> ( s `div` 10 ) + s `mod` 10) ns1     in  -- apply mod/mod formula from site and compare to last value in list        ns0!!8 == (10 - (sm `mod` 10)) `mod` 10 -- check a String to see if it represents a valid CUSIPcheckCUSIP :: String -> ResultcheckCUSIP cs        | l < 9     = TooShort       | l > 9     = TooLong       | otherwise = case allMaybe (fmap toValue cs) of                         Nothing -> InvalidContent                         Just ns -> if valid ns then Valid else BadCheck    where l = length cs testData =      [ "037833100"    , "17275R102"    , "38259P508"    , "594918104"    , "68389X106"    , "68389X105"    ] main = mapM_ putStrLn (fmap (\s -> s ++ ": " ++ show (checkCUSIP s)) testData)`
Output:
```037833100: Valid
17275R102: Valid
38259P508: Valid
594918104: Valid
68389X105: Valid
```

Or, picking some other possibilities from Haskell's rich libraries:

`import qualified Data.Map as M (Map, fromList, lookup)import Data.Maybe (fromMaybe) -------------------------- CUSIP ------------------------- cusipMap :: M.Map Char IntcusipMap =  M.fromList \$    zip (['0' .. '9'] <> ['A' .. 'Z'] <> "*@#") [0 ..] cusipValid :: String -> BoolcusipValid s =  let ns = (fromMaybe [] . traverse (`M.lookup` cusipMap)) s   in (9 == length ns)        && let qrSum =                 sum \$                   ( [quot, rem]                       <*> zipWith                         id                         (cycle [id, (* 2)])                         (take 8 ns)                   )                     <*> [10]            in last ns == rem (10 - rem qrSum 10) 10 --------------------------- TEST -------------------------main :: IO ()main =  mapM_    (print . ((,) <*> cusipValid))    [ "037833100",      "17275R102",      "38259P508",      "594918104",      "68389X106",      "68389X105"    ]`
Output:
```("037833100",True)
("17275R102",True)
("38259P508",True)
("594918104",True)
("68389X106",False)
("68389X105",True)```

## Icon and Unicon

`# cusip.icn -- Committee on Uniform Security Identification Procedures procedure main()   local code, codes   codes := ["037833100", "17275R102", "38259P508",            "594918104", "68389X106", "68389X105"]   while code := pop(codes) do {      writes(code, " : ")      if check_code(code) then         write("valid.")      else write("not valid.")      }end procedure check_code(c)   local p, sum, value   static codetable   initial codetable := buildtable()    sum   := 0   value := 0   every p := 1 to 8 do {      if p % 2 = 1 then    # odd position         value := codetable[c[p]]       else                 # even position         value := 2 * codetable[c[p]]      sum +:= (value / 10) + (value % 10)      }   sum := (10 - (sum % 10)) % 10   if sum = c[9] then return else failend procedure buildtable()   local chars, n, t   t := table()   chars := &digits || &ucase || "*@#"   every n := 1 to *chars do      t[chars[n]] := (n - 1)   return tend`
Output:
```037833100 : valid.
17275R102 : valid.
38259P508 : valid.
594918104 : valid.
68389X106 : not valid.
68389X105 : valid.

```

## J

One-liner:

`   ccd =. 10 | 10 - 10 | [: +/ [: , 10 (#.^:_1) (8 \$ 1 2) * '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' i. ]   ccd '68389X10'5`

More verbose version that checks for correct input:

`   CUSIPcheckdigit =. 3 : 0assert. 8 = \$ y NB. Only accept an 8-element long listassert. */ y e. '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' NB. Only accept characters from the list of 38values =. (8 \$ 1 2) * '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#' i. ] NB. Verb to translate characters and then double every second value.sumdigits =. +/@,@(10 10&#:) NB. Verb to sum the base-10 digits in a numerical arrayinvertedmod =. 10 | 10 - 10 | ] NB. Verb to find the mod-10 of 10 minus mod-10": invertedmod sumdigits values y NB. Return the check digit as a character)   addCUSIPcheckdigit =: , CUSIPcheckdigit   verifyCUSIPcheckdigit =: {: = [email protected]}:`

Examples:

`   addCUSIPcheckdigit '68389X10'68389X105   verifyCUSIPcheckdigit '68389X106'0   verifyCUSIPcheckdigit '68389X105'1   samples =: '037833100', '17275R102', '38259P508', '594918104', '68389X106',: '68389X105'   samples ; verifyCUSIPcheckdigit"1 samples┌─────────┬─┐│037833100│1││17275R102│1││38259P508│1││594918104│1││68389X106│0││68389X105│1│└─────────┴─┘`

## Java

Translation of: Kotlin

Uses Java 9

`import java.util.List; public class Cusip {    private static Boolean isCusip(String s) {        if (s.length() != 9) return false;        int sum = 0;        for (int i = 0; i <= 7; i++) {            char c = s.charAt(i);             int v;            if (c >= '0' && c <= '9') {                v = c - 48;            } else if (c >= 'A' && c <= 'Z') {                v = c - 55;  // lower case letters apparently invalid            } else if (c == '*') {                v = 36;            } else if (c == '@') {                v = 37;            } else if (c == '#') {                v = 38;            } else {                return false;            }            if (i % 2 == 1) v *= 2;  // check if odd as using 0-based indexing            sum += v / 10 + v % 10;        }        return s.charAt(8) - 48 == (10 - (sum % 10)) % 10;    }     public static void main(String[] args) {        List<String> candidates = List.of(                "037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105", "EXTRACRD8",                "EXTRACRD9", "BADCUSIP!", "683&9X106", "68389x105", "683\$9X106", "68389}105", "87264ABE4"        );        for (String candidate : candidates) {            System.out.printf("%s -> %s%n", candidate, isCusip(candidate) ? "correct" : "incorrect");        }    }}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
EXTRACRD8 -> incorrect
EXTRACRD9 -> correct
683&9X106 -> incorrect
68389x105 -> incorrect
683\$9X106 -> incorrect
68389}105 -> incorrect
87264ABE4 -> correct
```

## JavaScript

`(() => {    'use strict';     // cusipValid = Dict Char Int -> String -> Bool    const cusipValid = charMap => s => {        const            ns = fromMaybe([])(                traverse(flip(lookupDict)(charMap))(                    chars(s)                )            );        return 9 === ns.length && (            last(ns) === rem(                10 - rem(                    sum(apList(                        apList([quot, rem])(                            zipWith(identity)(                                cycle([identity, x => 2 * x])                            )(take(8)(ns))                        )                    )([10]))                )(10)            )(10)        );    };     //----------------------- TEST ------------------------    // main :: IO ()    const main = () => {         // cusipMap :: Dict Char Int        const cusipMap = dictFromList(            zip(chars(                "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#"            ))(enumFrom(0)));         console.log(unlines(map(            apFn(                s => validity => s + ' -> ' + str(validity)            )(cusipValid(cusipMap))        )([            '037833100',            '17275R102',            '38259P508',            '594918104',            '68389X106',            '68389X105'        ])));    };      //----------------- GENERIC FUNCTIONS -----------------     // Just :: a -> Maybe a    const Just = x => ({        type: 'Maybe',        Nothing: false,        Just: x    });      // Nothing :: Maybe a    const Nothing = () => ({        type: 'Maybe',        Nothing: true,    });      // Tuple (,) :: a -> b -> (a, b)    const Tuple = a =>        b => ({            type: 'Tuple',            '0': a,            '1': b,            length: 2        });      // apFn :: (a -> b -> c) -> (a -> b) -> a -> c    const apFn = f =>        // Applicative instance for functions.        // f(x) applied to g(x).        g => x => f(x)(            g(x)        );      // apList (<*>) :: [(a -> b)] -> [a] -> [b]    const apList = fs =>        // The sequential application of each of a list        // of functions to each of a list of values.        xs => fs.flatMap(            f => xs.map(f)        );      // append (++) :: [a] -> [a] -> [a]    // append (++) :: String -> String -> String    const append = xs =>        // A list or string composed by        // the concatenation of two others.        ys => xs.concat(ys);      // chars :: String -> [Char]    const chars = s =>        s.split('');      // cons :: a -> [a] -> [a]    const cons = x =>        xs => Array.isArray(xs) ? (            [x].concat(xs)        ) : 'GeneratorFunction' !== xs        .constructor.constructor.name ? (            x + xs        ) : ( // cons(x)(Generator)            function*() {                yield x;                let nxt = xs.next()                while (!nxt.done) {                    yield nxt.value;                    nxt = xs.next();                }            }        )();      // cycle :: [a] -> Generator [a]    function* cycle(xs) {        const lng = xs.length;        let i = 0;        while (true) {            yield(xs[i])            i = (1 + i) % lng;        }    }      // dictFromList :: [(k, v)] -> Dict    const dictFromList = kvs =>        Object.fromEntries(kvs);      // enumFrom :: Enum a => a -> [a]    function* enumFrom(x) {        // A non-finite succession of enumerable        // values, starting with the value x.        let v = x;        while (true) {            yield v;            v = succ(v);        }    }      // flip :: (a -> b -> c) -> b -> a -> c    const flip = f =>        1 < f.length ? (            (a, b) => f(b, a)        ) : (x => y => f(y)(x));      // fromEnum :: Enum a => a -> Int    const fromEnum = x =>        typeof x !== 'string' ? (            x.constructor === Object ? (                x.value            ) : parseInt(Number(x))        ) : x.codePointAt(0);      // fromMaybe :: a -> Maybe a -> a    const fromMaybe = def =>        // A default value if mb is Nothing        // or the contents of mb.        mb => mb.Nothing ? def : mb.Just;      // fst :: (a, b) -> a    const fst = tpl =>        // First member of a pair.        tpl[0];      // identity :: a -> a    const identity = x =>        // The identity function. (`id`, in Haskell)        x;      // last :: [a] -> a    const last = xs =>        // The last item of a list.        0 < xs.length ? xs.slice(-1)[0] : undefined;      // length :: [a] -> Int    const length = xs =>        // 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        (Array.isArray(xs) || 'string' === typeof xs) ? (            xs.length        ) : Infinity;      // liftA2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c    const liftA2 = f => a => b =>        a.Nothing ? a : b.Nothing ? b : Just(f(a.Just)(b.Just));      // lookupDict :: a -> Dict -> Maybe b    const lookupDict = k => dct => {        const v = dct[k];        return undefined !== v ? (            Just(v)        ) : Nothing();    };     // map :: (a -> b) -> [a] -> [b]    const map = f =>        // The list obtained by applying f        // to each element of xs.        // (The image of xs under f).        xs => (            Array.isArray(xs) ? (                xs            ) : xs.split('')        ).map(f);      // pureMay :: a -> Maybe a    const pureMay = x => Just(x);     // Given a type name string, returns a    // specialised 'pure', where    // 'pure' lifts a value into a particular functor.     // pureT :: String -> f a -> (a -> f a)    const pureT = t => x =>        'List' !== t ? (            'Either' === t ? (                pureLR(x)            ) : 'Maybe' === t ? (                pureMay(x)            ) : 'Node' === t ? (                pureTree(x)            ) : 'Tuple' === t ? (                pureTuple(x)            ) : pureList(x)        ) : pureList(x);      // pureTuple :: a -> (a, a)    const pureTuple = x =>        Tuple('')(x);     // quot :: Int -> Int -> Int    const quot = n =>        m => Math.floor(n / m);     // rem :: Int -> Int -> Int    const rem = n => m => n % m;     // snd :: (a, b) -> b    const snd = tpl => tpl[1];     // str :: a -> String    const str = x =>        x.toString();     // succ :: Enum a => a -> a    const succ = x => {        const t = typeof x;        return 'number' !== t ? (() => {            const [i, mx] = [x, maxBound(x)].map(fromEnum);            return i < mx ? (                toEnum(x)(1 + i)            ) : Error('succ :: enum out of range.')        })() : x < Number.MAX_SAFE_INTEGER ? (            1 + x        ) : Error('succ :: Num out of range.')    };     // sum :: [Num] -> Num    const sum = xs =>        // The numeric sum of all values in xs.        xs.reduce((a, x) => a + x, 0);     // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n =>        // The first n elements of a list,        // string of characters, or stream.        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];        }));     // The first argument is a sample of the type    // allowing the function to make the right mapping     // toEnum :: a -> Int -> a    const toEnum = e => x =>        ({            'number': Number,            'string': String.fromCodePoint,            'boolean': Boolean,            'object': v => e.min + v        } [typeof e])(x);      // traverse :: (Applicative f) => (a -> f b) -> [a] -> f [b]    const traverse = f =>        // Collected results of mapping each element        // of a structure to an action, and evaluating        // these actions from left to right.        xs => 0 < xs.length ? (() => {            const                vLast = f(xs.slice(-1)[0]),                t = vLast.type || 'List';            return xs.slice(0, -1).reduceRight(                (ys, x) => liftA2(cons)(f(x))(ys),                liftA2(cons)(vLast)(pureT(t)([]))            );        })() : [            []        ];      // uncons :: [a] -> Maybe (a, [a])    const uncons = xs => {        // Just a tuple of the head of xs and its tail,        // Or Nothing if xs is an empty list.        const lng = length(xs);        return (0 < lng) ? (            Infinity > lng ? (                Just(Tuple(xs[0])(xs.slice(1))) // Finite list            ) : (() => {                const nxt = take(1)(xs);                return 0 < nxt.length ? (                    Just(Tuple(nxt[0])(xs))                ) : Nothing();            })() // Lazy generator        ) : Nothing();    };      // uncurry :: (a -> b -> c) -> ((a, b) -> c)    const uncurry = f =>        // A function over a pair, derived        // from a curried function.        x => ((...args) => {            const                xy = 1 < args.length ? (                    args                ) : args[0];            return f(xy[0])(xy[1]);        })(x);      // unlines :: [String] -> String    const unlines = xs =>        // A single string formed by the intercalation        // of a list of strings with the newline character.        xs.join('\n');      // zip :: [a] -> [b] -> [(a, b)]    const zip = xs =>        // Use of `take` and `length` here allows for zipping with non-finite        // lists - i.e. generators like cycle, repeat, iterate.        ys => {            const                lng = Math.min(length(xs), length(ys)),                vs = take(lng)(ys);            return take(lng)(xs).map(                (x, i) => Tuple(x)(vs[i])            );        };     // Use of `take` and `length` here allows zipping with non-finite lists    // i.e. generators like cycle, repeat, iterate.     // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]    const zipWith = f => xs => ys => {        const lng = Math.min(length(xs), length(ys));        return Infinity > lng ? (() => {            const                as = take(lng)(xs),                bs = take(lng)(ys);            return Array.from({                length: lng            }, (_, i) => f(as[i])(                bs[i]            ));        })() : zipWithGen(f)(xs)(ys);    };      // zipWithGen :: (a -> b -> c) ->    // Gen [a] -> Gen [b] -> Gen [c]    const zipWithGen = f => ga => gb => {        function* go(ma, mb) {            let                a = ma,                b = mb;            while (!a.Nothing && !b.Nothing) {                let                    ta = a.Just,                    tb = b.Just                yield(f(fst(ta))(fst(tb)));                a = uncons(snd(ta));                b = uncons(snd(tb));            }        }        return go(uncons(ga), uncons(gb));    };     // MAIN ---    return main();})();`
Output:
```037833100 -> true
17275R102 -> true
38259P508 -> true
594918104 -> true
68389X106 -> false
68389X105 -> true```

## Julia

Works with: Julia version 0.6
`module CUSIP function _lastdigitcusip(input::AbstractString)    input = uppercase(input)    s = 0     for (i, c) in enumerate(input)        if isdigit(c)            v = Int(c) - 48        elseif isalpha(c)            v = Int(c) - 64 + 9        elseif c == '*'            v = 36        elseif c == '@'            v = 37        elseif c == '#'            v = 38        end         if iseven(i); v *= 2 end        s += div(v, 10) + rem(v, 10)    end     return Char(rem(10 - rem(s, 10), 10) + 48)end checkdigit(input::AbstractString) = input[9] == _lastdigitcusip(input[1:8]) end  # module CUSIP for code in ("037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105")    println("\$code is ", CUSIP.checkdigit(code) ? "correct." : "not correct.")end`
Output:
```037833100 is correct.
17275R102 is correct.
38259P508 is correct.
594918104 is correct.
68389X106 is not correct.
68389X105 is correct.```

## Kotlin

`// version 1.1.0 fun isCusip(s: String): Boolean {    if (s.length != 9) return false    var sum = 0    for (i in 0..7) {        val c = s[i]        var v = when (c) {            in '0'..'9'  -> c.toInt() - 48            in 'A'..'Z'  -> c.toInt() - 55  // lower case letters apparently invalid            '*'          -> 36            '@'          -> 37            '#'          -> 38            else         -> return false        }        if (i % 2 == 1) v *= 2  // check if odd as using 0-based indexing        sum += v / 10 + v % 10    }    return s[8].toInt() - 48  == (10 - (sum % 10)) % 10} fun main(args: Array<String>) {    val candidates = listOf(        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105"    )    for (candidate in candidates)         println("\$candidate -> \${if(isCusip(candidate)) "correct" else "incorrect"}")}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
```

## langur

If we don't strictly follow the pseudo-code, we can do this.

Works with: langur version 0.8.5
`val .isCusip = f(.s) {    if not isString(.s) or len(.s) != 9 {        return false    }     val .basechars = cp2s('0'..'9') ~ cp2s('A'..'Z') ~ "*@#"     val .sum = for[=0] .i of 8 {        var .v = index(s2s(.s, .i), .basechars)        if not .v: return false        .v = .v[1]-1        if .i div 2: .v x= 2        _for += .v \ 10 + .v rem 10    }     .s[9]-'0' == (10-(.sum rem 10)) rem 10} val .candidates = w/037833100 17275R102 38259P508 594918104 68389X106 68389X105/ for .c in .candidates {    writeln .c, ": ", if(.isCusip(.c): "good" ; "bad")}`

Following the pseudo-code would look more like the following.

Works with: langur version 0.8.5
Translation of: Go
`val .isCusip = f(.s) {    if not isString(.s) or len(.s) != 9 {        return false    }     val .sum = for[=0] .i of 8 {        val .c = .s[.i]        var .v = 0         given .c {            # note: default op between conditions "and"            # Use "case or" to make given act like a switch in some other languages.            case >= '0', <= '9':                .v = .c-'0'             case >= 'A', <= 'Z':                .v = .c-55 # .c-'A'+10             case '*': .v = 36            case '@': .v = 37            case '#': .v = 38             default: return false        }         if .i div 2: .v x= 2        _for += .v \ 10 + .v rem 10    }     .s[9]-'0' == (10-(.sum rem 10)) rem 10} val .candidates = w/037833100 17275R102 38259P508 594918104 68389X106 68389X105/ for .c in .candidates {    writeln .c, ": ", if(.isCusip(.c): "good" ; "bad")}`
Output:
```037833100: good
17275R102: good
38259P508: good
594918104: good
68389X105: good```

## Lua

The checkDigit function is a line-for-line translation of the pseudo-code algorithm.

`function checkDigit (cusip)  if #cusip ~= 8 then return false end   local sum, c, v, p = 0  for i = 1, 8 do    c = cusip:sub(i, i)    if c:match("%d") then      v = tonumber(c)    elseif c:match("%a") then      p = string.byte(c) - 55      v = p + 9    elseif c == "*" then      v = 36    elseif c == "@" then      v = 37    elseif c == "#" then      v = 38    end    if i % 2 == 0 then      v = v * 2    end     sum = sum + math.floor(v / 10) + v % 10  end   return tostring((10 - (sum % 10)) % 10)end local testCases = {  "037833100",  "17275R102",  "38259P508",  "594918104",  "68389X106",  "68389X105"}for _, CUSIP in pairs(testCases) do  io.write(CUSIP .. ": ")  if checkDigit(CUSIP:sub(1, 8)) == CUSIP:sub(9, 9) then    print("VALID")  else    print("INVALID")  endend`
Output:
```037833100: VALID
17275R102: VALID
38259P508: VALID
594918104: VALID
68389X106: INVALID
68389X105: VALID```

## Mathematica / Wolfram Language

`ClearAll[Cusip]rules = Thread[(ToString /@ Range[0, 9]) -> Range[0, 9]]~Join~   Thread[CharacterRange["A", "Z"] -> Range[26] + 9]~Join~   Thread[Characters["*@#"] -> {36, 37, 38}];Cusip[cusip_String] := Module[{s = cusip, sum = 0, c, value, check},  If[StringLength[s] != 9,   Print["Cusip must be 9 characters!"];   False   ,   s = Characters[ToUpperCase[s]];   Do[    c = s[[i]];    value = c /. rules;    If[EvenQ[i], value *= 2];    sum += Floor[value/10] + Mod[value, 10];    ,    {i, 8}    ];   check = Mod[(10 - Mod[sum, 10]), 10];   s[[-1]] === ToString[check]   ]  ]Cusip /@ {"037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105"}`
Output:
`{True, True, True, True, False, True}`

## Modula-2

`MODULE CUSIP;FROM FormatString IMPORT FormatString;FROM Terminal IMPORT WriteString,WriteLn,ReadChar; PROCEDURE WriteInt(n : INTEGER);VAR buf : ARRAY[0..10] OF CHAR;BEGIN    FormatString("%i", buf, n);    WriteString(buf)END WriteInt; PROCEDURE cusipCheckDigit(cusip : ARRAY OF CHAR) : INTEGER;VAR    i,v,sum : INTEGER;BEGIN    i := 0;    sum := 0;    WHILE cusip[i] # 0C DO        IF ('0' <= cusip[i]) AND (cusip[i] <= '9') THEN            v := ORD(cusip[i]) - 48 (* 0 *)        ELSIF ('A' <= cusip[i]) AND (cusip[i] <= 'Z') THEN            v := ORD(cusip[i]) - 65 (* A *) + 10        ELSIF cusip[i] = '*' THEN            v := 36        ELSIF cusip[i] = '@' THEN            v := 37        ELSIF cusip[i] = '#' THEN            v := 38        ELSE            RETURN -1        END;        IF i MOD 2 = 1 THEN v := 2 * v END;        IF i < 8 THEN            sum := sum + (v DIV 10) + (v MOD 10);        END;        INC(i)    END;     IF i # 9 THEN RETURN -1 END;    RETURN (10 - (sum MOD 10)) MOD 10END cusipCheckDigit; PROCEDURE isValidCusip(cusip : ARRAY OF CHAR) : BOOLEAN;VAR    check : INTEGER;BEGIN    check := cusipCheckDigit(cusip);    IF check < 0 THEN RETURN FALSE END;    RETURN cusip[8] = CHR(48 (* 0 *) + check)END isValidCusip; PROCEDURE Print(cusip : ARRAY OF CHAR);BEGIN    WriteString(cusip);    IF isValidCusip(cusip) THEN        WriteString(" : Valid")    ELSE        WriteString(" : Invalid")    END;    WriteLnEND Print; (* main *)BEGIN    WriteString("CUSIP       Verdict");    WriteLn;     Print("037833100");    Print("17275R102");    Print("38259P508");    Print("594918104");    Print("68389X106");    Print("68389X105");     ReadCharEND CUSIP.`
Output:
```CUSIP       Verdict
037833100 : Valid
17275R102 : Valid
38259P508 : Valid
594918104 : Valid
68389X106 : Invalid
68389X105 : Valid```

## Nanoquery

`def cusip_checksum(cusip)    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    num   = "0123456789"    sum   = 0     for i in range(1, 8)        c = cusip[i - 1]        v = 0        if c in num            v = int(c)        else if c in alpha            p = alpha[c] + 1            v = p + 9        else if c in "*@#"            v = "*@#"[c] + 36        end        if (i % 2) = 0            v *= 2        end         sum += int(v / 10) + (v % 10)    end     return (10 - (sum % 10)) % 10end if main    codes = {"037833100", "17275R102", "38259P508",\             "594918104", "68389X106", "68389X105"}     for code in codes        if int(code[len(code) - 1]) = cusip_checksum(code)            println code + " is valid"        else            println code + " is invalid"        end    endend`
Output:
```037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid```

## Nim

`import strutils proc cusipCheck(cusip: string): bool =  if cusip.len != 9:    return false   var     sum, v = 0  for i, c in cusip[0 .. ^2]:    if c.isDigit:      v = parseInt(\$c)    elif c.isUpperAscii:      v = ord(c) - ord('A') + 10    elif c == '*':      v = 36    elif c == '@':      v = 37    elif c == '#':      v = 38     if i mod 2 == 1:      v *= 2     sum += v div 10 + v mod 10  let check = (10 - (sum mod 10)) mod 10  return \$check == \$cusip[^1] proc main =  let codes = [    "037833100",    "17275R102",    "38259P508",    "594918104",    "68389X106",    "68389X105"  ]   for code in codes:    echo code, ": ", if cusipCheck(code): "Valid" else: "Invalid" main()`
Output:
```037833100: Valid
17275R102: Valid
38259P508: Valid
594918104: Valid
68389X106: Invalid
68389X105: Valid
```

## Objeck

Translation of: Kotlin
`class Cusip {    function : native : IsCusip(s : String) ~ Bool {        if(s->Size() <> 9) {            return false;        };         sum := 0;        for(i := 0; i < 7; i+=1;) {            c := s->Get(i);             v : Int;            if (c >= '0' & c <= '9') {                v := c - 48;            } else if (c >= 'A' & c <= 'Z') {                v := c - 55;  # lower case letters apparently invalid            } else if (c = '*') {                v := 36;            } else if (c = '@') {                v := 37;            } else if (c = '#') {                v := 38;            } else {                return false;            };             # check if odd as using 0-based indexing            if(i % 2 = 1) {                v *= 2;            };              sum += v / 10 + v % 10;        };         return s->Get(8) - 48 = (10 - (sum % 10)) % 10;    }     function : Main(args : String[]) ~ Nil {        candidates := [            "037833100",            "17275R102",            "38259P508",            "594918104",            "68389X106",            "68389X105"        ];         each(i : candidates) {            candidate := candidates[i];            "{\$candidate} => "->Print();             if(IsCusip(candidate)) {                "correct"->PrintLine();            }            else {                "incorrect"->PrintLine();            };        };    }}`

Output:

```037833100 => correct
17275R102 => correct
38259P508 => correct
594918104 => correct
68389X106 => incorrect
68389X105 => correct
```

## Perl

`\$cv{\$_} = \$i++ for '0'..'9', 'A'..'Z', '*', '@', '#'; sub cusip_check_digit {    my @cusip = split m{}xms, shift;    my \$sum = 0;     for \$i (0..7) {        return 'Invalid character found' unless \$cusip[\$i] =~ m{\A [[:digit:][:upper:]*@#] \z}xms;        \$v  = \$cv{ \$cusip[\$i] };        \$v *= 2 if \$i%2;        \$sum += int(\$v/10) + \$v%10;    }     \$check_digit = (10 - (\$sum%10)) % 10;    \$check_digit == \$cusip[8] ? '' : ' (incorrect)';} my %test_data = (    '037833100' => 'Apple Incorporated',    '17275R102' => 'Cisco Systems',    '38259P508' => 'Google Incorporated',    '594918104' => 'Microsoft Corporation',    '68389X106' => 'Oracle Corporation',    '68389X105' => 'Oracle Corporation',); print "\$_ \$test_data{\$_}" . cusip_check_digit(\$_) . "\n" for sort keys %test_data;`
Output:
```037833100 Apple Incorporated
17275R102 Cisco Systems
594918104 Microsoft Corporation
68389X105 Oracle Corporation
68389X106 Oracle Corporation (incorrect)```

## Phix

```sequence cch = {}

function CusipCheckDigit(string cusip)
integer s = 0, c, v
if length(cch)=0 then
cch = repeat(-1,256)
for i='0' to '9' do
cch[i] = i-'0'
end for
for i='A' to 'Z' do
cch[i] = i-55
end for
cch['*'] = 36
cch['@'] = 37
cch['#'] = 38
end if
if length(cusip)!=9 or find('\0',cusip) then return 0 end if
for i=1 to 8 do
c := cusip[i]
v := cch[c]
if v=-1 then return 0 end if
if remainder(i,2)=0 then
v *= 2
end if
s += floor(v/10)+mod(v,10)
end for
return cusip[9]=mod(10-mod(s,10),10)+'0'
end function

sequence tests = {"037833100",  -- Apple Incorporated
"17275R102",  -- Cisco Systems
"594918104",  -- Microsoft Corporation
"68389X106",  -- Oracle Corporation   (incorrect)
"68389X105"}  -- Oracle Corporation

for i=1 to length(tests) do
string ti = tests[i]
printf(1,"%s : %s\n",{ti,{"invalid","valid"}[CusipCheckDigit(ti)+1]})
end for
```
Output:
```037833100 : valid
17275R102 : valid
38259P508 : valid
594918104 : valid
68389X106 : invalid
68389X105 : valid
```

## PHP

`function IsCusip(string \$s) {    if (strlen(\$s) != 9) return false;    \$sum = 0;    for (\$i = 0; \$i <= 7; \$i++) {        \$c = \$s[\$i];        if (ctype_digit(\$c)) {            // if character is numeric, get character's numeric value            \$v = intval(\$c);        } elseif (ctype_alpha(\$c)) {            // if character is alphabetic, get character's ordinal position in alphabet            \$position = ord(strtoupper(\$c)) - ord('A') + 1;            \$v = \$position + 9;        } elseif (\$c == "*") {            \$v = 36;        } elseif (\$c == "@") {            \$v = 37;        } elseif (\$c == "#") {            \$v = 38;        } else {            return false;        }        // is this character position even?        if (\$i % 2 == 1) {            \$v *= 2;        }        // calculate the checksum digit        \$sum += floor(\$v / 10 ) + ( \$v % 10 );    }    return ord(\$s[8]) - 48 == (10 - (\$sum % 10)) % 10;} \$cusips = array("037833100",                "17275R102",                "38259P508",                "594918104",                "68389X106",                "68389X105"); foreach (\$cusips as \$cusip) echo \$cusip . " -> " . (IsCusip(\$cusip) ? "valid" : "invalid") . "\n";`
Output:
```037833100 -> valid
17275R102 -> valid
38259P508 -> valid
594918104 -> valid
68389X106 -> invalid
68389X105 -> valid```

## PicoLisp

`(de cusip (Str)   (let (Str (mapcar char (chop Str))  S 0)      (for (I . C) (head 8 Str)         (let V            (cond               ((<= 48 C 57) (- C 48))               ((<= 65 C 90) (+ 10 (- C 65)))               ((= C 42) 36)               ((= C 64) 37)               ((= C 35) 38) )            (or               (bit? 1 I)               (setq V (>> -1 V)) )            (inc               'S               (+ (/ V 10) (% V 10)) ) ) )      (=         (- (last Str) 48)         (% (- 10 (% S 10)) 10) ) ) ) (println   (mapcar      cusip      (quote         "037833100"         "17275R102"         "38259P508"         "68389X106"         "68389X105" ) ) )`
Output:
`(T T T NIL T)`

## PowerShell

` function Get-CheckDigitCUSIP {    [CmdletBinding()]    [OutputType([int])]    Param ( #  Validate input        [Parameter(Mandatory=\$true, Position=0)]        [ValidatePattern( '^[[email protected]#*]{8}\d\$' )] # @#*        [ValidateScript({\$_.Length -eq 9})]        [string]        \$cusip    )    \$sum = 0    0..7 | ForEach { \$c = \$cusip[\$_] ; \$v = \$null        if ([Char]::IsDigit(\$c)) { \$v = [char]::GetNumericValue(\$c) }        if ([Char]::IsLetter(\$c)) { \$v = [int][char]\$c - [int][char]'A' +10 }        if (\$c -eq '*') { \$v = 36 }        if (\$c -eq '@') { \$v = 37 }        if (\$c -eq '#') { \$v = 38 }        if(\$_ % 2){ \$v += \$v }        \$sum += [int][Math]::Floor(\$v / 10 ) + (\$v % 10)    }    [int]\$checkDigit_calculated = ( 10 - (\$sum % 10) ) % 10    return( \$checkDigit_calculated )} function Test-IsCUSIP {    [CmdletBinding()]    [OutputType([bool])]    Param (        [Parameter(Mandatory=\$true, Position=0)]        [ValidatePattern( '^[[email protected]#*]{8}\d\$' )]        [ValidateScript({\$_.Length -eq 9})]        [string]        \$cusip    )    [int]\$checkDigit_told = \$cusip[-1].ToString()    \$checkDigit_calculated = Get-CheckDigitCUSIP \$cusip    (\$checkDigit_calculated -eq \$checkDigit_told)} \$data = @"037833100`tApple Incorporated17275R102`tCisco Systems38259P508`tGoogle Incorporated594918104`tMicrosoft Corporation68389X106`tOracle Corporation   (incorrect)68389X105`tOracle Corporation"@ -split "`n"\$data |%{ Test-IsCUSIP \$_.Split("`t")[0] } `
Output:
```
True
True
True
True
False
True

```

## Python

### Procedural

Requires Python 3.6 for the string template literal in the print statement.

`#!/usr/bin/env python3 import math def cusip_check(cusip):    if len(cusip) != 9:        raise ValueError('CUSIP must be 9 characters')     cusip = cusip.upper()    total = 0    for i in range(8):        c = cusip[i]        if c.isdigit():            v = int(c)        elif c.isalpha():            p = ord(c) - ord('A') + 1            v = p + 9        elif c == '*':            v = 36        elif c == '@':            v = 37        elif c == '#':            v = 38         if i % 2 != 0:            v *= 2         total += int(v / 10) + v % 10    check = (10 - (total % 10)) % 10    return str(check) == cusip[-1] if __name__ == '__main__':    codes = [            '037833100',            '17275R102',            '38259P508',            '594918104',            '68389X106',            '68389X105'            ]    for code in codes:        print(f'{code} -> {cusip_check(code)}') `

Output:

```037833100 -> True
17275R102 -> True
38259P508 -> True
594918104 -> True
68389X106 -> False
68389X105 -> True
```

### Composition of pure functions

Works with: Python version 3.7

Composing a set of pure functions, including a number of general and reusable abstractions:

`'''CUSIP''' from itertools import (cycle, islice, starmap)from functools import (reduce)from operator import (add)from enum import (Enum)  # isCusip :: Dict -> String -> Booldef isCusip(dct):    '''Test for the validity of a CUSIP string in the       context of a supplied dictionary of char values'''    def go(s):        ns = [dct[c] for c in list(s) if c in dct]        return 9 == len(ns) and (            ns[-1] == (                10 - (                    sum(zipWith(                        lambda f, x: add(*divmod(f(x), 10))                    )(cycle([identity, double]))(                        take(8)(ns)                    )) % 10                )            ) % 10        )    return go  # cusipCharDict :: () -> Dict Char Intdef cusipCharDict():    '''Dictionary of integer values for CUSIP characters'''    def kv(a, ic):        i, c = ic        a[c] = i        return a    return reduce(        kv,        enumerate(            enumFromTo('0')('9') + (                enumFromTo('A')('Z') + list('*&#')            )        ),        {}    )  # TEST -------------------------------------------------# main :: IO ()def main():    '''Tests'''     # cusipTest :: String -> Bool    cusipTest = isCusip(cusipCharDict())     print(        tabulated('Valid as CUSIP string:')(            cusipTest        )([            '037833100',            '17275R102',            '38259P508',            '594918104',            '68389X106',            '68389X105'        ])    ) # GENERIC -------------------------------------------------  # double :: Num -> Numdef double(x):    '''Wrapped here as a function for the zipWith expression'''    return 2 * x  # enumFromTo :: Enum a => a -> a -> [a]def enumFromTo(m):    '''Enumeration of values [m..n]'''    def go(x, y):        t = type(m)        i = fromEnum(x)        d = 0 if t != float else (x - i)        return list(map(            lambda x: toEnum(t)(d + x),            range(i, 1 + fromEnum(y))        ) if int != t else range(x, 1 + y))    return lambda n: go(m, n)  # fromEnum :: Enum a => a -> Intdef fromEnum(x):    '''Index integer for enumerable value.'''    return ord(x) if str == type(x) else (        x.value if isinstance(x, Enum) else int(x)    )  # mul :: Num -> Num -> Numdef mul(x):    '''Function version of (*) operator;       a curried equivalent of operator.mul'''    return lambda y: x * y  # identity :: a -> adef identity(x):    '''The identity function.       The usual 'id' is reserved in Python.'''    return x  # tabulated :: String -> (a -> b) -> [a] -> Stringdef tabulated(s):    '''heading -> function -> input List -> tabulated output string'''    def go(f, xs):        def width(x):            return len(str(x))        w = width(max(xs, key=width))        return s + '\n' + '\n'.join([            str(x).rjust(w, ' ') + ' -> ' + str(f(x)) for x in xs        ])    return lambda f: lambda xs: go(f, xs)  # take :: Int -> [a] -> [a]# take :: Int -> String -> Stringdef take(n):    '''The prefix of xs of length n,       or xs itself if n > length xs.'''    return lambda xs: (        xs[0:n]        if isinstance(xs, list)        else list(islice(xs, n))    )  # toEnum :: Type -> Int -> adef toEnum(t):    '''Enumerable value from index integer'''    dct = {        int: int,        float: float,        str: chr,        bool: bool    }    return lambda x: dct[t](x) if t in dct else t(x)  # zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]def zipWith(f):    '''Zipping with a custom (rather than tuple) function'''    return lambda xs: lambda ys: (        list(starmap(f, zip(xs, ys)))    )  # MAIN ---if __name__ == '__main__':    main()`
Output:
```Test for validity as a CUSIP string:

'037833100' -> True
'17275R102' -> True
'38259P508' -> True
'594918104' -> True
'68389X106' -> False
'68389X105' -> True```

## Quackery

`  [ -1 split 0 peek char 0 -    swap 0 swap     witheach      [ [ dup char 0 char 9 1+ within iff            [ char 0 - ] done          dup char A char Z 1+ within iff            [ char A - 10 + ] done          dup char * = iff            [ drop 36 ] done          dup char @ = iff            [ drop 37 ] done          dup char # = iff            [ drop 38 ] done          \$ "Unexpected character '" swap          join \$ "' in CUSIP." join fail ]        i^ 1 & if [ 2 * ]        10 /mod + + ]    10 mod 10 swap - 10 mod = ]            is cusip ( \$ --> b )   [ dup echo\$ cusip iff      [ say " is correct." ]    else [ say " is incorrect." ]    cr ]                                   is task  ( \$ -->   )   \$ "037833100 17275R102 38259P508 594918104 68389X106 68389X105"   nest\$ witheach task`
Output:
```037833100 is correct.
17275R102 is correct.
38259P508 is correct.
594918104 is correct.
68389X106 is incorrect.
68389X105 is correct.
```

## Racket

`#lang racket(require srfi/14) (define 0-char (char->integer #\0))(define A-char (char->integer #\A)) (define (cusip-value c)    (cond    [(char-set-contains? char-set:digit c)     (- (char->integer c) 0-char)]    [(char-set-contains? char-set:upper-case c)     (+ 10 (- (char->integer c) A-char))]    [(char=? c #\*) 36]    [(char=? c #\@) 37]    [(char=? c #\#) 38])) (define (cusip-check-digit cusip)  (modulo   (- 10      (modulo       (for/sum        ((i (sequence-map add1 (in-range 8))) (c (in-string cusip)))         (let* ((v (cusip-value c)) (v′ (if (even? i) (* v 2) v)))           (+ (quotient v′ 10) (modulo v′ 10)))) 10)) 10)) (define (CUSIP? s)  (char=? (string-ref s (sub1 (string-length s)))          (integer->char (+ 0-char (cusip-check-digit s))))) (module+ test  (require rackunit)           (check-true (CUSIP? "037833100"))  (check-true (CUSIP? "17275R102"))  (check-true (CUSIP? "38259P508"))  (check-true (CUSIP? "594918104"))  (check-false (CUSIP? "68389X106"))  (check-true (CUSIP? "68389X105")))`

no output indicates all tests passed.

## Raku

(formerly Perl 6)

Works with: Rakudo version 2017.01
`sub divmod (\$v, \$r) { \$v div \$r, \$v mod \$r }my %chr = (flat 0..9, 'A'..'Z', <* @ #>) Z=> 0..*; sub cuisp-check (\$cuisp where *.chars == 9) {    my (\$code, \$chk) = \$cuisp.comb(8);    my \$sum = [+] \$code.comb.kv.map: { [+] ((\$^k % 2 + 1) * %chr{\$^v}).&divmod(10) };    so (10 - \$sum mod 10) mod 10 eq \$chk;} # TESTINGsay "\$_: ", \$_.&cuisp-check for <03783310017275R10238259P50859491810468389X10668389X105>`
Output:
```037833100: True
17275R102: True
38259P508: True
594918104: True
68389X106: False
68389X105: True```

## REXX

### idiomatic

`/*REXX program validates that the  last digit (the check digit)  of a  CUSIP  is valid. */@.=parse arg @.1 .if @.1=='' | @.1==","  then do;   @.1= 037833100       /* Apple Incorporated            */                                  @.2= 17275R102       /* Cisco Systems                 */                                  @.3= 38259P508       /* Google Incorporated           */                                  @.4= 594918104       /* Microsoft Corporation         */                                  @.5= 68389X106       /* Oracle Corporation (incorrect)*/                                  @.6= 68389X105       /* Oracle Corporation            */                            end      do j=1  while @.j\='';   chkDig=CUSIPchk(@.j)     /*calculate check digit from func*/     OK=word("isn't is", 1 + (chkDig==right(@.j,1) ) ) /*validate  check digit with func*/     say 'CUSIP '    @.j    right(OK, 6)     "valid."  /*display the CUSIP and validity.*/     end   /*j*/exit                                             /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/CUSIPchk: procedure;  arg x 9;  \$=0;                     abc= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'                                       do k=1  for 8                                       y=substr(x, k, 1)                                          select                                          when datatype(y,'W')  then #=y                                          when datatype(y,'U')  then #=pos(y, abc) + 9                                          when          y=='*'  then #=36                                          when          y=='@'  then #=37                                          when          y=='#'  then #=38                                          otherwise  return 0       /*invalid character.*/                                          end   /*select*/                                       if k//2==0  then #=#+#       /*K even?  Double it*/                                       \$=\$ + #%10 + #//10                                       end      /*k*/           return (10- \$//10) // 10`

output   when using the default input:

```CUSPID  037833100     is valid.
CUSPID  17275R102     is valid.
CUSPID  38259P508     is valid.
CUSPID  594918104     is valid.
CUSPID  68389X106  isn't valid.
CUSPID  68389X105     is valid.
```

### conciser function

`/*REXX program validates that the  last digit (the check digit)  of a  CUSIP  is valid. */@.=parse arg @.1 .if @.1=='' | @.1==","  then do;   @.1= 037833100       /* Apple Incorporated            */                                  @.2= 17275R102       /* Cisco Systems                 */                                  @.3= 38259P508       /* Google Incorporated           */                                  @.4= 594918104       /* Microsoft Corporation         */                                  @.5= 68389X106       /* Oracle Corporation (incorrect)*/                                  @.6= 68389X105       /* Oracle Corporation            */                            end      do j=1  while @.j\='';   chkDig=CUSIPchk(@.j)     /*calculate check digit from func*/     OK=word("isn't is", 1 + (chkDig==right(@.j,1) ) ) /*validate  check digit with func*/     say 'CUSIP '    @.j    right(OK, 6)     "valid."  /*display the CUSIP and validity.*/     end   /*j*/exit                                             /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/CUSIPchk: procedure; arg x 9;  \$=0;         abc= '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#'                                      /* [↓]  if  Y  isn' found,  then POS returns zero.*/                                    do k=1  for 8;   y=substr(x,k,1) /*get a character. */                                    #=pos(y, abc) - 1                /*get its position.*/                                    if #   == -1  then return 0      /*invalid character*/                                    if k//2==  0  then #=#+#         /*K even? double it*/                                    \$=\$ + #%10 + #//10                                    end      /*k*/          return (10-\$//10) // 10`

output   is the same as the idiomatic REXX version.

## Ring

` # Project : CUSIP inputstr = list(6)inputstr[1] = "037833100"inputstr[2] = "17275R102"inputstr[3] = "38259P508"inputstr[4] = "594918104"inputstr[5] = "68389X106"inputstr[6] = "68389X105"for n = 1 to len(inputstr)     cusip(inputstr[n])next func cusip(inputstr)         if len(inputstr) != 9            see " length is incorrect, invalid cusip"            return        ok        v = 0        sum = 0        for i = 1 to 8             flag = 0             x = ascii(inputstr[i])             if x >= ascii("0") and x <= ascii("9")                v = x - ascii("0")                flag = 1             ok             if x >= ascii("A") and x <= ascii("Z")                v = x - 55                flag = 1             ok             if x = ascii("*")                v= 36                flag = 1             ok             if x = ascii("@")                v = 37                flag = 1             ok             if x = ascii("#")                v = 38                flag = 1             ok             if flag = 0                   see " found a invalid character, invalid cusip" + nl             ok             if (i % 2) = 0                  v = v * 2             ok             sum = sum + floor(v / 10) + v % 10        next         sum = (10 - (sum % 10)) % 10        if sum = (ascii(inputstr[9]) - ascii("0"))           see inputstr + " is valid" + nl        else           see inputstr + " is invalid" + nl        ok `

Output:

```037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid
```

## Ruby

### Following pseudocode

` #!/usr/bin/env ruby def check_cusip(cusip)  abort('CUSIP must be 9 characters') if cusip.size != 9   sum = 0  cusip.split('').each_with_index do |char, i|    next if i == cusip.size - 1    case    when char.scan(/\D/).empty?      v = char.to_i    when char.scan(/\D/).any?      pos = char.upcase.ord - 'A'.ord + 1      v = pos + 9    when char == '*'      v = 36    when char == '@'      v = 37    when char == '#'      v = 38    end     v *= 2 unless (i % 2).zero?    sum += (v/10).to_i + (v % 10)  end   check = (10 - (sum % 10)) % 10  return 'VALID' if check.to_s == cusip.split('').last  'INVALID'end CUSIPs = %w[  037833100 17275R102 38259P508 594918104 68389X106 68389X105] CUSIPs.each do |cusip|  puts "#{cusip}: #{check_cusip(cusip)}"end  `

Output:

```037833100: VALID
17275R102: VALID
38259P508: VALID
594918104: VALID
68389X106: INVALID
68389X105: VALID
```

### More concise

Since it uses methods like chain, to_h, sum, and infinite Range syntax (0..), this needs a Ruby version > 2.5

` TABLE = ("0".."9").chain("A".."Z", %w(* @ #)).zip(0..).to_h def valid_CUSIP?(str)  sum = str[0..-2].chars.each_slice(2).sum do |c1,c2|    TABLE[c1].divmod(10).sum + (TABLE[c2]*2).divmod(10).sum  end  str[-1].to_i == (10 - (sum % 10)) % 10end CUSIPs = %w(037833100 17275R102 38259P508 594918104 68389X106 68389X105)CUSIPs.each{|cusip| puts "#{cusip}: #{valid_CUSIP? cusip}"} `

## Rust

`fn cusip_check(cusip: &str) -> bool {    if cusip.len() != 9 {        return false;    }     let mut v = 0;    let capital_cusip = cusip.to_uppercase();    let char_indices = capital_cusip.as_str().char_indices().take(7);     let total = char_indices.fold(0, |total, (i, c)| {        v = match c {            '*' => 36,            '@' => 37,            '#' => 38,            _ if c.is_digit(10) => c.to_digit(10).unwrap() as u8,            _ if c.is_alphabetic() => (c as u8) - b'A' + 1 + 9,            _ => v,        };         if i % 2 != 0 {            v *= 2        }        total + (v / 10) + v % 10    });     let check = (10 - (total % 10)) % 10;    (check.to_string().chars().nth(0).unwrap()) == cusip.chars().nth(cusip.len() - 1).unwrap()} fn main() {    let codes = [        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105",    ];    for code in &codes {        println!("{} -> {}", code, cusip_check(code))    }}`

Output:

```037833100 -> True
17275R102 -> True
38259P508 -> True
594918104 -> True
68389X106 -> False
68389X105 -> True
```

## Scala

Output:
See it running in your browser by ScalaFiddle (JavaScript, non JVM) or by Scastie (JVM).
`object Cusip extends App {   val candidates = Seq("037833100", "17275R102", "38259P508", "594918104", "68389X106", "68389X105")   for (candidate <- candidates)    printf(f"\$candidate%s -> \${if (isCusip(candidate)) "correct" else "incorrect"}%s%n")   private def isCusip(s: String): Boolean = {    if (s.length != 9) false    else {      var sum = 0      for (i <- 0 until 7) {        val c = s(i)        var v = 0        if (c >= '0' && c <= '9') v = c - 48        else if (c >= 'A' && c <= 'Z') v = c - 55 // lower case letters apparently invalid        else if (c == '*') v = 36        else if (c == '@') v = 37        else if (c == '#') v = 38        else return false        if (i % 2 == 1) v *= 2 // check if odd as using 0-based indexing        sum += v / 10 + v % 10      }      s(8) - 48 == (10 - (sum % 10)) % 10    }  } }`

## SNOBOL4

`#!/usr/local/bin/snobol4 -r*  cusip.sno*   -- Committee on Uniform Security Identification Procedures*  -r : read data placed after the end label.*  Verify check digit and size of cusip code.      define("cusipt()i")                  :(cusipt_end)cusipt     chars = &digits &ucase "*@#"     cusipt = table()     i = 0cusipt_1     chars pos(i) len(1) . c              :f(return)     cusipt[c] = i     i = i + 1                            :(cusipt_1)cusipt_end      define("check_cusip(line)c,i")       :(check_cusip_end)check_cusip     eq(size(line), 9)                    :f(freturn)     check_cusip = 0     i = 0check_cusip_1     line pos(i) len(1) . c     value = t[c]     value = eq(remdr(i, 2), 1) t[c] * 2     check_cusip = check_cusip + (value / 10) + remdr(value, 10)     i = lt(i, 7) i + 1                   :s(check_cusip_1)     check_cusip = remdr(10 - remdr(check_cusip, 10), 10)     eq(substr(line, 9, 1), check_cusip)  :s(return)f(freturn)check_cusip_end *** main ***     t = cusipt() read line = input                         :f(end)     check_cusip(line)                    :f(bad_cusip)     output = line " valid."              :(read)bad_cusip     output =  line " not valid."         :(read)end03783310017275R10238259P50859491810468389X10668389X10568389X1068389X105968389x105`
Output:
```037833100 valid.
17275R102 valid.
38259P508 valid.
594918104 valid.
68389X106 not valid.
68389X105 valid.
68389X10 not valid.
68389X1059 not valid.
68389x105 not valid.```

## Swift

`struct CUSIP {  var value: String   private static let alphabet = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ")   init?(value: String) {    if value.count == 9 && String(value.last!) == CUSIP.checkDigit(cusipString: String(value.dropLast())) {      self.value = value    } else if value.count == 8, let checkDigit = CUSIP.checkDigit(cusipString: value) {      self.value = value + checkDigit    } else {      return nil    }  }   static func checkDigit(cusipString: String) -> String? {    guard cusipString.count == 8, cusipString.allSatisfy({ \$0.isASCII }) else {      return nil    }     let sum = cusipString.uppercased().enumerated().reduce(0, {sum, pair in      let (i, char) = pair      var v: Int       switch char {      case "*":        v = 36      case "@":        v = 37      case "#":        v = 38      case _ where char.isNumber:        v = char.wholeNumberValue!      case _:        v = Int(char.asciiValue! - 65) + 10      }       if i & 1 == 1 {        v *= 2      }       return sum + (v / 10) + (v % 10)    })     return String((10 - (sum % 10)) % 10)  }} let testCases = [  "037833100",  "17275R102",  "38259P508",  "594918104",  "68389X106",  "68389X105"] for potentialCUSIP in testCases {  print("\(potentialCUSIP) -> ", terminator: "")   switch CUSIP(value: potentialCUSIP) {  case nil:    print("Invalid")  case _:    print("Valid")  }}`
Output:
```037833100 -> Valid
17275R102 -> Valid
38259P508 -> Valid
594918104 -> Valid
68389X106 -> Invalid
68389X105 -> Valid```

## Tcl

### Direct translation of pseudocode

`proc ordinal-of-alpha {c} {                     ;#  returns ordinal position of c in the alphabet (A=1, B=2...)    lsearch {_ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} [string toupper \$c]} proc Cusip-Check-Digit {cusip} {                ;# algorithm Cusip-Check-Digit(cusip) is    if {[string length \$cusip] != 8} {          ;#    Input: an 8-character CUSIP        return false    }     set sum 0                                   ;#    sum := 0    for {set i 1} {\$i <= 8} {incr i} {          ;#    for 1 ≤ i ≤ 8 do        set c [string index \$cusip \$i-1]        ;#       c := the ith character of cusip        if {[string is digit \$c]} {             ;#       if c is a digit then            set v \$c                            ;#          v := numeric value of the digit c        } elseif {[string is alpha \$c]} {       ;#       else if c is a letter then            set p [ordinal-of-alpha \$c]         ;#          p := ordinal position of c in the alphabet (A=1, B=2...)            set v [expr {\$p + 9}]               ;#          v := p + 9        } elseif {\$c eq "*"} {                  ;#       else if c = "*" then            set v 36                            ;#          v := 36        } elseif {\$c eq "@"} {                  ;#       else if c = "@" then            set v 37                            ;#          v := 37        } elseif {\$c eq "#"} {                  ;#       else if c = "#" then            set v 38                            ;#          v := 38        }                                       ;#       end if        if {\$i % 2 == 0} {                      ;#       if i is even then            set v [expr {\$v * 2}]               ;#          v := v × 2        }                                       ;#       end if         incr sum [expr {\$v / 10 + \$v % 10}]     ;#       sum := sum + int ( v div 10 ) + v mod 10    }                                           ;#    repeat     expr {(10 - (\$sum % 10)) % 10}              ;#    return (10 - (sum mod 10)) mod 10}proc check-cusip {cusip} {    set last  [string index \$cusip end]    set cusip [string range \$cusip 0 end-1]    expr {\$last eq [Cusip-Check-Digit \$cusip]}}`

### More idiomatic Tcl

`proc check-cusip {code} {    if {[string length \$code] != 9} {        return false    }    set alphabet [email protected]#    set code [split [string tolower \$code] ""]    foreach char \$code idx {1 2 3 4 5 6 7 8 9} {        set v [string first \$char \$alphabet]        if {\$v == -1} {return false}        if {\$idx % 2 == 0} {            incr v \$v        }        set v [::tcl::mathop::+ {*}[split \$v ""]]        incr sum \$v    }    expr {\$sum % 10 == 0}}`

### Common test harness

`proc test {} {    foreach {cusip name} {        037833100       "Apple Incorporated"        17275R102       "Cisco Systems"        38259P508       "Google Incorporated"        594918104       "Microsoft Corporation"        68389X106       "Oracle Corporation   (incorrect)"        68389X105       "Oracle Corporation"    } {        puts [format %-40s%s \$name [expr {[check-cusip \$cusip] ? "valid" : "invalid"}]]        puts [format %-40s%s \$name [expr {[cusip-check \$cusip] ? "valid" : "invalid"}]]    }}test`

### Output

Output:
```Apple Incorporated                      valid
Cisco Systems                           valid
Microsoft Corporation                   valid
Oracle Corporation   (incorrect)        invalid
Oracle Corporation                      valid```

## VBA

`Private Function Cusip_Check_Digit(s As Variant) As Integer    Dim Sum As Integer, c As String, v As Integer    For i = 1 To 8        c = Mid(s, i, 1)        If IsNumeric(c) Then            v = Val(c)        Else            Select Case c                Case "a" To "z"                    v = Asc(c) - Asc("a") + 10                Case "A" To "Z"                    v = Asc(c) - Asc("A") + 10                Case "*"                    v = 36                Case "@"                    v = 37                Case "#"                    v = 38                Case Else                    Debug.Print "not expected"            End Select        End If        If i Mod 2 = 0 Then v = v * 2        Sum = Sum + Int(v \ 10) + v Mod 10    Next i    Cusip_Check_Digit = (10 - (Sum Mod 10)) Mod 10End Function`
Output:
```037833100     is valid
17275R102     is valid
38259P508     is valid
594918104     is valid
68389X106     not valid
68389X105     is valid```

## Visual Basic .NET

Translation of: C#
`Module Module1     Function IsCUSIP(s As String) As Boolean        If s.Length <> 9 Then            Return False        End If         Dim sum = 0        For i = 0 To 7            Dim c = s(i)             Dim v As Integer            If "0" <= c AndAlso c <= "9" Then                v = Asc(c) - 48            ElseIf "A" <= c AndAlso c <= "Z" Then                v = Asc(c) - 55 ' Lower case letters are apparently invalid            ElseIf c = "*" Then                v = 36            ElseIf c = "#" Then                v = 38            Else                Return False            End If             If i Mod 2 = 1 Then                v *= 2 ' check if odd as using 0-based indexing            End If            sum += v \ 10 + v Mod 10        Next        Return Asc(s(8)) - 48 = (10 - (sum Mod 10)) Mod 10    End Function     Sub Main()        Dim candidates As New List(Of String) From {            "037833100",            "17275R102",            "38259P508",            "594918104",            "68389X106",            "68389X105"        }         For Each candidate In candidates            Console.WriteLine("{0} -> {1}", candidate, If(IsCUSIP(candidate), "correct", "incorrect"))        Next    End Sub End Module`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct```

## Vlang

Translation of: Go
`fn is_cusip(s string) bool {    if s.len != 9 { return false }    mut sum := 0    for i in 0..8 {        c := s[i]        mut v :=0        match true {            c >= '0'[0] && c <= '9'[0] {                v = c - 48			}            c >= 'A'[0] && c <= 'Z'[0] {                v = c - 55			}            c == '*'[0] {                v = 36			}            c == '@'[0] {                v = 37			}            c == '#'[0] {                v = 38			}            else {                return false			}        }        if i % 2 == 1 { v *= 2 }  // check if odd as using 0-based indexing        sum += v/10 + v%10    }    return int(s[8]) - 48 == (10 - (sum%10)) % 10} fn main() {    candidates := [        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105",	]     for candidate in candidates {        mut b :=' '        if is_cusip(candidate) {            b = "correct"        } else {            b = "incorrect"        }        println("\$candidate -> \$b")    }}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
```

## Wren

Translation of: Go
`var isCusip = Fn.new { |s|    if (s.count != 9) return false    var sum = 0    for (i in 0..7) {        var c = s[i].bytes[0]        var v        if (c >= 48 && c <= 57) { // '0' to '9'            v = c - 48        } else if (c >= 65 && c <= 90) { // 'A' to 'Z'            v = c - 55        } else if (s[i] == "*") {            v = 36        } else if (s[i] == "@") {            v = 37        } else if (s[i] == "#") {            v = 38        } else {            return false        }        if (i%2 == 1) v = v * 2 // check if odd as using 0-based indexing        sum = sum + (v/10).floor + v%10    }    return s[8].bytes[0] - 48 == (10 - (sum%10)) % 10} var candidates = [    "037833100",    "17275R102",    "38259P508",    "594918104",    "68389X106",    "68389X105"]for (candidate in candidates) {    var b = (isCusip.call(candidate)) ? "correct" : "incorrect"    System.print("%(candidate) -> %(b)")}`
Output:
```037833100 -> correct
17275R102 -> correct
38259P508 -> correct
594918104 -> correct
68389X106 -> incorrect
68389X105 -> correct
```

## XPL0

`string 0;               \use zero-terminated strings func    Valid(Cusip);   \Return 'true' if valid CUSIP codechar    Cusip;int     Sum, I, C, V;[Sum:= 0;for I:= 0 to 8-1 do        [C:= Cusip(I);        ChOut(0, C);        case of          C>=^0 & C<=^9: V:= C-^0;          C>=^A & C<=^Z: V:= C-^A+10;          C=^*: V:=36;          C=^@: V:=37;          C=^#: V:=38        other V:= -1;        if I&1 then V:= V*2;        Sum:= Sum + V/10 + rem(0);        ];C:= Cusip(I);ChOut(0, C);V:= rem( (10-rem(Sum/10)) / 10 );return V = C-^0;]; int Cusip, N;[Cusip:= ["037833100",          "17275R102",          "38259P508",          "594918104",          "68389X106",          "68389X105"];for N:= 0 to 6-1 do        [Text(0, if Valid(Cusip(N))                then " is valid"                else " is invalid");        CrLf(0);        ];]`
Output:
```037833100 is valid
17275R102 is valid
38259P508 is valid
594918104 is valid
68389X106 is invalid
68389X105 is valid
```

## Yabasic

Translation of: FreeBASIC
`sub cusip(inputStr\$)    local i, v, sum, x\$     Print inputStr\$;    If Len(inputStr\$) <> 9 Print " length is incorrect, invalid cusip" : return     For i = 1 To 8        x\$ = mid\$(inputStr\$, i, 1)        switch x\$            Case "*": v = 36 : break            Case "@": v = 37 : break            Case "#": v = 38 : break            default:                if x\$ >= "A" and x\$ <= "Z" then                    v = asc(x\$) - Asc("A") + 10                elsif x\$ >= "0" and x\$ <= "9" then                    v = asc(x\$) - asc("0")                else                    Print " found a invalid character, invalid cusip"                    return                end if        End switch         If and(i, 1) = 0 v = v * 2        sum = sum + int(v / 10) + mod(v, 10)    Next     sum = mod(10 - mod(sum, 10), 10)    If sum = asc(mid\$(inputStr\$, 9, 1)) - Asc("0") Then        Print " is valid"    Else        Print " is invalid"    End If End Sub // ------=< MAIN >=------ Data "037833100", "17275R102", "38259P508"Data "594918104", "68389X106", "68389X105", "" Printdo    Read inputStr\$    if inputStr\$ = "" break    cusip(inputStr\$)loop `

## Zig

`const std = @import("std");const print = std.debug.print; pub fn CusipCheckDigit(cusip: *const [9:0]u8) bool {    var i: usize = 0;    var sum: i32 = 0;    while (i < 8) {        const c = cusip[i];        var v: i32 = undefined;        if (c <= '9' and c >= '0') {            v = c - 48;        }        else if (c <= 'Z' and c >= 'A') {            v = c - 55;        }        else if (c == '*') {            v = 36;        }        else if (c == '@') {            v = 37;        }        else if (c == '#') {            v = 38;        }        else {            return false;        }        if (i % 2 == 1) {            v *= 2;        }        sum = sum + @divFloor(v, 10) + @mod(v, 10);        i += 1;    }    return (cusip[8] - 48 == @mod((10 - @mod(sum, 10)), 10));} pub fn main() void {    const cusips = [_]*const [9:0]u8 {        "037833100",        "17275R102",        "38259P508",        "594918104",        "68389X106",        "68389X105"    };    for (cusips) |cusip| {        print("{s} -> {}\n", .{cusip, CusipCheckDigit(cusip)});    }} `

## zkl

`fcn cusipCheckDigit(cusip){   var [const] vs=[0..9].chain(["A".."Z"],T("*","@","#")).pump(String);   try{      sum:=Walker.cycle(1,2).zipWith(fcn(n,c){ v:=vs.index(c)*n; v/10 + v%10 },           cusip[0,8]).reduce('+);      ((10 - sum%10)%10 == cusip[8].toInt()) and cusip.len()==9   }catch{ False }}`
`foreach cusip in (T("037833100", "17275R102",		    "38259P508", "594918104", "68389X106", "68389X105")){   println(cusip,": ",cusipCheckDigit(cusip));      }`
Output:
```037833100: True
17275R102: True
38259P508: True
594918104: True
68389X106: False
68389X105: True
```