import string, re
DIGITS = string.digits + string.ascii_uppercase
def check_base(base):
if not isinstance(base, int) or not 2 <= base <= 36: raise ValueError(f"Неверное основание: {base!r}.")
def to_base(n, base):
check_base(base)
result = ""
while True:
result = DIGITS[n % base] + result
n //= base
if n == 0: break
return result
def from_base(sn, base):
check_base(base)
result, multiplier = 0, 1
for sdig in reversed(sn):
if '0' <= sdig <= '9': digit = ord(sdig) - ord('0')
elif 'A' <= sdig <= 'Z': digit = ord(sdig) - ord('A') + 10
elif 'a' <= sdig <= 'z': digit = ord(sdig) - ord('a') + 10
else: digit = None
if digit is None or digit >= base: raise ValueError(f"Неверный {base}-разряд: {sdig!r}.")
result += multiplier * digit
multiplier *= base
return result
input_re = re.compile("""
\s* (?P<inp_value> [0-9A-Z]+)
(
\s* \( (?P<inp_base> \d+) \)
)?
(
\s* -> \s* (?P<target_base> \d+)
)?
\s*""", re.VERBOSE)
match = input_re.fullmatch(input("Введите запрос, например, FF(16)->2: "))
if match:
inp_value, inp_base, target_base = match['inp_value'], match['inp_base'], match['target_base']
inp_basev, target_basev = inp_base and int(inp_base), target_base and int(target_base)
if inp_base is None: inp_basev = 16 if target_basev == 10 else 10
if target_base is None: target_basev = 16 if inp_basev == 10 else 10
result = to_base(from_base(inp_value, inp_basev), target_basev)
print(f"\n{inp_value}({inp_basev}) = {result}({target_basev})")
else:
print("Не понял.")
aW1wb3J0IHN0cmluZywgcmUKRElHSVRTID0gc3RyaW5nLmRpZ2l0cyArIHN0cmluZy5hc2NpaV91cHBlcmNhc2UKCmRlZiBjaGVja19iYXNlKGJhc2UpOgoJaWYgbm90IGlzaW5zdGFuY2UoYmFzZSwgaW50KSBvciBub3QgMiA8PSBiYXNlIDw9IDM2OiByYWlzZSBWYWx1ZUVycm9yKGYi0J3QtdCy0LXRgNC90L7QtSDQvtGB0L3QvtCy0LDQvdC40LU6IHtiYXNlIXJ9LiIpCgpkZWYgdG9fYmFzZShuLCBiYXNlKToKCWNoZWNrX2Jhc2UoYmFzZSkKCXJlc3VsdCA9ICIiCgl3aGlsZSBUcnVlOgoJCXJlc3VsdCA9IERJR0lUU1tuICUgYmFzZV0gKyByZXN1bHQKCQluIC8vPSBiYXNlCgkJaWYgbiA9PSAwOiBicmVhawoJcmV0dXJuIHJlc3VsdAoKZGVmIGZyb21fYmFzZShzbiwgYmFzZSk6CgljaGVja19iYXNlKGJhc2UpCglyZXN1bHQsIG11bHRpcGxpZXIgPSAwLCAxCglmb3Igc2RpZyBpbiByZXZlcnNlZChzbik6CgkJaWYgJzAnIDw9IHNkaWcgPD0gJzknOiBkaWdpdCA9IG9yZChzZGlnKSAtIG9yZCgnMCcpCgkJZWxpZiAnQScgPD0gc2RpZyA8PSAnWic6IGRpZ2l0ID0gb3JkKHNkaWcpIC0gb3JkKCdBJykgKyAxMAoJCWVsaWYgJ2EnIDw9IHNkaWcgPD0gJ3onOiBkaWdpdCA9IG9yZChzZGlnKSAtIG9yZCgnYScpICsgMTAKCQllbHNlOiBkaWdpdCA9IE5vbmUKCQlpZiBkaWdpdCBpcyBOb25lIG9yIGRpZ2l0ID49IGJhc2U6IHJhaXNlIFZhbHVlRXJyb3IoZiLQndC10LLQtdGA0L3Ri9C5IHtiYXNlfS3RgNCw0LfRgNGP0LQ6IHtzZGlnIXJ9LiIpCgkJcmVzdWx0ICs9IG11bHRpcGxpZXIgKiBkaWdpdAoJCW11bHRpcGxpZXIgKj0gYmFzZQoJcmV0dXJuIHJlc3VsdAoKaW5wdXRfcmUgPSByZS5jb21waWxlKCIiIgoJXHMqICg/UDxpbnBfdmFsdWU+IFswLTlBLVpdKykKCSgKCQlccyogXCggKD9QPGlucF9iYXNlPiBcZCspIFwpCgkpPwoJKAoJCVxzKiAtPiBccyogKD9QPHRhcmdldF9iYXNlPiBcZCspCgkpPwoJXHMqIiIiLCByZS5WRVJCT1NFKQoKbWF0Y2ggPSBpbnB1dF9yZS5mdWxsbWF0Y2goaW5wdXQoItCS0LLQtdC00LjRgtC1INC30LDQv9GA0L7RgSwg0L3QsNC/0YDQuNC80LXRgCwgRkYoMTYpLT4yOiAiKSkKaWYgbWF0Y2g6CglpbnBfdmFsdWUsIGlucF9iYXNlLCB0YXJnZXRfYmFzZSA9IG1hdGNoWydpbnBfdmFsdWUnXSwgbWF0Y2hbJ2lucF9iYXNlJ10sIG1hdGNoWyd0YXJnZXRfYmFzZSddCglpbnBfYmFzZXYsIHRhcmdldF9iYXNldiA9IGlucF9iYXNlIGFuZCBpbnQoaW5wX2Jhc2UpLCB0YXJnZXRfYmFzZSBhbmQgaW50KHRhcmdldF9iYXNlKQoJaWYgaW5wX2Jhc2UgaXMgTm9uZTogaW5wX2Jhc2V2ID0gMTYgaWYgdGFyZ2V0X2Jhc2V2ID09IDEwIGVsc2UgMTAKCWlmIHRhcmdldF9iYXNlIGlzIE5vbmU6IHRhcmdldF9iYXNldiA9IDE2IGlmIGlucF9iYXNldiA9PSAxMCBlbHNlIDEwCgoJcmVzdWx0ID0gdG9fYmFzZShmcm9tX2Jhc2UoaW5wX3ZhbHVlLCBpbnBfYmFzZXYpLCB0YXJnZXRfYmFzZXYpCglwcmludChmIlxue2lucF92YWx1ZX0oe2lucF9iYXNldn0pID0ge3Jlc3VsdH0oe3RhcmdldF9iYXNldn0pIikKZWxzZToKCXByaW50KCLQndC1INC/0L7QvdGP0LsuIik=