Skip to content

Instantly share code, notes, and snippets.

@MaurizioB
Last active June 26, 2022 02:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MaurizioB/6bedeca961b5152006d030f56f817a2f to your computer and use it in GitHub Desktop.
Save MaurizioB/6bedeca961b5152006d030f56f817a2f to your computer and use it in GitHub Desktop.
Roman numeral encoding, based on XKCD#2637
import re
from PyQt5.QtWidgets import (QApplication, QVBoxLayout, QWidget, QLabel, QTextEdit)
'''
Inspired by https://xkcd.com/2637/
Based on the Python code of tools/roman.py
'''
RomanNumbers = 'ivxlcdmIVXLCDM'
NumberToRoman = (
(1000, 'm'),
( 900, 'cm'),
( 500, 'd'),
( 400, 'cd'),
( 100, 'c'),
( 90, 'xc'),
( 50, 'l'),
( 40, 'xl'),
( 10, 'x'),
( 9, 'ix'),
( 5, 'v'),
( 4, 'iv'),
( 1, 'i'),
)
RomanToNumber = tuple((v, k) for k, v in NumberToRoman)
RomanRegex = re.compile(r'm*(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})')
def romanToDigits(values):
result = 0
index = 0
for numeral, integer in RomanToNumber:
while values[index:index+len(numeral)].lower() == numeral.lower():
result += integer
index += len(numeral)
result = str(result)
if index < len(values):
result += romanToDigits(values[index:])
return result
def romanEncode(roman):
result = ''
current = ''
for l in roman:
if l in RomanNumbers:
current += l
else:
if current:
result += romanToDigits(current)
current = ''
result += l
if current:
result += romanToDigits(current)
return result
def digitsToRoman(value):
roman = ''
for n, r in NumberToRoman:
fact, value = divmod(value, n)
roman += r * fact
if not value:
break
return roman
def romanDecode(text):
result = ''
tempNumber = ''
for l in text:
if l.isdigit():
tempNumber += l
else:
if tempNumber:
result += digitsToRoman(int(tempNumber))
result += l
tempNumber = ''
if tempNumber:
result += digitsToRoman(int(tempNumber))
return result
class EncodeMMDCXXXVII(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
layout = QVBoxLayout(self)
sourceLabel = QLabel('Source')
layout.addWidget(sourceLabel)
self.sourceEdit = QTextEdit()
sourceLabel.setBuddy(self.sourceEdit)
layout.addWidget(self.sourceEdit)
encodeLabel = QLabel('Encoded')
layout.addWidget(encodeLabel)
self.encodedEdit = QTextEdit()
encodeLabel.setBuddy(self.encodedEdit)
layout.addWidget(self.encodedEdit)
decodeLabel = QLabel('Decoded')
layout.addWidget(decodeLabel)
self.decodedEdit = QTextEdit(readOnly=True)
decodeLabel.setBuddy(self.decodedEdit)
layout.addWidget(self.decodedEdit)
self.sourceEdit.textChanged.connect(self.encode)
self.encodedEdit.textChanged.connect(self.decode)
def encode(self):
self.encodedEdit.setText(
romanEncode(self.sourceEdit.toPlainText()))
def decode(self):
self.decodedEdit.setText(
romanDecode(self.encodedEdit.toPlainText()))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
win = EncodeMMDCXXXVII()
win.show()
sys.exit(app.exec_())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment