Created
December 8, 2012 01:40
-
-
Save feltnerm/4238090 to your computer and use it in GitHub Desktop.
a simple Roman number calculator. It is to read a Roman number, an operator (+, -, /, or *), and a second Roman number. It then shows the calculation using Arabic numbers and prints the result as a Roman number.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma License (Gpl); | |
-- ROMAN CONVERTER | |
-- This package provides two functions: one to convert an | |
-- integer to its Roman Numeral equivalent, and another to convert | |
-- a Roman Numeral (consisting of M,D,C,L,X,V,I) to its | |
-- integer equivalent. | |
--------------------------------------------------------------------- | |
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; | |
package RomanConverter is | |
function ToInteger(Roman : in Unbounded_String) return Integer; | |
function ToRoman(Value : in Integer) return Unbounded_String; | |
procedure AppendRoman(outString : in out Unbounded_String; | |
iterations : in Integer; | |
divisor : in Integer); | |
end RomanConverter; | |
-- // ROMANCONVERTER | |
package body RomanConverter is | |
-- ToInteger | |
-- Converts a String of Roman Numerals to a integer. | |
--------------------------------------------------------------------- | |
function ToInteger(Roman : in Unbounded_String) return Integer is | |
value : Integer := 0; | |
char : Character; | |
begin | |
for i in 1 .. Length(Roman) loop | |
char := Element(Roman, i); | |
case char is | |
when 'M' => value := value + 1000; | |
when 'D' => value := value + 500; | |
when 'C' => value := value + 100; | |
when 'L' => value := value + 50; | |
when 'X' => value := value + 10; | |
when 'V' => value := value + 5; | |
when 'I' => value := value + 1; | |
when others => null; | |
end case; | |
end loop; | |
return value; | |
end ToInteger; | |
-- // TOINTEGER | |
-- ToRoman | |
-- Converts an integer to a Roman Numeral string | |
--------------------------------------------------------------------- | |
function ToRoman(Value : in Integer) return Unbounded_String is | |
outString : Unbounded_String; | |
divisors : array(1..7) of Integer := (1000, 500, 100, 50, 10, 5, 1); | |
x : Integer; | |
abs_value : Integer := abs value; | |
begin | |
for i in divisors'range loop | |
x := abs_value / divisors(i); | |
if (x > 0) then | |
abs_value := abs_value mod divisors(i); | |
AppendRoman(outString, x, divisors(i)); | |
end if; | |
end loop; | |
If (value < 0) then | |
outString := "-" & outString; -- Check for a negative number | |
elsif (value = 0) then | |
outString := To_Unbounded_String("zero"); -- nullus | |
end if; | |
return outString; | |
end ToRoman; | |
-- // TOROMAN | |
-- AppendRoman | |
-- Utility function to append a Roman Numeral character to | |
-- an unbounded string a number of times based on its | |
-- divisor. | |
--------------------------------------------------------------------- | |
procedure AppendRoman(outString : in out Unbounded_String; | |
iterations : in Integer; | |
divisor : in Integer) is | |
begin | |
for i in 1 .. iterations loop | |
case divisor is | |
when 1000 => Append(outString, To_Unbounded_String("M")); | |
when 500 => Append(outString, To_Unbounded_String("D")); | |
when 100 => Append(outString, To_Unbounded_String("C")); | |
when 50 => Append(outString, To_Unbounded_String("L")); | |
when 10 => Append(outString, To_Unbounded_String("X")); | |
when 5 => Append(outString, To_Unbounded_String("V")); | |
when 1 => Append(outString, To_Unbounded_String("I")); | |
when others => null; | |
end case; | |
end loop; | |
end AppendRoman; -- // APPENDROMAN | |
end RomanConverter; | |
-- // ROMAN CONVERTER | |
-- CALCULATE | |
-- Using only addition, subtraction, multiplication, and division this | |
-- procedure calculates the result of applying one of the above | |
-- operations to two operands. | |
--------------------------------------------------------------------- | |
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; | |
procedure Calculate(operand1 : in Integer; | |
operator : in Unbounded_String; | |
operand2 : in Integer; | |
result : out Integer) is | |
operator_char : Character; | |
begin | |
operator_char := Element(operator, 1); | |
case operator_char is | |
when '*' => result := operand1 * operand2; | |
when '/' => result := operand1 / operand2; | |
when '+' => result := operand1 + operand2; | |
when '-' => result := operand1 - operand2; | |
when others => result := 0; | |
end case; | |
end Calculate; | |
-- // CALCULATE | |
-- MP4 :: MAIN | |
-- Main method for this Roman Numeral converter. Reads input from | |
-- stdin. First, reads the number of expressions, then calculates | |
-- the result of each expression in integer and Roman form. | |
--------------------------------------------------------------------- | |
with Ada.Text_IO.Unbounded_IO; | |
with Ada.Text_IO; | |
with GNAT.String_Split; | |
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; | |
with RomanConverter; use RomanConverter; | |
with Calculate; | |
procedure MP4 is | |
-- Renames | |
package IO renames Ada.Text_IO.Unbounded_IO; | |
package IO_int is new Ada.Text_IO.Integer_IO(Integer); | |
-- Declarations | |
numLines : Integer; | |
input : Unbounded_String; | |
dummy : Unbounded_String; | |
sliced : GNAT.String_Split.Slice_Set; | |
sep : String := " "; | |
romanOperand1 : Unbounded_String; | |
romanOperand2 : Unbounded_String; | |
operator : Unbounded_String; | |
integerOperand1 : Integer; | |
integerOperand2 : Integer; | |
result : Integer; | |
-- Utility method to correctly print the result and conversion of a | |
-- Roman numeral expression in the format: | |
-- #{operand1} #{operator} #{operand2} = #{result_int} = #{result_roman} | |
--------------------------------------------------------------------- | |
procedure Print(operand1 : in Integer; | |
operator : in String; | |
operand2 : in Integer; | |
result_int : in Integer; | |
result_roman : in String) is | |
begin | |
IO_int.Put(operand1, 0); | |
Ada.Text_IO.Put(" " & operator & " "); | |
IO_int.Put(operand2, 0); | |
Ada.Text_IO.Put(" = "); | |
IO_int.Put(result_int, 0); | |
Ada.Text_IO.Put_Line(" = " & result_roman); | |
end Print; | |
begin | |
IO_int.Get(numLines); | |
IO.Get_Line(dummy); -- get that extra newline | |
for i in 1 .. numLines loop | |
IO.Get_Line(input); | |
-- http://commons.ada.cx/Separate_a_string_into_substrings_using_GNAT.String_Split | |
GNAT.String_Split.Create(sliced, To_String(input), sep, Mode => GNAT.String_Split.Multiple); | |
romanOperand1 := To_Unbounded_String(GNAT.String_Split.Slice(sliced, 1)); | |
operator := To_Unbounded_String(GNAT.String_Split.Slice(sliced, 2)); | |
romanOperand2 := To_Unbounded_String(GNAT.String_Split.Slice(sliced, 3)); | |
integerOperand1 := RomanConverter.ToInteger(romanOperand1); | |
integerOperand2 := RomanConverter.ToInteger(romanOperand2); | |
Calculate(integerOperand1, operator, integerOperand2, result); | |
Print(integerOperand1, To_String(operator), integerOperand2, result, To_String(ToRoman(Result))); | |
end loop; | |
end MP4; | |
-- // MP4 | |
-- vim: textwidth=0 nowrap tabstop=3 shiftwidth=3 softtabstop=3 expandtab | |
-- vim: filetype=ada fileformat=unix |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment