RosettaCodeData/Task/CUSIP/Oberon-07/cusip.oberon
2026-04-30 12:34:36 -04:00

60 lines
2.1 KiB
Text

MODULE Cusip; (* validate CUSIP codes *)
IMPORT Strings, Out;
CONST cusipBase = 39;
cusipLength = 9;
VAR cusipDigits : ARRAY cusipBase + 1 OF CHAR; (* 39 digits + trailing nul *)
(* returns TRUE if cusip is a valid CUSIP code, FALSE otherwise *)
PROCEDURE isCusip( cusip : ARRAY OF CHAR ) : BOOLEAN;
VAR sum, digit, cPos, checkDigit : INTEGER;
isValid : BOOLEAN;
(* returns the base 39 digit corresponding to a character of a CUSIP code *)
PROCEDURE cusipDigit( cChar : CHAR ) : INTEGER;
VAR digit, dPos : INTEGER;
BEGIN
digit := -999;
dPos := 0;
WHILE ( dPos <= cusipBase ) & ( digit < 0 ) DO
IF cusipDigits[ dPos ] = cChar THEN digit := dPos END;
INC( dPos )
END
RETURN digit
END cusipDigit ;
BEGIN
IF Strings.Length( cusip ) # cusipLength THEN
isValid := FALSE (* invalid length code *)
ELSE
(* CUSIP code has the correct length *)
sum := 0;
checkDigit := cusipDigit( cusip[ cusipLength - 1 ] );
FOR cPos := 0 TO cusipLength - 2 DO
digit := cusipDigit( cusip[ cPos ] );
IF ODD( cPos ) THEN digit := digit * 2 END;
INC( sum, ( digit DIV 10 ) + ( digit MOD 10 ) )
END;
isValid := ( 10 - ( sum MOD 10 ) ) MOD 10 = checkDigit
END
RETURN isValid
END isCusip ;
PROCEDURE testCusip( cusip : ARRAY OF CHAR ) ;
BEGIN
Out.String( cusip );
IF isCusip( cusip ) THEN Out.String( " valid" ) ELSE Out.String( " invalid" ) END;
Out.Ln
END testCusip;
BEGIN
cusipDigits := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#";
testCusip( "037833100" );
testCusip( "17275R102" );
testCusip( "38259P508" );
testCusip( "594918104" );
testCusip( "68389X106" );
testCusip( "68389X105" )
END Cusip.