Advertisement
DeflagratingStar

2021-07-05 Challenge #397 [Easy] Roman Numeral Comparison with Python class

Jul 7th, 2021 (edited)
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.96 KB | None | 0 0
  1. import sys
  2. if sys.version[0] != '3':
  3.     raise Exception("Python 2 is no longer supported, please use Python 3")
  4.  
  5.  
  6. class RomanNumeral:
  7.  
  8.     _roman  = [ "N", "I", "V", "X", "L", "C", "D", "M"   ]
  9.     _arabic = [  0,   1,   5,   10,  50,  100, 500, 1000 ]
  10.     _maxnum = 3
  11.  
  12.     def __init__(self, numeral=None, modern=None, form="additive"):
  13.         self._errmsg = f"{numeral} is not a valid numeral in {form} notation"
  14.         if form == "additive": self._maxnum+=1
  15.         self.numeral = numeral
  16.         self.modern  = modern
  17.         self.form    = form
  18.         self._convert()
  19.  
  20.     def _convert(self):
  21.  
  22.         if self.modern is None:
  23.             numeral = self.numeral
  24.             sgn = 1
  25.             if "-" in numeral:
  26.                 sgn = -1
  27.                 numeral = numeral.replace("-","")
  28.  
  29.             if self.form != "irregular-additive" and \
  30.                (numeral.count("I") > self._maxnum or \
  31.                 numeral.count("X") > self._maxnum or \
  32.                 numeral.count("C") > self._maxnum): return
  33.  
  34.             self.modern = [ self._arabic[self._roman.index(k)] for k in numeral[::-1] ]
  35.             if self.form=='subtractive':
  36.                 self.modern = self.modern[0] + sum(v if v >= self.modern[i] else -v for i,v in enumerate(self.modern[1:]))
  37.             else:
  38.                 self.modern = self.modern[0] + sum(v for v in self.modern[1:])    
  39.  
  40.             self.modern *= sgn
  41.  
  42.         elif self.numeral is None:
  43.             if self.modern == 0:
  44.                 self.numeral = "N"
  45.                 return
  46.  
  47.             self.numeral = ""
  48.             modern = str(self.modern)
  49.             if modern[0] == "-":
  50.                 self.numeral = "-"
  51.                 modern = modern[1:]
  52.  
  53.             ones = int(modern[-1])
  54.             tens, huns, thns = 0, 0, 0
  55.             if len(modern) > 1: tens = int(modern[-2])
  56.             if len(modern) > 2: huns = int(modern[-3])
  57.             if len(modern) > 3: thns = int(modern[:-3])
  58.  
  59.             # Add thousands
  60.             self.numeral += thns*"M"
  61.  
  62.             if self.form=="subtractive":
  63.  
  64.                 # Add hundreds
  65.                 if huns == 9: self.numeral += f"{(huns//9)*'CM'}"
  66.                 if 4 < huns < 9: self.numeral += f"{(huns//5)*'D'}"
  67.                 if huns == 4: self.numeral += f"{(huns//4)*'CD'}"
  68.                 if 0 < (huns-5)%5 < 4: self.numeral += f"{((huns-5)%5)*'C'}"
  69.  
  70.                 # Add tens
  71.                 if tens == 9: self.numeral += f"{(tens//9)*'XC'}"
  72.                 if 4 < tens < 9: self.numeral += f"{(tens//5)*'L'}"
  73.                 if tens == 4: self.numeral += f"{(tens//4)*'XL'}"
  74.                 if 0 < (tens-5)%5 < 4: self.numeral += f"{((tens-5)%5)*'X'}"
  75.  
  76.                 # Add ones
  77.                 if ones == 9: self.numeral += f"{(ones//9)*'IX'}"
  78.                 if 4 < ones < 9: self.numeral += f"{(ones//5)*'V'}"
  79.                 if ones == 4: self.numeral += f"{(ones//4)*'IV'}"
  80.                 if 0 < (ones-5)%5 < 4: self.numeral += f"{((ones-5)%5)*'I'}"
  81.  
  82.             else:
  83.                 self.numeral += f"{(huns//5)*'D'}{((huns-5)%5)*'C'}"   # Add hundreds
  84.                 self.numeral += f"{(tens//5)*'L'}{((tens-5)%5)*'X'}"   # Add tens
  85.                 self.numeral += f"{(ones//5)*'V'}{((ones-5)%5)*'I'}"   # Add ones
  86.  
  87.  
  88.     def _validate_operation(self,other):
  89.         if self.modern is None: return False, f"{self._errmsg}"
  90.         if other.modern is None: return False, f"{other._errmsg}"
  91.         if self.form != other.form: return False, f"{self.form} and {other.form} are not the same notations!"
  92.         return True, ""
  93.  
  94.     def _validate_equality(self,other):
  95.         if self.modern is None: return False, f"{self._errmsg}"
  96.         if other.modern is None: return False, f"{other._errmsg}"
  97.         return True, ""
  98.  
  99.  
  100.     def __str__(self):
  101.         return self.numeral
  102.  
  103.     def __pos__(self):
  104.         return RomanNumeral(modern= abs(self.modern), form=self.form)
  105.  
  106.     def __neg__(self):
  107.         return RomanNumeral(modern= -self.modern, form=self.form)
  108.  
  109.     def __abs__(self):
  110.         return RomanNumeral(modern= abs(self.modern), form=self.form)
  111.  
  112.     def __add__(self,other):
  113.         valid, msg = self._validate_operation(other)
  114.         if not valid: return msg
  115.         return RomanNumeral(modern=self.modern + other.modern,form=self.form)
  116.  
  117.     def __sub__(self,other):
  118.         valid, msg = self._validate_operation(other)
  119.         if not valid: return msg
  120.         return RomanNumeral(modern=self.modern - other.modern,form=self.form)
  121.  
  122.     def __mul__(self,other):
  123.         valid, msg = self._validate_operation(other)
  124.         if not valid: return msg
  125.         return RomanNumeral(modern=self.modern * other.modern,form=self.form)
  126.  
  127.     def __floordiv__(self,other):
  128.         valid, msg = self._validate_operation(other)
  129.         if not valid: return msg
  130.         return RomanNumeral(modern=self.modern // other.modern,form=self.form)
  131.  
  132.     def __div__(self,other):
  133.         valid, msg = self._validate_operation(other)
  134.         if not valid: return msg
  135.         return RomanNumeral(modern=self.modern / other.modern,form=self.form)
  136.  
  137.     def __mod__(self,other):
  138.         valid, msg = self._validate_operation(other)
  139.         if not valid: return msg
  140.         return RomanNumeral(modern=self.modern % other.modern,form=self.form)
  141.  
  142.     def __pow__(self,other):
  143.         valid, msg = self._validate_operation(other)
  144.         if not valid: return msg
  145.         return RomanNumeral(modern=self.modern ** other.modern,form=self.form)
  146.  
  147.     def __iadd__(self,other):
  148.         valid, msg = self._validate_operation(other)
  149.         if not valid: return msg
  150.         return RomanNumeral(modern=self.modern + other.modern,form=self.form)
  151.  
  152.     def __isub__(self,other):
  153.         valid, msg = self._validate_operation(other)
  154.         if not valid: return msg
  155.         return RomanNumeral(modern=self.modern - other.modern,form=self.form)
  156.  
  157.     def __imul__(self,other):
  158.         valid, msg = self._validate_operation(other)
  159.         if not valid: return msg
  160.         return RomanNumeral(modern=self.modern * other.modern,form=self.form)
  161.  
  162.     def __ifloordiv__(self,other):
  163.         valid, msg = self._validate_operation(other)
  164.         if not valid: return msg
  165.         return RomanNumeral(modern=self.modern // other.modern,form=self.form)
  166.  
  167.     def __idiv__(self,other):
  168.         valid, msg = self._validate_operation(other)
  169.         if not valid: return msg
  170.         return RomanNumeral(modern=self.modern / other.modern,form=self.form)
  171.  
  172.     def __imod__(self,other):
  173.         valid, msg = self._validate_operation(other)
  174.         if not valid: return msg
  175.         return RomanNumeral(modern=self.modern % other.modern,form=self.form)
  176.  
  177.     def __ipow__(self,other):
  178.         valid, msg = self._validate_operation(other)
  179.         if not valid: return msg
  180.         return RomanNumeral(modern=self.modern ** other.modern,form=self.form)
  181.  
  182.     def __eq__(self,other):
  183.         valid, msg = self._validate_equality(other)
  184.         if not valid: return msg
  185.         return self.modern == other.modern
  186.  
  187.     def __ne__(self,other):
  188.         valid, msg = self._validate_equality(other)
  189.         if not valid: return msg
  190.         return self.modern != other.modern
  191.  
  192.     def __ge__(self,other):
  193.         valid, msg = self._validate_equality(other)
  194.         if not valid: return msg
  195.         return self.modern >= other.modern
  196.  
  197.     def __gt__(self,other):
  198.         valid, msg = self._validate_equality(other)
  199.         if not valid: return msg
  200.         return self.modern > other.modern
  201.  
  202.     def __le__(self,other):
  203.         valid, msg = self._validate_equality(other)
  204.         if not valid: return msg
  205.         return self.modern <= other.modern
  206.  
  207.     def __lt__(self,other):
  208.         valid, msg = self._validate_equality(other)
  209.         if not valid: return msg
  210.         return self.modern < other.modern
  211.  
  212.  
  213. def rDailyProggerTest(form="additive"):
  214.     rm_1   = RomanNumeral("-I",               form=form)
  215.     rm     = RomanNumeral("I",                form=form)
  216.     rm0    = RomanNumeral("N",                form=form)
  217.     rm1    = RomanNumeral("I",                form=form)
  218.     rm2    = RomanNumeral("II",               form=form)
  219.     rm4    = RomanNumeral("IIII",             form=form)
  220.     rm5    = RomanNumeral("V",                form=form)
  221.     rm7    = RomanNumeral("IIIIIII",          form=form)
  222.     rm1665 = RomanNumeral("MDCLXV",           form=form)
  223.     rm1666 = RomanNumeral("MDCLXVI",          form=form)
  224.     rm2000 = RomanNumeral("MM",               form=form)
  225.     rm1999 = RomanNumeral("MDCCCCLXXXXVIIII", form=form)
  226.     print(f"\n r/DailyProgrammer Tests ({form} notation)")
  227.     print(f" {rm1} < {rm1} : {rm1<rm1}")
  228.     print(f" {rm1} < {rm2} : {rm1<rm2}")
  229.     print(f" {rm2} < {rm1} : {rm2<rm1}")
  230.     print(f" {rm5} < {rm4} : {rm5<rm4}")
  231.     print(f" {rm5} < {rm7} : {rm5<rm7}")
  232.     print(f" {rm1665} < {rm1666} : {rm1665<rm1666}")
  233.     print(f" {rm2000} < {rm1999} : {rm2000<rm1999}\n")
  234.     print(f"\n Extra Tests ({form} notation)")
  235.     print(f" {rm1} = {rm1} : {rm1==rm1}")
  236.     print(f" {rm5} != {rm4} : {rm5!=rm4}")
  237.     print(f" {rm2000} + {rm5} : {rm2000+rm5}")
  238.     print(f" {rm4} - {rm4} : {rm4-rm4}")
  239.     print(f" {rm4} - {rm5} : {rm4-rm5}")
  240.     print(f" {rm5} - {rm1} : {rm5-rm1}")
  241.     print(f" {rm5} % {rm5} : {rm5%rm5}")
  242.     print(f" {rm5} % {rm4} : {rm5%rm4}")
  243.     print(f" {rm5} + {rm1} - {rm2} : {rm5+rm1-rm2}")
  244.     print(f" {rm5} + {rm1} - {rm4} : {rm5+rm1-rm4}")
  245.     print(f" {rm1999} * {rm4} : {rm1999*rm4}\n")
  246.     print(f" neg({rm1}) : {-rm1}")
  247.     print(f" pos({rm1}) : {+rm1}")
  248.     print(f" abs({rm1}) : {abs(rm1)}")
  249.     print(f" neg({rm_1}) : {-rm_1}")
  250.     print(f" pos({rm_1}) : {+rm_1}")
  251.     print(f" abs({rm_1}) : {abs(rm_1)}")
  252.     print(f" neg(neg({rm_1})) : {--rm_1}")
  253.     print(f" neg(neg(neg({rm_1}))) : {---rm_1}\n")
  254.     for i in range(10):
  255.         print(f"{i}: {rm}")
  256.         rm+=rm1
  257.  
  258.  
  259. if __name__ == '__main__':
  260.  
  261.     rDailyProggerTest(form="additive")
  262.     rDailyProggerTest(form="subtractive")
  263.     rDailyProggerTest(form="irregular-additive")
  264.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement