Task: Validate International Securities Identification Number





Java: public class ISIN {
 
    public static void main(String[] args) {
        String[] isins = {
            "US0378331005", 
            "US0373831005", 
            "U50378331005", 
            "US03378331005",
            "AU0000XVGZA3", 
            "AU0000VXGZA3", 
            "FR0000988040"
        };
        for (String isin : isins)
            System.out.printf("%s is %s\n", isin, ISINtest(isin) ? "valid" : "not valid");
    }
 
    static boolean ISINtest(String isin) {
        isin = isin.trim().toUpperCase();
 
        if (!isin.matches("^[A-Z]{2}[A-Z0-9]{9}\\d$"))
            return false;
 
        StringBuilder sb = new StringBuilder();
        for (char c : isin.substring(0, 12).toCharArray())
            sb.append(Character.digit(c, 36));
 
        return luhnTest(sb.toString());
    }

    static boolean luhnTest(String number) {
        int s1 = 0, s2 = 0;
        String reverse = new StringBuffer(number).reverse().toString();
        for (int i = 0; i < reverse.length(); i++){
            int digit = Character.digit(reverse.charAt(i), 10);
            
            if (i % 2 == 0){
                s1 += digit;
            } else { 
                s2 += 2 * digit;
                if(digit >= 5){
                    s2 -= 9;
                }
            }
        }
        return (s1 + s2) % 10 == 0;
    }
}







Ada: procedure ISIN is
   
   function Luhn_Test (Number: String) return Boolean is
      Sum  : Natural := 0;
      Odd  : Boolean := True;
      Digit: Natural range 0 .. 9;
   begin
      for p in reverse Number'Range loop
         Digit := Integer'Value (Number (p..p));
         if Odd then
            Sum := Sum + Digit;
         else
            Sum := Sum + (Digit*2 mod 10) + (Digit / 5);
         end if;
         Odd := not Odd;
      end loop;
      return (Sum mod 10) = 0;
   end Luhn_Test;
   
   subtype Decimal   is Character range '0' .. '9';
   subtype Letter    is Character range 'A' .. 'Z';
   subtype ISIN_Type is String(1..12);
   
   
   function To_Digits(S: String) return String is
      
      Offset: constant Integer := Character'Pos('A')-10;
   
      Invalid_Character: exception;
   begin
      if S = "" then
         return "";
      elsif S(S'First) = ' ' then 
         return To_Digits(S(S'First+1 .. S'Last)); 
      elsif S(S'First) in Decimal then 
         return S(S'First) & To_Digits(S(S'First+1 .. S'Last));
      elsif S(S'First) in Letter then
         return To_Digits(Integer'Image(Character'Pos(S(S'First))-Offset))
           & To_Digits(S(S'First+1 .. S'Last));
      else 
         raise Invalid_Character;
      end if;
   end To_Digits;
   
   function Is_Valid_ISIN(S: ISIN_Type) return Boolean is
      Number : String := To_Digits(S);
   begin
      return S(S'First)   in Letter  and
             S(S'First+1) in Letter  and
             S(S'Last)    in Decimal and
             Luhn_Test(Number);
   end Is_Valid_ISIN;

   Test_Cases : constant Array(1..6) of ISIN_Type :=
      ("US0378331005",
       "US0373831005",
       "U50378331005",
       
       
       "AU0000XVGZA3",
       "AU0000VXGZA3",
       "FR0000988040");
begin
   for I in Test_Cases'Range loop
      Ada.Text_IO.Put_Line(Test_Cases(I) & ":" &
        Boolean'Image(Is_Valid_ISIN(Test_Cases(I))));
   end loop;
   
   Ada.Text_IO.Put("US03378331005:");
   Ada.Text_IO.Put_Line(Boolean'Image(Is_Valid_Isin("US03378331005")));
exception
   when others =>
      Ada.Text_IO.Put_Line("Exception occured");
end ISIN;