

 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.



Task

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 
   38259P508       Google Incorporated 
   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 10
end function
See related tasks
 
 SEDOL
 ISIN


 
#!/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
 
 