from math import log10
def long_sqrt(number, precision=0):
# Split number into digit pairs
pairs = [int(number // 10 ** x % 100) for x in range(0,
int(log10(number) + 1), 2)[::-1]]
if precision > 0:
pairs.extend([int(number * 10 ** (2 * x) % 100) for x in
range(1, precision + 1)])
# Get the first digit: Solve A^2 <= [first pair]. This is the initial result.
start = pairs.pop(0)
result = max(filter(lambda x: x ** 2 <= start, range(10)))
remainder = start - result ** 2
while pairs:
# Bring down two digits
value = 100 * remainder + pairs.pop(0)
# Calculate B. Start with its highest possible value, then decrement as necessary
next_digit = value // 20 // result
while (result * 20 + next_digit) * next_digit > value:
next_digit -= 1
# Plug in B and calculate new remainder
remainder = value - ((result * 20 + next_digit) * next_digit)
# Add B to the final result
result = 10 * result + next_digit
# If precision was specified, we need to divide to put the decimal point in place. Otherwise, we have our int.
return result / 10 ** precision if precision else result
# Check sample inputs
assert long_sqrt(7720.17, 0) == 87
assert long_sqrt(7720.17, 1) == 87.8
assert long_sqrt(7720.17, 2) == 87.86
# Run challenge inputs
print(long_sqrt(12345))
print(long_sqrt(123456, 8))
print(long_sqrt(12345678901234567890123456789, 1))
ZnJvbSBtYXRoIGltcG9ydCBsb2cxMAoKZGVmIGxvbmdfc3FydChudW1iZXIsIHByZWNpc2lvbj0wKToKICAgICMgU3BsaXQgbnVtYmVyIGludG8gZGlnaXQgcGFpcnMKICAgIHBhaXJzID0gW2ludChudW1iZXIgLy8gMTAgKiogeCAlIDEwMCkgZm9yIHggaW4gcmFuZ2UoMCwgCmludChsb2cxMChudW1iZXIpICsgMSksIDIpWzo6LTFdXQogICAgaWYgcHJlY2lzaW9uID4gMDoKICAgICAgICBwYWlycy5leHRlbmQoW2ludChudW1iZXIgKiAxMCAqKiAoMiAqIHgpICUgMTAwKSBmb3IgeCBpbiAKcmFuZ2UoMSwgcHJlY2lzaW9uICsgMSldKQogICAgIyBHZXQgdGhlIGZpcnN0IGRpZ2l0OiBTb2x2ZSBBXjIgPD0gW2ZpcnN0IHBhaXJdLiBUaGlzIGlzIHRoZSBpbml0aWFsIHJlc3VsdC4KICAgIHN0YXJ0ID0gcGFpcnMucG9wKDApCiAgICByZXN1bHQgPSBtYXgoZmlsdGVyKGxhbWJkYSB4OiB4ICoqIDIgPD0gc3RhcnQsIHJhbmdlKDEwKSkpCiAgICByZW1haW5kZXIgPSBzdGFydCAtIHJlc3VsdCAqKiAyCiAgICB3aGlsZSBwYWlyczoKICAgICAgICAjIEJyaW5nIGRvd24gdHdvIGRpZ2l0cwogICAgICAgIHZhbHVlID0gMTAwICogcmVtYWluZGVyICsgcGFpcnMucG9wKDApCiAgICAgICAgIyBDYWxjdWxhdGUgQi4gU3RhcnQgd2l0aCBpdHMgaGlnaGVzdCBwb3NzaWJsZSB2YWx1ZSwgdGhlbiBkZWNyZW1lbnQgYXMgbmVjZXNzYXJ5CiAgICAgICAgbmV4dF9kaWdpdCA9IHZhbHVlIC8vIDIwIC8vIHJlc3VsdAogICAgICAgIHdoaWxlIChyZXN1bHQgKiAyMCArIG5leHRfZGlnaXQpICogbmV4dF9kaWdpdCA+IHZhbHVlOgogICAgICAgICAgICBuZXh0X2RpZ2l0IC09IDEKICAgICAgICAjIFBsdWcgaW4gQiBhbmQgY2FsY3VsYXRlIG5ldyByZW1haW5kZXIKICAgICAgICByZW1haW5kZXIgPSB2YWx1ZSAtICgocmVzdWx0ICogMjAgKyBuZXh0X2RpZ2l0KSAqIG5leHRfZGlnaXQpCiAgICAgICAgIyBBZGQgQiB0byB0aGUgZmluYWwgcmVzdWx0CiAgICAgICAgcmVzdWx0ID0gMTAgKiByZXN1bHQgKyBuZXh0X2RpZ2l0CiAgICAjIElmIHByZWNpc2lvbiB3YXMgc3BlY2lmaWVkLCB3ZSBuZWVkIHRvIGRpdmlkZSB0byBwdXQgdGhlIGRlY2ltYWwgcG9pbnQgaW4gcGxhY2UuIE90aGVyd2lzZSwgd2UgaGF2ZSBvdXIgaW50LgogICAgcmV0dXJuIHJlc3VsdCAvIDEwICoqIHByZWNpc2lvbiBpZiBwcmVjaXNpb24gZWxzZSByZXN1bHQKCiMgQ2hlY2sgc2FtcGxlIGlucHV0cwphc3NlcnQgbG9uZ19zcXJ0KDc3MjAuMTcsIDApID09IDg3CmFzc2VydCBsb25nX3NxcnQoNzcyMC4xNywgMSkgPT0gODcuOAphc3NlcnQgbG9uZ19zcXJ0KDc3MjAuMTcsIDIpID09IDg3Ljg2CiMgUnVuIGNoYWxsZW5nZSBpbnB1dHMKcHJpbnQobG9uZ19zcXJ0KDEyMzQ1KSkKcHJpbnQobG9uZ19zcXJ0KDEyMzQ1NiwgOCkpCnByaW50KGxvbmdfc3FydCgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OSwgMSkp