Yes
This commit is contained in:
parent
45200bb640
commit
d6cffc16e4
12 changed files with 954 additions and 0 deletions
79
README_en.md
Executable file
79
README_en.md
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
### if.03.22 Procedural Programming
|
||||
# Roman numbers
|
||||
|
||||
This assignment targets on string analysis and validation,
|
||||
pointer handling as well as a simple recursive calculation.
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
Roman numbers are used since ancient ages. They are expressed via letters which have the following values:
|
||||
|
||||
+ I: 1
|
||||
+ V: 5
|
||||
+ X: 10
|
||||
+ L: 50
|
||||
+ C: 100
|
||||
+ D: 500
|
||||
+ M: 1000
|
||||
+ some more higher value signs
|
||||
|
||||
The numerical value is calculated by simply adding the value of each letter:
|
||||
> MMCLXXXVII => 1000 + 1000 + 100 + 50 + 10 + 10 + 10 + 5 + 1 + 1 = 2187
|
||||
|
||||
In addition, values are subtracted, if one `I, X, or C` is placed before the next larger value.
|
||||
> IV => -1 + 5 = 4
|
||||
> IX => -1 + 10 = 9
|
||||
> XL => -10 + 50 = 40
|
||||
> CD => -100 + 500 = 400
|
||||
|
||||
An extension of this rule allows subtraction of the letters above if they are placed in front of even larger values
|
||||
|
||||
> IC => -1 + 100 = 99 instead of XCIX => -10 + 100 - 1 + 10
|
||||
|
||||
which simplifies the usage of the numbers.
|
||||
The letters `V, L, D` are never used as subtractive values.
|
||||
|
||||
Roman number letters are written in descending order of their nominal value, except for the special case of subtraction.
|
||||
|
||||
> MCMLXVII (1967) must not be written in different order, e.g. IIVXLMCM is not allowed
|
||||
|
||||
## Assignment
|
||||
|
||||
Your task is to implement an abstract data type calls `RomanNumber`, which encapsulates the numerical representation of a string that expresses a valid roman number.
|
||||
|
||||
The following functions for the ADT `RomanNumber` shall be implemented:
|
||||
|
||||
+ `rn_is_valid_number_str`
|
||||
A private function which determines whether a given string represents a valid roman number. If the string contains any other characters but the above defined ones, it DOES NOT represent a valid number!
|
||||
The validity can easily be done by iterating through all characters of the string and testing if the current letter is a defined one and its numerical value is equal or less the numerical letter of the previous letter. The only exception to this rule are valid subtraction patterns (e.g. IX). If the current and next letter form a valid subtraction pattern can be tested with the already implemented private function `rn_is_valid_subtraction`. If such a valid pattern was detected, the string remains valid for the current letter and the check stated above can be skipped. Nevertheless, the 'next' letter (which was used to test the subtraction pattern) still need regularly be checked.
|
||||
+ `rn_get_value_for_letter`:
|
||||
A private function that provides the numerical value of a single letter. Note that `switch / case` instructions work for characters as well.
|
||||
+ `rn_create`:
|
||||
Allocates a new `RomanNumber` out of a statically allocated pool of data structs for the ADT. The pool of `RomanNumber` data is allocated on the global scope with a size of `MAX_ROMAN_NUMBER_COUNT` as defined in `roman_number.c`.
|
||||
It MAY be trusted, that the pool is sufficiently large to provide instances for all unit tests without the need of returning instances to the pool.
|
||||
It MAY be trusted that a valid string is provided, although not necessarily a valid roman number string. If the string does not represent a valid roman number, an invalid (non-null)`RomanNumber` shall be provided. The given string need therefore be checked using the private function `rn_is_valid_number_str`, whether the string represents a valid roman number.
|
||||
If the given string is a valid roman number, its numerical value shall be calculated upon creation and stored within the ADTs data. The roman number is converted by simply adding the values of its letters, except a subtraction pattern is detected. In this case the value of the letter has to be subtracted. Use the function `rn_is_valid_subtraction` to check for subtractions.
|
||||
*Note* that an empty string is valid and results in the value zero (0), while a null-string is invalid.
|
||||
+ `rn_is_valid`:
|
||||
Determines whether or not the given `RomanNumber` is valid. It is, if it is neither 0 nor was created from an invalid roman number.
|
||||
+ `rn_get_value`:
|
||||
Provides the numerical value of the given `RomanNumber` as stored in the ADTs data or a value less than zero, if the `RomanNumber` is not valid.
|
||||
+ `rn_gcd`:
|
||||
Calculates the greatest common divisor of two `RomanNumber`s and returns the result again as `RomanNumber`.
|
||||
__Important note:__ This function DOES NOT actually calculate the GCD but uses the function `int_gcd` for this purpose. It only 'converts' the roman number back and forth.
|
||||
+ `int_gcd`:
|
||||
Actually calculates the greatest common divisor (GCD) of two positive integer values __using recursion__. It MAY be trusted, that the given integers are always positive.
|
||||
The GCD is defined as:
|
||||
- `gcd(x, 0) = x;`
|
||||
- `gcd(x, y) = gcd(y, x % y);`
|
||||
where `%` is the modulo operator.
|
||||
_Note_ the this function is independently tested and can be implemented even if the ADT is not working.
|
||||
|
||||
## Tasks
|
||||
+ Create a skeleton implmentation of the ADT to make the unit tests compilable.
|
||||
+ Implement all required functions to make the unit tests pass.
|
||||
+ A main application is not required.
|
||||
|
||||
### Good Luck!
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue