What is the fastest way to sum two strings made up of only numbers but without converting each to an int beforehand?

Question:

If I am given two strings made up of only numbers 0-9, what is the fastest way to sum the two? Doing something like str(int(num1) + int(num2)) is not allowed and fails.

It mentions in a failed test that the max for an int() is 4300 characters:

ValueError: Exceeds the limit (4300) for integer string conversion: value has 2102288 digits; use sys.set_int_max_str_digits() to increase the limit

Each of the two strings of numbers can be 1,000,000+ characters/numbers long, be empty strings, have mismatched lengths, and/or have leading zeros.

The only way that I can think of is to add each top/bottom digit one at a time from right-to-left and carry the 1 over when necessary.

My version passes all of the tests but fails on long numbers.

def sum_strings(x, y):
    if not x:
        x = '0'
    if not y:
        y = '0'
    x_len = len(x)
    y_len = len(y)

    if x_len > y_len:
        y = y.rjust(x_len, '0')
    elif y_len > x_len:
        x = x.rjust(y_len, '0')

    carry = 0
    total = ''
    for index in range(len(x) - 1, -1, -1):
        new_sum = int(x[index]) + int(y[index]) + carry
        if new_sum > 9:
            new_sum -= 10
            carry = 1
        else:
            carry = 0
        total = f'{new_sum}{total}'

    answer = f'{carry}{total}' if carry else total
    return answer if len(answer) > 1 else answer.lstrip('0')

Times out:

test output

Here are the example "easy" test cases.

@test.describe('Basic tests')
def test_examples():

    @test.it('Example tests')
    def basic_tests():
        test.assert_equals(sum_strings("1", "1"), "2")
        test.assert_equals(sum_strings("123", "456"), "579")

Is there any way to do it faster?

EDIT: Here is the updated/working version although now that I can see other submissions I think there are cleaner ways to do it than this:

def sum_strings(x, y):
    if not x:
        x = '0'
    if not y:
        y = '0'
    x_len = len(x)
    y_len = len(y)

    if x_len > y_len:
        y = y.rjust(x_len, '0')
    elif y_len > x_len:
        x = x.rjust(y_len, '0')

    carry = 0
    total = []
    for index in range(len(x) - 1, -1, -1):
        new_sum = int(x[index]) + int(y[index]) + carry
        if new_sum > 9:
            new_sum -= 10
            carry = 1
        else:
            carry = 0
        total.append(str(new_sum))

    if carry:
        total.append(str(carry))
    total_str = ''.join(reversed(total))
    return total_str[1:] if len(total_str) > 1 and total_str[0] == '0' else total_str
Asked By: JeffSpicoli

||

Answers:

Create a list of digits in the order you generate them, then create the final string using ''.join(reversed(digits)).

Answered By: Solomon Ucko