File : roman_numerals.sp


$ spar roman_numerals.sp
Welcome to the Roman Numeral Calculator program:

Please enter the FIRST Roman numeral: XVI
Please enter the SECOND Roman numeral: II

Please choose one of the following operations to be performed:
1) Add the two Roman Numerals.
2) Subtract the two Roman Numerals.
3) Multiply the two Roman Numerals.
4) Divide the two Roman Numerals.
----------------------------------------------------
Please enter choice: 3
Final Result is: XXXII


#!/usr/local/bin/spar

procedure roman_numerals is

  pragma annotate( summary, "roman_numerals" );
  pragma annotate( description, "Roman numeral arithmetic adapted from an Ada to SparForte" );
  pragma annotate( description, "Based on an example from the Public Ada Library" );
  pragma annotate( author, "Ken O. Burtch" );
  pragma license( unrestricted );

  pragma ada_95;
  pragma restriction( no_external_commands );

  -- Declare variables which will be used in main program out here

  MaxRomanLength : constant positive := 20;
  subtype RomanNumeralType is string;

--------------------------------------------------------------------------------

   -- Function for checking Valid Input from the user
   -- This function returns a boolean value

   function ValidRomanNumeral (PossibleNumeral : RomanNumeralType) return
       boolean is

         Position : positive := 1; -- position we are checking in the input

   begin -- ValidRomanNumeral
      if strings.length( PossibleNumeral ) > natural( MaxRomanLength ) then
         return false;
      end if;
      if strings.length( PossibleNumeral ) = 0 then
         return false;
      end if;
      loop
         if Position = MaxRomanLength then
            return true;   -- we have reached the maximum length without problems
         elsif Position > positive( strings.length( PossibleNumeral ) ) then
            return true;   -- we have reached the actual end without problems
         elsif strings.element( PossibleNumeral, Position) = 'I'
            or strings.element( PossibleNumeral, Position) = 'V'
            or strings.element( PossibleNumeral, Position) = 'X'
            or strings.element( PossibleNumeral, Position) = 'L'
            or strings.element( PossibleNumeral, Position) = 'C'
            or strings.element( PossibleNumeral, Position) = 'D'
            or strings.element( PossibleNumeral, Position) = 'M' then
               Position := Position + 1;
         else
            return false;  -- we have a problem, so return false
         end if;
      end loop;
      -- This will never happen
      return false;
   end ValidRomanNumeral;

--------------------------------------------------------------------------------

   function RomanToNatural (RomanNumeral : RomanNumeralType) return natural is
      Result : natural := 0;  -- result variable
      CurrentPosition : positive := 1; -- the current position in RomanNumeral being examined.
      Num_Value : integer:=0; -- Value of the corresponding roman numeral
      First  : integer:=0;
      Next : integer:=0;


   begin --RomanToNatural

      -- Loop to process the appropriate value from the user
      loop

         if CurrentPosition > positive( strings.length( RomanNumeral ) ) then
            exit;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'M' then
            Num_Value := 1000;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'D' then
            Num_Value := 500;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'C' then
            Num_Value := 100;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'L' then
            Num_Value := 50;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'X' then
            Num_Value := 10;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'V' then
            Num_Value := 5;
         elsif strings.element( RomanNumeral, CurrentPosition) = 'I' then
            Num_Value := 1;
         end if;

         -- If this is the first character then store the value
         -- of it in the variable 'First'

         if CurrentPosition = 1 then
            First := Num_Value;
         end if;

         Next := Num_Value; -- Store the second value in this variable(2nd iteration)

         -- This is for the second Iteration. Check if the second value
         -- is greater than the first value and perform the nescassary
         -- steps.
         if First < Next then
            Result := natural(Next - First) +Result - natural(First);
         else
            Result := Result + natural(Next);
      end if;

     -- Assign the value of first to next
     -- for comparison in later cases
     First := Next;

     CurrentPosition := CurrentPosition + 1; -- Increment the counter Variable

    end loop; -- End the loop here

    return Result; -- Return the final result to where function is being called

   end RomanToNatural; -- End the function

--------------------------------------------------------------------------------

   -- This Function Gets a valid choice from the user
   -- The user can chooose to perform arithmetic operations on the
   -- Roman numerals. The choices are 1 through 4.
   -- Will keep looping till the user gives correct Choice

   function GetValidChoice return integer is
    ValidChoice : integer;
    Choice : integer:=1;

    begin

      loop
         new_line;
         put("Please choose one of the following operations to be performed:");
         new_line;
         put("1) Add the two Roman Numerals.");
         new_line;
         put("2) Subtract the two Roman Numerals.");
         new_line;
         put("3) Multiply the two Roman Numerals.");
         new_line;
         put("4) Divide the two Roman Numerals.");
         new_line;
         put("----------------------------------------------------");
         new_line;
         put("Please enter choice: ");
         Choice := numerics.value( get_line );
         if (Choice>0) or (Choice<=4) then
            exit;
         else
            new_line;
            put("Please enter Valid Choice.");
            new_line;
         end if;

      end loop;

    ValidChoice := Choice;
    return ValidChoice;

   end GetValidChoice;

--------------------------------------------------------------------------------

   -- This procedure process the valid choice and performs the
   -- nescassary calculations on the Two user inputs
   function ProcessChoice(UserInput1 : natural;
                           UserInput2 : natural;
                           Choice     : integer ) return natural is
     Result : natural;
     -- Wrote this procedure in the morning
     -- what this essentially does is
     -- it takes in userinput1 and userinput2 and Choice as IN Variables
     -- According to the user's specified choice we can then compute the possible
     -- values and return Result
     -- This value of output will the in turn be stored in a variable called
     -- FinalInteger

      -- declare variables here

      Plus     : natural:=0;
      Minus    : natural:=0;
      Multiply : natural:=0;
      Divide   : natural:=0;


      begin -- ProcessChoice

      -- Start checking for user choice and perform nescassary action

      if (Choice = 1) then

         Plus := UserInput1 + UserInput2;
         Result := Plus;

      elsif (Choice = 2) then

         Minus := UserInput1 - UserInput2;
         Result := Minus;

      elsif (Choice = 3) then

         Multiply := UserInput1 * UserInput2;
         Result := Multiply;

      elsif (Choice = 4) then

         Divide := UserInput1 / UserInput2;
         Result := Divide;
      else
         put("SOMETHING HAS GONE WRONG");

      end if;

      return Result;
   end ProcessChoice;

-------------------------------------------------------------------------

   procedure ConvertBack(ConvertWhat : natural) is

     Num_Value : natural;

    begin

     Num_Value := ConvertWhat;
     for I in 1..20 loop
        if Num_Value<=4000 and Num_Value>=1 then

               while Num_Value>=1000 loop

                  put( "M" );
                  Num_Value:=Num_Value - 1000;

               end loop;

               while Num_Value>=500 loop

                  put( "D" );
                  Num_Value:=Num_Value - 500;
               end loop;

               while Num_Value>=100 loop
                  put( "C" );
                  Num_Value:=Num_Value - 100;
               end loop;

               while Num_Value>=50 loop
                  put( "L" );
                  Num_Value:=Num_Value - 50;
               end loop;

               while Num_Value>=10 loop
                  put( "X" );
                  Num_Value:=Num_Value - 10;
               end loop;

               while Num_Value>=5 loop
                  put( "V" );
                  Num_Value:=Num_Value - 5;
               end loop;

               while Num_Value>=1 loop
                  put( "I" );
                  Num_Value:=Num_Value - 1;
               end loop;

            end if;
         end loop;
         new_line;
   end ConvertBack;

--------------------------------------------------------------------------------

  RomanNumeral1 : RomanNumeralType;
  RomanNumeral2 : RomanNumeralType;

  FinalInteger : natural:=0;

  Input1 : natural:=0;
  Input2 : natural:=0;

  UserChoice : integer:=0;

begin -- Procedure Roman

  put("Welcome to the Roman Numeral Calculator program:");
  new_line;
  new_line;

  -- Get the valid roman numeral from the user
  -- This function returns two integer values in RomanInteger1 and RomanInteger2
  -- These values are the corresponding integer values of the entered roman numerals

  loop
     put( "Please enter the FIRST Roman numeral: ");
     RomanNumeral1 := get_line;

     put( "Please enter the SECOND Roman numeral: ");
     RomanNumeral2 := get_line;

     if ValidRomanNumeral(RomanNumeral1) then
        if ValidRomanNumeral(RomanNumeral2) then
           exit;
        end if;
     end if;

    put( "Please make sure BOTH the Roman Numerals are valid and try again");
    new_line;
  end loop;

  Input1 := RomanToNatural( RomanNumeral1 );
  Input2 := RomanToNatural( RomanNumeral2 );

  UserChoice := GetValidChoice;

  FinalInteger := ProcessChoice(Input1,Input2,UserChoice);

  put( "Final Result is: " );

  ConvertBack(FinalInteger);

end roman_numerals;

-- VIM editor formatting instructions
-- vim: ft=spar