Skip to content

Instantly share code, notes, and snippets.

@feltnerm
Created December 8, 2012 01:40
Show Gist options
  • Save feltnerm/4238090 to your computer and use it in GitHub Desktop.
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.
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;
-- PRINT
-- 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