Если мне даны две строки, состоящие только из чисел 0-9, как быстрее всего их суммировать? Делать что-то вроде str(int(num1) + int(num2)) не разрешено и не получится.
В неудачном тесте упоминается, что максимум для int() составляет 4300 символов:
ValueError: Exceeds the limit (4300) for integer string conversion: value has 2102288 digits; use sys.set_int_max_str_digits() to increase the limit
Каждая из двух строк чисел может иметь длину более 1 000 000 символов/цифр, быть пустой строкой, иметь несовпадающую длину и/или содержать начальные нули.
Единственный способ, который я могу придумать, - это добавлять каждую верхнюю / нижнюю цифру по одной справа налево и при необходимости переносить 1.
Моя версия проходит все тесты, но не работает на длинных числах.
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')
Время вышло:
Вот примеры «простых» тестов.
@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")
Есть ли способ сделать это быстрее?
Обновлено: Вот обновленная/рабочая версия, хотя теперь, когда я вижу другие материалы, я думаю, что есть более чистые способы сделать это, чем этот:
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
Да, предыдущий вопрос был закрыт до того, как я успел его отредактировать. Я сделал репост с более четким заголовком, так как я определенно испортил предыдущий заголовок. Я также добавил дополнительную информацию о тестовых примерах.
Улучшенные вопросы могут быть повторно открыты. Удаленные вопросы заморожены во времени, ожидая, пока SO выяснит, что от вас больше проблем, чем вы того стоите, и навсегда запретит вам (или близко к этому) задавать какие-либо вопросы. (Я не думаю, что это произойдет из-за одного этого случая, но лучше предупредить вас заранее.)
Чтобы объединить символы в строку, используйте оператор «+», а не «f'...'».
@Amadan хорошо, хорошо знать на будущее..
Строки неизменяемы в python, вы все время копируете «всего» (это делает его O (n ^ 2)), вам нужно что-то вроде построителя строк для создания результата. Извините, я недостаточно знаю python.
Вау, не знал, что у int есть ограничение по длине. Интересно, почему это так?
Не нужно делать это по одной цифре за раз, вы можете сделать 4299 цифр за раз.
@mark: размер int не ограничен. Существует ограничение на длину десятичного преобразования между строкой и целым числом. Это было введено, чтобы избежать DOS-атак на серверы. Сообщение об ошибке сообщает вам, как изменить ограничение, как и документы Python.
См. docs.python.org/3/library/…
@rici да, извините, я должен был дать понять, что говорю о функции int(), а не о типе int. В прошлом я делал миллионные целые числа для тестирования.
@mark: ты все еще можешь. Вам просто нужно использовать шестнадцатеричный (или восьмеричный).
Создайте список цифр в том порядке, в котором вы их генерируете, а затем создайте окончательную строку, используя ''.join(reversed(digits)).
Хорошо, использование списка звучит как хорошая идея ... сегодня вечером постараюсь отметить этот ответ, если я получу его, используя список
Да, это сработало ... Он показывает ответы, которые представили другие, теперь, когда я решил проблему, и многие из них намного лучше, чем мое решение ... но, по крайней мере, он прошел все.
Я почти уверен, что уже видел этот вопрос (хотя я не помню идентификатор пользователя). Поскольку вы новый пользователь, я чувствую, что должен предупредить вас, что удаление вопросов, за которые вы проголосовали против, может привести к автоматическому бану алгоритмом SO. Если это вы, вам следует отредактировать вопросы, за которые проголосовали против, и закрытые вопросы, чтобы улучшить их. Пожалуйста, прочитайте эту запись часто задаваемых вопросов.