Last active
June 26, 2022 02:47
-
-
Save MaurizioB/6bedeca961b5152006d030f56f817a2f to your computer and use it in GitHub Desktop.
Roman numeral encoding, based on XKCD#2637
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
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